我正在制作蛇游戏,我希望一旦按下按键,我的蛇就会连续移动。所以,我按下向下键,即使释放按键也会继续移动。现在,它只是在键被按下时移动。
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();
}
}
&#34; mySegment [0]&#34;是蛇,而且是'南方&#34;或任何方向只是移动它直接5 <像素
答案 0 :(得分:0)
使用“游戏循环”来驱动动画。由于这看起来可能是Swing或AWT GUI,因此最好的办法是使用Swing Timer - 请查看tutorial。要点是在Timer的ActionListener中,您可以增加蛇的位置,根据按键状态改变方向。
我会使用枚举来指示方向{UP,DOWN,LEFT,RIGHT}:
public enum Direction {
UP,
DOWN,
LEFT,
RIGHT
}
然后使用Map<Direction, Boolean>
来指示前往哪个方向:
private Map<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
在其他地方,您将初始化Map以在所有值中保持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应用程序,我会使用Key Bindings而不是KeyListener来执行此操作。在监听器中,我然后在GUI上调用repaint()
。
在Swing Timer中,迭代Map,根据Map的状态设置方向。
类字段:
private int spriteX = 0; // location of sprite
private int spriteY = 0;
private int directionX = 0; // direction sprite is heading
private int directionY = 0;
在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();
例如(不是蛇而是一个球 - 我会把蛇留给你)
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;
}
}
答案 1 :(得分: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;
}
}
}
设置当前方向的方法。 (这假设有一个名为&#39; currentDirection&#39;的字段,其中包含表示当前方向的枚举(Direction)
public void setDirection(Direction newDirection)
{
if(currentDirection != newDirection.oposite())
currentDirection = newDirection;
}
这是游戏循环中的某个地方(计时器或包含“睡眠呼叫以防止CPU拥抱”的while循环)
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();
当然,而不是打电话给mySegment [0] .moveNorth();&#39;或者在keyEvents的actionHandlers中使用equitant,你应该只调用&#39; setDirection();&#39;使蛇移动。
我希望这能帮到你。