2016-05-14 8 views
0

ich bin ziemlich neu in Java und bin verwirrt, wie dies zu tun ist. Ich habe einen Key-Listener, der auf WASD hört, was auf die Bewegung meiner Snake hinweist. Der Key-Listener ändert die X- und Y-Positionen meiner Snakes-Segmente. Ich habe einen Timer, der mit einem Listener namens "Listener" verbunden ist, der die Bewegungen in einen Puffer und auf den Bildschirm überspielt. Meine Frage ist, warum die Bewegung, die von meinem Schlüsselhörer angezeigt wird, es nicht in den Puffer schafft? Außerdem weiß ich, dass meine Bewegungsfunktion becuase snek.move (4) ist; arbeitet im Timer. Schlussbemerkung, dies ist ein Snake-Spiel, das ich gerade erst begonnen habe.Kommunikation zwischen einem Hörer und einem Timer

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.awt.image.*; 
public class SnekePanel extends JPanel 
{ 
    private static final int FRAME1 = 1000; 
    private static final int FRAME2 = 1000; 
    private static final Color BACKGROUND = new Color(0, 0, 0); 
    private BufferedImage myImage; 
    private Graphics myBuffer; 
    private Sneke snek; 
    private Food food; 
    private Timer t; 
    private int points = 0; 
    public SnekePanel() 
    { 
     myImage = new BufferedImage(FRAME1, FRAME2, BufferedImage.TYPE_INT_RGB); 
     myBuffer = myImage.getGraphics(); 
     myBuffer.setColor(BACKGROUND); 
     myBuffer.fillRect(0, 0, FRAME1,FRAME2); 
     int xPos = (int)(Math.random()*(FRAME1-100) + 50); 
     int yPos = (int)(Math.random()*(FRAME2-100)+ 50); 
     food = new Food(xPos, yPos, 10, Color.RED); 
     snek = new Sneke(200,200,1,Color.WHITE); 
     t = new Timer(5, new Listener()); 
     t.start(); 
     addKeyListener(new Key()); 
     setFocusable(true); 
    } 

    public void paintComponent(Graphics g) 
    { 
     g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null); 
    } 

    private class Key extends KeyAdapter 
    { 
     public void keyPressed(KeyEvent e) 
     { 
     if(e.getKeyCode() == KeyEvent.VK_W) 
     { 
      snek.move(1); 
     } 
     if(e.getKeyCode() == KeyEvent.VK_A) 
     { 
      snek.move(2); 
     } 
     if(e.getKeyCode() == KeyEvent.VK_S) 
     { 
      snek.move(3); 
     } 
     if(e.getKeyCode() == KeyEvent.VK_D) 
     { 
      snek.move(4); 
     } 

     } 

    } 

    private class Listener implements ActionListener 
    { 
     public void actionPerformed(ActionEvent e) 
     { 
     if(snek.checkBlock() != 0) 
     { 
      myBuffer.setColor(BACKGROUND); 
      myBuffer.fillRect(0,0,FRAME1,FRAME2); 
      snek.move(4); 
      collide(snek, food); 
      food.draw(myBuffer); 
      snek.draw(myBuffer); 
      myBuffer.setColor(Color.BLACK); 
      repaint(); 
     } 
     } 
    } 

    private void collide(Sneke b, Food pd) 
    { 
     int sx = b.getX(snek.getLength()-1); 
     int sy = b.getY(snek.getLength()-1); 
     int fx = pd.getX(); 
     int fy = pd.getY(); 
     if(sx == sy && fx == fy) 
     { 
     snek.setLength(snek.getLength()+1); 
     } 
    } 
} 

Antwort

2

warum die Bewegung durch meinen Schlüssel Hörer angezeigt, es nicht zu dem Puffer machen?

Eine wichtigere Frage in meinem Kopf ist: Warum denken Sie, dass es sollte es in den Puffer machen? Sie malen nur den Puffer nach dem Aufruf snek.move(4) und so scheint es, dass nur das würde es in den Puffer machen.

Myself, würde ich die Dinge anders tun, einschließlich (unter anderem)

  • Ich würde ein int Feld erzeugen - oder besser eine Richtung Enum, die bis kapselt, unten, links und rechts.
  • Ich würde meiner GUI ein Feld von diesem oben geben, und ich würde es in den KeyListener setzen.
  • Ich würde eigentlich Key-Bindings und nicht ein KeyListener bevorzugen, da es viel weniger zweifelhaft ist, wenn es darum geht, Probleme zu konzentrieren, aber beide könnten funktionieren.
  • In meinem Timer, würde ich das Sprit bewegt basierend auf dem Zustand des Wertes im Bereich

Zum Beispiel, versuchen Sie dies ausgeführt wird:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.util.LinkedList; 
import java.util.List; 

import javax.swing.*; 


@SuppressWarnings("serial") 
public class SnakePanel extends JPanel { 
    // size of the GUI 
    private static final int PREF_W = 1000; 
    private static final int PREF_H = 800; 

    // background and snake color 
    private static final Color BG = Color.BLACK; 
    private static final Color SNAKE_COLOR = Color.RED; 
    private static final int SEGMENT_WIDTH = 20; 

    // distance moved in each timer tick, and time between each tick 
    private static final int DELTA = 5; 
    private static final int TIMER_DELAY = 40; // in msecs 

    // number of segments in the worm 
    private static final int WORM_LENGTH = 80; 

    // initial direction 
    private Direction direction = Direction.RIGHT; 

    // initial point 
    private Point point = new Point(PREF_W/2, PREF_H/2); 

    // Snake is little more than a List of Points 
    private List<Point> snakePointList = new LinkedList<>(); 

    public SnakePanel() { 
     // set background color 
     setBackground(BG); 

     // fill snake list with points 
     for (int i = 0; i < WORM_LENGTH; i++) { 
      snakePointList.add(new Point(point)); 
     } 

     // set key bindings 
     setKeyBindings(); 

     // create and start Timer 
     new Timer(TIMER_DELAY, new TimerListener()).start(); 
    } 

    // set up our key bindings 
    private void setKeyBindings() { 
     int condition = WHEN_IN_FOCUSED_WINDOW; 
     InputMap inputMap = getInputMap(condition); 
     ActionMap actionMap = getActionMap(); 

     KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0); 
     setKeyStroke(inputMap, actionMap, keyStroke, Direction.UP);   
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0); 
     setKeyStroke(inputMap, actionMap, keyStroke, Direction.DOWN); 
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0); 
     setKeyStroke(inputMap, actionMap, keyStroke, Direction.LEFT); 
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0); 
     setKeyStroke(inputMap, actionMap, keyStroke, Direction.RIGHT); 
    } 

    private void setKeyStroke(InputMap inputMap, ActionMap actionMap, KeyStroke keyStroke, 
      Direction dir) { 
     inputMap.put(keyStroke, keyStroke.toString()); 
     actionMap.put(keyStroke.toString(), new MyKeyAction(dir)); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     // smooth out our graphics 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

     // draw each oval in the Snake 
     for (Point pt : snakePointList) { 
      drawPoint(g2, pt); 
     } 
    } 

    private void drawPoint(Graphics2D g2, Point pt) { 
     g2.setColor(SNAKE_COLOR); 

     // The pt is actually the center point 
     // so we need to draw an oval that is centered on this point 
     int x = pt.x - SEGMENT_WIDTH/2; 
     int y = pt.y - SEGMENT_WIDTH/2; 
     g2.drawOval(x, y, SEGMENT_WIDTH, SEGMENT_WIDTH); 
    } 

    // set gui's size 
    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    // Action used by key binding 
    private class MyKeyAction extends AbstractAction { 
     private Direction dir; 

     public MyKeyAction(Direction dir) { 
      this.dir = dir; 
     } 

     public void actionPerformed(ActionEvent e) { 
      // all it does is set the Direction direction enum field 
      // for this GUI 
      // the Timer then uses this field 
      SnakePanel.this.direction = dir; 
     }; 
    } 

    // timer ActionListener 
    private class TimerListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      // create a new Point whose direction depends 
      // on the direction field * multiplier, DELTA 
      int x = point.x + direction.getX() * DELTA; 
      int y = point.y + direction.getY() * DELTA; 

      // create new point and add to snakePointList 
      point = new Point(x, y); 
      snakePointList.add(point); 
      // remove last point in list 
      snakePointList.remove(0); 
      repaint(); 
     } 
    } 

    // Direction enum 
    enum Direction { 
     UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0); 

     private Direction(int x, int y) { 
      this.x = x; 
      this.y = y; 
     } 
     private int x; 
     private int y; 

     public int getX() { 
      return x; 
     } 

     public int getY() { 
      return y; 
     } 
    } 

    private static void createAndShowGui() { 
     SnakePanel mainPanel = new SnakePanel(); 

     JFrame frame = new JFrame("SnakePanel"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 
+0

gut, da der Schlüssel Zuhörer das ändern Schlangenfelder, dann wird die Schlange im Timer neu gezeichnet, ich erwarte, dass der Timer die E/A des Haupthörers widerspiegelt. –

+0

@SompTingWong: Nun, da Ihr Timer das Feld zurück ändert, müssen Sie Ihre Erwartungen anpassen. Vielleicht solltest du den Status der Schlange nicht im Timer einstellen. –

+0

@SompTingWong: siehe Beispiel mit Tastenbelegung bitte –

Verwandte Themen