SETUP:
我正在为iPhone开发基于2-D平铺的游戏(鸟瞰图)。该应用程序读取tile-tile(.tbx)tilemap文件,其tile为'blocked'属性,为true或false,表示英雄是否可以在tile中移动。我遍历地图中的每个图块并创建一个表示图块行和列的二维C数组,以保存每个图块的阻止属性(true / false)。当我将英雄移动到整个棋盘时,我用阵列检查英雄的位置,看看他移动的牌是否被阻挡。如果被阻挡,英雄的位置会被提前反转。
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;
}
}
答案 0 :(得分:4)
你的问题是你正在移动播放器,然后检查他移动的空间是否被阻止。相反,你想要找出他想要移动的位置,看看它是否被阻挡,然后只有在没有被阻挡的情况下才移动他。此外,您始终可以添加一个子句来排除其当前空间。即只要你的角色没有改变网格空间,他就可以总是移动,但是一旦他即将改变网格空间,你应该检查他是否会碰到某些东西。
以下是您的代码:
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:andY:”,因为这样你就可以将任何X和Y坐标放在你想要的位置,以便查看该位置是否被阻止。正如你现在所做的那样,你的代码太抽象了(传递整数而没有表明他们意味着什么除了你的实际if语句检查之外)并且它不能适用于任何情况。除了你一次性使用它。
真的,你应该有player.speed和player.animation以及[迷宫spaceIsOpen]等等。你使用的是Objective-C,而不仅仅是C.即使你使用的是C,这样做也是一个更好的主意。它以OO的方式。
答案 1 :(得分:0)
我认为问题在于你允许玩家移动到被阻挡的瓷砖上并且卡住了。
在尝试将玩家移动到那里之前,我会检查玩家移动的方向是否被阻挡。