我有关键事件,而我的角色(圆圈)的一切都拒绝移动。我已经搜索了所有这些并调整了人们的解决方案,但它不起作用。为了以防万一,我会在这里发布我的完整代码,所以请帮助。
Main.java
package minwoo.main;
import javax.swing.JFrame;
public class Main extends JFrame {
// just to set up the game
public static void main(String[] args) {
JFrame start = new JFrame("space game");
start.setVisible(true);
start.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
start.setContentPane(new GamePanel());
start.pack();
start.setLocationRelativeTo(null);
}
}
GamePanel.java
package minwoo.main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable, KeyListener {
// size
public final static int WIDTH = 400;
public final static int HEIGHT = 400;
//player
Player player;
//the loop variables
private Thread thread;
private boolean running = false;
//image
BufferedImage image;
Graphics2D g;
int FPS = 30;
double avFPS;
//the constructor
public GamePanel() {
addKeyListener(this);
setPreferredSize(new Dimension(WIDTH,HEIGHT ));
setFocusable(true);
requestFocus();
player = new Player();
}
//functions
public void addNotify() {
super.addNotify();
if(thread == null) {
thread = new Thread(this); // declares the thread.
thread.start();
}
}
public void run() {
running = true;
image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
long startTime;
long waitTime;
long ms;
long targetTime = 1000/30; // shows how much is needed to get 30 ticks
long frameCount = 0;
long max_Frame = 30; // maximum amount of frames you are allowed to reach.
long totalTime = 0;
while(running) { // start of the game loop
startTime = System.nanoTime(); // takes note of the current time
update();
render();
draw();
// System.nanoTime() at this point takes note of current time, which
//is different from what it was few nanoseconds ago.
ms = (System.nanoTime() - startTime) / 1000000;
// shows how much time has passed, and it is converted to miliseconds.
waitTime = targetTime - ms;
/**
* let me give you an example.
* ms is 25 milliseconds, but my target is 30 seconds. To get to
* that target time, we have to give up 5 seconds.
* **/
if(waitTime < 0) { waitTime = 5; } //sets default if waitTime is
// negative.
try {
Thread.sleep(waitTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
totalTime += System.nanoTime() - startTime; // accumulates
// total time it took for the whole process.
frameCount++; // frame is counted
if(frameCount == max_Frame) {
avFPS = 1000.0 / ((totalTime / frameCount) / 1000000);
frameCount = 0;
totalTime =0;
}
}// end of the game loop
} // end of run()
@Override
public void keyTyped(KeyEvent e) {
}
private void update() {
player.update();
} // end of update()
private void render() {
g.setColor(Color.WHITE);
g.fillRect(0, 0,WIDTH,HEIGHT);
g.setColor(Color.BLACK);
g.drawString("FPS: " + avFPS,150,100);
player.draw(g);
}// end of render()
@Override
public void keyPressed(KeyEvent e) {
int Key = e.getKeyCode();
if(Key == KeyEvent.VK_RIGHT) {
player.Direction_X(Player.SPEED);
}
if(Key == KeyEvent.VK_LEFT) {
player.Direction_X(Player.SPEED);
}
if(Key == KeyEvent.VK_UP) {
player.Direction_Y(Player.SPEED);
}
if(Key == KeyEvent.VK_DOWN) {
player.Direction_Y(Player.SPEED);
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
player.Direction_X(Player.SPEED);
}
if(e.getKeyCode() == KeyEvent.VK_LEFT) {
player.Direction_X(-Player.SPEED);
}
if(e.getKeyCode() == KeyEvent.VK_UP) {
player.Direction_Y(Player.SPEED);
}
if(e.getKeyCode() == KeyEvent.VK_DOWN) {
player.Direction_Y(-Player.SPEED);
}
}
//draw()
private void draw() {
Graphics g2 = this.getGraphics();
g2.drawImage(image,0,0,null);
g2.dispose();
}// end of draw()
}// end of GamePanel class
Player.java
package minwoo.main;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Player {
//fields
private int x;
private int y;
private int r;
private int dx;
private int dy;
public static final int SPEED = 5;
private int lives;
private Color character_Color = Color.WHITE;
private Color hit_Color = Color.RED;
// constructor
public Player() {
x = GamePanel.WIDTH / 2;
y = GamePanel.HEIGHT / 2;
r = 5;
dx = 0;
dy = 0;
lives = 3;
} // end of constructor
//movements
public void Direction_X(int speed) {
dx = speed;
}
public void Direction_Y(int speed)
{
dy = speed;}
//functions
public void update() {
move();
//to keep the bounds
if(x < r) { x = r;}
if(y < r) {y = r;}
if(x > GamePanel.WIDTH - r) { x = GamePanel.WIDTH - r;
}
if(y > GamePanel.HEIGHT - r) { y = GamePanel.HEIGHT - r; }
}// end of update()
private void move() {
x += dx;
y += dy;
}
public void draw(Graphics2D g) {
g.setColor(character_Color);
g.fillOval(dx, dy,2*r,2*r); // circle in the centre.
g.setStroke(new BasicStroke(3));
g.setColor(character_Color.darker());
g.drawOval(dx, dy,2*r,2*r);
g.setStroke(new BasicStroke(1));
}
}
答案 0 :(得分:1)
您的基本问题是您正在绘制delta值而不是位置值...
g.fillOval(dx, dy, 2 * r, 2 * r);
^---^---These are the deltas, not the position...
您将/可能会遇到的其他问题......
getGraphics
代替覆盖paintComponent
。 getGraphics
可以返回null
,下次绘制周期时,您绘制的任何内容都将被清除干净。 Swing使用被动绘画系统,可以在没有您的交互的情况下触发重绘KeyListener
。通常,您会发现使用Key Bindings API更容易,Performing Custom Painting不会受到KeyListener
遭受的同样焦点问题的影响Thread
来更新游戏状态,因为在您修改状态时可能会出现重绘,并且最终会出现脏涂料。GamePanel.WIDTH
)。如果我改变窗口的大小,这些值将没有任何意义。请改用经验值,将容器的实际宽度和高度传递给move
方法keyPressed
和keyReleased
来电与您的移动代码紧密相关。可以按下左并使球向右反弹......对于其他方向也是如此,在向正确方向移动之前,可以让球在相反方向反弹。另一个例子,如果我按住左,球会向右移动...... 看看