如何使slick2D显示我的精灵的运动

时间:2014-03-17 12:32:53

标签: java slick2d

我在Java Slick2D库中需要一些帮助,根据我使用这个库编写的经验我明白扩展BasicGameState的类会在无限循环中调用update()和render()方法,我的问题是找到一种在render()方法中调用一些方法的方法,它有一些精灵的运动,例如,我有这个方法:

public void move(Graphics g, Image sprite, int X, int Y){
    for(int i = 0; i < 32; i++)
        g.drawImage(sprite, X+i, Y);
}

当我在render()方法中调用move(g,sprite,posX,PosY)时,我的精灵将传送到下一个32像素而不显示动画。 我该怎么做才能解决这个问题并使我的精灵正确移动?

1 个答案:

答案 0 :(得分:1)

你的问题的答案在于一些人不得不说的话。

您需要依赖更新间隔。在光滑的情况下,人们倾向于将常见的错误放在他们的渲染方法中。这与许多游戏制作规则相悖,因为渲染方法需要尽可能轻,以确保良好的帧速率。话虽如此,在光滑的render()方法中使用move()方法有点效率低/未经优化。因此,在render()方法中对图像的坐标进行逻辑运算可以被视为一个繁重的操作,特别是如果你正在为所有移动对象执行此操作(想象一下物理引擎的强大程度,运行在渲染方法中)。

要解释您所看到的内容(即时“传送”到下一个32像素),您只需按照代码的操作方式进行操作即可。让我们来看看:

  1. 调用update()方法,检查输入(我猜,因为我不知道你的所有代码)
    • 发现玩家已按下移动按钮
  2. 调用render()方法
    • 擦屏(双缓冲区)
    • 按下了移动,所以调用move();图像当前位置=(x,y)
    • 通过循环将i应用于x坐标
        所有i + x位置的
      • g.drawImage
    • 全部打印到屏幕
  3. update()调用,未找到输入
  4. render()调用
    • 擦屏(双缓冲)
    • 在它的x和y
    • 处绘制精灵
    • 不会遍历move()因为没有按下输入
  5. 请注意,当你循环移动move()方法时,你告诉图形对象在x + i coorindates上绘制几次图像(不将图像视为自己的对象,即一个实例)几次。这发生在一帧中。因此,在下一帧中,您不会注意到任何图像被绘制,因为它发生得太快,因为双缓冲区“清理”屏幕(当“擦除屏幕”发生时注意)。

    THE FIX:

    要解决这个问题,如果你有一个实体类(某种“播放器类”拥有它自己的图像),你可以像这样设置它:

    update() {
        if(input is a direction of movement) {
            player.direction = direction of move
        } else { player.direction = player.IDLE; }
    
        player.update(delta)
    }
    render() {
        player.draw();
    }
    

    有了这个,您会注意到我在渲染方法中所做的就是绘制播放器的图像。看看与渲染方法中的逻辑相比有多轻?从这里你还可以看到一种处理输入的新方法。至于玩家类

    class player {
        private final int LEFT = 0;
        private final int RIGHT = 1;
        private final int IDLE = -1;
        Image img;
        int x, y;
        int direction;
    
        public player() {
            x = 0;
            y = 0;
            img = new Image("myplayerimage.png");
        }
    
        public void draw() {
            img.draw(position.x, position.y);
        }
        public void update(int delta) {
            move();
        }
        public void move() {
            if(direction == LEFT) {
                x -= 1;
            }
            else if(direction == RIGHT) {
                x += 1;
            }
            else if(direction == IDLE) {
                // Do nothing
            }
        }
    }
    

    虽然这个播放器类可能不是很先进,但它至少可以让你观察每帧更新的移动增量(每个render()调用被认为是帧更新)可以给出运动的效果。这是一种线性类型的运动,就像我的move()方法一样,每次调用更新时,我只增加1。这可能看起来不是很多动作,但如果你的FPS为60,你将在一秒钟内移动60个像素。

    总之,要获得所需的效果,您需要在每个游戏时更新()您的位置,并在每次更新()/ render()调用的位置绘制图像,以呈现任何类型的动作