我有英雄,地面和桌子。我想制作一个桌面活动用于碰撞并与英雄接触。但是英雄应该不能跳到顶端并且只是“穿过”并跳过它,如果玩家想要它,无论他想要什么。为了更好地展示我想要实现的目标 - 想想马里奥。当你在地面上奔跑时,会出现一些天空平台。你可以在平台中间跳上它并留在那里。因此,当他从底部接触时,我需要物理身体不要阻止英雄,但如果他在它上面,请抓住他。 到现在为止,我正在使用带有纹理的桌子:
self.table.physicsBody = SKPhysicsBody(texture:table.texture, size:self.table.size)
self.table.physicsBody?.dynamic = false
self.table.physicsBody?.categoryBitMask = ColliderType.Table.rawValue
self.table.physicsBody?.contactTestBitMask = ColliderType.Hero.rawValue
self.table.physicsBody?.collisionBitMask = ColliderType.Hero.rawValue
显然,它不起作用。我怎么能实现这样的事情?
答案 0 :(得分:2)
我不确定您的平台的外观(基于边缘或基于体积的主体),但您可以考虑其中一些:
<强> 1。检查职位
<强> 2。检查速度
我不能说这些内容中是否有任何一项可以完全帮助您完成游戏,或者是否可以通过您的设置实现,但您可以从中获取一些基本想法。
启用/禁用冲突可以通过更改播放器和平台的冲突位掩码来完成。如果可能,请尝试避免跟踪 isInTheAir , isOnPlatform , isFaling , isJumping 等类似因素,因为它可能会变得混乱随着国家数量的增长。例如,不是添加名为“isFalling”的自定义布尔变量并且不断维持其状态,您可以检查velocity.dy是否为负值以查看玩家是否在下降。
答案 1 :(得分:2)
这个问题的答案实际上并不太难,但对于你来说,实施一个完整的游戏对你来说会困难得多。对于新手程序员来说,这不是开始的。
首先是相同的代码项目(点击/点击屏幕跳转):
#import "GameScene.h"
typedef NS_OPTIONS(uint32_t, Level1PhysicsCategory) {
CategoryPlayer = 1 << 0,
CategoryFloor0 = 1 << 1,
CategoryFloor1 = 1 << 2,
};
@implementation GameScene {
int playerFloorLevel;
SKSpriteNode *node0;
SKSpriteNode *node1;
SKSpriteNode *node2;
}
-(void)didMoveToView:(SKView *)view {
self.backgroundColor = [SKColor whiteColor];
node0 = [SKSpriteNode spriteNodeWithColor:[SKColor grayColor] size:CGSizeMake(400, 10)];
node0.position = CGPointMake(300, 200);
node0.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:node0.size];
node0.physicsBody.dynamic = NO;
node0.physicsBody.categoryBitMask = CategoryFloor0;
node0.physicsBody.collisionBitMask = CategoryPlayer;
[self addChild:node0];
node1 = [SKSpriteNode spriteNodeWithColor:[SKColor grayColor] size:CGSizeMake(400, 10)];
node1.position = CGPointMake(300, 300);
node1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:node1.size];
node1.physicsBody.dynamic = NO;
node1.physicsBody.categoryBitMask = CategoryFloor1;
node1.physicsBody.collisionBitMask = CategoryPlayer;
[self addChild:node1];
node2 = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(50, 50)];
node2.position = CGPointMake(300, 250);
node2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:node2.size];
node2.physicsBody.categoryBitMask = CategoryPlayer;
node2.physicsBody.collisionBitMask = CategoryFloor0;
[self addChild:node2];
playerFloorLevel = 0;
}
-(void)update:(CFTimeInterval)currentTime {
if(((node2.position.y-25) > (node1.position.y+10)) && (playerFloorLevel == 0)) {
node2.physicsBody.collisionBitMask = CategoryFloor0 | CategoryFloor1;
playerFloorLevel = 1;
}
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInNode:self];
//SKNode *node = [self nodeAtPoint:touchLocation];
// change 75 value to 50 to see player jump half way up through floor 1
[node2.physicsBody applyImpulse:CGVectorMake(0, 75)];
}
}
代码的要点是玩家节点(node2)必须继续检查其相对于其他楼层的y位置(更新方法)。在该示例中,玩家跳过floor1。一旦玩家高于floor1,玩家节点的物理主体会修改其碰撞位掩码以包含floor1。
听起来很容易。但是,在真实游戏中,您将拥有大量的楼层,并且所有楼层的距离可能不均匀。编码时必须牢记所有这些。
答案 2 :(得分:1)
使用swift你可以像这样创建一个精灵节点子类:
class TableNode: SKSpriteNode {
var isBodyActivated: Bool = false {
didSet {
physicsBody = isBodyActivated ? activatedBody : nil
}
}
private var activatedBody: SKPhysicsBody?
init(texture: SKTexture) {
super.init(texture: texture, color: SKColor.clearColor(), size: texture.size())
// physics body setup. Assuming anchorPoint = (0.5, 0.5)
let bodyInitialPoint = CGPoint(x: -size.width/2, y: +size.height/2)
let bodyEndPoint = CGPoint(x: +size.width/2, y: +size.height/2)
activatedBody = SKPhysicsBody(edgeFromPoint: bodyInitialPoint, toPoint: bodyEndPoint)
activatedBody!.categoryBitMask = ColliderType.Table.rawValue
activatedBody!.collisionBitMask = ColliderType.Hero.rawValue
physicsBody = isBodyActivated ? activatedBody : nil
name = "tableNode"
}
}
然后,更新gameScene中的所有tableNodes:
override func didSimulatePhysics() {
self.enumerateChildNodesWithName("tableNode") {
node, stop in
if let tableNode = node as? TableNode {
// Assuming anchorPoint = (0.5, 0.5) for table and hero
let tableY = tableNode.position.y + tableNode.size.height/2
let heroY = hero.position.y - hero.size.height/2
tableNode.isBodyActivated = heroY > tableY
}
}
}
答案 3 :(得分:1)
我尝试更改平台碰撞位掩码,但工作不正常。我发现了一个不同的解决方案。
在update()函数中,您可以查看以下内容
if player.physicsBody?.velocity.dy <= 0 {
player.physicsBody?.collisionBitMask = PhysicsCategory.Platform
} else {
player.physicsBody?.collisionBitMask = PhysicsCategory.None
}
通过这种方式,每次玩家上升时,它都可以穿过岩石,每次落下时,它都能站立起来。