1

为什么矩形跳跃的高度不同?它似乎进入了一个循环。首先它跳得很低,然后它根本不跳,然后它跳得很高,然后它根本不跳。我不知道为什么使用相同的代码并且它是由相同的事件触发的。

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

2 回答 2

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

前 3 个已实现,最后一个(以及代码中注释的其他一个)是 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);
    }
}
于 2012-11-10T03:11:42.540 回答
4
  • 不要以任何方式阻塞事件调度线程,它会阻止 EDT 处理重绘请求(和其他事件),这会使你的程序看起来像是崩溃了。阅读Swing 中的并发以获取更多信息。
  • 仅从 EDT 修改 UI,切勿从任何其他线程修改 UI,这包括创建 UI 元素
  • 优先使用键绑定KeyListeners,它们更能解决焦点问题。阅读如何使用键绑定以获取更多详细信息
  • paintComponent更倾向于压倒一切paint。Paint 做了很多重要的工作,如果可以的话,你应该避免弄乱这些工作。除了其他任何东西之外,paintComponent组件的双缓冲中都将包含 aspaint不是(super.paint设置它)
  • 尽可能避免使用static状态变量
  • 我不知道这是否是故意的,但是,for (int i = 12; i < 0; i--);不会有任何结果,因为最后的半科伦意味着,计数 1 什么也不做
  • 就个人而言,尽量不要对宽度和高度之类的东西使用绝对值,这实际上依赖于父容器。您还应该在可能的情况下提供大小提示,以允许父容器更好地决定它实际需要多少空间

在此处输入图像描述

更新

修复了我的运动代码中的错误:P

我查看了您的碰撞检测代码(在 中move),坦率地说,无法对它做出正面或反面。我更正了它并改变了paint方法的工作方式,使 x,y 始终是左上角

public class TestGame {

    public static void main(String[] args) throws InterruptedException {
        new TestGame();
    }

    public TestGame() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                Game game = new Game();

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(game);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class GameThread extends Thread {

        private Game game;

        public GameThread(Game game) {
            setDaemon(false);
            this.game = game;
        }

        @Override
        public void run() {
            while (true) {
                game.move();
                try {
                    long startedAt = System.currentTimeMillis();
                    SwingUtilities.invokeAndWait(new Runnable() {
                        @Override
                        public void run() {
                            game.repaint();
                        }
                    });
                    long completedAt = System.currentTimeMillis();
                    long sleepFor = 30 - (completedAt - startedAt);
                    if (sleepFor < 0) {
                        sleepFor = 30;
                    }
                    Thread.sleep(sleepFor);
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            }

        }
    }

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

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "press-left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "press-right");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "press-down");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "press-up");

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "release-left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "release-right");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "release-down");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "release-up");    

            am.put("press-left", new PressLeftAction(square));
            am.put("press-right", new PressRightAction(square));
            am.put("press-down", new PressDownAction(square));
            am.put("press-up", new PressUpAction(square));

            am.put("release-left", new ReleaseLeftAction(square));
            am.put("release-right", new ReleaseRightAction(square));
            am.put("release-down", new ReleaseDownAction(square));
            am.put("release-up", new ReleaseUpAction(square));

            new GameThread(this).start();

//        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;
//            }
//
//
//
//
//
//        }
        }

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

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        // Don't override paint, use paintComponent instead
//        @Override
//        public void paint(Graphics g) {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            square.paint(g2d);
            ground.paint(g2d);
            g2d.dispose();
        }
    }

    public class Square {

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

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

        public void move() {

            y += ya;
            x += xa;

            if (x < 0) {
                x = 0;
            } else if (x + 30 > game.getWidth()) {
                x = game.getWidth() - 30;
            }

            if (y < 0) {
                y = 0;
            } else if (collision()) {
                onGround = true;
                y = game.ground.getBounds().y - d;
            }

//            if (x + xa > 0 && x + xa < game.getWidth() - 30) {
//                x = x + xa;
//            }
//
//            if (y + ya > 0 && y + ya < game.getHeight() - 60) {
//                // This was never going to do anything, look at the
//                // end of the line...the `;` is going to prevent the
//                // statemt ya += 10 from begin called within the loop
////                for (int i = 12; i < 0; i--);
//                for (int i = 12; i < 0; i--) {
//                    ya += 10;
//                }
//                y = y + ya;
//            }
//            if (collision()) {
//                y -= 10;
//                onGround = true;
//
//            }
//
//            y += 10;

        }

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

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

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

    public class Ground {

        private Game game;

        public Ground(Game game) {
            this.game = game;
        }

        public void paint(Graphics2D g) {
            g.setColor(Color.BLACK);
            g.fillRect(0, game.getHeight() - 30, game.getWidth(), 30);
        }

        public Rectangle getBounds() {
            return new Rectangle(0, game.getHeight() - 30, game.getWidth(), 30);
        }
    }

    public abstract class AbstractSquareAction extends AbstractAction {

        private Square square;

        public AbstractSquareAction(Square square) {
            this.square = square;
        }

        public Square getSquare() {
            return square;
        }

    }

    public class PressLeftAction extends AbstractSquareAction {

        public PressLeftAction(Square square) {
            super(square);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getSquare().xa = -3;
            System.out.println("pressLeft");
        }

    }

    public class PressRightAction extends AbstractSquareAction {

        public PressRightAction(Square square) {
            super(square);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getSquare().xa = 3;
        }

    }

    public class PressDownAction extends AbstractSquareAction {

        public PressDownAction(Square square) {
            super(square);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getSquare().ya = 30;
        }

    }

    public class PressUpAction extends AbstractSquareAction {

        public PressUpAction(Square square) {
            super(square);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getSquare().ya -= 30;
        }

    }

    public class ReleaseLeftAction extends AbstractSquareAction {

        public ReleaseLeftAction(Square square) {
            super(square);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getSquare().xa = 0;
        }

    }

    public class ReleaseRightAction extends AbstractSquareAction {

        public ReleaseRightAction(Square square) {
            super(square);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getSquare().xa = 0;
        }

    }

    public class ReleaseDownAction extends AbstractSquareAction {

        public ReleaseDownAction(Square square) {
            super(square);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getSquare().ya = 0;
        }

    }

    public class ReleaseUpAction extends AbstractSquareAction {

        public ReleaseUpAction(Square square) {
            super(square);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getSquare().ya = 0;
        }

    }

}
于 2012-11-10T04:10:16.097 回答