Jumping with ClassVR

Hello,

I programmed a scene for the ClassVR headsets. For this I have implemented code to jump. Everything works fine in the browser, but when you try to jump with the ClassVR headset, you fall through the floor. I also added a cuboid above the player and when the player jumps against that cuboid it doesn’t fall through the floor. Here is the code:

class JumpButton {

    private _jumpText: TextItem

    private _jumpButton: Ellipsoid

    private _update: Disposable

    private _isJumping = false

    private _canJump = true

    private _arc = new Arc()

    private _lastCollidingItem: BaseItem

    static V3_LERP = (start: Vector3, end: Vector3, percent: number): Vector3 => start.add((end.sub(start).mult(percent)));

    static LERP_SPEED = 30;

    static JUMP_DISTANCE = 10;

    static JUMP_DURATION = 0.65

    constructor() {

        if (Scene.getProperty('jumpButton_FEATURE') !== 'enabled') {

            Scene.setProperty('jumpButton_FEATURE', 'enabled')

            this._init()

        }

    }

    private _init() {

            //this._createButton()

            //this._bindButtonClick()

            this._onUpdate()

            this._bindCollision()

    }

    private _dispose() {

        if (this._update !== undefined) this._update.dispose()

        if (this._jumpButton) {

            this._jumpButton.deleteChildren()

            this._jumpButton.delete()

        }

    }

    private _createButton() {

            this._jumpText = Scene.createText(0, 0, 0, 'JUMP')

            this._jumpButton = Scene.createEllipsoid(0, 0, 0)

            this._jumpButton.radiusX = 0.4;

            this._jumpButton.radiusY = 0.01;

            this._jumpButton.radiusZ = 0.4;

            this._jumpText.getSlot('Bottom').attachTo(this._jumpButton.getSlot('Front'))

            this._jumpText.color = new Color(200,200,0);

            this._jumpButton.transform.scale = 0.2

            RayCast.addToFilter(this._jumpText)

            Camera.addToCollisionFilter(this._jumpButton)

            Camera.addToCollisionFilter(this._jumpText)        

    }

    private _bindCollision() {

        Camera.focusedItem.onCollisionEnter(item => {

            if (this._isJumping) {

                if (item !== this._lastCollidingItem) {

                    this._lastCollidingItem = item

                    this._canJump = false

                }

            }

        })

    }

    private _bindButtonClick() {

            this._jumpButton.input.onClick(() => {

                this._jump()

            })        

    }

    private _onUpdate() {

            this._update = Time.scheduleRepeating(delta => {

                let cameraTarget = Camera.transform.position.add(Camera.transform.forward.mult(0.5));

                cameraTarget = new Vector3(cameraTarget.x, cameraTarget.y, Camera.transform.position.z - 0.5)

                //this._jumpButton.transform.position = JumpButton.V3_LERP(this._jumpButton.transform.position, cameraTarget, JumpButton.LERP_SPEED * delta)

                //this._jumpButton.transform.lookAt(Camera.transform.position)

            })

    }

    public async _jump() {

        if (!this._isJumping) {

            //this._jumpButton.active = false

            this._isJumping = true

            let cameraDir = new Vector3(Camera.transform.forward.x, Camera.transform.forward.y, 0)

            let cameraPos = Camera.transform.position

            let jumpTrajectory = this._arc.calculateArcArray(cameraPos, cameraDir)

            /*for (let i = 0; i < jumpTrajectory.length - 1; i++) {

                await this._interpolateJump(jumpTrajectory[i], jumpTrajectory[i + 1], JumpButton.JUMP_DURATION / jumpTrajectory.length)

            }*/

            let time = 0

            let curStep = 0;

            let curStart = jumpTrajectory[0];

            let curEnd = jumpTrajectory[1];

            let duration = JumpButton.JUMP_DURATION / jumpTrajectory.length;

            let nextStepTime = duration;

            let update = Time.scheduleRepeating(d => {

                if (!this._canJump) {

                    update.dispose()

                    this._endJump();

                    return;

                }

                time += d;                

                Camera.focusedItem.transform.position = JumpButton.V3_LERP(curStart, curEnd, time / duration)

                if (time >= nextStepTime) {

                    if (curStep >= jumpTrajectory.length - 2 ) {

                        update.dispose();

                        this._endJump();

                        return;

                    }

                    curStep++;

                    curStart = jumpTrajectory[curStep];

                    curEnd = jumpTrajectory[curStep + 1];

                    nextStepTime += duration;

                }

            });

            

        }

    }

    private _endJump() {

        this._canJump = true

        this._isJumping = false

        this._lastCollidingItem = null

        //this._jumpButton.active = true

    }

}

class Arc {

    static Deg2Rad = 0.0174533

    static GRAVITY: number = Physics.gravityAcceleration

    public velocity: number = 7

    public angle: number = 60

    public resolution: number = 50

    private _radianAngle: number

    public calculateArcArray(origin: Vector3, direction: Vector3): Vector3[] {

        let arcArray: Vector3[] = []

        this._radianAngle = this.angle * Arc.Deg2Rad

        let maxDistance = (this.velocity * this.velocity * Math.sin(2 * this._radianAngle)) / Arc.GRAVITY

        for (let i = 0; i <= this.resolution; i++) {

            let t = i / this.resolution

            let arcPoint = this._calculateArcPoint(t, maxDistance, direction)

            arcPoint = origin.add(arcPoint)

            arcArray[i] = arcPoint

        }

        return arcArray

    }

    private _calculateArcPoint(t: number, maxDistance: number, direction: Vector3): Vector3 {

        let x = t * maxDistance

        let y = t * maxDistance

        if(!Application.isMobile){

            var z = x * Math.tan(this._radianAngle) - ((Arc.GRAVITY * x * x) / (2 * this.velocity * this.velocity * Math.cos(this._radianAngle) * Math.cos(this._radianAngle)))

        }else{

            var z = 0.25 * x * Math.tan(this._radianAngle) - ((Arc.GRAVITY * x * x) / (2 * this.velocity * this.velocity * Math.cos(this._radianAngle) * Math.cos(this._radianAngle)))

        }

        return new Vector3(

            x * direction.x,

            y * direction.y,

            z

        )

    }

}

var jumpButton = new JumpButton()
jumpButton._jump();
1 Like

Hi @Daniel,

could you please share your space, so I could take a look?

Hi,

here is the link for my space: CoSpaces Edu :: Jump 'n run2

You wrote a lot of nice code! And on my phone jump works great.
It is really not easy to understand what causes that bug. You could try to separate the code and test it on simpler spaces, so it would be easier to find the problem.