Java Draw不能动蛇

时间:2019-06-24 10:34:36

标签: java swing

作为一种实践,我正在尝试创建蛇克隆。香港专业教育学院画蛇并添加了移动模式,但当我按任意键移动时,蛇会自己吃掉它。但它没有动。阵列将反作用力缩回起点,什么也不做。

这是我的蛇课,我删除了我的注释,因为这些注释超出了代码和发布系统的限制,不允许我发布

修改

如果您需要其他课程的任何内容,请告诉我。但我认为我的错误在这里

编辑2

添加了完整的代码,您只需将粘贴复制到新项目中,即可重现我的错误。

public class Snake {

    List<Point> sPoints;
    int xDir,yDir;
    boolean isMoving,addTail;
    final int sSize = 20, startX = 150 , startY = 150;
    public Snake(){

        sPoints = new ArrayList<Point>();

        xDir = 0;
        yDir = 0;

        isMoving = false;

        addTail = false;
        sPoints.add(new Point(startX,startY));

        for(int i=1; i<sSize; i++) {


            sPoints.add(new Point(startX - i * 4,startY));
        }
    }

    public void draw(Graphics g){

        g.setColor(Color.white);

        for(Point p : sPoints) {

            g.fillRect(p.getX(),p.getY(),4,4);
        }
    }

    public void move(){
        if (isMoving) {
            Point temp = sPoints.get(0);
            Point last = sPoints.get(sPoints.size() - 1);

            Point newstart = new Point(temp.getX() + xDir * 4, temp.getY() + yDir * 4);


            for (int i = sPoints.size() - 1; i >= 1; i--) {

                sPoints.set(i, sPoints.get(i - 1));
            }

            sPoints.set(0, newstart);
        }
    }

    public int getxDir() {
        return xDir;
    }

    public void setxDir(int x) {
        this.xDir = xDir;
    }

    public int getyDir() {
        return yDir;
    }

    public void setyDir(int y) {
        this.yDir = yDir;
    }

    public  int getX(){
        return sPoints.get(0).getX();
    }

    public int getY(){
        return sPoints.get(0).getY();
    }

    public boolean isMoving() {
        return isMoving;
    }

    public void setIsMoving(boolean b) {
        isMoving = b;
    }
}

以下是点类。只是一些吸气剂设置点,对于那些我使用IntelliJ自动生成的点。。(再次删除注释)

public class Point {

    private  int x,y;

    public Point() {

        x = 0;
        y = 0;
    }


      public Point(int x, int y) {

          this.x =x;
          this.y =y;
      }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }


}

最后我的主要班级叫做游戏。 在这里,我要做的是创建我的applet并为其赋予背景色。对可运行者造成威胁并添加上/右/下/左的运动模式... 并使用几个类来更新我的绘画图案,以便它可以通过更新我的矩形列表的每个状态来模拟运动。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Game extends Applet implements Runnable, KeyListener {

    //setting up double buffering.
    Graphics graphics;
    Image img;
    Thread thread;
    Snake snake;
    public void init() {
        //setting the size of our Applet
        this.resize(400,400);
        //we gonna create the image just the same size as our applet.
        img = createImage(400,400);
        //this represents our offscreen image that we will draw
        graphics = img.getGraphics();
       this.addKeyListener(this);
        snake = new Snake();
        thread = new Thread(this);
        thread.start();
    }

    public void paint(Graphics g) {
        //Setting the background of our applet to black
        graphics.setColor(Color.black);
        //Fill rectangle 0 , 0 (starts from) for top left corner and then 400,400 to fill our entire background to black
        graphics.fillRect(0,0,400,400);
        snake.draw(graphics);
        //painting the entire image
        g.drawImage(img,0,0,null);
    }

    //Update will call on Paint(g)
    public void update(Graphics g){
        paint(g);
    }
    //Repaint will call on Paint(g)
    public  void repaint(Graphics g){
        paint(g);
    }


    public void run() {
        //infinite loop
        for(;;) {
            snake.move();
            //drawing snake
            this.repaint();
        //Creating a time delay
            try {
                Thread.sleep(40);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }


    public void keyTyped(KeyEvent keyEvent) {


    }

    public void keyPressed(KeyEvent keyEvent) {
        if(!snake.isMoving()){ //this will allow the snake to start moving, but will disable LEFT for just the 1st move
            if(keyEvent.getKeyCode() == KeyEvent.VK_UP || keyEvent.getKeyCode() == KeyEvent.VK_RIGHT ||
                    keyEvent.getKeyCode() == KeyEvent.VK_DOWN ) {
                snake.setIsMoving(true);
            }
        }

        //setting up Key mapping so when the user presses UP,RIGHT,DOWN,LEFT. the Snake will move accordingly
        if(keyEvent.getKeyCode() == KeyEvent.VK_UP) {
            if (snake.getyDir() != 1) {
                snake.setyDir(-1);
                snake.setxDir(0);
            }
        }
        if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
            if (snake.getxDir() != -1) {
                snake.setxDir(1);
                snake.setyDir(0);
            }
        }
        if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
            if (snake.getyDir() != -1) {
                snake.setyDir(1);
                snake.setxDir(0);
            }
        }
        if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
            if (snake.getxDir() != 1) {
                snake.setxDir(-1);
                snake.setyDir(0);
            }
        }

    }

    public void keyReleased(KeyEvent keyEvent) {

    }
}

2 个答案:

答案 0 :(得分:1)

这里有一些意见,我已经阅读了您的代码。

  1. 您的蛇不会移动的原因是您的snake.setyDir()snake.setxDir()没有接受输入来覆盖xDiryDir。他们正在分配自己。
  2. JDK中为您准备了一个Point2D
  3. 移动蛇时,您只需要移开尾巴并添加一条 头部前有更多障碍物。你可以保持身体紧绷(根据 以我的常识蛇)。 enter image description here 考虑一下左侧的L形蛇,下端是头部,当前正向右侧。要移动蛇,请移除尾巴(绿色方块),然后根据其方向(红色方块)向头部添加另一条。它的最终状态成为右边的蛇。 LinkedList符合需求。
  4. 如果使用两个int(xDiryDir)来控制蛇的方向 令人困惑,您可以通过创建enum来帮助自己。 -1 0、1与x和y可能会使您感到困惑。
  5. 声明常量而不是幻数。例如第4块的宽度 图片大小400
  6. Snake.addTail不必要吗?
  7. 属性应具有辅助功能修改器

最终结果:

enter image description here

Game.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;

public class Game extends Applet implements Runnable, KeyListener {

    private final int GAMEBOARD_WIDTH = 400;

    // setting up double buffering.
    private Graphics graphics;
    private Image img;
    private Thread thread;
    private Snake snake;

    public void init() {
        // setting the size of our Applet
        this.resize(GAMEBOARD_WIDTH, GAMEBOARD_WIDTH);
        // we gonna create the image just the same size as our applet.
        img = createImage(GAMEBOARD_WIDTH, GAMEBOARD_WIDTH);
        // this represents our offscreen image that we will draw
        graphics = img.getGraphics();
        this.addKeyListener(this);
        snake = new Snake();
        thread = new Thread(this);
        thread.start();
    }

    public void paint(Graphics g) {
        // Setting the background of our applet to black
        graphics.setColor(Color.BLACK);
        // Fill rectangle 0 , 0 (starts from) for top left corner and then 400,400 to
        // fill our entire background to black
        graphics.fillRect(0, 0, GAMEBOARD_WIDTH, GAMEBOARD_WIDTH);
        snake.draw(graphics);
        // painting the entire image
        g.drawImage(img, 0, 0, null);
    }

    // Update will call on Paint(g)
    public void update(Graphics g) {
        paint(g);
    }

    // Repaint will call on Paint(g)
    public void repaint(Graphics g) {
        paint(g);
    }

    public void run() {
        // infinite loop
        for (;;) {
            snake.move();
            // drawing snake
            this.repaint();
            // Creating a time delay
            try {
                Thread.sleep(40);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public void keyTyped(KeyEvent keyEvent) {

    }

    public void keyPressed(KeyEvent keyEvent) {

        int keyCode = keyEvent.getKeyCode();

        if (!snake.isMoving()) {
            // this will allow the snake to start moving, but will disable LEFT for just the
            // 1st move
            if (matchKey(keyCode, KeyEvent.VK_UP, KeyEvent.VK_RIGHT, KeyEvent.VK_DOWN)) {
                snake.setIsMoving(true);
            }
        }

        // setting up Key mapping so when the user presses UP,RIGHT,DOWN,LEFT. the Snake
        // will move accordingly
        if (matchKey(keyCode, KeyEvent.VK_UP)) {
            snake.setDirection(Direction.UP);
        }
        if (matchKey(keyCode, KeyEvent.VK_RIGHT)) {
            snake.setDirection(Direction.RIGHT);
        }
        if (matchKey(keyCode, KeyEvent.VK_DOWN)) {
            snake.setDirection(Direction.DOWN);
        }
        if (matchKey(keyCode, KeyEvent.VK_LEFT)) {
            snake.setDirection(Direction.LEFT);
        }

    }

    // return true if targetKey contains the provided keyCode
    private boolean matchKey(int keyCode, int... targetKey) {
        return Arrays.stream(targetKey).anyMatch(i -> i == keyCode);
    }

    public void keyReleased(KeyEvent keyEvent) {

    }
}

Snake.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Point2D;
import java.util.LinkedList;

public class Snake {

    private final int sSize = 20, startX = 150, startY = 150;
    private final int BLOCK_WIDTH = 4;

    private LinkedList<Point2D.Float> sPoints;

    private boolean isMoving;

    private Direction direction;

    public Snake() {

        sPoints = new LinkedList<Point2D.Float>();

        isMoving = false;

        sPoints.add(new Point2D.Float(startX, startY));

        for (int i = 1; i < sSize; i++) {
            sPoints.add(new Point2D.Float(startX - i * BLOCK_WIDTH, startY));
        }
    }

    public void draw(Graphics g) {

        g.setColor(Color.white);
        for (Point2D p : sPoints) {
            g.fillRect((int) p.getX(), (int) p.getY(), BLOCK_WIDTH, BLOCK_WIDTH);
        }
    }

    public void move() {
        if (isMoving) {
            sPoints.removeLast();
            steer(sPoints.getFirst());
        }
    }

    private void steer(Point2D head) {

        Point2D.Float newHead = new Point2D.Float();
        switch (this.getDirection()) {
        case UP:
            newHead.setLocation(head.getX(), head.getY() - BLOCK_WIDTH);
            break;
        case DOWN:
            newHead.setLocation(head.getX(), head.getY() + BLOCK_WIDTH);
            break;
        case LEFT:
            newHead.setLocation(head.getX() - BLOCK_WIDTH, head.getY());
            break;
        case RIGHT:
            newHead.setLocation(head.getX() + BLOCK_WIDTH, head.getY());
            break;
        }

        this.sPoints.addFirst(newHead);

    }

    public int getX() {
        return (int) sPoints.get(0).getX();
    }

    public int getY() {
        return (int) sPoints.get(0).getY();
    }

    public boolean isMoving() {
        return isMoving;
    }

    public void setIsMoving(boolean b) {
        isMoving = b;
    }

    public Direction getDirection() {
        return direction;
    }

    public void setDirection(Direction d) {
        if (this.getDirection() == null) {
            this.direction = d;
        } else if (!this.getDirection().isOpposite(d)) {
            this.direction = d;
        }
    }
}

Direction.java

public enum Direction {
    UP(-1), DOWN(1), LEFT(-2), RIGHT(2);

    int vector;

    Direction(int i) {
        this.vector = i;
    }

    public boolean isOpposite(Direction d) {
        return this.vector + d.vector == 0;
    }

}

答案 1 :(得分:0)

Snack.java

import java.awt.EventQueue;
import javax.swing.JFrame;

public class Snake extends JFrame {

    public Snake() {

        initUI();
    }

    private void initUI() {

        add(new Board());

        setResizable(false);
        pack();

        setTitle("Snake");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }


    public static void main(String[] args) {

        EventQueue.invokeLater(() -> {
            JFrame ex = new Snake();
            ex.setVisible(true);
        });
    }
}

Board.java

enter image description here

enter image description here enter image description here enter image description here

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Board extends JPanel implements ActionListener {

    private final int B_WIDTH = 300;
    private final int B_HEIGHT = 300;
    private final int DOT_SIZE = 10;
    private final int ALL_DOTS = 900;
    private final int RAND_POS = 29;
    private final int DELAY = 140;

    private final int x\[\] = new int\[ALL_DOTS\];
    private final int y\[\] = new int\[ALL_DOTS\];

    private int dots;
    private int apple_x;
    private int apple_y;

    private boolean leftDirection = false;
    private boolean rightDirection = true;
    private boolean upDirection = false;
    private boolean downDirection = false;
    private boolean inGame = true;

    private Timer timer;
    private Image ball;
    private Image apple;
    private Image head;

    public Board() {

        initBoard();
    }

    private void initBoard() {

        addKeyListener(new TAdapter());
        setBackground(Color.black);
        setFocusable(true);

        setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
        loadImages();
        initGame();
    }

    private void loadImages() {

        ImageIcon iid = new ImageIcon("src/resources/dot.png");
        ball = iid.getImage();

        ImageIcon iia = new ImageIcon("src/resources/apple.png");
        apple = iia.getImage();

        ImageIcon iih = new ImageIcon("src/resources/head.png");
        head = iih.getImage();
    }

    private void initGame() {

        dots = 3;

        for (int z = 0; z < dots; z++) {
            x\[z\] = 50 - z * 10;
            y\[z\] = 50;
        }

        locateApple();

        timer = new Timer(DELAY, this);
        timer.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        doDrawing(g);
    }

    private void doDrawing(Graphics g) {

        if (inGame) {

            g.drawImage(apple, apple_x, apple_y, this);

            for (int z = 0; z < dots; z++) {
                if (z == 0) {
                    g.drawImage(head, x\[z\], y\[z\], this);
                } else {
                    g.drawImage(ball, x\[z\], y\[z\], this);
                }
            }

            Toolkit.getDefaultToolkit().sync();

        } else {

            gameOver(g);
        }        
    }

    private void gameOver(Graphics g) {

        String msg = "Game Over";
        Font small = new Font("Helvetica", Font.BOLD, 14);
        FontMetrics metr = getFontMetrics(small);

        g.setColor(Color.white);
        g.setFont(small);
        g.drawString(msg, (B_WIDTH - metr.stringWidth(msg)) / 2, B_HEIGHT / 2);
    }

    private void checkApple() {

        if ((x\[0\] == apple_x) && (y\[0\] == apple_y)) {

            dots++;
            locateApple();
        }
    }

    private void move() {

        for (int z = dots; z > 0; z--) {
            x\[z\] = x\[(z - 1)\];
            y\[z\] = y\[(z - 1)\];
        }

        if (leftDirection) {
            x\[0\] -= DOT_SIZE;
        }

        if (rightDirection) {
            x\[0\] += DOT_SIZE;
        }

        if (upDirection) {
            y\[0\] -= DOT_SIZE;
        }

        if (downDirection) {
            y\[0\] += DOT_SIZE;
        }
    }

    private void checkCollision() {

        for (int z = dots; z > 0; z--) {

            if ((z > 4) && (x\[0\] == x\[z\]) && (y\[0\] == y\[z\])) {
                inGame = false;
            }
        }

        if (y\[0\] >= B_HEIGHT) {
            inGame = false;
        }

        if (y\[0\] < 0) {
            inGame = false;
        }

        if (x\[0\] >= B_WIDTH) {
            inGame = false;
        }

        if (x\[0\] < 0) {
            inGame = false;
        }

        if (!inGame) {
            timer.stop();
        }
    }

    private void locateApple() {

        int r = (int) (Math.random() * RAND_POS);
        apple_x = ((r * DOT_SIZE));

        r = (int) (Math.random() * RAND_POS);
        apple_y = ((r * DOT_SIZE));
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        if (inGame) {

            checkApple();
            checkCollision();
            move();
        }

        repaint();
    }

    private class TAdapter extends KeyAdapter {

        @Override
        public void keyPressed(KeyEvent e) {

            int key = e.getKeyCode();

            if ((key == KeyEvent.VK_LEFT) && (!rightDirection)) {
                leftDirection = true;
                upDirection = false;
                downDirection = false;
            }

            if ((key == KeyEvent.VK_RIGHT) && (!leftDirection)) {
                rightDirection = true;
                upDirection = false;
                downDirection = false;
            }

            if ((key == KeyEvent.VK_UP) && (!downDirection)) {
                upDirection = true;
                rightDirection = false;
                leftDirection = false;
            }

            if ((key == KeyEvent.VK_DOWN) && (!upDirection)) {
                downDirection = true;
                rightDirection = false;
                leftDirection = false;
            }
        }
    }
}

enter image description here