2

我正在用 Java 开发一个小游戏,并且我正在重写玩家运动系统,使其不是基于网格的。它是一个 2D 横向卷轴,我想要实现的是基本的玩家移动,因此当用户按住并按住右键时,玩家向右移动,左键也是如此。我遇到的问题是另一个类中的 Paint 组件在屏幕上绘制了播放器的图像,位置 X 和 Y 存储在设置类中。然后当用户按下右时,一个 KeyListener 类得到,并添加到 X 值(左相同,但每次减 1)。这会在屏幕上创建一个缓慢移动的角色,我想要做的是让他移动得更快,而不是每次添加超过 1px,因为它看起来像是在跳过像素(我已经尝试过)。

我想知道是否有更好的方法来解决这个问题,因为我使用的代码是最低限度的,我的结果将是一个平稳移动的 Player。

KeyListener 片段:

public void keyPressed(KeyEvent arg0) {
    int key = arg0.getKeyCode();

    if(key == 39) { // Right Key
        Settings.player_pos_x++;
    }else if(key == 37) { // Left Key
        Settings.player_pos_x--;
    }

    main.Game.redo();
}

在屏幕上绘制用户:

g.drawImage(player_image, Settings.player_pos_x, Settings.player_pos_y, this);

任何帮助表示赞赏,如果您需要更多信息或代码,请随时询问。

4

4 回答 4

3

让我们再试一次 :)

双缓冲

引用:http: //msdn.microsoft.com/en-us/library/b367a457.aspx

闪烁是编程图形时的常见问题。需要多个复杂绘制操作的图形操作可能会导致渲染图像出现闪烁或具有其他不可接受的外观。

启用双缓冲时,所有绘制操作首先呈现到内存缓冲区而不是屏幕上的绘图表面。在所有绘制操作完成后,内存缓冲区被直接复制到与其关联的绘图表面。由于在屏幕上只进行了一次图形操作,因此消除了与复杂绘画操作相关的图像闪烁。

引用:http ://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html

假设您必须在屏幕上逐个像素或逐行绘制整幅图片。如果您要将这样的东西直接绘制到屏幕上(例如,使用 Graphics.drawLine),您可能会非常失望地注意到这需要一些时间。您甚至可能会注意到您的图片是如何绘制的可见伪影。大多数程序员不是看着以这种方式和速度绘制的东西,而是使用一种称为双缓冲的技术。

于 2012-04-20T20:24:09.407 回答
1

也许您可以编写应用程序以向右迭代多次重绘,每个接收到的键盘输入只有 1 或 2 个像素。这样,您就可以人为地设置您希望它移动的速度。否则,您将受限于用户如何设置键盘迭代速度。

此外,java 的 jPanel 并不完全是寻找视频游戏效率的地方。只是说;你可能想看看像openGL这样的东西。

充其量,您可以优化它以在 jpanel 绘图逻辑之外有一个过渡缓冲区,具有与 jPanel 相同的绘图功能,这样您就可以写入缓冲区,然后在 writeImage 调用期间复制整个缓冲区......我不'不知道你是否已经这样做了,但我认为它可以避免闪烁或其他东西......很久以前读过它,它被称为双缓冲。

于 2012-04-20T20:22:48.153 回答
1

虽然双缓冲可能会帮助您首先解决如何计算每次移动的距离。

距离变化 (dx) 可以定义为速度 (v) 乘以时间变化 (dt),dx = v * dt。据我所知,您省略了 dt (时间变化)。您应该计算与上次移动角色的时间差,并将其乘以您的速度。这样,如果您的距离处理代码在 10 秒内执行 10 次或 100 次,角色将始终移动相同的距离。

代码将如下所示:

int currentTime = System.nanoTime();
int deltaTime = currentTime - previousTime;

Settings.player_pos_x += velX * deltaTime;

previousTime = currentTime;

使用此代码,您可能需要显着增加 velX。通常我会有一个常数,我会乘以速度,所以它们是较小的数字。

此外,如果您想要更好的运动和物理效果,请查看 JBox2D,尽管它现在可能对您来说太过分了。他们的文档也可能有助于理解基础物理学。

于 2012-04-20T21:19:37.777 回答
0

为了回答您关于速度的问题,我见过的大多数游戏都为每个平面(x 和 y 平面)中的速度存储了一个全局 int,然后将速度应用于当前位置,而不是像您所做的那样简单地增加它多于。

public int velX = 2;
public int velY = 2;

public void keyPressed(KeyEvent arg0) { 
    int key = arg0.getKeyCode(); 

    if(key == 39) { // Right Key 
        Settings.player_pos_x += velX; 
    }else if(key == 37) { // Left Key 
        Settings.player_pos_x -= velX; 
    } 

    main.Game.redo(); 
} 

设置完成后,尝试添加可能会增加速度的操作(即长时间按住键,或其他);

另外,尝试实现跳跃操作,让玩家的 Y 位置上升,并尝试添加重力场以使其返回。

于 2012-04-20T20:39:14.503 回答