Well "unit" isn't an actual variable or anything. It's just the distance you want to move in a given amount of time. That could be 200 pixels per second or 1 inch per minute, etc. So, in the example, clientTick is the actual framerate you get that may or may not fluctuate wildly from one second to the next, while gameTick is sort of the theoretical, constant framerate that you want to achieve a.k.a the "unit" value. The interpolation mechanism, then, sort of works as an intermediary between the actual and theoretical framerate to keep the sprite moving at constant "unit" increments. Thus, if you want ALL of your movement to appear to move faster, you would increase your "unit" value, which, in the case of the example given would be the value of GAMETICKS_PER_SECOND. Anyway, that's my current understanding of it...
I still got a problem. I have a simple application where a spaceship can be moved along the x-axis of the screen.
the movement (pixels/second) is very slow with the abve example (but smooth). I can't figure out how to speed up the movement of them ship. If I set the increment to a higher value, the movement becomes inconsistent.
here's my implementation of the loop:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| public class GameWindow extends JFrame implements Runnable {
private static final int GAMETICKS_PER_SECOND = 25; private static final int MILLISECONDS_PER_GAMETICK = 1000 / GAMETICKS_PER_SECOND; private static final int screenwidth = 800; private static final int screenheight = 600; private ScenePanel pScene = new ScenePanel(this); boolean running = true; boolean left = false; boolean right = false; boolean fire = false; boolean lock = false; int fps; int dir = 1;
Ship player = new Ship("gfx/bat.gif", 480, 4, 8, 100,500); Ship enemy = new Ship("gfx/cow.gif", 40, 4, 8, 100, 500);
public GameWindow() { this.setResizable(false); this.setTitle("Spacefight"); this.addKeyListener(new java.awt.event.KeyAdapter() { public void keyPressed(KeyEvent e) { this_keyPressed(e); } }); this.addKeyListener(new java.awt.event.KeyAdapter() { public void keyReleased(KeyEvent e) { this_keyReleased(e); } }); this.setContentPane(pScene); setSize(screenwidth, screenheight); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension size = getSize(); screenSize.height = screenSize.height/2; screenSize.width = screenSize.width/2; size.height = size.height/2; size.width = size.width/2; int y = screenSize.height - size.height; int x = screenSize.width - size.width; setLocation(x, y);
setVisible(true); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } void this_keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_SPACE) { if(!lock ) { fire = true; player.shoot(player.posX+player.w/2); } } if (e.getKeyCode() == KeyEvent.VK_LEFT) { right = false; left = true; } if (e.getKeyCode() == KeyEvent.VK_RIGHT) { right = true; left = false; } } void this_keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_LEFT) { left = false; } if (e.getKeyCode() == KeyEvent.VK_RIGHT) { right = false; } }
public void run() { long previousTime = System.currentTimeMillis(); long passedTime = 0; long frametime = previousTime; int framecount = 0; while (running) { float interpolation = passedTime/(float)MILLISECONDS_PER_GAMETICK; clientTick(interpolation); long time = System.currentTimeMillis(); passedTime += (time-previousTime); previousTime = time; while (passedTime>MILLISECONDS_PER_GAMETICK) { framecount++; if (time > (frametime + 999)) { fps = framecount; framecount = 0; frametime = time; } gameTick(); passedTime-=MILLISECONDS_PER_GAMETICK; } } } public void clientTick(float interpolation) { player.posX =(int) player.xIFloat.getValue(interpolation); enemy.posX =(int) enemy.xIFloat.getValue(interpolation); repaint(); } public void gameTick() { if (left) { if (player.posX > 8) { player.xFloatPos = player.xIFloat.getValue(1); player.xFloatPos-=1; player.xIFloat.setValue(player.xFloatPos); } else { player.posX = 8; } } if (right) { if (player.posX < screenwidth-player.w-12) { player.xFloatPos = player.xIFloat.getValue(1); player.xFloatPos+=1; player.xIFloat.setValue(player.xFloatPos); } else { player.posX = screenwidth-player.w-12; } } }
public void update(Graphics g) { paint(g); }
} |