One-way platform collisions in the Sprite kit

I make a Doodle Jump clown in Swift, and the problem is that when a player jumps, he bangs his head to the bottom of the platform and does not pass. How can I make a player go through the platform and slip through them? I have the code here:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var hero = SKSpriteNode(imageNamed: "hero");
    var stepSizeTest = SKSpriteNode(imageNamed: "step");
    var start = false;
    var jumpSpeed = CGFloat(0);
    var gravity = CGFloat(0);
    var stepPositionDivision:CGFloat = 0 //allows the step to spawn on specific places on y axes
    var setpPositionHeightIncrease:CGFloat = 0;

    var positionX:CGFloat = 0;
    var timeInterval:NSTimeInterval = 0;
    var CurTime:NSTimeInterval = 0;
    var TimeWhenThePreviousStepSpawned:NSTimeInterval = 0;
    var standart:Bool = false;
    var move:Bool = false;
    var oneJumpOnly:Bool = false;
    var cracked:Bool = false;
    var jumped:Bool = false;

    struct PhysicsCategory{
        static var None: UInt32 = 0;
        static var step: UInt32 = 0b1;
        static var hero: UInt32 = 0b10;
        static var All: UInt32 = UInt32.max;
    }

    func didBeginContact(contact: SKPhysicsContact) {
        var contactBody1: SKPhysicsBody;
        var contactBody2: SKPhysicsBody;
        if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask){
            contactBody1 = contact.bodyA;
            contactBody2 = contact.bodyB;
        }
        else{
            contactBody1 = contact.bodyB;
            contactBody2 = contact.bodyA;
        }

        if (contactBody1.categoryBitMask == PhysicsCategory.step && contactBody2.categoryBitMask == PhysicsCategory.hero){
            jumpSpeed = CGFloat(self.frame.size.height*0.01320422535);

        }
//        if (contactBody1.categoryBitMask == PhysicsCategory.ground && contactBody2.categoryBitMask == PhysicsCategory.hero){
//
//        }
    }

    override func didMoveToView(view: SKView) {
        /* Setup your scene here */
        stepPositionDivision = self.frame.size.height/23;

        jumpSpeed = CGFloat(self.frame.size.height*0.01320422535);
        gravity = CGFloat(self.frame.size.height*(-0.0003521126761));

        self.physicsWorld.contactDelegate = self;

        self.physicsWorld.gravity = CGVectorMake(0,0);

        let sceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame);
        sceneBody.friction = 0;
        self.physicsBody = sceneBody;


        self.hero.anchorPoint = CGPoint(x: 0.5, y: 0.5);
        self.hero.position = CGPoint(x:self.frame.size.width/2, y:self.hero.size.height/2);
        self.hero.physicsBody = SKPhysicsBody(rectangleOfSize: self.hero.size)
        self.hero.physicsBody?.restitution = 1;
        self.hero.physicsBody?.affectedByGravity = false;
        self.hero.physicsBody?.friction = 0;
        self.hero.physicsBody?.categoryBitMask = PhysicsCategory.hero;
        self.hero.physicsBody?.collisionBitMask = PhysicsCategory.step;
        self.hero.physicsBody?.contactTestBitMask = PhysicsCategory.step;

        self.addChild(self.hero);
    }

    func ranPositionX() -> CGFloat{
        let stepSise = UInt32(self.stepSizeTest.size.width)
        let posX = arc4random_uniform(UInt32(self.frame.size.width) - stepSise) + stepSise
        return CGFloat(posX)
    }

    func stepSpawn(){
        if (setpPositionHeightIncrease < self.frame.size.height){
            let step = SKSpriteNode(imageNamed: "step");
            let posX = ranPositionX()

            step.anchorPoint = CGPoint(x: 0.5, y: 0.5);
            step.position = CGPoint(x:posX, y:setpPositionHeightIncrease);
            step.physicsBody = SKPhysicsBody(rectangleOfSize: step.size);
            step.physicsBody?.affectedByGravity = false;
            step.physicsBody?.dynamic = true;
            step.physicsBody?.friction = 0;
            step.physicsBody?.categoryBitMask = PhysicsCategory.step;
            step.physicsBody?.collisionBitMask = PhysicsCategory.None;
            step.physicsBody?.contactTestBitMask = PhysicsCategory.hero;

            self.addChild(step);
            setpPositionHeightIncrease += stepPositionDivision
        }
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
       /* Called when a touch begins */
        for touch in touches {

        }
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */

        self.hero.position.y += jumpSpeed
        jumpSpeed += gravity

        if (start == false){
            //self.hero.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 40))
            start = true;
        }
        stepSpawn()
    }
}
+4
source share
2 answers

One way to do this is to turn on or off the corresponding collision bit if the hero falls or jumps. The hero falls if his speed property is dyless than zero and jumps (or bounces) if it is dygreater than zero. Here is an example of how to do this:

// Add this to the update method
if let body = hero.physicsBody {
    let dy = body.velocity.dy
    if dy > 0 {
        // Prevent collisions if the hero is jumping
        body.collisionBitMask &= ~PhysicsCategory.step
    }
    else {
        // Allow collisions if the hero is falling
        body.collisionBitMask |= PhysicsCategory.step
    }
}
+5
source

- 2 , CollisionPlatform NoCollisionPlatform.

SKSpriteNode Hero

NoCollisionPlatform

SKPhysicsBody , . , .

Hero CollisionPlatform collisionBitMask, CollisionPlatform NoCollisionPlatform contactTestBitMask.

Hero .

didBeginContact, NoCollisionPlatform, , Hero , Hero . , categoryBitMask CollisionPlatform

didEndContact method categoryBitMask NoCollisionPlatform

, , , , x, - . 1/2 , Int

, , Hero, categoryBitMask NoCollisionPlatform.

, Hero, , , . , .

, , - Hero, , SKAction . , , , , Hero 0, , ( ). ( ), , , , , , , , .

, 1 , , , Hero , , , Hero , ( 1 1 , , , .

, , , , , , , 1 , , . 30, , 31 , .

, 1 Hero

Heroes, -.

- Hero collisionBitMask. , , .

, , categoryBitMask Hero

+1

Source: https://habr.com/ru/post/1654228/


All Articles