我的圈子没动

时间:2014-01-23 00:23:11

标签: java swing awt

我有关键事件,而我的角色(圆圈)的一切都拒绝移动。我已经搜索了所有这些并调整了人们的解决方案,但它不起作用。为了以防万一,我会在这里发布我的完整代码,所以请帮助。

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

}

}

1 个答案:

答案 0 :(得分:1)

您的基本问题是您正在绘制delta值而不是位置值...

g.fillOval(dx, dy, 2 * r, 2 * r);
           ^---^---These are the deltas, not the position...

您将/可能会遇到的其他问题......

  • 使用getGraphics代替覆盖paintComponentgetGraphics可以返回null,下次绘制周期时,您绘制的任何内容都将被清除干净。 Swing使用被动绘画系统,可以在没有您的交互的情况下触发重绘
  • 使用KeyListener。通常,您会发现使用Key Bindings API更容易,Performing Custom Painting不会受到KeyListener遭受的同样焦点问题的影响
  • 小心使用Thread来更新游戏状态,因为在您修改状态时可能会出现重绘,并且最终会出现脏涂料。
  • 使用“魔术”数字(即GamePanel.WIDTH)。如果我改变窗口的大小,这些值将没有任何意义。请改用经验值,将容器的实际宽度和高度传递给move方法
  • 您的keyPressedkeyReleased来电与您的移动代码紧密相关。可以按下并使球向右反弹......对于其他方向也是如此,在向正确方向移动之前,可以让球在相反方向反弹。另一个例子,如果我按住,球会向右移动......

看看