javascriptclassgame-physicspixi.js

Pixi.js wrong collision


I'm trying to create a game on pixi.js and implement custom physics for the Hero instance.

I'm stuck on a jump down right now. My problem is that the collision should disappear with state === jump, but the Pixi.update method logically changes state === fall and when I have fall does not occur.

If you remove the if (this.#speed.speed > 0 && this.is Jump()) everything works, but I can't figure out how to get the collision back so that the character jumps down only one platform.

I tried to enter an additional state of jumping down. I also tried using setTimeout (this leads to a memory leak) and a timer via a variable, but in this case there will be bugs when jumping in place.

I will attach a link to the github, as well as to the problematic parts of the code.

Thanks!

Github https://github.com/yanballas/contra

Code:

Hero instance

    update() {
        this.#speed.speedX = this.#movement.x * this.#speed.maxSpeed;
        this.x += this.#speed.speedX;
        
        if (this.#speed.speedY > 0 && this.isJump()) {
            console.log('down');
            this.#stateHero = $STATESCHARTER.fall
        }
        
        this.#speed.speedY += this.#gravity.gravityForce
        this.y += this.#speed.speedY
    }
    
    stay() {
        this.#stateHero = $STATESCHARTER.stay
        this.#speed.speedY = 0
    }
    
    jump() {
        if (this.#stateHero === $STATESCHARTER.jump || this.#stateHero === $STATESCHARTER.fall) return
        this.#stateHero = $STATESCHARTER.jump
        this.#speed.speedY -= this.#gravity.jumpForce
    }
    
    jumpDown() {
        console.log('jump down')
        this.#stateHero = $STATESCHARTER.jump
        console.log(this.isJump())
    }
    
    isJump() {
        return this.#stateHero === $STATESCHARTER.jump
    }

// Game instance

isCheckCollision(entity, area) {
        return entity.x < area.x + area.width &&
            entity.x + entity.width > area.x &&
            entity.y < area.y + area.height &&
            entity.y + entity.height > area.y;
    }
    
    update() {
        const previousPoint = {
            x: this.#hero.x,
            y: this.#hero.y
        }
        
        this.#hero.update()
        
        this.#platforms.forEach(platform => {
            
            if (this.#hero.isJump()) return
            
            const resultCollision = this.resultEntityCollision(this.#hero, platform, previousPoint);
            
            if (resultCollision.vertical) {
                this.#hero.stay();
            }
        })
    }
    
    resultEntityCollision(charter, platform, previousPoint) {
        const collisionResult = this.checkResultEntityCollision(charter, platform, previousPoint);
        
        if (collisionResult.vertical) {
            charter.y = previousPoint.y
        }
        
        return collisionResult
    }
    
    checkResultEntityCollision(rectangleA, rectangleB, previousPointRectangleA) {
        const collisionResult = {
            horizontal: false,
            vertical: false,
        }
        
        let isCollision = this.isCheckCollision(rectangleA, rectangleB)
        if (!isCollision) return collisionResult;
        
        rectangleA.y = previousPointRectangleA.y
        
        isCollision = this.isCheckCollision(rectangleA, rectangleB)
        if (!isCollision) {
            collisionResult.vertical = true
            return collisionResult
        }
        
        collisionResult.horizontal = true
        return collisionResult
    }

Solution

  • I don't get the issue with the fall state but why don't just ignore the "jumped down" platform until the player touches another ?

    Hero instance
    
        update() {
            this.#speed.speedX = this.#movement.x * this.#speed.maxSpeed;
            this.x += this.#speed.speedX;
            
            if (this.#speed.speedY > 0 && this.isJump()) {
                console.log('down');
                this.#stateHero = $STATESCHARTER.fall
            }
            
            this.#speed.speedY += this.#gravity.gravityForce
            this.y += this.#speed.speedY
        }
        
        stay(platform) {
            this.#stateHero = $STATESCHARTER.stay
            this.#speed.speedY = 0;
            // re enable collision on previously jumped down platform
            this.#jumpedDownPlatform = null;
            // keep track of the platform you are currently on
            this.#lastPlatform = platform;
        }
        
        jump() {
            if (this.#stateHero === $STATESCHARTER.jump || this.#stateHero === $STATESCHARTER.fall) return
            this.#stateHero = $STATESCHARTER.jump
            this.#speed.speedY -= this.#gravity.jumpForce
        }
        
        jumpDown() {
            console.log('jump down')
            this.#stateHero = $STATESCHARTER.jump
            // signal we will be ignoring the current platform in
            // collision detection until we touch another
            this.#jumpedDownPlatform = this.#lastPlatform;
            console.log(this.isJump())
        }
        
        isJump() {
            return this.#stateHero === $STATESCHARTER.jump
        }
    
    // Game instance
    
    isCheckCollision(entity, area) {
            return entity.x < area.x + area.width &&
                entity.x + entity.width > area.x &&
                entity.y < area.y + area.height &&
                entity.y + entity.height > area.y;
        }
        
        update() {
            const previousPoint = {
                x: this.#hero.x,
                y: this.#hero.y
            }
            
            this.#hero.update()
            
            this.#platforms.forEach(platform => {
                
                if (platform === this.#hero.#jumpedDownPlatform ||this.#hero.isJump()) {
                    // ignore collision when player is jumping up or
                    // when we are jumpingDown the current platform
                    return
                }
                
                const resultCollision = this.resultEntityCollision(this.#hero, platform, previousPoint);
                
                if (resultCollision.vertical) {
                    this.#hero.stay(platform);
                }
            })
        }
        
        resultEntityCollision(charter, platform, previousPoint) {
            const collisionResult = this.checkResultEntityCollision(charter, platform, previousPoint);
            
            if (collisionResult.vertical) {
                charter.y = previousPoint.y
            }
            
            return collisionResult
        }
        
        checkResultEntityCollision(rectangleA, rectangleB, previousPointRectangleA) {
            const collisionResult = {
                horizontal: false,
                vertical: false,
            }
            
            let isCollision = this.isCheckCollision(rectangleA, rectangleB)
            if (!isCollision) return collisionResult;
            
            rectangleA.y = previousPointRectangleA.y
            
            isCollision = this.isCheckCollision(rectangleA, rectangleB)
            if (!isCollision) {
                collisionResult.vertical = true
                return collisionResult
            }
            
            collisionResult.horizontal = true
            return collisionResult
        }