使用键绑定使精灵继续移动和蛇体

时间:2014-01-09 15:33:54

标签: java swing awt paint key-bindings

这是我正在做的同一个游戏,我遇到了一个我无法理解的问题。我正在使用Key Bindings移动我的精灵,它的工作效果很好!但由于它是一个蛇游戏,我需要精灵在不停止的情况下继续前进并改变方向并在玩家键入一个键后继续移动。我知道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

1 个答案:

答案 0 :(得分:0)

  

但是因为它是一个蛇游戏我需要精灵继续前进而不停止”

您需要使用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。这就是你用swing做动画的方法。因此,如果没有按任何键,精灵将自动移动。它的工作方式与按钮非常相似。按下按钮时会触发事件。但是在计时器的情况下,计时器是触发事件的计时器。您可以指定所需的任何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