Pacman java 移动问题
Posted
技术标签:
【中文标题】Pacman java 移动问题【英文标题】:Pacman java movement issues 【发布时间】:2015-03-31 05:46:14 【问题描述】:我现在正在做的 pacman 运动遇到了一个小问题。
我似乎无法找到一种方法使该运动类似于起源的 pacman 运动。为了解释我希望它如何移动,我上传了这张图片。
就目前而言,我已经在黄色矩形和蓝色墙壁之间进行了碰撞。问题是当我如图所示向左移动并单击向上箭头时,它不应停止,而是继续移动,然后在有空闲空间时向上移动。
现在,如果您像这样单击向上箭头,黄色矩形将停止:
已上传包含我的动作的 pacman 类,以及检测到碰撞时我的板类中的代码。
pacman 类
public class Pacman
private String pacmanup = "pacmanup.png";
private String pacmandown = "pacmandown.png";
private String pacmanleft = "pacmanleft.png";
private String pacmanright = "pacmanright.png";
private int dx;
private int dy;
private int x;
private int y;
private int width;
private int height;
private boolean visible;
private Image imageup;
private Image imagedown;
private Image imageleft;
private Image imageright;
public Pacman()
Thread thread = new Thread();
thread.start();
ImageIcon i1 = new ImageIcon(this.getClass().getResource(pacmanup));
imageup = i1.getImage();
ImageIcon i2 = new ImageIcon(this.getClass().getResource(pacmandown));
imagedown = i2.getImage();
ImageIcon i3 = new ImageIcon(this.getClass().getResource(pacmanleft));
imageleft = i3.getImage();
ImageIcon i4 = new ImageIcon(this.getClass().getResource(pacmanright));
imageright = i4.getImage();
width = imageup.getWidth(null);
height = imageup.getHeight(null);
visible = true;
x = 27;
y = 27;
public int getDx()
return dx;
public void setDx(int dx)
this.dx = dx;
public int getDy()
return dy;
public void setDy(int dy)
this.dy = dy;
public int getX()
return x;
public int getY()
return y;
public void setX(int x)
this.x = x;
public void setY(int y)
this.y = y;
public Image getImageup()
return imageup;
public Image getImagedown()
return imagedown;
public Image getImageleft()
return imageleft;
public Image getImageright()
return imageright;
public void setVisible(boolean visible)
this.visible = visible;
public boolean isVisible()
return visible;
public Rectangle getBounds()
return new Rectangle(x, y, width, height);
public Rectangle getOffsetBounds()
return new Rectangle(x + dx, y + dy, width, height);
public void move()
x += dx;
y += dy;
public void keyPressed(KeyEvent e)
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
dx = -1;
dy = 0;
if (key == KeyEvent.VK_RIGHT)
dx = 1;
dy = 0;
if (key == KeyEvent.VK_UP)
dx = 0;
dy = -1;
if (key == KeyEvent.VK_DOWN)
dx = 0;
dy = 1;
public void keyReleased(KeyEvent e)
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
if (key == KeyEvent.VK_RIGHT)
if (key == KeyEvent.VK_UP)
if (key == KeyEvent.VK_DOWN)
Board 类的代码
Rectangle r5 = pacman.getOffsetBounds();
for (int j = 0; j<barriers.size(); j++)
Barrier b = (Barrier) barriers.get(j);
Rectangle r4 = b.getBounds();
if (r5.intersects(r4))
pacman.setDx(0);
pacman.setDy(0);
break;
pacman.move();
在我的棋盘类中创建了一个名为 direction 的字符串,用于检测黄色矩形的移动方向。
“左”“上”“右”或“下”
已经尝试过编写一些代码,但无法正常工作。这是我尝试过的:
// moving to the left and tried go up
else if (pacman.getDx() == 0 && pacman.getDy() == -1 && direction.equals("left"))
pacman.setDy(0);
pacman.setDx(-1);
break;
好吧,当它向左移动并且你点击向上时,它会继续向左移动,但它不会像它应该做的那样上升到可用空间:)
是keydapter / 按键的问题吗?也许当你点击时按下的键没有激活或什么?
【问题讨论】:
我会避免KeyListener
支持键绑定。 How to Use Key Bindings。但是,我们检测到按键,您需要确定玩家可以朝那个方向移动,并且只在可以的情况下更新移动增量,如果不能,则保持增量不变
如果您添加一些逻辑来检查向上移动是否真的发生(碰撞 == false)而不是立即递减 dY,该怎么办?
【参考方案1】:
在我看来你有两个问题。
(问题 1)
如果您希望 pacman 继续移动,请不断更改 dx or dy
的值,直到按下另一个键。无论如何,经典的吃豆人就是这样工作的。它总是一直在移动/试图继续朝着最后一个keypressed
的方向移动。 (亲自在这里查看游戏机制 - https://www.google.com/doodles/30th-anniversary-of-pac-man)
(问题 2)
如果您不尝试实现经典 pacman(从您尝试执行的操作来看,您看起来不像是在实现经典 pacman),并且如果您想稍微改变控件的工作方式,就像根据按键历史智能切换方向,考虑存储按键。问题是您要跟踪多少个按键方向?
假设您只想跟踪两个按键,您需要有一个大小为 2 的 array
,它在任何时候都只能存储两个 key:value
对。 key 将是 direction 而 value 将是 如果你可以在那个方向上移动而不是(即 @987654326 @true
或 false
)。
您可以通过以下方式使用array
来解决您的问题:
按下方向键时,将其设置为array[0].key
,并检查您是否可以朝该方向移动。如果可以,将array[0].value
的值设置为true
并使用该值查看是否需要通过检查array[0].key
和array[0].value
在另一个函数中更改dx
或dy
变量的值状态来决定你是否可以朝那个方向移动。实际move
函数的细节将在后面解释。您已经实现了基本的move
方法,这很好,您只需要添加一些条件并稍作修改即可。
现在,当按下第二个键(如up key
)时,请执行以下操作:
-
设置
temp = array[0]
设置array[0].key = 'up'
设置array[1].value
= 检查是否可以朝array[0].key
的方向移动,如果可以设置为true,如果不能设置为false。
设置array[1] = temp
并检查array[1].value
是true
还是false
请注意,您已将最早的按键操作移至 array[1]
,并将最新按键操作移至 array[0]
。
此时,设置一个约定,您将始终首先尝试向array[0]
的方向移动,因为它存储了最新按下的键的方向值,然后您才会尝试向array[1]
移动.
通过将array[0]
和array[1]
的布尔值设置为array[0].value
和array[1].value
来检查您是否可以向它们的方向移动后,您现在知道可以移动的位置并准备实际移动:
所以在你的移动方法中,执行以下操作,if(array[0].value==true)
然后:
-
向
array[0]
的方向移动并忽略array[1]
(即在使用循环实现移动逻辑的情况下中断)
else if(array[1].value == true)
:
向array[1]
的方向移动
一旦您的 move()
函数返回,并且您处于新的 (x,y) 处,请返回第一步并重新开始。
希望您需要执行的步骤很明确。
【讨论】:
以上是关于Pacman java 移动问题的主要内容,如果未能解决你的问题,请参考以下文章
将 jLabel 移动到 jPanel 中的不同位置(类似 Pacman 的游戏)