Old post:
[quote]I have a problem. I can’t get this to animate right
Spritesheet:
http://www.javadaemon.com/charsheet.png
My game is a rough pokemon clone. The world is tiled.
The player movement is smooth and great, but the animation is not working and I can’t think of a way to implement it correctly.
Basicly, this functionality is my goal:
When just pressing once (moving one tile), the animation should be mid-layer on the spritesheet, downer layer, and when hitting the right position still (upper layer).
When holding down it should be mid-layer, upper layer, downer-layer, upper layer, and repeating (in order to get a nice walking animation).
I’ve tried my best here (a peice of my player-class):
public void update(long delta) {
if (appearenceUpdate) {
image = ImagesLoader.character[moveDir - 1][imageY];
appearenceUpdate = false;
}
if (animUpdate) {
switch (lastY) {
case 1:
lastY = 2;
break;
case 2:
lastY = 1;
break;
}
switch (imageY) {
case 0:
imageY = lastY;
break;
case 1:
imageY = 0;
break;
case 2:
imageY = 0;
break;
}
image = ImagesLoader.character[moveDir - 1][imageY];
animUpdate = false;
}
// Position logic
if (isMoving) {
if (map.targX != map.mapStartX
|| map.targY != map.mapStartY) {
long now = System.nanoTime();
timeSinceLocUpdate += (long) (now - delta); //* 1000000;
if (timeSinceLocUpdate > locFPS) { // Move 1 px
if (animPointX == map.mapStartX && animPointY == map.mapStartY) {
animUpdate = true;
}
move(moveDir);
timeSinceLocUpdate = 0;
}
} else if (isKeyDown) {
coordX = targX;
coordY = targY;
calcNewCoords(moveDir);
animUpdate = true;
} else {
coordX = targX;
coordY = targY;
//appearenceUpdate = true;
//imageY = 0;
isMoving = false;
gpTop.blockInput = false;
}
} else {
//imageY = 0;
gpTop.blockInput = false;
}
}
public void calcNewCoords(int dir) {
switch (dir) {
case 1:
targY = coordY - 1;
targX = coordX;
if (map.checkObstacle(targX, targY)) {
map.targX = map.mapStartX;
map.targY = map.mapStartY + map.tileHeight;
animPointX = map.targX;
animPointY = map.targY - (map.tileHeight / 2);
} else {
targX = coordX;
targY = coordY;
}
break;
case 2:
targX = coordX + 1;
targY = coordY;
if (map.checkObstacle(targX, targY)) {
map.targX = map.mapStartX - map.tileWidth;
map.targY = map.mapStartY;
animPointY = map.targY;
animPointX = map.targX + (map.tileWidth / 2);
} else {
targX = coordX;
targY = coordY;
}
break;
case 3:
targY = coordY + 1;
targX = coordX;
if (map.checkObstacle(targX, targY)) {
map.targY = map.mapStartY - map.tileHeight;
map.targX = map.mapStartX;
animPointX = map.targX;
animPointY = map.targY + (map.tileHeight / 2);
} else {
targX = coordX;
targY = coordY;
}
break;
case 4:
targX = coordX - 1;
targY = coordY;
if (map.checkObstacle(targX, targY)) {
map.targX = map.mapStartX + map.tileWidth;
map.targY = map.mapStartY;
animPointY = map.targY;
animPointX = map.targX - (map.tileWidth / 2);
} else {
targX = coordX;
targY = coordY;
}
break;
}
}
In player, targX and -Y is the coords to where my player is going.
map.targX and -Y is the pixel coords to where the map should stop.
animPointX and -Y is the pixel location of where the player-image should change state (upper-layer to downer-layer or vice-versa).
The appearenceUpdate boolean is a flag that is set when a movement-key is pressed. The animUpdate boolean, is a flag that is set when the image should change due to animation.
My ImagesLoader loads the spritesheet and slices it, making it available through coordinates via. a bufferedimage[][] (x, and y).
EDIT:
I’m beginning to think that the calcNewCoords methods does not calculate the animPoints correctly, even though it seems to me that they are
EDIT 2:
Am I trying to do this the wrong way? :-\
Here is a video of the current functionality (just uploaded so it might be processing…):
…and here is a video of the functionality I want (just in case…):
Oh, and the keylistener:
private void processKey(KeyEvent e) {
int keyCode = e.getKeyCode();
player.appearenceUpdate = true;
if (!blockInput) {
if (keyCode == KeyEvent.VK_UP) {
player.moveDir = 1;
player.isKeyDown = true;
blockInput = true;
player.calcNewCoords(player.moveDir);
player.isMoving = true;
}
if (keyCode == KeyEvent.VK_RIGHT) {
player.moveDir = 2;
player.isKeyDown = true;
blockInput = true;
player.calcNewCoords(player.moveDir);
player.isMoving = true;
}
if (keyCode == KeyEvent.VK_DOWN) {
player.moveDir = 3;
player.isKeyDown = true;
blockInput = true;
player.calcNewCoords(player.moveDir);
player.isMoving = true;
}
if (keyCode == KeyEvent.VK_LEFT) {
player.moveDir = 4;
player.isKeyDown = true;
blockInput = true;
player.calcNewCoords(player.moveDir);
player.isMoving = true;
}
if (keyCode == KeyEvent.VK_X) {
player.locFPS = 1000000 / 100;
}
}
} // end of processKey()
Any ideas? :-X
[/quote]
Since that didn’t work out too well, I tried to just play an animation of three images (y coordinate: 2,0,1), while walking.
This is what I got:
private long timeSinceLocUpdate;
private long timeSinceAnimUpdate;
public long locFPS = 1000000 / 9;
public long animFPS = (locFPS * 16) / 3;
public int animation[] = {1,0,2};
private int counter = 0;
public void update(long delta) {
long now = System.nanoTime();
if (isMoving) {
timeSinceAnimUpdate += (long) (now - delta);
if (timeSinceAnimUpdate > animFPS) { // A third of the time moving has past
counter++;
if (2 < counter) {
counter = 2;
}
timeSinceAnimUpdate = 0;
}
} else {
counter = 0;
}
// Position logic
if (isMoving) {
if (map.targX != map.mapStartX
|| map.targY != map.mapStartY) {
timeSinceLocUpdate += (long) (now - delta); //* 1000000;
if (timeSinceLocUpdate > locFPS) { // Move 1 px
move(moveDir);
timeSinceLocUpdate = 0;
}
} else if (isKeyDown) {
coordX = targX;
coordY = targY;
calcNewCoords(moveDir);
} else {
coordX = targX;
coordY = targY;
appearenceUpdate = true;
isMoving = false;
gpTop.blockInput = false;
}
} else {
}
}
public void draw(Graphics g) {
x = (map.PWIDTH / 2) - (width / 2);
y = (map.PHEIGHT / 2) - (height / 2);
g.setColor(Color.ORANGE);
if (isMoving) {
g.drawImage(ImagesLoader.character[moveDir - 1][animation[counter]], x, y, null);
} else {
g.drawImage(ImagesLoader.character[moveDir - 1][0], x, y, null);
}
}
calcNewCoords now only handles location targets, and the keylistener now just sets the isMoving boolean, and the moveDir (the direction the sprite is facing).
However, this doesn’t work right: The animation isn’t “smooth”. The last frame (animation[2]) is usually a lot longer than the other two.
I think this implementation of animating the walking is easier to manage, and the problem is smaller.
I think what’s happening, is that the animation-counter quickly reaches 2, and stays there for the two last frames. To me, it looks like it should not.