在2-d的iPhone游戏瓷砖的碰撞检测问题
-
19-09-2019 - |
题
<强> SETUP:强>结果 我工作的一个2-d瓷砖的游戏(鸟瞰)的iPhone。该应用程序在一个区块的d(.tbx)tilemap的与真或假的“阻塞”属性瓦片的文件读取表示的主人公是否可以通过瓷砖移动。我迭代在图中的每个瓦片与创建表示瓷砖行列数以保持每瓦片的阻挡属性(真/假)的2维C数组。当我全线移动的英雄,我检查了英雄的立场与阵列,看他感动的瓷砖被堵塞。如果受阻,英雄的位置由尽可能多的逆转,因为它是先进的。
<强> PROB:强>结果 问题是,当一个英雄在阻止瓷砖台阶,他不能动它了。瓷砖位置是在封闭检测瓷砖,他们应该是英雄,但被卡住仍然感觉是正确的。英雄“由像素”而不是“由瓦片”前进。这就是全部。唯一剩下的就是显示的代码:(英雄是28个像素由在尺寸为36个像素)
//Code from GameScreen.m
-(void)generateCollisionMap
{
for(int layer=0; layer < 2; layer++) {
for(int yy=0; yy < _screenTilesHeight; yy++) {
NSLog(@"Row %i", yy);
for(int xx=0; xx < _screenTilesWide; xx++) {
int _globalTileID = [[[tileMap layers] objectAtIndex:layer] getGlobalTileIDAtX:xx y:yy];
NSString *_value = [tileMap getTilePropertyForGlobalTileID:_globalTileID key:@"blocked" defaultValue:@"false"];
if([_value isEqualToString:@"true"]) {
_blocked[xx][yy] = YES;
NSLog(@"Cell %i = YES", xx);
}else{
if(_blocked[xx][yy] == YES){
NSLog(@"Leaving Cell %i as = YES", xx);
//Leave As Is
}else{
_blocked[xx][yy] = NO;
NSLog(@"Cell %i = NO", xx);
}
}
}
}
}
}
//Code from Hero.m
-(void)moveHero
{
// Up
if(moveDirection == 1 && !doesNeedShiftWorld) {
heroY += _playerSpeed;
[self checkBlocked:1];
_currentAnimation = _upAnimation;
_moving = YES;
}
// Down
if(moveDirection == 2 && !doesNeedShiftWorld) {
heroY -= _playerSpeed;
[self checkBlocked:2];
_currentAnimation = _downAnimation;
_moving = YES;
}
// Left
if(moveDirection == 3 && !doesNeedShiftWorld) {
heroX -= _playerSpeed;
[self checkBlocked:3];
_currentAnimation = _leftAnimation;
_moving = YES;
}
// Right
if(moveDirection == 4 && !doesNeedShiftWorld) {
heroX += _playerSpeed;
[self checkBlocked:4];
_currentAnimation = _rightAnimation;
_moving = YES;
}
}
// ...
- (void) checkBlocked:(int)checkDirection
{
float xx = (heroX+160.0f+_tileWidth) / _tileWidth;
float yy = 11-((heroY+300.0f+_tileHeight) / _tileHeight);
switch (checkDirection) {
case 1:
yy -= 1;
if([_scene isBlocked:xx y:yy] ||
[_scene isBlocked:(heroX+160.0f) y:yy]) {
NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
heroY -= _playerSpeed;
}else{
NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);
}
break;
case 2:
if([_scene isBlocked:xx y:yy] ||
[_scene isBlocked:xx y:(heroY+300.0f)] ||
[_scene isBlocked:(heroX+160.0f) y:(heroY+300.0f)]) {
NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
heroY += _playerSpeed;
}else{
NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);
}
break;
case 3:
xx += 1;
if([_scene isBlocked:xx y:yy] ||
[_scene isBlocked:(heroX+160.0f) y:yy] ||
[_scene isBlocked:(heroX+160.0f) y:(heroY+300.0f)]) {
NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
heroX += _playerSpeed;
}else{
NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);
}
break;
case 4:
if([_scene isBlocked:xx y:yy] ||
[_scene isBlocked:xx y:(heroY+300.0f)]) {
NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
heroX -= _playerSpeed;
}else{
NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);
}
break;
}
}
解决方案
您的问题是,你的移动播放器,然后的检查,看他是否移动的空间被封锁。相反,你要弄清楚,他将要移动到,看它是否堵塞,然后只动他,如果它不阻塞的位置。此外,您还可以在条款中随时添加排除他目前的空间。即只要你的性格是不会改变网格空间,他可以的总是的举动,但一旦他即将改变网格空间,你应该检查,看他是否会与某物相撞。
下面低于您的代码:
if(moveDirection == 1 && !doesNeedShiftWorld) {
heroY += _playerSpeed;
[self checkBlocked:1];
_currentAnimation = _upAnimation;
_moving = YES;
}
它应该是这样的:
if(moveDirection == 1 && !doesNeedShiftWorld)
{
//Figure out if the player is changing grid spaces.
BOOL isChangingSpaces = ((int)((heroY + _playerSpeed) / myGridSizeVariable) != (int)(heroY / myGridSizeVariable));
//The player should be able to move either if he isn't
//changing grid spaces or if his destination space is free.
if ( !isChangingSpaces || (spaceIsOpenAtX:heroX andY:heroY+_playerSpeed) )
{
heroY += _playerSpeed;
_currentAnimation = _upAnimation;
_moving = YES;
}
}
和你真的应该尽量使你的代码的多的更多的面向对象的。在这一点上,这似乎是完全程序和所有的变量是全局,这肯定不是一个很好的路要走。 “checkBlocked”应该被改写为“spaceIsOpenAtX:安迪:”因为那样的话,你可以把任何的X和Y坐标,你为了想看看那个位置被阻止。正如你现在已经做到了,你的代码是过于抽象(绕过整数,没有指示他们的的意思是比你的实际的其他if语句检查),并不能适用于任何任何情况下除了单独使用,你给了它。
真的,你应该已经player.speed和player.animation和[迷宫spaceIsOpen],您使用的Objective-C,不只是C.而且,即使你用C这将是一个更好的主意,这样做等。它在OO方式。
其他提示
我认为这个问题是你让玩家移动到阻塞瓷砖和他卡住。
我会检查,查看是否播放器的移动方向正试图那里移动玩家之前阻止。