防止玩家从地面掉落 – 精灵套装

我一直在尝试一个简单的Sprite Kit游戏,涉及躲避红球。 我正在使用内置重力机制,但我无法阻止玩家从地面掉落。 我已经查找了一个解决方案(设置ground.physicsBody.dynamic = NO),但播放器仍然没有通过。 我到底需要做什么?

编辑:绿色和棕色纹理是地面。 现在玩家被设置为不动态,所以它’飞’

这是MyScene.m文件中的代码:

// // MyScene.m // DodgeMan // // Created by Cormac Chester on 3/8/14. // Copyright (c) 2014 Testman Industries. All rights reserved. // #import "MyScene.h" #import "EndGameScene.h" static const uint32_t redBallCategory = 0x1 << 0; static const uint32_t playerCategory = 0x1 <= 75) { //Prevents balls from spawning in the ground redBall.position = CGPointMake(self.frame.size.width + redBall.size.width/2, actualY); [self addChild:redBall]; } redBall.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:redBall.size.width/2]; redBall.physicsBody.dynamic = YES; redBall.physicsBody.categoryBitMask = redBallCategory; redBall.physicsBody.contactTestBitMask = playerCategory; redBall.physicsBody.collisionBitMask = 0; redBall.physicsBody.affectedByGravity = NO; redBall.physicsBody.usesPreciseCollisionDetection = YES; //Determine speed of red ball int minDuration = 3.0; int maxDuration = 5.0; int rangeDuration = maxDuration - minDuration; int actualDuration = (arc4random() % rangeDuration) + minDuration; // Create the actions SKAction *actionMove = [SKAction moveTo:CGPointMake(-redBall.size.width/2, actualY) duration:actualDuration]; SKAction *actionMoveDone = [SKAction removeFromParent]; SKAction *ballCross = [SKAction runBlock:^{ score++; self.scoreString = [NSString stringWithFormat:@"%i", score]; self.scoreLabel.text = self.scoreString; NSLog(@"Score was incremented. Score is now %d", score); }]; [redBall runAction:[SKAction sequence:@[actionMove, ballCross, actionMoveDone]]]; } - (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast { self.lastSpawnTimeInterval += timeSinceLast; if (self.lastSpawnTimeInterval > 0.5) { self.lastSpawnTimeInterval = 0; [self addBall]; } } -(void)update:(CFTimeInterval)currentTime { /* Called before each frame is rendered */ // Handle time delta. //Prevents bad stuff happening CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval; self.lastUpdateTimeInterval = currentTime; if (timeSinceLast > 1) { // more than a second since last update timeSinceLast = 1.0 / 120.0; self.lastUpdateTimeInterval = currentTime; } [self updateWithTimeSinceLastUpdate:timeSinceLast]; } NSDate *startTime; -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* Called when a touch begins */ [super touchesBegan:touches withEvent:event]; //Starts Timer startTime = [NSDate date]; UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInNode:self]; SKNode *node = [self nodeAtPoint:location]; //Pauses Scene if ([node.name isEqualToString:@"pauseButton"]) { NSLog(@"Pause button pressed"); } } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { /* Called when a touch ends */ [super touchesEnded:touches withEvent:event]; NSTimeInterval elapsedTime = [startTime timeIntervalSinceNow]; NSString *elapsedTimeString = [NSString stringWithFormat:@"Elapsed time: %f", elapsedTime]; NSLog(@"%@", elapsedTimeString); for (UITouch *touch in touches) { //Gets location of touch CGPoint location = [touch locationInNode:self]; NSLog(@"Touch Location X: %f \n Touch Location Y: %f", location.x, location.y); //Prevents destination from being in the ground if (location.y < 88) { location.y = 87.5; } //Moves and animates player //int velocity = elapsedTime * -3000; int velocity = 800.0/1.0; NSLog(@"Velocity: %i", velocity); float realMoveDuration = self.size.width / velocity; SKAction *actionMove = [SKAction moveTo:location duration:realMoveDuration]; [self.playerSprite runAction:[SKAction sequence:@[actionMove]]]; } NSLog(@"Touch ended"); } //Collision between ball and player - (void)redBall:(SKSpriteNode *)redBall didCollideWithPlayer:(SKSpriteNode *)playerSprite { NSLog(@"Player died"); [redBall removeFromParent]; [playerSprite removeFromParent]; SKTransition *reveal = [SKTransition crossFadeWithDuration:0.5]; SKScene *endGameScene = [[EndGameScene alloc] initWithSize:self.size gameEnded:YES]; [self.view presentScene:endGameScene transition: reveal]; } - (void)didBeginContact:(SKPhysicsContact *)contact { SKPhysicsBody *firstBody, *secondBody; if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) { firstBody = contact.bodyA; secondBody = contact.bodyB; } else { firstBody = contact.bodyB; secondBody = contact.bodyA; } //Red ball collides with the player if ((firstBody.categoryBitMask & redBallCategory) != 0 && (secondBody.categoryBitMask & playerCategory) != 0) { [self redBall:(SKSpriteNode *) firstBody.node didCollideWithPlayer:(SKSpriteNode *) secondBody.node]; } } @end 

你绝对不能把它的动态设置为没有兄弟。 你需要那个玩家的重力效应。 (他不受物理世界的影响所以他现在正在飞行。我们需要他倒在地上不是吗?:)

所以这是简单的解决方案。 我们的想法是你在地面上创造一个具有物理身体的“隐形矩形块”。 并且您需要将其动态设置为no以防止其掉落

所以这个块显然是一个节点,它的大小:高到地面,和屏幕一样宽。 你需要稍微调整一下位置,将其上限放在地面上。

祝你好运

我实际上画了一张照片,但由于我的声誉,我不能在这里张贴:(

你的问题在于physicsBody的categoryBitMask和collisionTestBitMask。 你的按位声明:

 static const uint32_t redBallCategory = 0x1 << 0; static const uint32_t playerCategory = 0x1 << 1; 

这实际上设置了以下位模式(例如,我缩短为8位):redBallCategory - 00000001和playerCategory - 00000010

但是在下面的代码中,您告诉玩家只碰撞碰撞位掩码 - 00000000; self.playerSprite.physicsBody.collisionBitMask = 0;

所以你的第一个问题就在这里。 玩家不会与您定义的任何类别发生碰撞。

你的第二个问题是你没有给出categoryBitMask或collisionBitMask。 默认情况下,这意味着所有位都被置位,IE的地面的collisionBitMask等于11111111;

这两个物理团体之间不会发生碰撞。

试试这个 - 我只是添加了第三个物理类别,并稍微编辑了你的代码以设置地面类别BitMask / collisionBitMask和你的玩家collisionBitMask。

 static const uint32_t redBallCategory = 0x1 << 0; static const uint32_t playerCategory = 0x1 << 1; static const uint32_t groundCategory = 0x1 << 2; @implementation MyScene -(id)initWithSize:(CGSize)size { if (self = [super initWithSize:size]) { /* Setup your scene here */ //Sets player location playerLocX = 50; playerLocY = 100; //Sets player score score = 0; //Set Background self.backgroundColor = [SKColor colorWithRed:0.53 green:0.81 blue:0.92 alpha:1.0]; //Set Ground SKSpriteNode *ground = [SKSpriteNode spriteNodeWithImageNamed:@"ground"]; ground.position = CGPointMake(CGRectGetMidX(self.frame), 34); ground.xScale = 0.5; ground.yScale = 0.5; ground.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ground.size]; ground.physicsBody.categoryBitMask=groundCategory; ground.physicsBody.collisionBitMask=playerCategory|redBallCategory; ground.physicsBody.dynamic = NO; //Player self.playerSprite = [SKSpriteNode spriteNodeWithImageNamed:@"character"]; self.playerSprite.position = CGPointMake(playerLocX, playerLocY); //Set Player Physics self.playerSprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.playerSprite.size]; self.playerSprite.physicsBody.dynamic = YES; self.playerSprite.physicsBody.categoryBitMask = playerCategory; self.playerSprite.physicsBody.contactTestBitMask = redBallCategory; self.playerSprite.physicsBody.collisionBitMask = groundCategory|redBallCategory; self.playerSprite.physicsBody.usesPreciseCollisionDetection = YES; //Score Label self.scoreLabel = [SKLabelNode labelNodeWithFontNamed:@"Arial-BoldMT"]; self.scoreLabel.text = @"0"; self.scoreLabel.fontSize = 40; self.scoreLabel.fontColor = [SKColor blackColor]; self.scoreLabel.position = CGPointMake(50, 260); //Pause Button self.pauseButton = [SKSpriteNode spriteNodeWithImageNamed:@"pauseButton"]; self.pauseButton.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height - 40); self.pauseButton.name = @"pauseButton"; //Add nodes [self addChild:ground]; [self addChild:self.playerSprite]; [self addChild:self.scoreLabel]; //[self addChild:self.pauseButton]; //Sets gravity self.physicsWorld.gravity = CGVectorMake(0,-2); self.physicsWorld.contactDelegate = self; } return self; 

}

只是:

 self.playerSprite.physicsBody.dynamic = NO; 

应该管用。

您的问题是由于缩放问题。 由于某些原因,在精灵套件缩放中,图像在下面的代码中使用时不会改变它的大小。 根据你的照片来判断,你的物理身体矩形实际上是你想象的两倍,并且已经吞没了玩家,这就是没有碰撞检测的原因。 这是近期与非常相似的风格游戏的经验。

你在场景周围有一个边缘循环physcis体吗? 碰撞标志和类别标志设置正确,以便玩家与地面发生碰撞?

我有同样的问题,我只是简单地说…

在更新方法上,我推出了一个if语句:

 if(player.position.y 

比较因你所拥有的锚点而不同。希望它有助于某人