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 (Event Dispatch Thread) をブロックしないでください。ブロックすると、GUI が「フリーズ」します。呼び出す代わりに、アニメーションなどの繰り返しタスク用Thread.sleep(n)に Swing を実装します。Timer詳細については、Swingでの同時実行を参照してください。
  2. frame.setSize(600, 700);代わりに、コンテンツに適切なサイズを設定し、その周りにフレームを詰めることをお勧めします。これは、さまざまな PLAF または OS でのゲームのサイズが一定であることを示唆しています。
  3. トップレベルのコンテナー以外の Swing コンポーネント (JFrameや など) の場合は、ではなくJWindowオーバーライドします。paintComponent(Graphics)paint(Graphics)
  4. Swing のキー リスナーではなく、キー バインドを調べます。

最初の 3 つが実装され、最後の 1 つ (およびコードでコメントされている他の 1 つ) は 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での同時実行をお読みください。
  • UI は EDT からのみ変更し、他のスレッドからは決して変更しないでください。これには UI 要素の作成が含まれます
  • よりもキーバインディングを優先しますKeyListeners。特にフォーカスの問題を解決する能力が高くなります。詳細については、キーバインディングの使用方法をお読みください
  • paintComponentよりもオーバーライドを優先しますpaint。ペイントは、できればいじらないようにする必要がある多くの重要な作業を行います。他のものとは別に、そうではないpaintComponentコンポーネントのダブルバッファリングに含まれる予定ですpaintsuper.paint設定されているとおり)
  • static可能な限り状態変数の使用を避ける
  • これが意図的なものかどうかはわかりませんがfor (int i = 12; i < 0; i--);、最後のセミコロンが意味するように、何も達成するつもりはありません。
  • 個人的には、実際には親コンテナーに依存する幅や高さなどに絶対値を使用しないようにしてください。また、可能な場合は、親コンテナーが実際に必要なスペースをより適切に決定できるように、サイズ変更のヒントを提供する必要があります。

ここに画像の説明を入力

更新しました

私の移動コードのバグを修正しました:P

私はあなたの衝突検出コード ( 内move) を調べましたが、率直に言って、表も裏もわかりませんでした。paintx、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 に答える