2016-12-01 14 views
0

私は蛇のゲームを作っています。キーを押すと、蛇が連続的に動くようにしたいと思います。だから、私はダウンキーを押して、キーが離されても動き続けます。今は、キーが押されている間に動きます。矢印キーを使用してオブジェクトを移動し続けるにはどうすればよいですか?

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(); 
     } 
    } 

「mySegment [0]」蛇であり、そして「moveSouth」または任意の方向だけではdirectinに5つの画素

+0

中断されるまで動きをループするメソッドを呼び出しましたか? – DejaVuSansMono

答えて

0

アニメーションを駆動するための「ゲームループ」を使用し、それを移動させます。これはおそらくSwingまたはAWT GUIに見えるので、スイングタイマーを使用するのが最善の方法です - tutorialをご覧ください。要点は、TimerのActionListener内で、ヘビの位置をインクリメントし、キーの押下の状態に応じて方向を変更することです。

私は{RIGHT、UP、DOWN LEFT}の方向性を示すために、列挙型を使用します。

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

、その後Map<Direction, Boolean>頭にどの方向を示すために、:

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

ますでしょうマップを初期化してすべての値がfalseになるようにします。

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

コード内のキープレスとリリースのリッスンのためのマップ内の項目は、たとえば上キーが押されたときにmap.put(Direction.UP, true)と呼び出し、同様に解放されたときはmap.put(Direction.UP, false)と呼びます。他のキーと同じです。あなたのアプリケーションがSwingアプリケーションの場合は、KeyBindingsを使用し、KeyListenerは使用しません。リスナーでは、GUI上でrepaint()と呼ぶことにします。

スイングタイマー内で、マップを繰り返して、マップの状態に基づいて方向を設定します。

クラスフィールド:ActionListenerの例

// 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(); 

以内

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

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

(ないヘビしかし、ボール - 私はあなたに蛇を残しておきます)

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

このようにして、OPはHashMap内の1つの値だけが 'true'に設定されていることを確認する必要があります。そうでなければ、かなり動作します。現在の方向を設定/確認する単一のフィールドを選択します。 EnumHasMapは、enumを使用してMap実装を使用するときは、より良い選択となる場合があります。 – n247s

+0

また、OPは、キーが離されたとしても、ヘビが動いている場所を探しています。ですから、設定をリットルビットに変更してください。今のところ、これはOPが現在 – n247s

+0

@ n247sと同じ結果を生み出します:コードを見て実行してください。これにより、キーが離されても継続的な動きが発生します。さらに、キーが押されていると、動きがより速くなります。それを試してみてください。 –

0

ヘビの動きを維持したい場合は、(前に述べたように)何らかのゲームループが必要です。最も簡単な方法は、現在の方向を含む単一のフィールドを持ち、それを入力に基づいて設定することです。だからここにあなたが正しい方向/位置

方向列挙

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; 
      } 
    } 
} 

電流方向を設定するための方法を設定するために使用することができますいくつかのメソッド/クラスです。

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

これはあなたのゲームループのどこかにある(タイマー、あるいは「睡眠を含むwhileループのいずれか(これは、現在の方向を表す列挙型(方向)に含まれている「currentDirection」という名前のフィールドがあると仮定し) mySegment [0] .moveNorth() '

 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(); 

そしてもちろんの代わりに呼び出すの)CPUのハグを防ぐために呼び出します ';' keyEventsのactionHandler内でequalivantを使用している場合は、 'setDirection();'ヘビを動かす。

これがあなたを助けてくれることを願っています。

関連する問題