ChouChou
JGO n00b  Posts: 46
|
 |
«
on:
2010-02-07 09:01:14 » |
|
Hi, I'm ChouChou, I've been lurking around this great forum for a while and this is my first post. I have a question regarding the character states and animation, I' ve read some great posts from http://www.java-gaming.org/topics/making-the-character-attack-once/21788/view.htmland http://www.java-gaming.org/topics/simple-sprite-animation-loop/16829/view.htmlI'm doing a side scroller game like rockmanX4(using Zero's light saber as weapon) and hopefully the control/animation will be smooth like it in the future, but I felt like I coded my character states and animation class wrong as I need a bunch of if statements just to get things working. Following is the code and I'm seeking advice on how to improve my state/animation system to make things better, thanks in advance! P.S I will post additional code if required. States Class 1 2 3 4 5 6 7 8 9 10 11 12
| public class States { public static final int IDLE = 0; public static final int RUNNING = 1; public static final int JUMPING = 2; public static final int HIT = 3; public static final int ATTACKING = 4; public static final int LEFT = -1; public static final int RIGHT = -2; } |
Animation Class 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
| public class Animation { private BufferedImage img; private int frameDuration = 60; private int frameNumberY, frameNumberX, frameX, frameY, charWidth, charHeight, sheetWidth, sheetHeight, playStyle; private long lastFrameChange; private long lastLoopTime = System.currentTimeMillis(); private boolean isFinished = false; public static final int PLAY_ONCE = 0; public static final int LOOPING = 1; private int currentState = States.IDLE; private int animState = States.IDLE; public void createAnimation(BufferedImage img, int x, int y, int offsetX, int offsetY, int charWidth, int charHeight, int sheetWidth, int sheetHeight, int frameDuration, int startFrame, int playStyle) { if(currentState > animState || currentState == States.IDLE) { animState = currentState; frameNumberX = 0; lastFrameChange = 0; this.img = img; this.charWidth = charWidth; this.charHeight = charHeight; this.sheetWidth = sheetWidth; this.sheetHeight = sheetHeight; this.frameDuration = frameDuration; this.playStyle = playStyle; } } public void update() { if(currentState == animState && !isFinished) { long delta = System.currentTimeMillis() - lastLoopTime; lastLoopTime = System.currentTimeMillis(); lastFrameChange += delta; if (lastFrameChange > frameDuration) { lastFrameChange = 0; frameNumberX++; if (frameNumberX >= sheetWidth) { if(playStyle == PLAY_ONCE) { isFinished = true; currentState = States.IDLE; animState = States.IDLE; } else if(playStyle == LOOPING) { frameNumberX = 0; } } frameNumberY++; if (frameNumberY >= sheetHeight) { frameNumberY = 0; } } frameX = (frameNumberX % sheetWidth) * charWidth; frameY = (frameNumberY % sheetHeight) * charHeight; } if(isFinished) { isFinished = false; } } public BufferedImage getCurrentImage() { return img.getSubimage(frameX, frameY, charWidth, charHeight); } public int getAnimState() { return animState; } public int getCurrentState() { return currentState; } public void setCurrentState(int state) { this.currentState = state; } public void setAnimState(int state) { this.animState = state; } public boolean isFinished() { return isFinished; } public void setFinished(boolean isFin) { isFinished = isFin; } } |
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #1 on:
2010-02-07 09:02:56 » |
|
Part of the Player class 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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
| int key = -1; public void update(long elapsedTime) { float dx = 0, dy = 0; setPlayerState(dx, dy); enemyCollision(); changeStatus(elapsedTime); fallCheck(); jump(); offsetX = (int)((GameCore.mapPosX + GameCore.fixX)* Map.TILE_SIZE); offsetY = (int)((GameCore.mapPosY + GameCore.fixY) * Map.TILE_SIZE); xp = (int) (Map.TILE_SIZE * px); yp = (int) (Map.TILE_SIZE * py); updateAnim(); } long totalDuration = 0; private void changeStatus(long elapsedTime) { if(status == Status.INVINCIBLE) { totalDuration += elapsedTime; if(totalDuration > 1000) { status = Status.NORMAL; totalDuration = 0; } } }
private void jump() { if(jumping) { idle = false; jumpDistance += gravity; if(jumpDistance < 0 && space) { if(validLocation(px, py - moveSPeed)) { moveY(-moveSPeed); } else { space = false; } } else if(jumpDistance > 0 || !space) { moveY(moveSPeed); } anim.setCurrentState(States.JUMPING); } }
private void fallCheck() { if(!jumping) { if(validLocation(px, py + moveSPeed)) { jumpDistance = 0; jumping = true; } } } private void setPlayerState(float dx, float dy) { if(hit) { if(status != Status.INVINCIBLE) { idle = false; left = false; right = false; jumping = false; hp -= 1; anim.setCurrentState(States.HIT); status = Status.INVINCIBLE; } hit = false; } if(attacking) { if(States.ATTACKING > anim.getCurrentState()) { idle = false; anim.setCurrentState(States.ATTACKING); } } if(space && !jumping) { if(anim.getAnimState() == States.ATTACKING || anim.getAnimState() == States.HIT) { } else { idle = false; jumping = true; jumpDistance = maxJumpHeight; } } if(left) { idle = false; faceDir = States.LEFT; if(anim.getAnimState() == States.ATTACKING || anim.getAnimState() == States.HIT) { } else if(jumping) { dx = -moveSPeed; } else { if(States.RUNNING >= anim.getCurrentState()) { anim.setCurrentState(States.RUNNING); dx = -moveSPeed; } else if(attacking) { } else { idle = true; } } } if(right) { idle = false; faceDir = States.RIGHT; if(anim.getAnimState() == States.ATTACKING || anim.getAnimState() == States.HIT) { } else if(jumping) { dx = moveSPeed; } else { if(States.RUNNING >= anim.getCurrentState()) { anim.setCurrentState(States.RUNNING); dx = moveSPeed; } else if(attacking) { } else { idle = true; } } } if(idle) { anim.setCurrentState(States.IDLE); } if(moveX(dx)) { } } public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_C && !pressAttack) { attacking = true; pressAttack = true; } if (e.getKeyCode() == KeyEvent.VK_SPACE && !jumping && !attacking && !pressSpace) { space = true; pressSpace = true; } if (e.getKeyCode() == KeyEvent.VK_LEFT) { left = true; } if (e.getKeyCode() == KeyEvent.VK_RIGHT) { right = true; } if (e.getKeyCode() == KeyEvent.VK_UP) { } if (e.getKeyCode() == KeyEvent.VK_DOWN) { } } public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_LEFT) { left = false; idle = true; } if (e.getKeyCode() == KeyEvent.VK_RIGHT) { right = false; idle = true; } if (e.getKeyCode() == KeyEvent.VK_UP) { } if (e.getKeyCode() == KeyEvent.VK_DOWN) { } if(e.getKeyCode() == KeyEvent.VK_SPACE) { space = false; pressSpace = false; } if (e.getKeyCode() == KeyEvent.VK_C) { attacking = false; pressAttack = false; } } private void updateAnim() { if(anim.getCurrentState() == States.HIT) { if(faceDir == States.LEFT) { anim.createAnimation(img.getPlayerAnim()[img.GET_HIT_L], xp, yp, offsetX, offsetY, 56, 53, 6, 1, 80, 0, Animation.PLAY_ONCE); } else { anim.createAnimation(img.getPlayerAnim()[img.GET_HIT_R], xp, yp, offsetX, offsetY, 56, 53, 6, 1, 80, 0, Animation.PLAY_ONCE); } } else if(anim.getCurrentState() == States.ATTACKING) { if(faceDir == States.LEFT) { anim.createAnimation(img.getPlayerAnim()[img.ATTACK_L], xp, yp, offsetX, offsetY - 20, 103, 71, 5, 1, 60, 0, Animation.PLAY_ONCE); } else { anim.createAnimation(img.getPlayerAnim()[img.ATTACK_R], xp, yp, offsetX, offsetY - 20, 103, 71, 5, 1, 60, 0, Animation.PLAY_ONCE); } } else if(anim.getCurrentState() == States.RUNNING) { if(faceDir == States.LEFT) { anim.createAnimation(img.getPlayerAnim()[img.RUN_L], xp, yp, offsetX, offsetY, 54, 45, 15, 1, 60, 0, Animation.PLAY_ONCE); } else { anim.createAnimation(img.getPlayerAnim()[img.RUN_R], xp, yp, offsetX, offsetY, 54, 45, 15, 1, 60, 0, Animation.PLAY_ONCE); } } else if(anim.getCurrentState() == States.JUMPING) { if(faceDir == States.LEFT) { anim.createAnimation(img.getPlayerAnim()[img.JUMP_L], xp, yp, offsetX, offsetY, 54, 58, 5, 1, 60, 0, Animation.PLAY_ONCE); } else { anim.createAnimation(img.getPlayerAnim()[img.JUMP_R], xp, yp, offsetX, offsetY, 54, 58, 5, 1, 60, 0, Animation.PLAY_ONCE); } } else if(anim.getCurrentState() == States.IDLE) { if(faceDir == States.LEFT) { anim.createAnimation(img.getPlayerAnim()[img.IDLE_L], xp, yp, offsetX, offsetY, 54, 45, 1, 1, 60, 0, Animation.LOOPING); } else { anim.createAnimation(img.getPlayerAnim()[img.IDLE_R], xp, yp, offsetX, offsetY, 54, 45, 1, 1, 60, 0, Animation.LOOPING); } } anim.update(); } |
|
|
|
|
|
zoto
Full Member   Posts: 234 Medals: 7
|
 |
«
Reply #2 on:
2010-02-07 10:32:07 » |
|
You should probably just use the same update signature on the animation as you do for the player, then you can pass the elapsed time instead of recalculating it.
In your animation update function it looks like you increase frameNumberY every time instead of just if(frameNumberX >= sheetWidth), basically traversing diagonally across the sprite sheet.
I'm not sure how your sprite sheets are setup but the way I usually do it is to have a separate sheet for each action. The animation class has no player logic in it all it does is update and draw. The player class has an animation object for each action and the player class chooses what animation to update/draw based on its current state.
|
|
|
|
|
Games published by our own members! Go get 'em!
|
|
Swattkidd7
Full Member   Posts: 198
|
 |
«
Reply #3 on:
2010-02-07 15:28:58 » |
|
It seems like every time you update you create a new animation, you should try loading the animations once and then just setting the currentAnimation to whichever animation is happening at the time. For example have a jumping animation, running, etc, etc and a currentAnimation. Then when you check if the character is "running" set the currentAnimation to running.
But as you can tell by the first post you linked to, this method may not be the best method or even a correct method.
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #4 on:
2010-02-07 23:39:28 » |
|
Thanks for the replies! My sprite sheet is set up with image after image horizontally(but each action has a separate sheet ), so Y never increases( keep it simple for now), only X will need to change. something like this: [0 1 2 3 4 5 6 7] with numbers representing each image.
I also have a LoadImage class to load the sprite sheet and store them into an array, so that the images are only loaded once. I can play most of the animations correctly but when I switch from left button to right button really quickly( I have a faceDir boolean in the player class to show which direction the player is currently facing ) I have a problem that the correct running animation wont be played unless the previous direction animation has finished playing, is that the problem of my animation class or did i somehow set up the character states wrong in the player class?
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #5 on:
2010-02-07 23:40:54 » |
|
You should probably just use the same update signature on the animation as you do for the player, then you can pass the elapsed time instead of recalculating it.
I'm going to implement that next .
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #6 on:
2010-02-09 08:47:07 » |
|
After I implemented elapsedTime(delta for some people) to my moveSpeed variables I start seeing multiple images for my running animation, is there a reason for that? 
|
|
|
|
|
zoto
Full Member   Posts: 234 Medals: 7
|
 |
«
Reply #7 on:
2010-02-09 09:32:58 » |
|
Do you mean multiple images off the sprite sheet? drawing the same image multiple places? Regardless it's hard to say what the problem is without seeing the code.
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #8 on:
2010-02-09 09:34:54 » |
|
Do you mean multiple images off the sprite sheet? drawing the same image multiple places? Regardless it's hard to say what the problem is without seeing the code.
Yea, mutiple images drawing near where the sprite is, do you want me to send you the code?
|
|
|
|
|
zoto
Full Member   Posts: 234 Medals: 7
|
 |
«
Reply #9 on:
2010-02-09 09:37:25 » |
|
Sure you can send it to me or just post it some public place so more people can help. Multiple images off the sprite sheet probably means your sub image is just too big.
|
|
|
|
|
Games published by our own members! Go get 'em!
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #10 on:
2010-02-09 09:40:37 » |
|
This is my new Animation class, changed delta to elapsedTime as you suggested  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
| public void createAnimation(BufferedImage img, int x, int y, int offsetX, int offsetY, int charWidth, int charHeight, int sheetWidth, int sheetHeight, int frameDuration, int startFrame, int playStyle) { animState = currentState; this.img = img; this.charWidth = charWidth; this.charHeight = charHeight; this.sheetWidth = sheetWidth; this.sheetHeight = sheetHeight; this.frameDuration = frameDuration; this.playStyle = playStyle; } public void update(long elapsedTime) { if(currentState == animState && !isFinished) { lastFrameChange += elapsedTime; if (lastFrameChange > frameDuration) { lastFrameChange = 0; frameNumberX++; if (frameNumberX >= sheetWidth) { if(playStyle == PLAY_ONCE) { isFinished = true; frameNumberX = 0; lastFrameChange = 0; currentState = States.IDLE; animState = States.IDLE; } else if(playStyle == LOOPING) { frameNumberX = 0; } } frameNumberY++; if (frameNumberY >= sheetHeight) { frameNumberY = 0; } } frameX = (frameNumberX % sheetWidth) * charWidth; frameY = (frameNumberY % sheetHeight) * charHeight; } if(isFinished) { isFinished = false; } } |
This is part of the player class, I've made some modification and trying things out, I moved the setting animation methods into here, they were originally in the updateAnim method: 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
| private void setPlayerState(float dx, float dy, long elapsedTime) { if(hit) { if(status != Status.INVINCIBLE) { idle = false; left = false; right = false; jumping = false; hp -= 1; anim.setCurrentState(States.HIT); status = Status.INVINCIBLE; if(faceDir == States.LEFT) { anim.createAnimation(img.getPlayerAnim()[img.GET_HIT_L], xp, yp, offsetX, offsetY, 56, 53, 6, 1, 80, 0, Animation.PLAY_ONCE); } else { anim.createAnimation(img.getPlayerAnim()[img.GET_HIT_R], xp, yp, offsetX, offsetY, 56, 53, 6, 1, 80, 0, Animation.PLAY_ONCE); } } hit = false; } if(attacking) { if(States.ATTACKING > anim.getCurrentState()) { idle = false; } anim.setCurrentState(States.ATTACKING); if(faceDir == States.LEFT) { anim.createAnimation(img.getPlayerAnim()[img.ATTACK_L], xp, yp, offsetX, offsetY - 20, 103, 71, 5, 1, 60, 0, Animation.PLAY_ONCE); } else { anim.createAnimation(img.getPlayerAnim()[img.ATTACK_R], xp, yp, offsetX, offsetY - 20, 103, 71, 5, 1, 60, 0, Animation.PLAY_ONCE); } if(book != null) { book = null; } book = new SpellBook(px, py, faceDir); book.enemyCollision(); attacking = false; } if(space && !jumping) { if(anim.getAnimState() == States.ATTACKING || anim.getAnimState() == States.HIT) { } else { idle = false; jumping = true; jumpDistance = maxJumpHeight; } } if(left) { idle = false; faceDir = States.LEFT; dx = -moveSPeed * elapsedTime * 0.05f; if(States.RUNNING >= anim.getCurrentState()) { anim.setCurrentState(States.RUNNING); anim.createAnimation(img.getPlayerAnim()[img.RUN_L], xp, yp, offsetX, offsetY, 54, 45, 15, 1, 60, 0, Animation.PLAY_ONCE); } } if(right) { idle = false; faceDir = States.RIGHT; dx = moveSPeed * elapsedTime * 0.05f; if(States.RUNNING >= anim.getCurrentState()) { anim.setCurrentState(States.RUNNING); anim.createAnimation(img.getPlayerAnim()[img.RUN_R], xp, yp, offsetX, offsetY, 54, 45, 15, 1, 60, 0, Animation.PLAY_ONCE); } } if(idle) { anim.setCurrentState(States.IDLE); if(faceDir == States.LEFT) { anim.createAnimation(img.getPlayerAnim()[img.IDLE_L], xp, yp, offsetX, offsetY, 54, 45, 1, 1, 60, 0, Animation.LOOPING); } else { anim.createAnimation(img.getPlayerAnim()[img.IDLE_R], xp, yp, offsetX, offsetY, 54, 45, 1, 1, 60, 0, Animation.LOOPING); } } if(moveX(dx)) { } }
|
Thanks alot for the help, greatly appreciated!
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #11 on:
2010-02-09 09:53:49 » |
|
Sure you can send it to me or just post it some public place so more people can help. Multiple images off the sprite sheet probably means your sub image is just too big.
Sorry I copied wrong, it was "drawing the same image multiple places?" They are closely overlapped so it seems like 1 image with "shadows" of the same image around it.
|
|
|
|
|
zoto
Full Member   Posts: 234 Medals: 7
|
 |
«
Reply #12 on:
2010-02-09 10:04:38 » |
|
I don't see the drawing code in there.
You can probably safely move the state out of the animation class. Once all the player specific code is out of the animation class it will be a lot more useful to you as you will be able to use it for all the game animations.
Is your game multi-threaded?
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #13 on:
2010-02-09 10:08:02 » |
|
I don't see the drawing code in there.
You can probably safely move the state out of the animation class. Once all the player specific code is out of the animation class it will be a lot more useful to you as you will be able to use it for all the game animations.
Is your game multi-threaded?
My game is single-threaded, the actual drawing code is in the GameCore class which I'll post below, and yea you are right about seperating states with animation class, I'll implement that next.  My game loop is based on Kevin Glass's awesome tutorial on his site(coke and code) and abit of killer programming in java. GameCore.java 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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
| import java.awt.Canvas; import java.awt.Color; import java.awt.Frame; import java.awt.Graphics2D; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferStrategy; import java.util.ArrayList;
public class GameCore extends Canvas implements KeyListener { private static final long serialVersionUID = 1L; public static final int WINDOWS_WIDTH = 1024; public static final int WINDOWS_HEIGHT = 768; private BufferStrategy strategy; public boolean gameRunning = true; LoadImage img; Map map; Player player; Enemy1 enemy1; Enemy1 enemy2; Animation anim = new Animation(); public static float mapPosX; public static float mapPosY; public static float fixX, fixY, fixX1, fixY1;
static ArrayList<Enemy> enemyList = new ArrayList<Enemy>(); GameCore() { Frame frame = new Frame("Side Scroller"); frame.setLayout(null); setBounds(0,0,WINDOWS_WIDTH,WINDOWS_HEIGHT); frame.add(this); frame.setSize(WINDOWS_WIDTH,WINDOWS_HEIGHT); frame.setResizable(false); frame.setLocationRelativeTo(null); frame.setVisible(true); frame.addKeyListener(this); addKeyListener(this); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); createBufferStrategy(2); strategy = getBufferStrategy(); img = new LoadImage(); img.load(); map = new Map(img); enemyList.add(new Enemy1(map, 8, 20, img)); enemyList.add(new Enemy1(map, 13, 20, img)); player = new Player(map, 3, 2, img, anim); mapPosX = Player.visibleX - Player.px; mapPosY = Player.visibleY - Player.py; gameLoop(); } public static void main(String[] args) { new GameCore(); }
private void gameLoop() { long lastLoopTime = System.currentTimeMillis(); while(gameRunning) { long elapsedTime = System.currentTimeMillis() - lastLoopTime; lastLoopTime = System.currentTimeMillis();
gameUpdate(elapsedTime); gameRender(); try { Thread.sleep(calcSleepTime()); } catch (InterruptedException e) { e.printStackTrace(); } } }
private void gameUpdate(long elapsedTime) { mapPosX = Player.visibleX - Player.px; mapPosY = Player.visibleY - Player.py; cornerShift(); for(int i = 0; i < enemyList.size(); i++) { enemyList.get(i).update(elapsedTime); } player.update(elapsedTime); }
private void cornerShift() { if(Player.visibleX > Player.px - 1) { fixX = Player.px - Player.visibleX - 1; } else if(Player.px > Map.MAP_WIDTH - Player.visibleX - 1) { fixX = Player.px - Map.MAP_WIDTH + Player.visibleX + 1; } if(Player.visibleY > Player.py - 1) { fixY = Player.py - Player.visibleY - 1; } else if(Player.py > Map.MAP_HEIGHT- Player.visibleY - 1 ) { fixY = Player.py - Map.MAP_HEIGHT + Player.visibleY + 1; } } private void gameRender() { Graphics2D g = (Graphics2D) strategy.getDrawGraphics(); g.setColor(Color.BLACK); g.fillRect(0,0,WINDOWS_WIDTH,WINDOWS_HEIGHT); g.translate(0, 30); map.paint(g); for(int i = 0; i < enemyList.size(); i++) { if(enemyList.get(i).isAlive()) { enemyList.get(i).paint(g); } } player.paint(g); g.dispose(); strategy.show(); }
private long calcSleepTime() { long beforeTime, timeDiff, sleepTime; beforeTime = System.currentTimeMillis(); timeDiff = System.currentTimeMillis() - beforeTime; sleepTime = 10 - timeDiff; if(sleepTime <= 0) { sleepTime = 5; } return sleepTime; } @Override public void keyPressed(KeyEvent e) { player.keyPressed(e); } @Override public void keyReleased(KeyEvent e) { player.keyReleased(e); }
@Override public void keyTyped(KeyEvent e) {} public static ArrayList<Enemy> getEnemyList() { return enemyList; } } |
|
|
|
|
|
zoto
Full Member   Posts: 234 Medals: 7
|
 |
«
Reply #14 on:
2010-02-09 16:27:25 » |
|
There are a few problems I noticed when quickly looking over GameCore mostly in the calcSleepTime() method. The function is returning how long the System.currentTimeMillis() took to execute when it should be calculating how long the game took to update and render for the previous tick. The System.currentTimeMillis() is not recommended for a game System.nanoTime() should be used instead as it is much more accurate, and math corrected for the change of course. You may wish to check out this post http://www.java-gaming.org/topics/basic-game/21919/view.html. Hope this helps.
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #15 on:
2010-02-09 22:05:39 » |
|
There are a few problems I noticed when quickly looking over GameCore mostly in the calcSleepTime() method. The function is returning how long the System.currentTimeMillis() took to execute when it should be calculating how long the game took to update and render for the previous tick. The System.currentTimeMillis() is not recommended for a game System.nanoTime() should be used instead as it is much more accurate, and math corrected for the change of course. You may wish to check out this post http://www.java-gaming.org/topics/basic-game/21919/view.html. Hope this helps. Thanks for the reply! I'll go fix that up as soon as I get off work =D
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #16 on:
2010-02-10 08:14:37 » |
|
Yea, after implementing the loop from that thread my multiple image problem is gone, thanks!  I don't get some of the maths tho, why is he dividing by 1000 * 1000? Isnt nano 1000*1000*1000? 1
| update((int) ((currentUpdateTime - lastUpdateTime)/(1000*1000))); |
|
|
|
|
|
Gudradain
Sr. Member   Posts: 364 Medals: 8
|
 |
«
Reply #17 on:
2010-02-11 10:10:43 » |
|
Dividing nanoseconds by (1000*1000) give you milliseconds. The deltaTime in the update method is usually in milliseconds for game.
|
|
|
|
|
ChouChou
JGO n00b  Posts: 46
|
 |
«
Reply #18 on:
2010-02-11 20:41:03 » |
|
Dividing nanoseconds by (1000*1000) give you milliseconds. The deltaTime in the update method is usually in milliseconds for game.
Ah I understand now, that makes alot of sense. Thanks for your loop!
|
|
|
|
|
|