我正在开发一个类似于高峰时间/交通堵塞/阻塞益智游戏的Android游戏。板是一个正方形,包含长方形的部分。长的部分只能水平移动,高的部分只能垂直移动。目标是释放红色的部分,并将其从板上移出。这个游戏只是我在任何语言中的第二个编程项目,所以任何提示或最佳实践都将与您的回答一起感谢。
我有一个名为gives的游戏片段类,它描述了它们的大小和绘制到屏幕上的方式,提供了拖放功能,并检测和处理冲突。
然后,我有一个名为GameView的活动类,它创建我的布局,并创建要添加到名为RelativeLayout的RelativeLayout中的碎片对象。我已经考虑过让董事会成为它自己的班级,但还没有必要。
以下是我正在进行的工作:
我的问题:
除了我的碰撞处理之外,大部分的操作都很好。它似乎能很好地探测碰撞,但当发生碰撞时,它不会把碎片推到彼此的外面,而是疯狂地在物体被拖到的地方和它应该在的位置之间来回切换。看起来是这样的:
另一个奇怪之处是:当被拖动的物体与左边的一个物体发生碰撞时,碰撞处理似乎工作得很完美。只有上面、下面和右边的部分会引起问题。
以下是碰撞代码:
@Override
public boolean onTouchEvent(MotionEvent event){
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//check if touch is on piece
if (eventX > x && eventX < (x+width) && eventY > y && eventY < (y+height)){
initialX=x;
initialY=y;
break;
}else{
return false;
}
case MotionEvent.ACTION_MOVE:
//determine if piece should move horizontally or vertically
if(width>height){
for (Pieces piece : aPieces) {
//if object equals itself in array, skip to next object
if(piece==this){
continue;
}
//if next to another piece,
//do not allow to move any further towards said piece
if(eventX<x&&(x==piece.right+1)){
return false;
}else if(eventX>x&&(x==piece.x-width-1)){
return false;
}
//move normally if no collision
//if collision, do not allow to move through other piece
if(collides(this,piece)==false){
x = (eventX-(width/2));
}else if(collidesLeft(this,piece)){
x = piece.right+1;
break;
}else if(collidesRight(this,piece)){
x = piece.x-width-1;
break;
}
}
break;
}else if(height>width){
for (Pieces piece : aPieces) {
if(piece==this){
continue;
}else if(collides(this,piece)==false){
y = (eventY-(height/2));
}else if(collidesUp(this,piece)){
y = piece.bottom+1;
break;
}else if(collidesDown(this,piece)){
y = piece.y-height-1;
break;
}
}
}
invalidate();
break;
case MotionEvent.ACTION_UP:
// end move
if(this.moves()){
GameView.counter++;
}
initialX=x;
initialY=y;
break;
}
// parse puzzle
invalidate();
return true;
}
这是在onDraw期间发生的:
width = sizedBitmap.getWidth();
height = sizedBitmap.getHeight();
right = x+width;
bottom = y+height;
我的碰撞测试方法如下所示,每种方法都有不同的数学计算:
private boolean collidesDown(Pieces piece1, Pieces piece2){
float x1 = piece1.x;
float y1 = piece1.y;
float r1 = piece1.right;
float b1 = piece1.bottom;
float x2 = piece2.x;
float y2 = piece2.y;
float r2 = piece2.right;
float b2 = piece2.bottom;
if((y1<y2)&&(y1<b2)&&(b1>=y2)&&(b1<b2)&&((x1>=x2&&x1<=r2)||(r1>=x2&&x1<=r2))){
return true;
}else{
return false;
}
}
private boolean collides(Pieces piece1, Pieces piece2){
if(collidesLeft(piece1,piece2)){
return true;
}else if(collidesRight(piece1,piece2)){
return true;
}else if(collidesUp(piece1,piece2)){
return true;
}else if(collidesDown(piece1,piece2)){
return true;
}else{
return false;
}
}
作为第二个问题,我的x,y,对,底部,宽度,高度变量应该是整数,而不是像现在这样的浮点数吗?此外,任何关于如何更好地执行事情的建议都会受到极大的赞赏,即使与问题无关!提前感谢你的帮助,感谢你坐着回答这么长的问题!
更新:
下面的代码(这不包括垂直部分的代码)使它几乎完美地工作了:
@Override
public boolean onTouchEvent(MotionEvent event){
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//check if touch is on piece
if (eventX > x && eventX < (x+width) && eventY > y && eventY < (y+height)){
initialX=x;
initialY=y;
break;
}else{
return false;
}
case MotionEvent.ACTION_MOVE:
//determine if piece should move horizontally or vertically
if(width>height){
for (Pieces piece : aPieces) {
//if object equals itself in array, skip to next object
if(piece==this){
continue;
}
//check if there the possibility for a horizontal collision
if(this.isAllignedHorizontallyWith(piece)){
//check for and handle collisions while moving left
if(this.isRightOf(piece)){
if(eventX>piece.right+(width/2)){
x = (int)(eventX-(width/2)); //move normally
}else{
x = piece.right+1;
}
}
//check for and handle collisions while moving right
if(this.isLeftOf(piece)){
if(eventX<piece.x-(width/2)){
x = (int)(eventX-(width/2));
}else{
x = piece.x-width-1;
}
}
break;
}else{
x = (int)(eventX-(width/2));
}
这段代码的唯一问题是,它只检测移动部件与另一个(优先于左侧)之间的冲突。如果有一块在左边与另一块在右边碰撞,它只会检测到与左边的那块碰撞。我认为这是因为一旦它发现可能的碰撞,它处理它,而不完成循环通过数组保存所有的部分。如何让它同时检查多个可能的碰撞?
发布于 2011-03-13 22:12:01
我最好的猜测是,被拖的碎片被拖到另一块,然后移回来,这样它就不再碰撞,然后再被拖入另一块。至少这是我所期望的,如果在绘制之后会发生碰撞响应。
顺便提一下,下面的代码让我有点好奇:
//if next to another piece,
//do not allow to move any further towards said piece
if(eventX<x&&(x==piece.right+1)){
return false;
}else if(eventX>x&&(x==piece.x-width-1)){
return false;
}
在浮点数上检查等式(==
)通常是一个非常糟糕的主意,请参阅“浮点精度”主题。备选方案a)使用ints而不是浮点数。( b)使用范围比较法(>=
等)。但是,不要使用(a),微小的(时间)步骤有很多缺点。
尝试使用与触摸检测相同的方法:
//check if touch is on piece
if (eventX > x && eventX < (x+width) && eventY > y && eventY < (y+height))
发布于 2011-03-14 14:46:48
您应该能够更简单地做到这一点:)
注意,我对你如何存储运动方向做了一些假设,你可能需要根据你的喜好进行调整。
还请注意,我将piece1视为我们所关注的移动部件,而piece2则简单地将其视为与其碰撞的对象。所以piece1被重新定位,piece2没有。
// Horizontal:
if( piece1.isMovingLeft )
piece1.x += Math.max( 0, piece2.right - piece1.x );
else if( piece1.isMovingRight )
piece1.x -= Math.max( 0, piece1.right - piece2.x );
// Vertical:
if( piece1.isMovingUp )
piece1.y -= Math.max( 0, piece2.bottom - piece1.y );
else if( piece1.isMovingDown )
piece1.y += Math.max( 0, piece1.bottom - piece2.y )
我在此所做的工作如下:
。
你可以将这个简单的例程应用于每一个可能的两块组合,它们将不再穿透。
希望这能帮到你!
发布于 2011-03-16 11:51:22
在回答你的第二个问题时:
这段代码的唯一问题是它只检测到移动的部分和另一个之间的冲突(优先于左边的一个)。如果有一块在左边与另一块在右边碰撞,它只会检测到与左边的那块碰撞。
循环中有一个中断语句--特别是在左碰撞检查中。;)
https://stackoverflow.com/questions/5292323
复制相似问题