Skip to content

Commit

Permalink
Game loop implemented, user input handler fixed and improved
Browse files Browse the repository at this point in the history
  • Loading branch information
vstepchik committed Sep 5, 2014
1 parent 03c7da8 commit 31af744
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.gmail.vitalatron.game.exec;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public abstract class AbstractTimedLoop implements TimedLoop {
protected volatile int delay = 50;
protected volatile boolean paused = false;
protected volatile boolean stopped = false;
protected List<GameTask> tasks = new CopyOnWriteArrayList<>();

@Override
public synchronized void setTimeout(int milliseconds) {
if (milliseconds <= 0) {
throw new IllegalArgumentException("Loop timeout should be > 0");
}
delay = milliseconds;
}

@Override
public synchronized void setIterationsPerSecond(int ips) {
if (ips <= 0) {
throw new IllegalArgumentException("IPS should be > 0");
}
if (ips > 1000) {
throw new IllegalArgumentException("> 1000ips!? UMAD?");
}
delay = 1000 / ips;
}

@Override
public void removeAllTasks() {
tasks.clear();
}

@Override
public void removeTask(GameTask task) {
tasks.remove(task);
}

@Override
public void addTask(GameTask task) {
tasks.add(task);
}

@Override
public synchronized void setPaused(boolean paused) {
this.paused = paused;
}

@Override
public synchronized void stop() {
stopped = true;
}
}
37 changes: 37 additions & 0 deletions src/main/java/com/gmail/vitalatron/game/exec/ExecutorGameLoop.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.gmail.vitalatron.game.exec;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class ExecutorGameLoop extends AbstractTimedLoop {
protected Executor executor = Executors.newSingleThreadExecutor();
protected long lastExecutionNanoTime;

protected Runnable loop = new Runnable() {
@Override
public void run() {
while (!stopped) {
long t = System.nanoTime();
double delta = ((t - lastExecutionNanoTime) / 1000000) / (double) delay;

for (GameTask task : tasks) {
task.execute(delta);
}

lastExecutionNanoTime = System.nanoTime();
t = (lastExecutionNanoTime - t) / 1000000;

try {
Thread.sleep(delay - t);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
};

public ExecutorGameLoop() {
lastExecutionNanoTime = System.nanoTime();
executor.execute(loop);
}
}
6 changes: 1 addition & 5 deletions src/main/java/com/gmail/vitalatron/game/exec/GameTask.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package com.gmail.vitalatron.game.exec;

public abstract class GameTask implements Runnable {
public interface GameTask {

public abstract void execute(double delta);

@Override
public void run() {
this.execute(1D); // FIXME
}
}

This file was deleted.

7 changes: 6 additions & 1 deletion src/main/java/com/gmail/vitalatron/game/exec/TimedLoop.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.gmail.vitalatron.game.exec;

public interface TimedLoop {
public static final int DEFAULT_DELAY = 33; // 30 fps

public void addTask(GameTask task);
public void removeTask(GameTask task);
public void removeAllTasks();

public void setTimeout(int milliseconds);
public void setFps(int fps);
public void setIterationsPerSecond(int fps);

public void setPaused(boolean paused);
public void stop();
}
85 changes: 64 additions & 21 deletions src/main/java/com/gmail/vitalatron/game/input/KeyboardButton.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,18 @@ public enum KeyboardButton {
X(KeyEvent.VK_X, "x"),
Y(KeyEvent.VK_Y, "y"),
Z(KeyEvent.VK_Z, "z"),
TILDE(KeyEvent.VK_BACK_QUOTE, "~", "`"),
TAB(KeyEvent.VK_TAB, "tab"),

ONE(KeyEvent.VK_1, "1", "!", "one"),
TWO(KeyEvent.VK_2, "2", "@", "two"),
THREE(KeyEvent.VK_3, "3", "#", "three"),
FOUR(KeyEvent.VK_4, "4", "$", "four"),
FIVE(KeyEvent.VK_5, "5", "%", "five"),
SIX(KeyEvent.VK_6, "6", "^", "six"),
SEVEN(KeyEvent.VK_7, "7", "&", "seven"),
EIGHT(KeyEvent.VK_8, "8", "*", "eight"),
NINE(KeyEvent.VK_9, "9", "(", "nine"),
ZERO(KeyEvent.VK_0, "0", ")", "zero"),

F1(KeyEvent.VK_F1, "f1"),
F2(KeyEvent.VK_F2, "f2"),
F3(KeyEvent.VK_F3, "f3"),
Expand All @@ -50,28 +60,61 @@ public enum KeyboardButton {
F13(KeyEvent.VK_F13, "f13"),
F14(KeyEvent.VK_F14, "f14"),
F15(KeyEvent.VK_F15, "f15"),
ONE(KeyEvent.VK_1, "1", "!", "one"),
TWO(KeyEvent.VK_2, "2", "@", "two"),
THREE(KeyEvent.VK_3, "3", "#", "three"),
FOUR(KeyEvent.VK_4, "4", "$", "four"),
FIVE(KeyEvent.VK_5, "5", "%", "five"),
SIX(KeyEvent.VK_6, "6", "^", "six"),
SEVEN(KeyEvent.VK_7, "7", "&", "seven"),
EIGHT(KeyEvent.VK_8, "8", "*", "eight"),
NINE(KeyEvent.VK_9, "9", "(", "nine"),
ZERO(KeyEvent.VK_0, "0", ")", "zero"),

TILDE(KeyEvent.VK_BACK_QUOTE, "~", "`"),
MINUS(KeyEvent.VK_MINUS, "-", "_", "minus", "dash", "underscore"),
EQUALS_ADD(KeyEvent.VK_EQUALS, "=", "+", "plus", "equals"),
INSERT(KeyEvent.VK_INSERT, "insert", "ins"),
DEL(KeyEvent.VK_DELETE, "del", "delete"),
HOME(KeyEvent.VK_HOME, "home"),
ADD(KeyEvent.VK_ADD, "add"),
PAGE_UP(KeyEvent.VK_PAGE_UP, "prior", "pageup"),
PAGE_DOWN(KeyEvent.VK_PAGE_DOWN, "next", "pagedown"),
NUM_LOCK(KeyEvent.VK_NUM_LOCK, "numlock", "numberlock"),
EQUALS(KeyEvent.VK_EQUALS, "=", "equals", "+", "plus"),
SEMICOLON(KeyEvent.VK_SEMICOLON, ";", ":"),
QUOTE(KeyEvent.VK_QUOTE, "'", "\""),
LESS(KeyEvent.VK_COMMA, "<", ","),
GREATER(KeyEvent.VK_PERIOD, ">", "."),
SLASH(KeyEvent.VK_SLASH, "/"),
BACKSLASH(KeyEvent.VK_BACK_SLASH, "\\"),
SQBRACKET_LEFT(KeyEvent.VK_OPEN_BRACKET, "[", "{"),
SQBRACKET_RIGHT(KeyEvent.VK_CLOSE_BRACKET, "]", "}"),
SEMICOLON(KeyEvent.VK_SEMICOLON, ";", ":");

INSERT(KeyEvent.VK_INSERT, "insert", "ins"),
DELETE(KeyEvent.VK_DELETE, "delete", "del"),
HOME(KeyEvent.VK_HOME, "home"),
END(KeyEvent.VK_END, "end"),
PAGE_UP(KeyEvent.VK_PAGE_UP, "pageup", "pgup", "pg_up", "prior"),
PAGE_DOWN(KeyEvent.VK_PAGE_DOWN, "pagedown", "pgdn", "pg_dn", "next"),
PRINT_SCREEN(KeyEvent.VK_PRINTSCREEN, "printscreen", "prtsc", "prtscr", "print_screen"),
PAUSE(KeyEvent.VK_PAUSE, "pause"),

NUM_DIVIDE(KeyEvent.VK_DIVIDE, "num_divide", "gray_divide", "num_slash", "divide"),
NUM_MULTIPLY(KeyEvent.VK_MULTIPLY, "num_multiply", "gray_multiply", "num_asterisk", "asterisk", "star"),
NUM_MINUS(KeyEvent.VK_SUBTRACT, "num_minus", "gray_minus", "num_subtract", "subtract"),
NUM_PLUS(KeyEvent.VK_ADD, "num_plus", "gray_plus", "num_add", "add"),
NUM_1(KeyEvent.VK_NUMPAD1, "num_1", "num1"),
NUM_2(KeyEvent.VK_NUMPAD2, "num_2", "num2"),
NUM_3(KeyEvent.VK_NUMPAD3, "num_3", "num3"),
NUM_4(KeyEvent.VK_NUMPAD4, "num_4", "num4"),
NUM_5(KeyEvent.VK_NUMPAD5, "num_5", "num5"),
NUM_6(KeyEvent.VK_NUMPAD6, "num_6", "num6"),
NUM_7(KeyEvent.VK_NUMPAD7, "num_7", "num7"),
NUM_8(KeyEvent.VK_NUMPAD8, "num_8", "num8"),
NUM_9(KeyEvent.VK_NUMPAD9, "num_9", "num9"),
NUM_0(KeyEvent.VK_NUMPAD0, "num_0", "num0"),
NUM_DOT(KeyEvent.VK_DECIMAL, "num_dot", "num_decimal"),

SPACE(KeyEvent.VK_SPACE, "space", "spacebar"),
BACKSPACE(KeyEvent.VK_BACK_SPACE, "backspace"),
TAB(KeyEvent.VK_TAB, "tab"),
SHIFT(KeyEvent.VK_SHIFT, "shift"),
CTRL(KeyEvent.VK_CONTROL, "ctrl", "control"),
ALT(KeyEvent.VK_ALT, "alt"),
ENTER(KeyEvent.VK_ENTER, "enter", "return"),
ESC(KeyEvent.VK_ESCAPE, "esc", "escape"),

UP(KeyEvent.VK_UP, "up", "arrow_up"),
RIGHT(KeyEvent.VK_RIGHT, "right", "arrow_right"),
DOWN(KeyEvent.VK_DOWN, "down", "arrow_down"),
LEFT(KeyEvent.VK_LEFT, "left", "arrow_left"),

NUM_LOCK(KeyEvent.VK_NUM_LOCK, "numlock", "num_lock", "numberlock"),
SCROLL_LOCK(KeyEvent.VK_SCROLL_LOCK, "scrolllock", "scroll_lock"),
CAPS_LOCK(KeyEvent.VK_CAPS_LOCK, "capslock", "caps_lock");

private static final Map<Integer, KeyboardButton> codeToButtonMap = new HashMap<>();
private static final Map<String, KeyboardButton> textToButtonMap = new LinkedHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ public void keyTyped(KeyEvent e) {
@Override
public void keyPressed(KeyEvent e) {
processKeyboardButtonPressed(KeyboardButton.get(e.getKeyCode()));
e.consume();
}

@Override
public void keyReleased(KeyEvent e) {
processKeyboardButtonReleased(KeyboardButton.get(e.getKeyCode()));
e.consume();
}

@Override
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/gmail/vitalatron/game/meh/core/InputHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gmail.vitalatron.game.meh.core;

import com.gmail.vitalatron.game.input.KeyboardButton;
import com.gmail.vitalatron.game.input.UserInputAdapter;

public class InputHandler extends UserInputAdapter {

@Override
public void keyReleased(KeyboardButton button) {
System.out.println(button);
}
}
18 changes: 15 additions & 3 deletions src/main/java/com/gmail/vitalatron/game/meh/core/MehGame.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
package com.gmail.vitalatron.game.meh.core;

import com.gmail.vitalatron.game.exec.ExecutorGameLoop;
import com.gmail.vitalatron.game.exec.TimedLoop;
import com.gmail.vitalatron.game.input.SwingUserInputHandler;
import com.gmail.vitalatron.game.input.UserInputHandler;
import com.gmail.vitalatron.game.visual.GameWindow;
import com.gmail.vitalatron.game.visual.SwingGameWindow;

import java.awt.*;

public class MehGame {
public static final String GAME_TITLE = "Meh";
protected final GameWindow gameWindow;
protected final UserInputHandler inputHandler;
protected final UserInputHandler userInputHandler;
protected final TimedLoop gameLoop;

protected final InputHandler inputListener;

public MehGame() {
SwingGameWindow swingGameWindow = new SwingGameWindow();
SwingGameWindow swingGameWindow = new SwingGameWindow(GAME_TITLE, new Dimension(200, 300));
this.gameWindow = swingGameWindow;
this.inputHandler = new SwingUserInputHandler(swingGameWindow.getFrame());
this.userInputHandler = new SwingUserInputHandler(swingGameWindow.getFrame());
this.gameLoop = new ExecutorGameLoop();
this.inputListener = new InputHandler();

this.userInputHandler.addListener(inputListener);
}

public void start() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
import java.awt.*;

public class SwingGameWindow implements GameWindow {
protected static final String FRAME_TITLE = "Meh";
protected static final Dimension FRAME_SIZE = new Dimension(200, 300);
public static final Dimension DEFAULT_FRAME_SIZE = new Dimension(400, 400);
private final JFrame frame;

public SwingGameWindow() {
frame = createGameFrame(FRAME_TITLE, FRAME_SIZE);
public SwingGameWindow(String title, Dimension size) {
frame = createGameFrame(title, size);
}

@Override
Expand Down Expand Up @@ -48,7 +47,10 @@ protected static JFrame createGameFrame(String title, Dimension size) {
frame.setMinimumSize(size);
frame.setPreferredSize(size);

// TODO: add input listener
// input handling
frame.setFocusTraversalKeysEnabled(false);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setUndecorated(true);

return frame;
}
Expand Down

0 comments on commit 31af744

Please sign in to comment.