为什么矩形跳跃的高度会有所不同?

use*_*507 1 java graphics animation swing game-physics

为什么矩形跳跃的高度会有所不同?它似乎进入了一个循环.首先它跳低然后它根本不跳,然后它跳高然后它根本不跳.我无法弄清楚为什么使用相同的代码并且它由同一事件触发.

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;


@SuppressWarnings("serial")
 class Game extends JPanel{
Square square = new Square(this);
 Ground ground = new Ground (this);
public Game() {
    addKeyListener(new KeyListener() {
        @Override
        public void keyTyped(KeyEvent e) {
        }

        @Override
        public void keyReleased(KeyEvent e) {
            square.keyReleased(e);
        }

        @Override
        public void keyPressed(KeyEvent e) {
            square.keyPressed(e);
        }

    });
    setFocusable(true);
}
public static void main(String[] args) throws InterruptedException {

    JFrame frame = new JFrame("My Mario");
    Game game = new Game();
    frame.add(game);
    frame.setSize(600, 700);
    frame.setVisible(true);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


    while (true) {
        game.move();
        game.repaint();
        Thread.sleep(30);





    }

}
private void move() {

    square.move();
}
@Override
public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    square.paint(g2d);
    ground.paint(g2d);
}
}

public class Square {

Square square;
int x,xa;
static int y;
int ya;
private Game game;
public static int fistX,fistY;
static int d = 60;
int wide;
boolean onGround;

public Square(Game game) {
this.game = game;
x = 100;
y = 631;
xa = 0;
ya = 0;
onGround = false;
wide = game.getWidth();
}

public void move() {


if (x + xa > 0 && x + xa < game.getWidth()-30)
    x = x + xa;

if (y + ya > 0 && y + ya < game.getHeight()-60){


    for(int i=12; i< 0; i--);
    ya+=10;
    y = y + ya;
}
if  (  collision()  ) {
    y-=10;
    onGround = true;

}

Square.y+=10;



}



public void paint(Graphics2D g) {
g.setColor(Color.RED);
g.fillRoundRect(x, y-d, 30, d, 10, 10);



}
private boolean collision() {
return game.ground.getBounds().intersects(getBounds());
}
public Rectangle getBounds() {
return new Rectangle(x, y, 30, 60);
}
public void keyReleased(KeyEvent e) {



if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa=0;

if (e.getKeyCode() == KeyEvent.VK_RIGHT)
    xa=0;
if(e.getKeyCode() == KeyEvent.VK_DOWN)
    d = 60;

if(e.getKeyCode() == KeyEvent.VK_UP);





}



public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_LEFT)

    xa = xa -3;

if (e.getKeyCode() == KeyEvent.VK_RIGHT)

    xa = xa + 3;

if(e.getKeyCode() == KeyEvent.VK_DOWN)
    d = 30;

if(e.getKeyCode() == KeyEvent.VK_UP)

        ya  -= 60;





}









}


class Ground {

    int y,x,h,w;
public Ground(Game game){
    x = 0;
    y = game.getHeight()-30;
    w = game.getWidth();
    h = 30;
}
public void paint(Graphics2D g){
    g.setColor(Color.BLACK);
    g.fillRect(0, 700, 99999999, 30);

}
public Rectangle getBounds() {
return new Rectangle(0, 700, 99999999, 30);
}
}
Run Code Online (Sandbox Code Playgroud)

And*_*son 6

  1. 不要阻止EDT(事件调度线程) - 当发生这种情况时,GUI将"冻结".而不是为动画等重复任务调用Thread.sleep(n)实现Swing Timer.有关更多详细信息,请参阅Swing中的并发.
  2. frame.setSize(600, 700);我建议改为为内容设置首选大小并在其周围打包框架.这表明在不同的PLAF或OS'上游戏的大小不变.
  3. 对于除顶级容器之外的Swing组件(例如JFrameJWindow),覆盖paintComponent(Graphics)而不是paint(Graphics).
  4. 查看键绑定而不是Swing的键侦听器.

前三个是实现的,最后一个(和代码中注释的其他一个)是TODO - BNI.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class SuperMarioGame extends JPanel {

    private static final long serialVersionUID = 1L;
    Square square = new Square(this);
    Ground ground = new Ground (this);

    public SuperMarioGame() {
        // TODO Update to Key Bindings
        addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
            }

            @Override
            public void keyReleased(KeyEvent e) {
                square.keyReleased(e);
            }

            @Override
            public void keyPressed(KeyEvent e) {
                square.keyPressed(e);
            }

        });
        setFocusable(true);

        // Use a listener/timer combo.
        ActionListener gameAnimation = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                move();
                repaint();
            }
        };
        Timer timer = new Timer(30,gameAnimation);
        timer.start();

        // Set a preferred size for the panel.
        Dimension preferred = new Dimension(600,700);
        this.setPreferredSize(preferred);
    }

    public static void main(String[] args) throws InterruptedException {
        JFrame frame = new JFrame("My Mario");
        SuperMarioGame game = new SuperMarioGame();
        frame.add(game);
        // Pack the frame to the preferred size.
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void move() {
        square.move();
    }

    @Override
    // for Swing components, generally override 
    // paintComponent rather than paint
    //public void paint(Graphics g) {
    public void paintComponent(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        square.paint(g2d);
        ground.paint(g2d);
    }
}

class Square {

    Square square;
    int x,xa;
    static int y;
    int ya;
    private SuperMarioGame game;
    public static int fistX,fistY;
    static int d = 60;
    int wide;
    boolean onGround;

    public Square(SuperMarioGame game) {
        this.game = game;
        x = 100;
        y = 631;
        xa = 0;
        ya = 0;
        onGround = false;
        wide = game.getWidth();
    }

    public void move() {
        if (x + xa > 0 && x + xa < game.getWidth()-30)
            x = x + xa;

        if (y + ya > 0 && y + ya < game.getHeight()-60){
            for(int i=12; i< 0; i--);
            ya+=10;
            y = y + ya;
        }

        if  (  collision()  ) {
            y-=10;
            onGround = true;
        }

        Square.y+=10;
    }

    public void paint(Graphics2D g) {
        g.setColor(Color.RED);
        g.fillRoundRect(x, y-d, 30, d, 10, 10);
    }

    private boolean collision() {
        return game.ground.getBounds().intersects(getBounds());
    }

    public Rectangle getBounds() {
        return new Rectangle(x, y, 30, 60);
    }

    public void keyReleased(KeyEvent e) {
        // TODO Else-if would be better here..
        if (e.getKeyCode() == KeyEvent.VK_LEFT)
            xa=0;
        if (e.getKeyCode() == KeyEvent.VK_RIGHT)
            xa=0;
        if(e.getKeyCode() == KeyEvent.VK_DOWN)
            d = 60;
        if(e.getKeyCode() == KeyEvent.VK_UP);
    }

    public void keyPressed(KeyEvent e) {
        // TODO Else-if would be better here..
        if (e.getKeyCode() == KeyEvent.VK_LEFT)
            xa = xa -3;
        if (e.getKeyCode() == KeyEvent.VK_RIGHT)
            xa = xa + 3;
        if(e.getKeyCode() == KeyEvent.VK_DOWN)
            d = 30;
        if(e.getKeyCode() == KeyEvent.VK_UP)
            ya  -= 60;
    }
}

class Ground {

    int y,x,h,w;

    public Ground(SuperMarioGame game){
        x = 0;
        y = game.getHeight()-30;
        w = game.getWidth();
        h = 30;
    }

    public void paint(Graphics2D g){
        g.setColor(Color.BLACK);
        g.fillRect(0, 700, 99999999, 30);
    }

    public Rectangle getBounds() {
        return new Rectangle(0, 700, 99999999, 30);
    }
}
Run Code Online (Sandbox Code Playgroud)