我在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像素而不显示动画。 我该怎么做才能解决这个问题并使我的精灵正确移动?
答案 0 :(得分:1)
你的问题的答案在于一些人不得不说的话。
您需要依赖更新间隔。在光滑的情况下,人们倾向于将常见的错误放在他们的渲染方法中。这与许多游戏制作规则相悖,因为渲染方法需要尽可能轻,以确保良好的帧速率。话虽如此,在光滑的render()方法中使用move()方法有点效率低/未经优化。因此,在render()方法中对图像的坐标进行逻辑运算可以被视为一个繁重的操作,特别是如果你正在为所有移动对象执行此操作(想象一下物理引擎的强大程度,运行在渲染方法中)。
要解释您所看到的内容(即时“传送”到下一个32像素),您只需按照代码的操作方式进行操作即可。让我们来看看:
请注意,当你循环移动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()调用的位置绘制图像,以呈现任何类型的动作