Ios 当我点击屏幕左侧时,炮塔以错误的方式开火

Ios 当我点击屏幕左侧时,炮塔以错误的方式开火,ios,cocos2d-iphone,Ios,Cocos2d Iphone,我对这一切都很陌生,所以如果这是一个非常无知的问题,我道歉。我正试图制造一个旋转的炮塔,面对水龙头,朝那个方向开火。在Ray Wenderlich的旋转炮塔教程中找到了一些代码,我将炮塔移动到屏幕的底部中心,并将炮弹的起点重新定位到同一点。这个位置更类似于老式的导弹指挥风格的游戏 不幸的是,现在当我点击屏幕右侧时,武器可以正确地发射,但当我点击左侧时,它会在屏幕外向下和向右发射,就像它不知怎么地翻转了命令一样。有人能帮我把这件事弄清楚吗?是否有另一种编码方法,这样我就不会出现左触发问题,或者我是

我对这一切都很陌生,所以如果这是一个非常无知的问题,我道歉。我正试图制造一个旋转的炮塔,面对水龙头,朝那个方向开火。在Ray Wenderlich的旋转炮塔教程中找到了一些代码,我将炮塔移动到屏幕的底部中心,并将炮弹的起点重新定位到同一点。这个位置更类似于老式的导弹指挥风格的游戏

不幸的是,现在当我点击屏幕右侧时,武器可以正确地发射,但当我点击左侧时,它会在屏幕外向下和向右发射,就像它不知怎么地翻转了命令一样。有人能帮我把这件事弄清楚吗?是否有另一种编码方法,这样我就不会出现左触发问题,或者我是否需要输入一些额外的内容来转换坐标,以便正确地注册抽头

// Import the interfaces
#import "HelloWorldLayer.h"
#import "SimpleAudioEngine.h"
#import "GameOverLayer.h"
#import "Monster.h"
#import "LevelManager.h"

// Needed to obtain the Navigation Controller
#import "AppDelegate.h"

#pragma mark - HelloWorldLayer

// HelloWorldLayer implementation
@implementation HelloWorldLayer

// Helper class method that creates a Scene with the HelloWorldLayer as the only child.
+(CCScene *) scene
{
    // 'scene' is an autorelease object.
    CCScene *scene = [CCScene node];

    // 'layer' is an autorelease object.
    HelloWorldLayer *layer = [HelloWorldLayer node];

    // add layer as a child to scene
    [scene addChild: layer];

// return the scene
return scene;
}

- (void) addMonster {

    //CCSprite * monster = [CCSprite spriteWithFile:@"monster.png"];
    Monster * monster = nil;
    if (arc4random() % 2 == 0) {
        monster = [[[WeakAndFastMonster alloc] init] autorelease];
    } else {
        monster = [[[StrongAndSlowMonster alloc] init] autorelease];
    }

    // Determine where to spawn the monster along the Y axis
    CGSize winSize = [CCDirector sharedDirector].winSize;
    int minY = monster.contentSize.height / 2;
    int maxY = winSize.height - monster.contentSize.height/2;
    int rangeY = maxY - minY;
    int actualY = (arc4random() % rangeY) + minY;

    // Create the monster slightly off-screen along the right edge,
    // and along a random position along the Y axis as calculated above
    monster.position = ccp(winSize.width + monster.contentSize.width/2, actualY);
    [self addChild:monster];

    // Determine speed of the monster
    int minDuration = monster.minMoveDuration; //2.0;
    int maxDuration = monster.maxMoveDuration; //4.0;
    int rangeDuration = maxDuration - minDuration;
    int actualDuration = (arc4random() % rangeDuration) + minDuration;

    // Create the actions
    CCMoveTo * actionMove = [CCMoveTo actionWithDuration:actualDuration position:ccp(-monster.contentSize.width/2, actualY)];
    CCCallBlockN * actionMoveDone = [CCCallBlockN actionWithBlock:^(CCNode *node) {
        [_monsters removeObject:node];
        [node removeFromParentAndCleanup:YES];

        CCScene *gameOverScene = [GameOverLayer sceneWithWon:NO];
        [[CCDirector sharedDirector] replaceScene:gameOverScene];
    }];
    [monster runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];

    monster.tag = 1;
    [_monsters addObject:monster];

}

-(void)gameLogic:(ccTime)dt {
    [self addMonster];
}

- (id) init
{
    if ((self = [super initWithColor:[LevelManager sharedInstance].curLevel.backgroundColor])) {

        CGSize winSize = [CCDirector sharedDirector].winSize;
        _player = [CCSprite spriteWithFile:@"player2.png"];
        _player.position = ccp(winSize.width/2, 20);
        [self addChild:_player];

        [self schedule:@selector(gameLogic:) interval:[LevelManager sharedInstance].curLevel.secsPerSpawn];

        [self setTouchEnabled:YES];

        _monsters = [[NSMutableArray alloc] init];
        _projectiles = [[NSMutableArray alloc] init];

        [self schedule:@selector(update:)];

        [[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"background-music-aac.caf"];

    }
    return self;
}

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    if (_nextProjectile != nil) return;

    // Choose one of the touches to work with
    UITouch *touch = [touches anyObject];
    CGPoint location = [self convertTouchToNodeSpace:touch];

    // Set up initial location of projectile
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    _nextProjectile = [[CCSprite spriteWithFile:@"projectile2.png"] retain];
    _nextProjectile.position = ccp(winSize.width/2, 20);

    // Determine offset of location to projectile
    CGPoint offset = ccpSub(location, _nextProjectile.position);

    // Bail out if you are shooting down or backwards
    //if (offset.x <= 0) return;

    // Determine where you wish to shoot the projectile to
    int realX = winSize.width + (_nextProjectile.contentSize.width/2);
    float ratio = (float) offset.y / (float) offset.x;
    int realY = (realX * ratio) + _nextProjectile.position.y;
    CGPoint realDest = ccp(realX, realY);

    // Determine the length of how far you're shooting
    int offRealX = realX - _nextProjectile.position.x;
    int offRealY = realY - _nextProjectile.position.y;
    float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
    float velocity = 480/1; // 480pixels/1sec
    float realMoveDuration = length/velocity;

    // Determine angle to face
    float angleRadians = atanf((float)offRealY / (float)offRealX);
    float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
    float cocosAngle = -1 * angleDegrees;
    float rotateDegreesPerSecond = 180 / 0.5; // Would take 0.5 seconds to rotate 180 degrees, or half a circle
    float degreesDiff = _player.rotation - cocosAngle;
    float rotateDuration = fabs(degreesDiff / rotateDegreesPerSecond);
    [_player runAction:
     [CCSequence actions:
      [CCRotateTo actionWithDuration:rotateDuration angle:cocosAngle],
      [CCCallBlock actionWithBlock:^{
         // OK to add now - rotation is finished!
         [self addChild:_nextProjectile];
         [_projectiles addObject:_nextProjectile];

         // Release
         [_nextProjectile release];
         _nextProjectile = nil;
     }],
      nil]];

    // Move projectile to actual endpoint
    [_nextProjectile runAction:
     [CCSequence actions:
      [CCMoveTo actionWithDuration:realMoveDuration position:realDest],
      [CCCallBlockN actionWithBlock:^(CCNode *node) {
         [_projectiles removeObject:node];
         [node removeFromParentAndCleanup:YES];
    }],
      nil]];

    _nextProjectile.tag = 2;

    [[SimpleAudioEngine sharedEngine] playEffect:@"pew-pew-lei.caf"];
}

- (void)update:(ccTime)dt {

    NSMutableArray *projectilesToDelete = [[NSMutableArray alloc] init];
    for (CCSprite *projectile in _projectiles) {

        BOOL monsterHit = FALSE;
        NSMutableArray *monstersToDelete = [[NSMutableArray alloc] init];
        for (Monster *monster in _monsters) {

            if (CGRectIntersectsRect(projectile.boundingBox, monster.boundingBox)) {
                monsterHit = TRUE;
                monster.hp --;
                if (monster.hp <= 0) {
                    [monstersToDelete addObject:monster];
                }
                break;
            }
        }

        for (CCSprite *monster in monstersToDelete) {

            [_monsters removeObject:monster];
            [self removeChild:monster cleanup:YES];

            _monstersDestroyed++;
            if (_monstersDestroyed > 30) {
                CCScene *gameOverScene = [GameOverLayer sceneWithWon:YES];
                [[CCDirector sharedDirector] replaceScene:gameOverScene];
            }
        }

        if (monsterHit) {
            [projectilesToDelete addObject:projectile];
            [[SimpleAudioEngine sharedEngine] playEffect:@"explosion.caf"];
        }
        [monstersToDelete release];
    }

    for (CCSprite *projectile in projectilesToDelete) {
        [_projectiles removeObject:projectile];
        [self removeChild:projectile cleanup:YES];
    }
    [projectilesToDelete release];
}


// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
    [_monsters release];
    _monsters = nil;
    [_projectiles release];
    _projectiles = nil;
    [super dealloc];
}
@end
//导入接口
#导入“HelloWorldLayer.h”
#导入“SimpleAudioEngine.h”
#导入“GameOverLayer.h”
#导入“Monster.h”
#导入“LevelManager.h”
//需要获取导航控制器
#导入“AppDelegate.h”
#pragma标记-HelloWorldLayer
//HelloWorldLayer实现
@HelloWorldLayer的实现
//帮助器类方法,用于创建将HelloWorldLayer作为唯一子对象的场景。
+(场景*)场景
{
//“场景”是一个自动释放对象。
CCScene*scene=[CCScene节点];
//“层”是一个自动释放对象。
HelloWorldLayer*层=[HelloWorldLayer节点];
//将层作为子层添加到场景中
[场景添加子对象:层];
//返回现场
返回场景;
}
-(空)怪物{
//CCSprite*monster=[CCSprite spriteWithFile:@“monster.png”];
怪物*怪物=零;
如果(arc4random()%2==0){
怪物=[[WeakAndFastMonster alloc]初始化]自动释放];
}否则{
怪物=[[StrongAndSlowMonster alloc]init]自动释放];
}
//确定沿Y轴产卵怪物的位置
CGSize winSize=[CCDirector sharedDirector].winSize;
int minY=monster.contentSize.height/2;
int maxY=winSize.height-monster.contentSize.height/2;
int rangy=maxY-minY;
int实际=(arc4random()%rangeY)+minY;
//沿右边缘在屏幕外创建怪物,
//以及沿Y轴的随机位置,如上所述
monster.position=ccp(实际为winSize.width+monster.contentSize.width/2);
[自我添加的孩子:怪物];
//确定怪物的速度
int minDuration=monster.minMoveDuration;//2.0;
int maxDuration=monster.maxMoveDuration;//4.0;
int rangeDuration=maxDuration-minDuration;
int actualDuration=(arc4random()%rangeDuration)+minDuration;
//创建操作
CCMoveTo*actionMove=[CCMoveTo actionWithDuration:actualDuration位置:ccp(-monster.contentSize.width/2,actually)];
CCCallBlockN*actionMoveDone=[CCCallBlockN actionWithBlock:^(CCNode*node){
[_怪物移除对象:节点];
[节点从父节点移除和清除:是];
CCScene*gameOverScene=[GameOverLayer scenewithon:NO];
[[CCDirector sharedDirector]replaceSecene:gameOverScene];
}];
[monster runAction:[CCSequence actions:actionMove,actionMoveDone,nil];
monster.tag=1;
[_怪物添加对象:怪物];
}
-(无效)游戏逻辑:(ccTime)dt{
[自我添加怪物];
}
-(id)init
{
if((self=[super initWithColor:[LevelManager sharedInstance].curLevel.backgroundColor])){
CGSize winSize=[CCDirector sharedDirector].winSize;
_player=[CCSprite spriteWithFile:@“player2.png”];
_player.position=ccp(winSize.width/2,20);
[self addChild:_player];
[self schedule:@selector(gameLogic:)interval:[LevelManager sharedInstance].curLevel.secsPerSpawn];
[自设置触摸启用:是];
_怪物=[[NSMutableArray alloc]init];
_射弹=[[NSMutableArray alloc]init];
[自行安排:@选择器(更新:)];
[[SimpleAudioEngine sharedEngine]播放背景音乐:@“背景音乐aac.caf”];
}
回归自我;
}
-(无效)ccTouchesEnded:(NSSet*)接触事件:(UIEvent*)事件{
如果(_nextproject!=nil)返回;
//选择要使用的触摸之一
UITouch*touch=[触摸任何对象];
CGPoint location=[self-convertTouchToNodeSpace:touch];
//设置投射物的初始位置
CGSize winSize=[[CCDirector sharedDirector]winSize];
_nextproject=[[CCSprite spriteWithFile:@“projectle2.png”]retain];
_nextproject.position=ccp(winSize.width/2,20);
//确定位置对射弹的偏移量
CGPoint offset=ccpSub(位置,下一个投影位置);
//如果你正在向下射击或向后射击,请跳伞

//如果(offset.x我想说你应该用
atan2f
替换你的
atanf
,即替换

float angleRadians = atanf((float)offRealY / (float)offRealX);
with(注意,
atan2f
分别接受
Y
X


看看。你会看到从0-PI/2
atanf
atan2f
会给你同样的结果。但是,当你从PI/2到PI时,你会使用
atanf
得到负角度,而
atan2f
会产生正确的角度。

我再次查看了你的代码,并注意到其他问题嗯,我已经改变了以下几点:

  • 在下面拍摄时的“保释”条件(注意顺序的变化,否则在第一次满足保释条件后您将无法拍摄!)
  • 计算
    realY
    realX
    -您保留了Ray教程中的代码,并将目标位置设置为始终位于右侧,而在下面的代码中,目标位置始终位于顶部
  • 删除了
    atan
    /
    atan2
    函数并使用
    ccpToAngle(ccp(offreax,offRealY))
下面
float angleRadians = atan2f((float)offRealY, (float)offRealX);
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (_nextProjectile != nil) return;

    CGSize winSize = [[CCDirector sharedDirector] winSize];

    // Choose one of the touches to work with
    UITouch *touch = [touches anyObject];
    CGPoint location = [self convertTouchToNodeSpace:touch];

    CGPoint targetPosition = ccp(winSize.width / 2, 20);

    // Determine offset of location to projectile
    CGPoint offset = ccpSub(location, targetPosition);

    // Bail out if you are shooting down or backwards
    if (offset.y <= 0)
    {
    return;
    }

    // Set up initial location of projectile
    _nextProjectile = [[CCSprite spriteWithFile:@"projectile2.png"] retain];
    _nextProjectile.position = targetPosition;

    // Determine where you wish to shoot the projectile to
    int realY = winSize.height + (_nextProjectile.contentSize.height/2);
    float ratio = (float) offset.x / (float) offset.y;
    int realX = (realY * ratio) + _nextProjectile.position.x;
    CGPoint realDest = ccp(realX, realY);

    // Determine the length of how far you're shooting
    int offRealX = realX - _nextProjectile.position.x;
    int offRealY = realY - _nextProjectile.position.y;
    float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
    float velocity = 480/1; // 480pixels/1sec
    float realMoveDuration = length/velocity;

    // Determine angle to face
    float angleRadians = ccpToAngle(ccp(offRealX, offRealY));