做简单步行动画的好方法?

时间:2012-02-12 21:20:14

标签: java swing animation jpanel

我正在写一个简单的2D游戏,任何敌人走向你,你必须射击他。现在,我通过创建一个包含所有8个不同图像的数组,然后每5个刻度循环一次来为步行设置动画。有没有更好或更简单的方法来做到这一点?这是代码:

public class Soldier {

private int xpos, ypos, curImg;
private Image[] soldier;
private Image currentImg;

    public Soldier(){
        xpos = 500;
        ypos = 250;
        curImg = 0;
        soldier = new Image[8];
        for(int i=0; i<soldier.length; i++){
            soldier[i] = Images.loadImage("res/soldier/s"+(i+1)+".png");
        }
    }

    public void draw(Graphics2D g2){
        currentImg = soldier[curImg/5];
        g2.drawImage(currentImg, xpos, ypos, null);
        if(curImg == 35){
            curImg = 0;
        }
        else{
            curImg++;
        }
    }

    public void move(){
        xpos-=1;
    }
}

函数Images.loadImage只是一个加载图像的自定义方法

3 个答案:

答案 0 :(得分:4)

你有没有听说过一种叫做Frame独立运动的东西 你应该考虑根据时间进行运动,这样你就可以在所有情况下保持一致的运动

建议你一些帮助: 创建一个包裹动画运动的类

public class Animation {

  public static final int ANIMATION_LOOPING = 0;
    public static final int ANIMATION_NONLOOPING = 1;

private Image [] sprites;
private float frameDuration ; 

public Animation (Image ... sprites, float frameDuration){

this.sprites =sprites;
this.frameDuration = frameDuration;
}  

//this function takes a the walking time of the soldier 
public Image getKeyFrame(float stateTime , int mode){


int frameNumber = (int) stateTime/ frameDuration;

if(mode == ANIMATION_NONLOOPING){
frameNumber = Math.min( sprites.length , frameNumber);
}
else{
frameNumber = frameNumber % sprites.length;
}

return sprites[frameNumber];
}

}

你的士兵应该充当模特

public class Solider {

float walkingTime = 0;

  int xpos ;
 int ypos ;
 int xspeed;

public Solider(int xpos,int ypos,int xspeed){

this.xpos = xpos;
this.ypos = ypos;
this.xspeed = xspeed;//movementPerSecond in the x axis for example -3
}

//deltaTime is the time elapsed in milliseconds
public void update(float deltaTime){


xpos += xspeed * (deltaTime / 1000.0);
walkingTime += deltaTime ;
}

}

然后在你的游戏主世界类中定义一个动画对象,它代表你想要为士兵制作的动画,并按照你想要的方式制作士兵对象的实例,你将定义动画一次,即你不要每次你想要创建一个士兵和另一个你将拥有一个松散耦合的应用程序的benifet时必须创建8个图像

示例

public class MyGameWorld {

Animation soldierAnimation ; 

Soldier [] soliders ;

public MyGameWorld(int numbers_of_soliders){

soliders = new Soldier[numbers_of_soliders];

//loop over the array to instantiate them 
for( int i =0; i < numbers_of_soliders;++i){
soliders[i] = new Soldier(randomx ,randomy ,-5); // randomx , randomy is random values you can supply 
}

//then instantiate the animation object
//first get the images 
Image [] sprites = new sprites [8]; 
sprites [0] = new Image ......


soldierAnimation = new Animation(0.2, sprites);// this will make it flip each 0.2 seconds you can put any value that fits your need 
}


//in the game loop update you soldiers 

for(int i =0 ; i <numbers_of_soliders ; ++i){
soliders[i].update(deltaTime);
}

then render them using the animation 
for(int i =0 ; i< number_of_soliders ; ++i){

drawOnScreenThisImageWithThisPosition( soliders[i].xpos, soliders[i].ypos,soldierAnimation.getKeyFrame(soliders[i].walkingTime, Animation.ANIMATION_LOOPING);


}

}

答案 1 :(得分:3)

我看到的一个问题:你的“curImg”不依赖于时间,而是依赖于迄今为止绘制的图像。因此,如果您提高或降低FPS(例如,为了更平滑的背景滚动),图像将更快或更慢地翻转。可能在特定时间绘制动画图像,例如5个图像步行周期1秒。您应该具有(全局或场景相对)时间值,并根据时间值选择图像。

答案 2 :(得分:0)

public class Soldier {

private int xpos, ypos, curImg;
private Image[] soldier;
private Image currentImg;

    public Soldier(){
        xpos = 500;
        ypos = 250;
        curImg = 0;
        soldier = new Image[8];
        for(int i=0; i<soldier.length; i++){
            soldier[i] = Images.loadImage("res/soldier/s"+(i+1)+".png");
        }
    }

    public void draw(Graphics2D g2){
        currentImg = soldier[curImg % 8];
        g2.drawImage(currentImg, xpos, ypos, null);
        curImg++;
        Thread.sleep(noOfSeconds * 1000); // if you don't do it, images will keep changing in the very next millisecond
    }

    public void move(){
        xpos-=1;
    }
}

如果您使用JFrame,请不要忘记repaint()。