I am trying to start my game from a Main Menu class that implements NiftyGUI. I am using OpenGL (LWJGL) and Java. The problem is that I am never able to get the main menu to disappear and then start the game class, which is World.java.
The following is what I would usually do when I have no main menu.
package com.dev.voxy;
import com.dev.voxy.utilities.GLScreen;
import com.dev.voxy.world.World;
public class Main extends GLScreen {
public static int WIDTH = 1280;
public static int HEIGHT = 720;
private World world;
public static void main(String[] args) {
Main main = new Main();
main.GLScreen(WIDTH, HEIGHT, false, 60, "Voxy");
}
#Override
public void init() {
world = new World();
}
#Override
public void update() {
world.update();
}
#Override
public void dispose() {
world.dispose();
}
That is my main class and extends GLScreen
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.gluPerspective;
public abstract class GLScreen {
protected static int SCREEN_WIDTH;
protected static int SCREEN_HEIGHT;
protected boolean FULL_SCREEN;
protected static int FPS = 60;
protected static String SCREEN_TITLE;
private static long lastFPS;
private static int lfps;
public static int fps;
public void GLScreen(int width, int height, boolean fullscreen, int sync, String title) {
this.SCREEN_HEIGHT = height;
this.SCREEN_WIDTH = width;
this.FULL_SCREEN = fullscreen;
this.FPS = sync;
this.SCREEN_TITLE = title;
InitScreen();
}
public void InitScreen() {
createWindow();
InitGL();
init();
Run();
}
void createWindow() {
try {
Display.setFullscreen(FULL_SCREEN);
Display.setTitle(SCREEN_TITLE);
DisplayMode displayMode = new DisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT);
Display.setDisplayMode(displayMode);
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
}
void InitGL(){
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glViewport(0, 0, Display.getWidth(), Display.getHeight());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(67.0f, SCREEN_WIDTH / SCREEN_HEIGHT, 0.001f, 1000f); //TODO watch coding universe video
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
lastFPS = getTime();
}
public abstract void init();
public abstract void update();
public static int getFPS() {
int cfps;
if (getTime() - lastFPS > 1000 && lfps != fps) {
lfps = fps;
fps = 0; //reset the FPS counter
lastFPS += 1000; //add one second
cfps = fps;
} else {
cfps = lfps;
}
fps++;
return cfps;
}
public static long getTime() {
return (Sys.getTime() * 1000) / Sys.getTimerResolution();
}
void Run(){
while(!Display.isCloseRequested()){
try{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0f, 0f);
glLoadIdentity();
update();
Display.update();
Display.sync(FPS);
} catch (Exception e){
e.printStackTrace();
}
}
dispose();
destroy();
}
public abstract void dispose();
public void destroy() {
Display.destroy();
System.exit(0);
}
}
And finally my World Class is below.
import com.dev.voxy.Main;
import org.lwjgl.opengl.Display;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glLoadIdentity;
public class World extends WorldManager {
private Chunk chunk;
public World() {
super(Main.WIDTH, Main.HEIGHT);
init();
}
#Override
public void init() {
chunk = new Chunk(0, 0, 0);
setRenderStats(true);
}
public void update() {
input();
render();
}
public void render() {
render3D();
Translate();
chunk.render();
glLoadIdentity();
if (isRenderStats()) {
render2D();
glColor3f(1, 1, 1);
renderStats();
}
}
#Override
public void dispose() {
chunk.dispose();
Display.destroy();
System.exit(0);
}
}
The problem is that when I try and incorporate my Menu into this it never works. First I tried GameStates so that whenever the game state is GAME the nifty should no longer render but this causes the Window to close because nifty no longer keeps it open, so then I tried to have the loop be outside the MainMenu Class but that also did not work because I kept running into static/non-static errors which I could not figure out. Then my last idea was why not try and put the gameloop inside the MainMenu Class but try to stop the nifty render while I try to start the game, but that left elements of the nifty on the screen and the rest was blank and the World class did not render. The following are my current Main, MainMenu, GLScreen and MyScreenController and MainMenu.xml files The MyscreenController controls what happens when the respective buttons are pressed and the MainMenu.xml is the nifty xml file that lays out everything.
All relevant files and classes may be found at the following link, they are the current ones where I am trying to get the main menu working. The classes shown above show what I did to get ONLY the game part working in the first place, without a menu.
LINK
To sum up, I can get my game working when there is not main menu and I can get my main menu working when there is no game, I have tried as many things I can think of but after 3 days I'm simply lost and would like any suggestion/recommendation or idea. I think I just can't figure out how to manage game states and the game loop when there is a main menu and a game, I was thinking maybe if there was a way to stop nifty completely then clear the screen then set OpenGL to 3D I can get my game rendered, this is what I was trying to do near the end but could not figure it out.
Thank you.
Related
At this moment I have 2 screens: MainScreen (it's the main menu of the game) and GameScreen. I have a "button" (it's an image) that when the user clicks on it, the MainScreen switchs to the GameScreen.
The problem is that all the images of the MainScreen don't disappear when the second screen appears (the button and the main title). I have been working on this for days and I don't know what more to do.
Main class of the game:
public class MyGame extends Game {
#Override
public void create () {
Sounds.load();
Texts.load();
Buttons.load();
setScreen(new MainScreen(this));
}
#Override
public void dispose () {
super.dispose();
Sounds.dispose();
Texts.dispose();
Buttons.dispose();
}
}
MainScreen:
public class MainScreen implements Screen {
private MyGame game;
private Stage stage;
private OrthographicCamera camera;
private Viewport viewport;
public static Image tituloPrincipal, botonPlay;
public MainScreen(final MyGame game) {
this.game = game;
//stage
camera = new OrthographicCamera(Settings.SCREEN_WIDTH, Settings.SCREEN_HEIGHT);
viewport = new StretchViewport(Settings.SCREEN_WIDTH, Settings.SCREEN_HEIGHT, camera);
stage = new Stage(viewport);
//background
stage.addActor(new Image(Sprites.mainBackground));
//Title of the game
tituloPrincipal = new Image();
tituloPrincipal.setPosition(Settings.SCREEN_WIDTH * 1 / 6, Settings.SCREEN_HEIGHT * 4 / 12);
tituloPrincipal.setDrawable(new TextureRegionDrawable(new TextureRegion(Texts.tituloPrincipal)));
tituloPrincipal.setSize(Texts.tituloPrincipal.getWidth()/3,
Texts.tituloPrincipal.getHeight()/3);
stage.addActor(tituloPrincipal);
//Play Button
botonPlay = new Image();
botonPlay.setPosition(Settings.SCREEN_WIDTH * 4 / 10, Settings.SCREEN_HEIGHT / 16);
botonPlay.setDrawable(new TextureRegionDrawable(new TextureRegion(Buttons.playbutton)));
botonPlay.setSize(Buttons.playbutton.getWidth()/16,
Buttons.playbutton.getHeight()/18);
stage.addActor(botonPlay);
//Song
Sounds.musicMainScreen.play();
}
#Override
public void show() {
Gdx.input.setInputProcessor(stage);
}
#Override
public void render(float delta) {
botonPlay.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen(new GameScreen(game));
dispose();
}
});
stage.draw();
stage.act(delta);
}
#Override
public void resize ( int width, int height){
}
#Override
public void pause () {
}
#Override
public void resume () {
}
#Override
public void hide () {
}
#Override
public void dispose () {
}
}
GameScreen:
public class GameScreen implements Screen {
private Game game;
private Stage stage;
public GameScreen(Game game) {
this.game = game;
stage = new Stage();
Gdx.input.setInputProcessor(stage);
deleteMainScreenSources();
//song
Sounds.musicGameScreen.play();
}
public void deleteMainScreenSources() {
Sounds.musicMainScreen.stop();
}
#Override
public void show() {
}
#Override
public void render(float delta) {
}
#Override
public void resize ( int width, int height){
}
#Override
public void pause () {
}
#Override
public void resume () {
}
#Override
public void hide () {
}
#Override
public void dispose () {
}
}
Button class:
public class Buttons {
public static Texture playbutton;
public static void load() {
playbutton = new Texture(Gdx.files.internal("playbutton.png"));
playbutton.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
}
public static void dispose() {
playbutton.dispose();
}
}
The class of the title it's like the class of the button.
Your render method is what draws your screen. If you are not aware, it is kind of a game loop , which gets executed non stop ( around 60/sec by default I believe). So all your drawing and redrawing goes here.Usually , you would be clearing your screen at first and then draw other images on the screen. Libgdx provide interfacing to opengl to clear the screen. In my case, I always clear screen at the very first line of render method and draw additional things on it so that it makes sure my stale content of the screens are gone.In your GameScreen , your render method is empty , so your previous screen is not yet wiped out. I believe adding clear and drawing your new stage in GameScreen will resolve your issue.
Make your code in GameScreen render something like this and try ,
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
Also, I would try to avoid creation of any new object in 'render` method for the same reason. Your addListener method in your menu screen can go in it's constructor. So that you don't create anonymous listener in every game loop execution. This may not impact by that much in your current scenario, but if you create some heavy object or some Sprites in this way in game loop, that can drag your game perfomance a lot.
I'm making a simple 2D game in LibGDX. This is my first project with it.
On my phone everything works fine, nothing bad (6.0.1), but on other phones (no matter what version) it doesn't work. It's clear that the render method doesn't work, but I don't know why. I've tried to add super.render(); but it made it red, so it's not working or I've made some mistake.
This is a menu screen, what comes first. It works fine, than I play and die, than I call it again and it crashes.
public class MenuScreen implements Screen {
private DualisAutosapp game;
private OrthographicCamera camera;
...
public MenuScreen(DualisAutosapp game)
{
super();
Gdx.app.log("Menu","Started");
this.game = game;
camera = new OrthographicCamera();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.app.log("Menu","Camera");
logoTexture = new Texture(Gdx.files.internal("background.png"));
logoTexture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
logo = new Sprite(logoTexture);
Gdx.app.log("Menu","Background");
startTexture = new Texture(Gdx.files.internal("start.png"));
startTexture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
start = new Sprite(startTexture);
Gdx.app.log("Menu","Start");
carChooseTexture = new Texture(Gdx.files.internal(prefs.getString("playercar", "player/mazda2.png")));
carChooseTexture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
carChoose = new Sprite(carChooseTexture);
Gdx.app.log("Menu","Car");
font = new BitmapFont(Gdx.files.internal("font/joystix_monospace.fnt"), Gdx.files.internal("font/joystix_monospace.png"), false);
batch = new SpriteBatch();
Gdx.app.log("Menu","batch");
calculateSpriteLocation(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
Gdx.app.log("Menu","calculate");
}
#Override
public void show() {
}
#Override
public void resize(int width, int height) {
camera = new OrthographicCamera();
camera.setToOrtho(false,Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
calculateSpriteLocation(width,height);
}
#Override
public void render (float delta) {
Gdx.app.log("Menu","render");
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
...
}
#Override
public void resume() {
Gdx.app.log("Menu","Rizjúm");
carChooseTexture = new Texture(Gdx.files.internal(prefs.getString("playercar", "player/mazda2.png")));
carChooseTexture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
carChoose = new Sprite(carChooseTexture);
}
#Override
public void hide() {
}
private void calculateSpriteLocation(int width, int height)
{
logo.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
logo.setPosition(width/2-logo.getWidth()/2, height/2-logo.getHeight()/2);
start.setSize(Gdx.graphics.getWidth()/3.6f, Gdx.graphics.getHeight()/6.4f);
start.setPosition(width/2-start.getWidth()/2, height/2-start.getHeight()/2);
carChoose.setSize(Gdx.graphics.getWidth()/3.6f, Gdx.graphics.getHeight()/6.4f);
carChoose.setPosition(width/2-carChoose.getWidth()/2, height/10-carChoose.getHeight()/2);
}
}
Everything is ok until the log of the render where it crashes.
EDIT
Game Class
public class DualisAutosapp extends Game {
#Override
public void create () {
showMenuScreen();
}
public void switchScreen(Screen newScreen){
Screen previousScreen = getScreen();
setScreen( newScreen );
if (previousScreen != null)
{
previousScreen.dispose();
}
}
public void showMenuScreen()
{
switchScreen(new MenuScreen(this));
}
public void showGameScreen()
{
switchScreen(new GameScreen(this));
}
public void showCarChangeScreen() {
switchScreen( new CarChange(this));
}
}
First of all I'll recommend you to follow Life cycle method of Game/Screen of Libgdx API. If you not override lifecycle method of Game then it call Screen corresponding method.
You're initialize your objects whenever you want but it's not a good way. It's better to initialize all your screen object inside show method of Screen Interface.
Create object's of all screens inside Game class at once and only use that object in setScreen(screen) method.
#Override
public void show() {
..//create objects
}
Use dispose() method and destroy objects that you created in show().
Method resize() can be used to update viewport of camera with device size.
Use pause() and resume() according to your requirement like music pause but not for object initialization.
Well,i think you should not pass Game class to screen constructors every time, and you could try something like this for screen management.
import com.badlogic.gdx.Screen;
public enum MyScreens {
GAME_SCREEN {
public Screen getScreenInstance() {
return new GameScreen();
}
},
MAIN_MENU {
public Screen getScreenInstance() {
return new MainMenu();
}
},
SPLASH_SCREEN {
public Screen getScreenInstance() {
return new SplashScreen();
}
};
public abstract Screen getScreenInstance();
}
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.utils.IntMap;
public class ScreenManager {
private static ScreenManager instance;
private Game game;
private IntMap<Screen> screens;
private ScreenManager() {
screens = new IntMap<Screen>();
}
public static ScreenManager getInstance() {
if (instance == null) {
instance = new ScreenManager();
}
return instance;
}
public void initialize(Game game) {
this.game = game;
}
public void show(MyScreens screen) {
if (game == null) {
return;
}
if (!screens.containsKey(screen.ordinal())) {
screens.put(screen.ordinal(), screen.getScreenInstance());
}
game.setScreen(screens.get(screen.ordinal()));
}
public void dispose(MyScreens screen) {
if (!screens.containsKey(screen.ordinal())) {
return;
}
screens.remove(screen.ordinal()).dispose();
}
public void dispose() {
for (Screen screen : screens.values()) {
screen.dispose();
}
screens.clear();
instance = null;
}
}
In my game I have currently two screens. The MenuScreen and the GameScreen. Through the Play option in the menu the player can switch to the GameScreen and start the Gameplay and with Escape he can get back to the MenuScreen. I dispose the used Assets when I switch to the other Screen in the hide() method and load the needed Assets for the new Screen in the constructor of the Screen I switch to. The problem is that the Textures and Sound Effects aren't rendered/played when I switch back.
For example when I start the game in the MenuScreen, then switch to the GameScreen everything is fine. But when I switch back to the MenuScreen the MenuScreen is just a black window. When I then switch to the GameScreen again it's black too except for the BitmapFont.
Maybe there is a fundemental flaw in the way I handle this. I tried to leave out as much unnecessary things as I can from the code I post here, but I fear that it's still too much.
RessourceLoader Class:
public class RessourceLoader {
public static AssetManager manager;
public static void create() {
manager = new AssetManager();
}
public static void loadMenuScreen() {
manager.load("gfx/menuBackground.png", Texture.class);
}
public static void getMenuScreen() {
menuBackground = manager.get("gfx/menuBackground.png", Texture.class);
}
public static void disposeMenuScreen() {
menuBackground.dispose();
}
public static void loadGameScreen() {
// load GameScreen Assets through AssetManager
}
public static void getGameScreen() {
// get GameScreen Assets through AssetManager
}
public static void disposeGameScreen() {
// dispose all GameScreen Assets
}
public static void dispose() {
manager.dispose();
}
}
MenuScreen Class:
public class MenuScreen implements Screen {
// Game starts in the MenuScreen
// Instance of game
private PHGame game;
// Orthographic camera
private OrthographicCamera cam;
public MenuScreen(PHGame phGame) {
game = phGame;
RessourceLoader.loadMenuScreen();
RessourceLoader.manager.finishLoading();
RessourceLoader.getMenuScreen();
cam = new OrthographicCamera();
cam.setToOrtho(true, 640, 480);
game.batcher.setProjectionMatrix(cam.combined);
}
#Override
public void render(float delta) {
// Fills background with black to avoid flickering
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Begin Drawing
game.batcher.begin();
// Draw Menu
// Stop drawing
game.batcher.end();
// Pressing Space confirms currently selected menu item
if (GameKeys.isPressed(GameKeys.SPACE)) {
game.setScreen(new GameScreen(game));
}
// Update Key Presses
GameKeys.update();
}
#Override
public void hide() {
dispose();
}
#Override
public void dispose() {
RessourceLoader.disposeMenuScreen();
}
}
GameScreen Class:
public class GameScreen implements Screen {
// Instance of game
private PHGame game;
private GameWorld world;
private GameRenderer renderer;
private float runTime;
public GameScreen(PHGame phGame) {
game = phGame;
RessourceLoader.loadGameScreen();
RessourceLoader.manager.finishLoading();
RessourceLoader.getGameScreen();
world = new GameWorld(game, this);
renderer = new GameRenderer(world, game);
}
#Override
public void render(float delta) {
// runTime is the amount of time the game is running
runTime += delta;
// Updates the Game World
world.update(delta);
// Renders everything
renderer.render(runTime);
// Update Key Presses
GameKeys.update();
}
#Override
public void hide() {
dispose();
}
#Override
public void dispose() {
RessourceLoader.disposeGameScreen();
}
}
GameRenderer Class:
public class GameRenderer {
// Instance of PHGame
PHGame game;
// Instance of Game World
private GameWorld world;
// Orthographic Camera
private OrthographicCamera cam;
// If true hitbox's will be shown
private boolean showHitbox;
// Game Objects
private Player player;
public GameRenderer(GameWorld world, PHGame game) {
this.game = game;
this.world = world;
player = world.getPlayer();
cam = new OrthographicCamera();
cam.setToOrtho(true, 640, 480);
showHitbox = false;
game.batcher.setProjectionMatrix(cam.combined);
}
public void render(float runTime) {
// draw objects and hud
}
}
If there are any questions regarding my problem I'll try to answer then as good as I can.
Refer to the github article 'managing your assets'. AssetManagers should not be static. 'This typically would cause black/missing textures or incorrect assets.'
After you dispose your asset manager it can no londer be used. Instead use manager.unload to unload assets. manager.unload("gfx/menuBackground.png");
EDIT:
I also didn't see any overriden show() methods. If you want your assets back you will need to load your assets in the screen's show method every time.
I have a simple physics loop that does a calculation for a time interval, waits for the interval to pass, and then renders the results on the screen. It's very simple code (even though the timing is probably wrong, but that's exactly what I'm trying to learn about) and works well when I am moving the mouse around the screen.
package physicssim;
import java.awt.Graphics;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PhysicsSim extends JFrame {
private static class PhysicsObject {
public PhysicsObject(double x, double y, double v_x, double v_y) {
this.x = x;
this.y = y;
this.v_x = v_x;
this.v_y = v_y;
}
public double x;
public double y;
public double v_x;
public double v_y;
}
PhysicsObject particle;
boolean running = true;
DrawPane drawPane;
public PhysicsSim() {
particle = new PhysicsObject(10,10, .1, .2);
drawPane = new DrawPane(particle);
this.setSize(800,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setContentPane(drawPane);
this.setVisible(true);
}
private static class DrawPane extends JPanel {
PhysicsObject p;
public DrawPane(PhysicsObject p) {
this.p = p;
}
#Override
public void paint(Graphics g) {
super.paint(g); //To change body of generated methods, choose Tools | Templates.
g.fillOval((int)p.x, (int) p.y, 10, 10);
}
}
public void start() {
int FPS = 60;
long TIME_BETWEEN_FRAMES_NS = 1000000000/FPS;
// Initial draw
drawPane.repaint();
long lastDrawTime = System.nanoTime();
while(running) {
// Update physics
particle.x+=particle.v_x*(TIME_BETWEEN_FRAMES_NS*.0000001);
particle.y+=particle.v_y*(TIME_BETWEEN_FRAMES_NS*.0000001);
// While there is time until the next draw wait
while(TIME_BETWEEN_FRAMES_NS > (System.nanoTime()-lastDrawTime)) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(PhysicsSim.class.getName()).log(Level.SEVERE, null, ex);
}
}
drawPane.repaint();
long currentTime = System.nanoTime();
System.out.println(currentTime - lastDrawTime);
lastDrawTime = currentTime;
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
PhysicsSim sim = new PhysicsSim();
sim.start();
}
}
The last bit about printing the time difference was just a sanity check to make sure that it was in fact calling around the requested interval. The results are fairly consistent so I don't see why there should be any choppiness.
As I mentioned above, this code works great if I a moving the mouse around the screen, everything is smooth.
If I am not moving the mouse it becomes very choppy until I start moving the mouse over the application.
I assume this is something simple, but I hope that you guys can help me. Thank you.
Alright, it looks like my problem was I was drawing directly to g in paint(). After replacing with the following everything worked correctly.
#Override
public void paint(Graphics g) {
BufferedImage img = new BufferedImage(800, 600, BufferedImage.TYPE_3BYTE_BGR);
img.getGraphics().fillOval((int) p.x, (int) p.y, 10, 10);
g.drawImage(img, 0, 0, null);
}
I was considering deleting this code snippet because it's rough and shameful, but maybe it will help someone else. Happy coding.
I am trying to make my own engine but I need some help.
I am currently doing the level system. The level class extends the render class and the level class overides the Render classes render method. Finally the render class is called from the main class but I dont call the level class.
EDIT:
I have removed the static but now cannot call the render method. I know I am very nooby I kind of teach my self.
package SimpleEngine.Render;
Render Class (This is called)
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import SimpleEngine.Primitives.*;
import static org.lwjgl.opengl.GL11.glClear;
public class Render {
public void Render() {
}
}
Level Class (This is not called) I want this Render method to override the Render classes render method but it doesn't work.
package SimpleEngine.Level;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import SimpleEngine.Render.*;
import SimpleEngine.Primitives.*;
public class Level extends Render {
public void Render() {
glClear(GL_COLOR_BUFFER_BIT);
Primitives.DrawSquare(200, 200, 50, 50, 1, 0, 0);
}
}
My main method (calls render but cannot anymore)
package SimpleEngine;
import org.lwjgl.LWJGLException;
import SimpleEngine.Level.*;
import SimpleEngine.Logic.*;
import SimpleEngine.Input.*;
import SimpleEngine.Render.*;
import SimpleEngine.Entites.*;
import SimpleEngine.Timer.*;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
public class simpleEngine {
public static final int WIDTH = 640;
public static final int HEIGHT = 480;
private static boolean isRunning = true;
public static void main(String[] args) {
setUpDisplay();
setUpOpenGL();
Entity.setUpEntities();
Timer.setUpTimer();
while (isRunning) {
Render.Render();
Logic.logic(Timer.getDelta());
Input.input();
Display.update();
Display.sync(60);
if (Display.isCloseRequested()) {
isRunning = false;
}
}
Display.destroy();
System.exit(0);
}
private static void setUpDisplay() {
try {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.setTitle("SimpleEngine");
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
Display.destroy();
System.exit(1);
}
}
private static void setUpOpenGL() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 640, 480, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
}
}
You can't override static methods.
As per Oracle tutorail
If a subclass defines a class method with the same signature as a class method in the superclass, the method in the subclass hides the one in the superclass.
AND
You will get a compile-time error if you attempt to change an instance method in the superclass to a class method in the subclass, and vice versa.
Remove static from Render class render() method and change Level class Render method to render() to introduce overriding behavior
EDIT:
while (isRunning) {
new Level().Render();
Note: Java naming convention suggests that method name should start with small letter and name should be camelcase.
You can't override a static method.
Also, be careful because Java is a case sensitive language, so Render() is not the same as render(), and could be a completely different method.
I would recommend doing something more generic such as having an interface which defines common methods for any state your game could be in which actually looks like the direction you're heading in. This would just combine your Logic and Render classes. For example:
public Interface IGameState {
public void update(int delta);
public void render();
}
And then you can have a class that implements that interface such as:
public class InGameState implements IGameState {
public InGameState() { }
// This is similar to your Logic class
public void update(int delta) {
// Perform any updates necessary such as handling keyboard input
}
public void render() {
// What you included in your example
glClear(GL_COLOR_BUFFER_BIT);
Primitives.DrawSquare(200, 200, 50, 50, 1, 0, 0);
}
}
And then your main method could look something like this:
public static final int WIDTH = 640;
public static final int HEIGHT = 480;
private static boolean isRunning = true;
private IGameState currentGameState;
public static void main(String[] args) {
setUpDisplay();
setUpOpenGL();
Entity.setUpEntities();
Timer.setUpTimer();
// Create a new game state
currentGameState = new InGameState();
while (isRunning) {
// Change to this type of thing
// The delta would be the time since last frame so you can stay frame rate
// independent
currentGameState.update(delta);
currentGameState.render();
Display.update();
Display.sync(60);
if (Display.isCloseRequested()) {
isRunning = false;
}
}
Display.destroy();
System.exit(0);
}