【问题标题】:Using keybinding to make sprite continue to move and Snake body使用键绑定使精灵继续移动和蛇体
【发布时间】:2014-01-28 06:05:28
【问题描述】:

这是我正在开发的同一款游戏,但我又遇到了一个我无法理解的问题。我正在使用键绑定来移动我的精灵,它工作得很好!但由于这是一款蛇类游戏,我需要精灵继续移动而不会停止并改变方向并在玩家键入键后继续移动。我知道 KeyListener 是可能的,但我真的不想完全改变我的程序。如果可能的话,我只需要知道需要更改哪些代码。

除此之外,我还在研究蛇身的 x 和 y 坐标的两个数组,以便方块会跟随在头部后面,但我无法将其绘制出来。以及如何显示分数的整数。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
import java.util.ArrayList;

 public class Snake2 extends JFrame {

 /* Sprite: snake head co-ordinates */
 int x = 400;
 int y = 450;
 int width = 10;
 int height = 10;

 /* Sprite: snake body */
 int length = 0;
 ArrayList <Integer> bodyX = new ArrayList <Integer>();
 ArrayList <Integer> bodyY = new ArrayList <Integer>();

 /* Score */
 int point = 0;

/* Sprite: mouse co-ordinates */
Random rand = new Random();
int addx = (rand.nextInt(10))*10;
int addy = (rand.nextInt(10))*10;
int mx = ((rand.nextInt(5)+1)*100) + addx;
int my = ((rand.nextInt(6)+2)*100) + addy;

DrawPanel drawPanel = new DrawPanel();

public Snake2() {

addMouseListener(new MouseListener());
System.out.print(mx + " " + my);

/* move snake up */
Action upAction = new AbstractAction(){
  public void actionPerformed(ActionEvent e) {
    y -=10;

    if (y >= my && y <= my+9 && x >= mx && x <= mx+9)
    {
      addx = (rand.nextInt(10))*10;
      addy = (rand.nextInt(10))*10;
      mx = ((rand.nextInt(5)+1)*100) + addx;
      my = ((rand.nextInt(6)+1)*100) + addy;
      point += 100;
      length++;
      bodyY.add(0, y);
    }

    if (y <99)
    {
       new GameOver();
       dispose();
    }
    drawPanel.repaint();
  }
};

/* move snake down */
Action downAction = new AbstractAction(){
   public void actionPerformed(ActionEvent e) {
     y +=10;

     if (y >= my && y <= my+9 && x >= mx && x <= mx+9)
     {
       addx = (rand.nextInt(10))*10;
       addy = (rand.nextInt(10))*10;
       mx = ((rand.nextInt(5)+1)*100) + addx;
       my = ((rand.nextInt(6)+1)*100) + addy;
       point += 100;
       length++;
       bodyY.add(0, y);
     }

     if (y > 799)
     {
       new GameOver();
       dispose();
     }
     drawPanel.repaint();
   }
};

/* move snake left */
Action leftAction = new AbstractAction(){
   public void actionPerformed(ActionEvent e) {
     x -=10;

     if (x >= mx && x <= mx+9 && y >= my && y <= my+9)
     {
       addx = (rand.nextInt(10))*10;
       addy = (rand.nextInt(10))*10;
       mx = ((rand.nextInt(5)+1)*100) + addx;
       my = ((rand.nextInt(6)+1)*100) + addy;
       point += 100;
       length++;
       bodyX.add(0, x);
     }

     if (x <99)
     {
       new GameOver();
       dispose();
     }
     drawPanel.repaint();
   }
};

/* move snake right */
Action rightAction = new AbstractAction(){
  public void actionPerformed(ActionEvent e) {
    x +=10;

    if (x >= mx && x <= mx+9 && y >= my && y <= my+9)
    {
       addx = (rand.nextInt(10))*10;
       addy = (rand.nextInt(10))*10;
       mx = ((rand.nextInt(5)+1)*100) + addx;
       my = ((rand.nextInt(6)+1)*100) + addy;
       point += 100;
       length++;
       bodyX.add(0, x);
    }

    if (x > 699)
    {
      new GameOver();
      dispose();
    }
    drawPanel.repaint();
  }
};

InputMap inputMap = drawPanel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = drawPanel.getActionMap();

inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "rightAction");
actionMap.put("rightAction", rightAction);

inputMap.put(KeyStroke.getKeyStroke("LEFT"), "leftAction");
actionMap.put("leftAction", leftAction);

inputMap.put(KeyStroke.getKeyStroke("DOWN"), "downAction");
actionMap.put("downAction", downAction);

inputMap.put(KeyStroke.getKeyStroke("UP"), "upAction");
actionMap.put("upAction", upAction);

add(drawPanel);

pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);

}//Snake2()

private class GameOver extends JFrame implements ActionListener{
JLabel answer = new JLabel("");
JPanel pane = new JPanel(); // create pane object
JButton pressme = new JButton("Quit");
JButton replay = new JButton("Replay?");
GameOver()   // the constructor
{
  super("Game Over"); setBounds(100,100,300,200);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  Container con = this.getContentPane(); // inherit main frame
  con.add(pane); pressme.setMnemonic('Q'); // associate hotkey
  pressme.addActionListener(this);   // register button listener
  replay.addActionListener(this);
  pane.add(answer); pane.add(pressme); pane.add(replay); pressme.requestFocus();
  answer.setText("You Lose");
  setVisible(true); // make frame visible
}//GameOver()

// here is the basic event handler
public void actionPerformed(ActionEvent event)
{
  Object source = event.getSource();
  if (source == pressme)
    System.exit(0);
  if (source == replay)
  {
    dispose();
    EventQueue.invokeLater(new Runnable(){
  public void run(){
    new Snake2();
  }
});
  }
}//actionPreformed

}//GameOver


private class DrawPanel extends JPanel {

protected void paintComponent(Graphics g) {

  super.paintComponent(g);

  Font ith = new Font("Ithornît", Font.BOLD, 78);

        /* Background: Snake */
  g.setColor(Color.darkGray);
        g.fillRect(0, 0, getWidth(), getHeight());
  g.setColor(Color.gray);
        g.fillRect(100,100,600,700); 
  g.setColor(Color.white);
        g.drawRect(99,99,601,701);

        g.drawString("Quit",102,86);
        g.drawRect(100,70,30,20);
        g.drawString("Score: ", 602, 86);

        g.setFont(ith);
        g.drawString("SNAKE",350,60);

              /* Sprite: Mouse */
  g.setColor(Color.black);
        g.fillRect(mx, my, width, height);
        //System.out.print(mx + " " + my);

        /* Sprite: Snake Body */
        if (length != 0){
        for(int i = 0; i >= length; i++)
        {
  g.setColor(Color.darkGray);
        g.fillRect(bodyX.get(i), bodyY.get(i), width, height);
        }
        }

        /* Sprite: Snake head */
  g.setColor(Color.white);
        g.fillRect(x, y, width, height);

  }//Paint Component

  public Dimension getPreferredSize() {
  return new Dimension(800, 850);
  }//Dimension

}//DrawPanel

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
    public void run(){
    new Snake2();
    }
    });
  }// main

}//Snake Class


/* Tracks where mouse is clicked */
class MouseListener extends MouseAdapter {

public void mouseReleased(MouseEvent me) {
  if (me.getX() >= 101 && me.getX() <= 131 && me.getY() >= 94 && me.getY() <= 115){
  System.exit(0);
}

String str="Mouse Released at "+me.getX()+","+me.getY();
System.out.println(str);
}
}//MouseAdapter

【问题讨论】:

    标签: java swing awt paint key-bindings


    【解决方案1】:

    但由于这是一款蛇类游戏,我需要让精灵不停地移动”

    您需要使用javax.swing.Timer。基本构造函数是这样的

    Timer(int delay, ActionListener listener)  // delay is in milliseconds
    

    一个基本的实现是这样的

    Timer timer = new Timer(100, new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            // do something
        }
    });
    timer.start();
    

    基本上计时器的作用是每隔几毫秒触发一次ActionEvent。这就是你如何使用摇摆来制作动画。因此,无需您按任何键,精灵就会自行移动。它的工作原理与按钮非常相似。当您按下按钮时,会触发一个事件。但是在计时器的情况下,计时器是触发事件的那个。您可以指定任何您想要的delay。许多人甚至希望在达到某个级别时动态更改持续时间。 timer.setDelay(someInt)


    更新

    我对您当前的代码做了很少的改动。我做了几乎我在下面评论中所说的

    好的,所以我考虑了一下,我会做这样的事情:有一个方向变量。对于动作,你应该做的就是改变方向。在计时器 actionPerformed 中,这就是你所有逻辑应该去的地方。检查方向。如果 if 等于“left”,则继续向左移动,就像按下按键一样。以此类推

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.util.Random;
    import java.util.ArrayList;
    
    public class Snake2 extends JFrame {
    
        String direction = "right";
    
        //String duration = 
    
        /* Sprite: snake head co-ordinates */
        int x = 400;
        int y = 450;
        int width = 10;
        int height = 10;
    
        /* Sprite: snake body */
        int length = 0;
        ArrayList<Integer> bodyX = new ArrayList<Integer>();
        ArrayList<Integer> bodyY = new ArrayList<Integer>();
    
        /* Score */
        int point = 0;
    
        /* Sprite: mouse co-ordinates */
        Random rand = new Random();
        int addx = (rand.nextInt(10)) * 10;
        int addy = (rand.nextInt(10)) * 10;
        int mx = ((rand.nextInt(5) + 1) * 100) + addx;
        int my = ((rand.nextInt(6) + 2) * 100) + addy;
    
        DrawPanel drawPanel = new DrawPanel();
        Timer timer;
        public Snake2() {
    
            addMouseListener(new MouseListener());
    
            timer = new Timer(50, new TimerListener());     ////////////// <<<<<<<<<<<<<<<<<< TIMER
            timer.start();
            System.out.print(mx + " " + my);
    
            /* move snake up */
            Action upAction = new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    direction = "up";                       ////////////// <<<<<<<<<<<<<<<<<< direction only change
                }
            };
    
            /* move snake down */
            Action downAction = new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    direction = "down";
                }
            };
    
            /* move snake left */
            Action leftAction = new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    direction = "left";
                }
            };
    
            /* move snake right */
            Action rightAction = new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    direction = "right";
                }
            };
    
            InputMap inputMap = drawPanel
                    .getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = drawPanel.getActionMap();
    
            inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "rightAction");
            actionMap.put("rightAction", rightAction);
    
            inputMap.put(KeyStroke.getKeyStroke("LEFT"), "leftAction");
            actionMap.put("leftAction", leftAction);
    
            inputMap.put(KeyStroke.getKeyStroke("DOWN"), "downAction");
            actionMap.put("downAction", downAction);
    
            inputMap.put(KeyStroke.getKeyStroke("UP"), "upAction");
            actionMap.put("upAction", upAction);
    
            add(drawPanel);
    
            pack();
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setLocationRelativeTo(null);
            setVisible(true);
    
        }// Snake2()
    
        private class TimerListener implements ActionListener {
            public void actionPerformed(ActionEvent e) {                /////////////////// <<<<<<<<<<<<<< All logic here
                if ("right".equals(direction)) { 
                    x += 10;
    
                    if (x >= mx && x <= mx + 9 && y >= my && y <= my + 9) {
                        addx = (rand.nextInt(10)) * 10;
                        addy = (rand.nextInt(10)) * 10;
                        mx = ((rand.nextInt(5) + 1) * 100) + addx;
                        my = ((rand.nextInt(6) + 1) * 100) + addy;
                        point += 100;
                        length++;
                        bodyX.add(0, x);
                    }
    
                    if (x > 699) {
                        new GameOver();
                        dispose();
                    }
                } else if ("left".equals(direction)) {
                    x -= 10;
    
                    if (x >= mx && x <= mx + 9 && y >= my && y <= my + 9) {
                        addx = (rand.nextInt(10)) * 10;
                        addy = (rand.nextInt(10)) * 10;
                        mx = ((rand.nextInt(5) + 1) * 100) + addx;
                        my = ((rand.nextInt(6) + 1) * 100) + addy;
                        point += 100;
                        length++;
                        bodyX.add(0, x);
                    }
    
                    if (x < 99) {
                        new GameOver();
                        dispose();
                    }
                } else if ("up".equals(direction)) {
                    y -= 10;
    
                    if (y >= my && y <= my + 9 && x >= mx && x <= mx + 9) {
                        addx = (rand.nextInt(10)) * 10;
                        addy = (rand.nextInt(10)) * 10;
                        mx = ((rand.nextInt(5) + 1) * 100) + addx;
                        my = ((rand.nextInt(6) + 1) * 100) + addy;
                        point += 100;
                        length++;
                        bodyY.add(0, y);
                    }
    
                    if (y < 99) {
                        new GameOver();
                        dispose();
                    }
    
    
                } else if ("down".equals(direction)) {
                    y += 10;
    
                    if (y >= my && y <= my + 9 && x >= mx && x <= mx + 9) {
                        addx = (rand.nextInt(10)) * 10;
                        addy = (rand.nextInt(10)) * 10;
                        mx = ((rand.nextInt(5) + 1) * 100) + addx;
                        my = ((rand.nextInt(6) + 1) * 100) + addy;
                        point += 100;
                        length++;
                        bodyY.add(0, y);
                    }
    
                    if (y > 799) {
                        new GameOver();
                        dispose();
                    }
                } 
                drawPanel.repaint();
            }
        }
    
        private class GameOver extends JFrame implements ActionListener {
            JLabel answer = new JLabel("");
            JPanel pane = new JPanel(); // create pane object
            JButton pressme = new JButton("Quit");
            JButton replay = new JButton("Replay?");
    
            GameOver() // the constructor
            {
    
                super("Game Over");
                timer.stop();                                           ////////////////////// <<<<<<<<<< Stop TIMER
                setBounds(100, 100, 300, 200);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                Container con = this.getContentPane(); // inherit main frame
                con.add(pane);
                pressme.setMnemonic('Q'); // associate hotkey
                pressme.addActionListener(this); // register button listener
                replay.addActionListener(this);
                pane.add(answer);
                pane.add(pressme);
                pane.add(replay);
                pressme.requestFocus();
                answer.setText("You Lose");
                setVisible(true); // make frame visible
            }// GameOver()
    
            // here is the basic event handler
            public void actionPerformed(ActionEvent event) {
                Object source = event.getSource();
                if (source == pressme)
                    System.exit(0);
                if (source == replay) {
                    dispose();
                    EventQueue.invokeLater(new Runnable() {
                        public void run() {
                            new Snake2();
                        }
                    });
                }
            }// actionPreformed
    
        }// GameOver
    
        private class DrawPanel extends JPanel {
    
            protected void paintComponent(Graphics g) {
    
                super.paintComponent(g);
    
                Font ith = new Font("Ithornît", Font.BOLD, 78);
    
                /* Background: Snake */
                g.setColor(Color.darkGray);
                g.fillRect(0, 0, getWidth(), getHeight());
                g.setColor(Color.gray);
                g.fillRect(100, 100, 600, 700);
                g.setColor(Color.white);
                g.drawRect(99, 99, 601, 701);
    
                g.drawString("Quit", 102, 86);
                g.drawRect(100, 70, 30, 20);
                g.drawString("Score: ", 602, 86);
    
                g.setFont(ith);
                g.drawString("SNAKE", 350, 60);
    
                /* Sprite: Mouse */
                g.setColor(Color.black);
                g.fillRect(mx, my, width, height);
                // System.out.print(mx + " " + my);
    
                /* Sprite: Snake Body */
                if (length != 0) {
                    for (int i = 0; i >= length; i++) {
                        g.setColor(Color.darkGray);
                        g.fillRect(bodyX.get(i), bodyY.get(i), width, height);
                    }
                }
    
                /* Sprite: Snake head */
                g.setColor(Color.white);
                g.fillRect(x, y, width, height);
    
            }// Paint Component
    
            public Dimension getPreferredSize() {
                return new Dimension(800, 850);
            }// Dimension
    
        }// DrawPanel
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new Snake2();
                }
            });
        }// main
    
    }// Snake Class
    
    /* Tracks where mouse is clicked */
    class MouseListener extends MouseAdapter {
    
        public void mouseReleased(MouseEvent me) {
            if (me.getX() >= 101 && me.getX() <= 131 && me.getY() >= 94
                    && me.getY() <= 115) {
                System.exit(0);
            }
    
            String str = "Mouse Released at " + me.getX() + "," + me.getY();
            System.out.println(str);
        }
    }// MouseAdapter
    

    【讨论】:

    • 它会在代码中的什么位置出现?它会取代 AbstractAction 吗?
    • 您只需要在构造函数中使用它。我不太确定你的程序是如何工作的,所以我不想对你的代码提供太多建议。我不想让你头疼。
    • 好吧,我想了想,我会做这样的事情:有一个direction 变量。对于动作,你应该做的就是改变方向。在计时器 actionPerformed 中,这就是你所有逻辑应该去的地方。检查direction。如果 if 等于“左”,则继续向左移动,就像在按键上一样。以此类推
    • 查看我的更新。您将在 cmets 中看到我所做的更改。
    猜你喜欢
    • 1970-01-01
    • 2021-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-05-29
    • 2020-03-06
    • 1970-01-01
    相关资源
    最近更新 更多