这是我的主要代码的代码。我尝试创建一个包含检查键盘操作的函数的包,但它不起作用。所以现在两个代码都在你看到的同一个文件下。到目前为止程序打开,我可以看到圆圈,但它不会向左或向右移动。我一直都在这,因为3小时相信与否。
编辑:我刚刚意识到更新函数从名为“input”的包中获取数据。那是在我将两个类放在相同的文件名之前,但即使有一个类名为“gamesample.input。*”的类,它仍然无效。
package gamesample;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
/**
* Main class for the game
*/
public class GameSample extends JFrame
{
boolean isRunning = true;
int fps = 30;
int windowWidth = 500;
int windowHeight = 500;
BufferedImage backBuffer;
Insets insets;
InputHandler input;
int x = 0;
public static void main(String[] args)
{
GameSample game = new GameSample();
game.run();
System.exit(0);
}
/**
* This method starts the game and runs it in a loop
*/
public void run()
{
initialize();
while(isRunning)
{
long time = System.currentTimeMillis();
update();
draw();
// delay for each frame - time it took for one frame
time = (1000 / fps) - (System.currentTimeMillis() - time);
if (time > 0)
{
try
{
Thread.sleep(time);
}
catch(Exception e){}
}
}
setVisible(false);
}
/**
* This method will set up everything need for the game to run
*/
void initialize()
{
setTitle("Game Tutorial");
setSize(windowWidth, windowHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
insets = getInsets();
setSize(insets.left + windowWidth + insets.right,
insets.top + windowHeight + insets.bottom);
backBuffer = new BufferedImage(windowWidth, windowHeight, BufferedImage.TYPE_INT_RGB);
input = new InputHandler(this);
}
/**
* This method will check for input, move things
* around and check for win conditions, etc
*/
void update()
{
if (input.isKeyDown(KeyEvent.VK_RIGHT))
{
x += 5;
}
if (input.isKeyDown(KeyEvent.VK_LEFT))
{
x -= 5;
}
}
/**
* This method will draw everything
*/
void draw()
{
Graphics g = getGraphics();
Graphics bbg = backBuffer.getGraphics();
bbg.setColor(Color.WHITE);
bbg.fillRect(0, 0, windowWidth, windowHeight);
bbg.setColor(Color.BLACK);
bbg.drawOval(x, 10, 20, 20);
g.drawImage(backBuffer, insets.left, insets.top, this);
}
}
这是键盘代码
package gamesample;
import java.awt.Component;
import java.awt.event.*;
/**
* Makes handling input a lot simpler
*/
public class InputHandler implements KeyListener
{
boolean keys[];
/**
* Assigns the newly created InputHandler to a Component
* @param c Component to get input from
*/
public InputHandler(Component c)
{
c.addKeyListener(this);
}
/**
* Checks whether a specific key is down
* @param keyCode The key to check
* @return Whether the key is pressed or not
*/
public boolean isKeyDown(int keyCode)
{
if (keyCode > 0 && keyCode < 256)
{ keys = new boolean [256];
return keys[keyCode];
}
return false;
}
/**
* Called when a key is pressed while the component is focused
* @param e KeyEvent sent by the component
*/
public void keyPressed(KeyEvent e)
{ boolean keys[];
if (e.getKeyCode() > 0 && e.getKeyCode() < 256)
{ keys = new boolean [256];
keys[e.getKeyCode()] = true;
}
}
/**
* Called when a key is released while the component is focused
* @param e KeyEvent sent by the component
*/
public void keyReleased(KeyEvent e)
{ boolean keys[];
if (e.getKeyCode() > 0 && e.getKeyCode() < 256)
{ keys = new boolean [256];
keys[e.getKeyCode()] = false;
}
}
/**
* Not used
*/
public void keyTyped(KeyEvent e){}
}
答案 0 :(得分:1)
Graphics g = getGraphics();
不是应该如何进行自定义绘画。 Swing使用被动渲染算法,这意味着您的UI可以随时重新绘制,原因有很多,其中许多原因是您无法控制的。默认情况下,Swing也是双缓冲的,所以如果您实际使用JPanel
并覆盖它的paintComponent
方法,您将免费获得双缓冲并且您将成为通知任何系统相关的油漆事件。
有关详细信息,请参阅Painting in AWT and Swing和Performing Custom Painting
不要使用KeyListener
,它太麻烦了,而且键绑定API解决了它所遇到的所有问题。有关详细信息,请参阅How to Use Key Bindings。
请记住,Swing是一个单线程框架,并不是线程安全的。这意味着你永远不应该以任何方式阻止事件调度线程(比如使用永无止境的循环),你应该只在EDT的上下文中更新UI。
你&#34;主循环&#34;两者都有危险。代码不会阻止EDT,这是JVM性质的侥幸,但这也意味着你违反了Swing的单线程特性。
有关详细信息,请参阅Concurrency in Swing。
通常情况下,我会使用Swing Timer
进行此类工作,因为它的回调会在EDT的上下文中同步,但您可以使用{{1} },但您必须手动将更新同步回EDT。
如果您希望完全控制绘画过程,则应使用Thread
,有关详细信息,请参阅BufferStrategy
和BufferStrategy and BufferCapabilities
作为上述概念的basic example