2016-12-01 5 views
0

Ich mache ein Schlangenspiel, und ich möchte, dass sich meine Schlange kontinuierlich bewegt, sobald eine Taste gedrückt wird. Also, ich drücke die Abwärtstaste und es bewegt sich weiter, auch wenn die Taste losgelassen wird. Im Moment bewegt es sich nur, während die Taste gedrückt gehalten wird.Wie bewahre ich ein Objekt mit den Pfeiltasten?

public void keyPressed(KeyEvent e) { 
     if (e.getKeyCode() == KeyEvent.VK_DOWN) { 
      mySegment[0].moveSouth(); 
      repaint(); 
     } 
    else if (e.getKeyCode() == KeyEvent.VK_UP) { 
     mySegment[0].moveNorth(); 
     repaint(); 
    } 
    else if(e.getKeyCode() == KeyEvent.VK_LEFT){ 
     mySegment[0].moveWest(); 
     repaint(); 
    } 
    else if (e.getKeyCode() == KeyEvent.VK_RIGHT){ 
     mySegment[0].moveEast(); 
     repaint(); 
    } 

    for (int a = 0; a < 10; a++) { 
     if (myFruit[a].distance (mySegment[0].getX(), mySegment[0].getY())     
     <= 20) { 
      myFruit[a].hide(); 
     } 
    } 

Die "mySegment [0]" ist die Schlange, und der "moveSouth" oder welche Richtung auch immer bewegt er nur 5 Pixel in dieser DirectIn

+0

Lassen Sie es eine Methode aufrufen, die die Bewegung so lange wiederholt, bis sie unterbrochen wird. – DejaVuSansMono

Antwort

0

Verwendung ein "Spiel Schleife" um die Animation zu steuern. Da dies möglicherweise eine Swing- oder AWT-GUI ist, ist es am besten, einen Swing-Timer zu verwenden - bitte werfen Sie einen Blick auf die tutorial. Das Wichtigste ist, dass Sie innerhalb des ActionListener des Timers die Position der Schlange erhöhen, indem Sie je nach dem Zustand Ihres Tastendrucks ihre Richtung ändern.

ich eine Enumeration verwenden würde Richtung anzuzeigen {oben, unten, links, rechts}:

public enum Direction { 
    UP, 
    DOWN, 
    LEFT, 
    RIGHT 
} 

UND ein dann Map<Direction, Boolean>, um anzuzeigen, in welche Richtung zu gehen:

private Map<Direction, Boolean> dirMap = new EnumMap<>(Direction.class); 

An anderer Stelle würden Sie initialisiere die Karte, um in allen Werten den Wert false zu halten:

// initialize the map to all false 
for (Direction dir : Direction.values()) { 
    dirMap.put(dir, false); 
} 

Dann ändere den Zustand von die Elemente in der Karte in Ihrem Code zum Abhören von Tasten drücken und Freigaben - Anruf map.put(Direction.UP, true) zum Beispiel, wenn die Aufwärts-Taste gedrückt wird, und ebenso map.put(Direction.UP, false), wenn es freigegeben wurde, gleich für die anderen Schlüssel. Beachten Sie, dass wenn Sie eine Swing-Anwendung verwenden, ich Key Bindings und keinen KeyListener dafür verwenden würde. Im Listener würde ich dann repaint() auf der GUI anrufen.

Innerhalb des Swing-Timers durchlaufen Sie die Karte und legen die Richtung basierend auf dem Status der Karte fest.

Klassenfelder:

private int spriteX = 0; // location of sprite 
private int spriteY = 0; 

private int directionX = 0; // direction sprite is heading 
private int directionY = 0; 

Im Action

// within the Swing Timer's ActionListener 
if (dirMap.get(Direction.UP)) { 
    directionY -= 1; 
} 
if (dirMap.get(Direction.DOWN)) { 
    directionY += 1; 
} 
if (dirMap.get(Direction.RIGHT)) { 
    directionX += 1; 
} 
if (dirMap.get(Direction.LEFT)) { 
    directionY -= 1; 
} 

// here multiply directionX and directionY by some scale factor and use to place new snake head 
// then call repaint(); 

Zum Beispiel (nicht eine Schlange, sondern ein Ball - Ich werde die Schlange auf Sie verlassen)

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.util.EnumMap; 
import java.util.Map; 
import java.util.Map.Entry; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class DirTest extends JPanel { 
    private static final int PREF_W = 800; 
    private static final int PREF_H = PREF_W; 
    private static final int TIMER_DELAY = 40; 
    private static final Color SPRITE_COLOR = Color.RED; 
    private static final int SPRITE_W = 20; 
    private static final Color BG = Color.BLACK; 
    public static final int SCALE = 1; 
    private Map<Direction, Boolean> dirMap = new EnumMap<>(Direction.class); 
    private int spriteX = 0; 
    private int spriteY = 0; 
    private int directionX = 0; 
    private int directionY = 0; 
    private Timer gameLoopTimer = new Timer(TIMER_DELAY, new TimerListener()); 

    public DirTest() { 
     setKeyBindings(); 

     setBackground(BG); 
     // initialize map to all 0; 
     for (Direction dir : Direction.values()) { 
      dirMap.put(dir, false); 
     } 

     gameLoopTimer.start(); 
    } 

    private void setKeyBindings() { 
     int condition = WHEN_IN_FOCUSED_WINDOW; // bind to keys if component in active window 
     InputMap inputMap = getInputMap(condition); 
     ActionMap actionMap = getActionMap(); 

     setKeyBinding(inputMap, actionMap, KeyEvent.VK_UP, Direction.UP); 
     setKeyBinding(inputMap, actionMap, KeyEvent.VK_DOWN, Direction.DOWN); 
     setKeyBinding(inputMap, actionMap, KeyEvent.VK_LEFT, Direction.LEFT); 
     setKeyBinding(inputMap, actionMap, KeyEvent.VK_RIGHT, Direction.RIGHT); 
    } 

    private void setKeyBinding(InputMap inputMap, ActionMap actionMap, int keyCode, Direction dir) { 
     KeyStroke press = KeyStroke.getKeyStroke(keyCode, 0, false); 
     KeyStroke released = KeyStroke.getKeyStroke(keyCode, 0, true); 

     Action pressAction = new PressedAction(dir, true); 
     Action releasedAction = new PressedAction(dir, false); 

     inputMap.put(press, press.toString()); 
     inputMap.put(released, released.toString()); 

     actionMap.put(press.toString(), pressAction); 
     actionMap.put(released.toString(), releasedAction); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setColor(SPRITE_COLOR); 
     g2.fillOval(spriteX, spriteY, SPRITE_W, SPRITE_W); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class PressedAction extends AbstractAction { 
     private boolean pressed; 
     private Direction dir; 

     public PressedAction(Direction dir, boolean pressed) { 
      this.dir = dir; 
      this.pressed = pressed; 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      dirMap.put(dir, pressed); 
     } 
    } 

    private class TimerListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      for (Entry<Direction, Boolean> entry : dirMap.entrySet()) { 
       if (entry.getValue()) { 
        directionX += entry.getKey().getX(); 
        directionY += entry.getKey().getY(); 
       } 
      } 

      spriteX += SCALE * directionX; 
      spriteY += SCALE * directionY; 

      repaint(); 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("DirTest"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new DirTest()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

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

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

    private int x; 
    private int y; 

    private Direction(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 
    public int getX() { 
     return x; 
    } 
    public int getY() { 
     return y; 
    } 

} 
+0

Auf diese Weise muss das OP sicherstellen, dass nur ein Wert in der HashMap auf 'true' gesetzt ist, sonst kann es ziemlich seltsam wirken. Ich würde für ein einzelnes Feld wählen, in dem Sie die gegenwärtige Richtung einstellen/überprüfen. Außerdem könnte eine EnumHasMap eine bessere Wahl für die Verwendung einer Map-Implementierung mit Enums sein. – n247s

+0

Auch der OP sucht nach einem Weg, auf dem sich die Schlange bewegt, auch wenn der Schlüssel losgelassen wurde. Vielleicht modifiziere das Setup ein wenig. Ab sofort wird dies zu dem gleichen Ergebnis führen, wie das OP derzeit hat – n247s

+0

@ n247s: Bitte schauen Sie sich Code an und führen Sie ihn aus. Dies führt zu fortgesetzter Bewegung, selbst wenn die Taste losgelassen wird. Wenn die Taste gedrückt gehalten wird, wird die Bewegung schneller. Versuch es. –

0

Wenn du die Schlange in Bewegung halten willst, brauchst du eine Art Game-Loop (wie bereits erwähnt). Der einfachste Weg ist ein einzelnes Feld, das die aktuelle Richtung enthält, und es basierend auf der Eingabe festzulegen. So sind hier ein paar Methoden/Klassen, die Sie in die richtige Richtung/Position

einstellen

Die Richtung Enum

public enum Direction 
{ 
    NORTH, EAST, SOUTH, WEST; 

    public Direction oposite() 
    { 
     switch(this) 
     { 
      case NORTH: return SOUTH; 
      case SOUTH: return NORTH; 
      case EAST: return WEST; 
      case WEST: return EAST; 
      } 
    } 
} 

Das Verfahren zur Einstellung der Stromrichtung nutzen könnten.(Dies setzt voraus, gibt es ein Feld ‚currentDirection‘ genannt, der eine ENUM enthält (Richtung) die Stromrichtung darstellt)

public void setDirection(Direction newDirection) 
{ 
     if(currentDirection != newDirection.oposite()) 
      currentDirection = newDirection; 
} 

Dies ist irgendwo in der Spielschleife (entweder ein Zeitgeber oder eine while-Schleife einschließlich einem ‚Schlaf 'rufen CPU umarmen zu verhindern)

 switch(currentDirection) 
    { 
      case NORTH: mySegment[0].moveNorth(); break; 
      case EAST: mySegment[0].moveEast(); break; 
      case SOUTH: mySegment[0].moveSouth(); break; 
      case WEST: mySegment[0].moveWest(); break; 
    } 
    repaint(); 

Und natürlich statt des Aufrufs 'mySegment [0] .moveNorth();' oder etwas, das in den actionHandlers für die keyEvents gleich ist, sollten Sie nur 'setDirection();' um die Schlange bewegen zu lassen.

Ich hoffe, das hat dir geholfen.

Verwandte Themen