Java绘制组件刷新率?

Java绘制组件刷新率?,java,swing,animation,buffer,Java,Swing,Animation,Buffer,我正在用Java开发一个小游戏,我正在重写玩家移动系统,使其不基于网格。这是一个2D侧边滚动条,我试图实现的是播放器的基本移动,因此当用户按下并按住右键时,播放器会向右移动,左键也是如此。我遇到的问题是,另一个类中的Paint组件在屏幕上绘制播放器的图像,位置X和Y存储在设置类中。然后,当用户按下Right键时,一个KeyListener类会得到一个值,并将其添加到X值中(对于Left值也是如此,但每次都减1)。这会在屏幕上创建一个缓慢移动的角色,我想做的是让他移动得更快,而每次添加的像素数不会

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

我想知道是否有更好的方法来实现这一点,因为我使用的代码是最低限度的,我的结果将是一个平稳运行的播放器

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);
屏幕上的绘图用户:

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

非常感谢您的帮助,如果您需要更多信息或代码,请随时询问。

也许您可以编写应用程序,在右侧重复多次重画,每个键盘输入仅1或2像素。这样,你就可以人为地设定你想要它移动的速度。否则,您将受限于用户如何设置键盘迭代速度

另外,java的jPanel也不是一个追求视频游戏效率的地方。只是说说而已;为此,您可能希望使用类似openGL的工具

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

让我们再试一次:)

双缓冲 引述:

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

启用双缓冲时,所有绘制操作首先渲染到内存中 缓冲区,而不是屏幕上的绘图面。所有喷漆操作完成后 完成后,内存缓冲区将直接复制到与关联的图形表面 信息技术因为在屏幕上只执行一个图形操作,所以图像 消除了与复杂绘制操作相关的闪烁

引述:

假设你必须在屏幕上画一幅完整的画,逐像素或逐行 线路。如果你把这样的东西直接画到屏幕上(比如, 图形。抽绳),您可能会非常失望地注意到 一点时间。你甚至可能会注意到你的照片是怎样的 绘制。而不是看着事物以这种方式和速度绘制,大多数 程序员使用一种称为双缓冲的技术


为了回答你关于速度的问题,我看过的大多数游戏都会在每个平面(x和y平面)中存储速度的全局整数,然后将速度应用到当前位置,而不是像上面那样简单地增加它

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位置上升时,尝试添加重力场使其下降。

而双缓冲可能有助于您首先解决如何计算每次移动的距离

距离变化(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,尽管它现在对您来说可能已经太危险了。他们的文档也可能有助于理解基本物理。

双缓冲@Ozzy我不是在开发小程序,这还能用吗?原理是一样的-双缓冲区!看看这个相关的问题:@Ozzy我会试试看。所以KeyListener很好,我应该继续使用它吗?如果你阅读我发布的applet教程链接(上面),你就会明白为什么你需要在动画中使用双缓冲,而监听器与此无关。一个监听器只听一些用户输入。问题不是闪烁,我根本没有。
我的结果将是一个平滑移动的播放器。
如果你想要平滑移动的精灵,你需要双缓冲。你没有注意到我为你发布的双缓冲教程链接中的3个小程序之间的区别吗?
我想做的是让他移动得更快,而每次添加的像素数不超过1px,因为他似乎跳过了像素
你不能一次移动1px,并期望他以给定的速度移动,你必须以这个速度移动他,并使用双缓冲!你提到的
跳过像素
就是我们正在讨论的闪烁。我注意到演示中的闪烁,是的,我将查看双b