Хороший способ сделать простую анимацию ходьбы? - PullRequest
1 голос
/ 13 февраля 2012

Я пишу простую 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 ]

4 голосов
/ 13 февраля 2012

Если бы вы когда-либо слышали о чем-то, называемом независимым от фрейма движением, вам следует подумать о том, чтобы сделать движение основанным на времени, чтобы у вас было последовательное движение во всех случаях

предложит вам некоторую помощь: создайте класс для анимацииДвижение

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 ;
}

}

, тогда в вашей игре основной мировой класс определит объект Animation, который представляетанимацию, которую вы хотите сделать для солдат и сделать столько экземпляров объектов, сколько хотите, таким образом, вы определите анимацию один раз, т.е. вам не нужно создавать 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);


}

}
3 голосов
/ 13 февраля 2012

Одна проблема, которую я вижу: ваша "curImg" не зависит от времени, но от изображений, нарисованных до сих пор. Поэтому, если вы повысите или понизите FPS (например, для более плавной прокрутки фона), изображения будут переворачиваться быстрее или медленнее. Вероятно, анимационные изображения отрисовываются в течение определенного времени, например цикл ходьбы 5 изображений в течение 1 секунды. У вас должно быть (глобальное или относительное к сцене) значение времени и выберите изображение, зависящее от значения времени.

0 голосов
/ 13 февраля 2012
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;
    }
}

Не забудьте о repaint (), если вы используете JFrame.

...