package tfg; import org.jsfml.graphics.Color; import org.jsfml.graphics.RenderWindow; import org.jsfml.graphics.TextStyle; import org.jsfml.system.Clock; import org.jsfml.system.Vector2i; import org.jsfml.window.Keyboard; import org.jsfml.window.Keyboard.Key; import org.jsfml.window.VideoMode; import org.jsfml.window.event.Event; /** * TFG Game's main class. * This class ideally should be as short as possible. * @author Ritchie Cunningham */ public class Game { /** * Main window where everything will be rendered to and handle input. */ private RenderWindow window = new RenderWindow(); /** * Set's the window title. */ private final String windowTitle = "TFG Game"; /** * Set dimensions (resolution) the window is created with. */ private final Vector2i windowDimensions = new Vector2i(640, 480); /** * Main object representing the player. */ private Player player = new Player(); /** * UI Element responsible for displaying the FPS. */ private final TextUIElement fpsUI = new TextUIElement(InterfacePosition.TOP_LEFT, Color.YELLOW,24,TextStyle.BOLD); /** * Repesents whether or not the user has the window opened and in focus. */ private boolean windowFocus = true; /** * Allows the window to shift focus. */ private Camera camera; /** * Create an instance of the game and run it. * @param args Command line arguments passed in at run-time. */ public static void main(String[] args) { Game g = new Game(); /* Create temp object of self. */ g.run(); /* Invoke run. */ } /** * Configure one-time settings at start-up. */ public void handleInitialization() { window.create(new VideoMode(windowDimensions.x, windowDimensions.y), windowTitle); player.changeMap(new Map(10, 10, Tile.SAND)); camera = new Camera(window); // window.setFramerateLimit(60); } /** * Initializes the game and holds the main loop. */ public void run() { handleInitialization(); int framesDrawn = 0; /* Count each frame that is rendered */ float updateRate = 20.0f; /* Limit the logic loop to update at 20hz */ Clock updateClock = new Clock(); /* Clock used to restrict update loop rate */ Clock frameClock = new Clock(); /* Used to calc average FPS. */ updateClock.restart(); /* Reset update clock. */ /* Calc next update time in millisecs. */ long nextUpdate = updateClock.getElapsedTime().asMilliseconds(); /* As long as window is open, run main loop. */ while(window.isOpen()) { handleInput(); /* Make note of the current update time. */ long updateTime = updateClock.getElapsedTime().asMicroseconds(); while ((updateTime-nextUpdate) >= updateRate) { handleLogic(); nextUpdate += updateRate; /* Compute next appropriate update time. */ } handleDrawing(); framesDrawn++; // Frame has rendered, increment. /* How long has it been since last calulating FPS? */ float elapsedTime = frameClock.getElapsedTime().asSeconds(); if(elapsedTime >= 1.0f) { /* If one second */ /* Divide the frames rendered by one second. */ fpsUI.updateString("FPS: " + (int) (framesDrawn/elapsedTime)); framesDrawn = 0; /* Reset the count. */ frameClock.restart(); /* Reset the frame clock. */ } } } public void handleInput() { /* * Window based event queue. * Good for single-press actions, not for repeated actions though. */ for(Event event : window.pollEvents()) { switch(event.type) { case CLOSED: window.close(); break; case GAINED_FOCUS: windowFocus = true; break; case LOST_FOCUS: windowFocus = false; default: break; } } /* * Real-time input. * Good for repeated actions, bad for single-press actions. */ if(windowFocus) { if(Keyboard.isKeyPressed(Key.W)) { player.move(Direction.NORTH); } else if(Keyboard.isKeyPressed(Key.S)) { player.move(Direction.SOUTH); } else if(Keyboard.isKeyPressed(Key.A)) { player.move(Direction.WEST); } else if(Keyboard.isKeyPressed(Key.D)) { player.move(Direction.EAST); } else if(Keyboard.isKeyPressed(Key.ESCAPE)) { window.close(); } } } /** * Update at a fixed rate (20Hz). */ public void handleLogic() { player.update(); } /** * Updates as fast as possible. Draws all objects onto the screen. */ public void handleDrawing() { /* The window has automatic double-buffering. */ window.clear(); /* Draw each object like layers, background to foreground. */ camera.centerOn(player.getAnimatedSprite()); window.draw(player.getMap()); window.draw(player); camera.centerOnDefault(); window.draw(fpsUI); window.display(); } }