GamePad class

I have an instance of ‘GamePads’ class and I can get one gamepad by doing: ‘const gamepad = gamepads.findByIndex(pc.PAD_1)’
I would like to pass this gamepad as a parameter to another function, but if I try to do:
‘const gamepad = gamepads.findByIndex(pc.PAD_1) as pc.GamePad’ or
‘function readInput(gamepad:pc.GamePad)’ I get the error:

playcanvas has no exported member named ‘GamePad’

Is there a reason for that? How can a pass a reference of gamepad without using ‘any’?
Thanks

Playcanvas uses an different method for the gamepads, if you look into my game I made with PC & Xbox (Gamepad) controls you’ll kinda understand it

var ControllerAlpha = pc.createScript('ControllerAlpha');

// Attributes
ControllerAlpha.attributes.add('boost_EXP', { type: 'entity' });
ControllerAlpha.attributes.add('boost_EXP2', { type: 'entity' });
ControllerAlpha.attributes.add('bersekBoom', { type: 'entity' });
ControllerAlpha.attributes.add('Forward_EXP', { type: 'entity' });
ControllerAlpha.attributes.add('base', { type: 'entity' });
ControllerAlpha.attributes.add('airsp', { type: 'entity' });
ControllerAlpha.attributes.add('playerCam', { type: 'entity' });
ControllerAlpha.attributes.add('txtas', { type: 'entity' });
ControllerAlpha.attributes.add('hit', { type: 'entity' });
ControllerAlpha.attributes.add("doubleClickSpeed", { type: "number", default: 0.5 });
ControllerAlpha.attributes.add("speed", { type: "number", default: 1 });
ControllerAlpha.attributes.add("deadzone", { type: "number", default: 0.5 });
ControllerAlpha.attributes.add("focusMode", { type: "number", default: 0.2 });
ControllerAlpha.attributes.add("darkness", { type: "number", default: 0.3 });
ControllerAlpha.attributes.add("offset", { type: "number", default: 0.3 });
ControllerAlpha.attributes.add("hue", { type: "number", default: 0.165 });
ControllerAlpha.attributes.add("sat", { type: "number", default: 0.25 });
ControllerAlpha.attributes.add("chromaticAberrationIntensity", { type: "number", default: 1 });
ControllerAlpha.attributes.add("highlightThreshold", { type: "number", default: 0.3 });
ControllerAlpha.attributes.add("MaxEventMotionPercent", { type: "number", default: 0.7 });
ControllerAlpha.attributes.add("NormalMotionPercent", { type: "number", default: 0.93 });
ControllerAlpha.attributes.add("EventMotionPercent", { type: "number", default: 0.45 });
ControllerAlpha.attributes.add("EventBokehPercent", { type: "number", default: 0.0008 });
ControllerAlpha.attributes.add("EventBokehFOCUSPercent", { type: "number", default: 0.0008 });
ControllerAlpha.attributes.add("NormalBokehPercent", { type: "number", default: 0.0002 });

// Initialization  bersekBoom   darkness offset
ControllerAlpha.prototype.initialize = function () {
    this.resetFlags();
    this.setupInputListeners();
    this.prevGamepadState = {};

    this.boostDisabled = false;
    this.boostDisabledOP = false;
    this.boostDisabledOPbersek = false;
    this.updateBoostDisabledOP();
    this.updateBerserker();

    this.leftShift = false;
    this.rightShift = false;

    window.addEventListener('keydown', (e) => {
        if (e.key === "Shift" && e.location === 1) this.leftShift = true;
        if (e.key === "Shift" && e.location === 2) this.rightShift = true;
    });

    window.addEventListener('keyup', (e) => {
        if (e.key === "Shift" && e.location === 1) this.leftShift = false;
        if (e.key === "Shift" && e.location === 2) this.rightShift = false;
    });
    this.entity.collision.on('contact', this.onContact, this);
};

ControllerAlpha.prototype.onContact = function (result) {
    if (this.entity.sound) {
        this.entity.sound.play("hitBox");
    }
    this.hit.particlesystem.reset();
    this.hit.particlesystem.play();

    this.app.fire('boostDisabledOP:active');


    // Restore camera after delay
    setTimeout(() => {

        this.app.fire('boostDisabledOP:end');


    }, 700);
};

ControllerAlpha.prototype.resetFlags = function () {
    this.velocityX = this.velocityY = this.velocityZ = 0;
    this.speed = 0;
    this.engineOn = true;
    this.can = true;
    this.ControllerAlphas = true;
    this.force_gravity = 0;
    this.force_lift = 2.5;
    this.k = false;
    this.temp = false;
    this.isonfire = false;
    this.timeSinceLastClick = this.doubleClickSpeed;
};

ControllerAlpha.prototype.setupInputListeners = function () {
    if (this.app.mouse) {
        this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
        this.app.mouse.on(pc.EVENT_MOUSEUP, this.onMouseUp, this);
    }
    if (this.app.touch) {
        this.app.touch.on(pc.EVENT_TOUCHSTART, this.onTouchStart, this);
        this.app.touch.on(pc.EVENT_TOUCHEND, this.onTouchEndCancel, this);
        this.app.touch.on(pc.EVENT_TOUCHCANCEL, this.onTouchEndCancel, this);
    }
};

ControllerAlpha.prototype.update = function (dt) {
    this.updateGamepadState();
    this.handleInput(dt);
    this.handleSoundEffects();
    this.handleFlightPhysics(dt);
    this.updateUI();
};

ControllerAlpha.prototype.updateGamepadState = function () {
    this.gamepad = navigator.getGamepads()[0];
    this.usingGamepad = this.gamepad && this.gamepad.connected;
};

ControllerAlpha.prototype.handleInput = function (dt) {
    const deadZone = this.deadzone;
    const axisLX = this.usingGamepad ? this.gamepad.axes[0] : 0;
    const axisLY = this.usingGamepad ? this.gamepad.axes[1] : 0;
    const axisRX = this.usingGamepad ? this.gamepad.axes[2] : 0;

    const btn = (index) => this.usingGamepad && this.gamepad.buttons[index]?.pressed;

    this.isWDown = this.app.keyboard.isPressed(pc.KEY_W) || (axisLY < -deadZone);
    this.isSDown = this.app.keyboard.isPressed(pc.KEY_S) || (axisLY > deadZone);
    this.isADown = this.app.keyboard.isPressed(pc.KEY_A) || (axisLX < -deadZone);
    this.isDDown = this.app.keyboard.isPressed(pc.KEY_D) || (axisLX > deadZone);

    this.isqdown = this.app.keyboard.isPressed(pc.KEY_Q) || (axisRX < -deadZone);
    this.isedown = this.app.keyboard.isPressed(pc.KEY_E) || (axisRX > deadZone);

    this.isSpaceDown = this.app.keyboard.isPressed(pc.KEY_SPACE) || btn(0);
    this.isXDown = this.app.keyboard.isPressed(pc.KEY_X) || btn(4);

    if (!this.boostDisabled) {
        const boostNow = (this.shiftDown && this.app.keyboard.isPressed(pc.KEY_UP)) || (btn(9) && btn(8));

        if (boostNow && !this.shiftDownBoost) {
            this.app.fire('boost:active');
            // this.entity.script.fireballAttack.enabled = false; // 🔥 disable fireball
        }

        if (!boostNow && this.shiftDownBoost) {
            this.app.fire('boost:end');
            //this.entity.script.fireballAttack.enabled = true; // 🔥 enable fireball
        }

        this.shiftDownBoost = boostNow;
    } else {
        this.app.fire('boost:end');
        //his.entity.script.fireballAttack.enabled = true; // 🔥 enable fireball
        this.shiftDownBoost = false;
    }

    if (!this.boostDisabledOP) {
        this.shiftDown = this.app.keyboard.isPressed(pc.KEY_SHIFT) || btn(9);

    } else {
        this.shiftDown = false;

    }

    if (!this.boostDisabledOPbersek) {
        const bersekbreak = (this.app.keyboard.isPressed(pc.KEY_SHIFT) && this.app.keyboard.isPressed(pc.KEY_CONTROL) && this.app.keyboard.isPressed(pc.KEY_UP)) || (btn(9) && btn(8) && btn(7));

        if (bersekbreak && !this.bersekbooster) {
            this.app.fire('bersekboost:active');
            this.entity.sound.play('bersekrer');
            this.entity.script.thermalVison.enabled = false;
            // this.entity.script.fireballAttack.enabled = false; // 🔥 disable fireball
        }

        if (!bersekbreak && this.bersekbooster) {
            this.app.fire('bersekboost:end');
            this.entity.sound.play('laugh');
            this.entity.script.thermalVison.enabled = true;
            //  this.entity.script.fireballAttack.enabled = true; // 🔥 enable fireball
        }

        this.bersekbooster = bersekbreak;
    } else {
        if (this.bersekbooster) {
            this.app.fire('bersekboost:end');
            //   this.entity.script.fireballAttack.enabled = true; // 🔥 enable fireball
        }
        this.bersekbooster = false;
    }
};
// Audio logic// Audio logic
ControllerAlpha.prototype.handleSoundEffects = function () {

    const btn = (index) => this.usingGamepad && this.gamepad.buttons[index]?.pressed;
    const deadZone = this.deadzone;
    // this.originalAmount = this.playerCam.script.movementBlur.amount;

    const axisLX = this.usingGamepad ? this.gamepad.axes[0] : 0;
    const axisLY = this.usingGamepad ? this.gamepad.axes[1] : 0;
    const axisRX = this.usingGamepad ? this.gamepad.axes[2] : 0;
    // const axisRY = this.usingGamepad ? this.gamepad.axes[3] : 0;

    if (this.app.keyboard.wasPressed(pc.KEY_W) || (axisLY < -deadZone)) this.entity.sound.play('boost');
    if (this.app.keyboard.isPressed(pc.KEY_W) || (axisLY < -deadZone)) this.entity.sound.play('boost');

    if (this.app.keyboard.isPressed(pc.KEY_W) || (axisLY < -deadZone)) this.entity.sound.play('boost');

    if (this.app.keyboard.wasPressed(pc.KEY_W) || (axisLY < -deadZone)) this.entity.sound.play('up');
    if (this.app.keyboard.isPressed(pc.KEY_W) || (axisLY < -deadZone)) this.entity.sound.play('up');
    if (this.app.keyboard.wasPressed(pc.KEY_S) || (axisLY > deadZone)) this.entity.sound.play('up');
    if (this.app.keyboard.isPressed(pc.KEY_S) || (axisLY > deadZone)) this.entity.sound.play('up');
    if (this.leftShift && this.rightShift && this.app.keyboard.isPressed(pc.KEY_UP) || (btn(9) && btn(8) && btn(7))) this.entity.sound.play('bersekrer');
    if (this.app.keyboard.wasPressed(pc.KEY_Q) || (axisRX < -deadZone)) this.entity.sound.play('zoom');
    if (this.app.keyboard.isPressed(pc.KEY_Q) || (axisRX < -deadZone)) this.entity.sound.play('zoom');
    if (this.app.keyboard.isPressed(pc.KEY_E) || (axisRX > deadZone)) this.entity.sound.play('zoom');
    if (this.app.keyboard.wasPressed(pc.KEY_E) || (axisRX > deadZone)) this.entity.sound.play('zoom');
    if (this.app.keyboard.wasPressed(pc.KEY_SPACE) || btn(0)) this.entity.sound.play('up');
    if (this.app.keyboard.isPressed(pc.KEY_SPACE) || btn(0)) this.entity.sound.play('up');
    if (this.app.keyboard.wasPressed(pc.KEY_X) || btn(4)) this.entity.sound.play('zoom');
    if (this.app.keyboard.isPressed(pc.KEY_X) || btn(4)) this.entity.sound.play('zoom');

    //   this.playerCam.script.movementBlur.amount = this.originalAmount; // = Start + Select
    //   this.entity.sound.play('laugh');

};
// Physics & movement logic
ControllerAlpha.prototype.handleFlightPhysics = function (dt) {

    const entity = this.entity;

    if (!this.can) {
        this.resetMotion();
        return;
    }

    if (this.shiftDown && this.engineOn) {
        entity.rigidbody.teleport(entity.getPosition(this.entity.translateLocal(0, 0, this.speed / 3)));
        this.boost_EXP.particlesystem.reset();
        this.boost_EXP.particlesystem.play();
        if (this.speed < 23) this.speed += 0.05;
        // this.entity.sound.play('boost');
        // this.entity.script.fireballAttack.enabled = false; // 🔥 disable fireball

        if (this.playerCam && this.playerCam.script && this.playerCam.script.movementBlur) {
            this.playerCam.script.movementBlur.amount = this.EventMotionPercent;
        }
        //   this.entity.script.fireballAttack.enabled = true; // 🔥 disable fireball

        if (this.playerCam && this.playerCam.script && this.playerCam.script.bokeh) {
            this.playerCam.script.bokeh.maxBlur = this.EventBokehPercent;
            this.playerCam.script.bokeh.focus = this.EventBokehFOCUSPercent;
            this.playerCam.script.bokeh.aperture = 0.5;
        }
        // this.entity.script.fireballAttack.enabled = false; // 🔥 disable fireball


    } else {
        //   this.entity.sound.stop('boost-ultra');

        // 🔥 Reset camera effect when not boosting
        if (this.playerCam && this.playerCam.script && this.playerCam.script.movementBlur) {
            this.playerCam.script.movementBlur.amount = this.NormalMotionPercent;
        }

        if (this.playerCam && this.playerCam.script && this.playerCam.script.bokeh) {
            this.playerCam.script.bokeh.maxBlur = this.NormalBokehPercent;
            this.playerCam.script.bokeh.aperture = 1;
            this.playerCam.script.bokeh.focus = 1;

        }
        //  this.entity.script.fireballAttack.enabled = true; // 🔥 disable fireball


    }

    if (this.shiftDownBoost && this.engineOn) {
        entity.rigidbody.teleport(entity.getPosition(this.entity.translateLocal(0, 0, this.speed)));
        this.boost_EXP2.particlesystem.reset();
        this.boost_EXP2.particlesystem.play();
        if (this.speed < 35) this.speed += 0.2;
        //  this.entity.sound.play('boost-ultra');

        // 🔥 Camera effect ON while boosting
        if (this.playerCam && this.playerCam.script && this.playerCam.script.movementBlur) {
            this.playerCam.script.movementBlur.amount = this.MaxEventMotionPercent;
        }

        //  this.entity.script.fireballAttack.enabled = false; // 🔥 disable fireball

    } else {
        //   this.entity.sound.stop('boost-ultra');

        // 🔥 Reset camera effect when not boosting
        if (this.playerCam && this.playerCam.script && this.playerCam.script.movementBlur) {
            this.playerCam.script.movementBlur.amount = this.NormalMotionPercent;
        }
        // this.entity.script.fireballAttack.enabled = true; // 🔥 disable fireball

    }


    if (!this.shiftDown && !this.shiftDownBoost && this.engineOn) {
        if (this.speed > 4) this.speed -= 0.1;
        if (this.speed < 4) this.speed += 0.15;
        //   this.entity.sound.play('boost-ultra');
        //   this.entity.script.fireballAttack.enabled = false; // 🔥 disable fireball

        this.app.fire('boost:activeHalf');




    } else {
        //  this.entity.sound.stop('boost-ultra');
        this.app.fire('boost:endHalf');

        //  this.entity.script.fireballAttack.enabled = true; // 🔥 disable fireball

    }


    if (!this.engineOn && this.speed > 0) {
        this.speed -= 0.05;
    }



    if (this.bersekbooster && this.engineOn) {
        entity.rigidbody.teleport(entity.getPosition(this.entity.translateLocal(0, 0, this.speed * 4.2)));
        this.bersekBoom.particlesystem.reset();
        this.bersekBoom.particlesystem.play();
        this.bersekBoom.particlesystem.reset();

        this.boost_EXP2.enabled = false;
        this.entity.script.thermalVison.enabled = false;
        //   this.entity.script.fireballAttack.enabled = false; // 🔥 disable fireball

        if (this.speed < 50) this.speed += 0.3;
        if (this.playerCam && this.playerCam.script && this.playerCam.script.movementBlur) {
            this.playerCam.script.movementBlur.amount = this.EventMotionPercent - 0.263;
        }
        if (this.playerCam && this.playerCam.script && this.playerCam.script.cameraDepthOfField) {
            this.playerCam.script.cameraDepthOfField.focusMode = 1.4;
            this.playerCam.script.cameraDepthOfField.highlightThreshold = 0.35;
            this.playerCam.script.cameraDepthOfField.chromaticAberrationIntensity = 4;
        }

        if (this.playerCam && this.playerCam.script && this.playerCam.script.postEffectOutline) {
            this.playerCam.script.postEffectOutline.enabled = true;
        }

        if (this.playerCam && this.playerCam.script && this.playerCam.script.hueSaturation) {
            this.playerCam.script.hueSaturation.hue = 0;
            this.playerCam.script.hueSaturation.saturation = 0.8937;
        }

        if (this.playerCam && this.playerCam.script && this.playerCam.script.vignette) {
            this.playerCam.script.vignette.offset = 1.45;
            this.playerCam.script.vignette.darkness = 1;
        }

    } else {

        // 🔥 Reset camera effect when not boosting
        if (this.playerCam && this.playerCam.script && this.playerCam.script.movementBlur) {
            this.playerCam.script.movementBlur.amount = this.NormalMotionPercent;
        }

        if (this.playerCam && this.playerCam.script && this.playerCam.script.cameraDepthOfField) {
            this.playerCam.script.cameraDepthOfField.focusMode = this.focusMode;
            this.playerCam.script.cameraDepthOfField.highlightThreshold = this.highlightThreshold;
            this.playerCam.script.cameraDepthOfField.chromaticAberrationIntensity = this.chromaticAberrationIntensity;
        }

        if (this.playerCam && this.playerCam.script && this.playerCam.script.hueSaturation) {
            this.playerCam.script.hueSaturation.hue = this.hue;
            this.playerCam.script.hueSaturation.saturation = this.sat;
        }

        if (this.playerCam && this.playerCam.script && this.playerCam.script.postEffectOutline) {
            this.playerCam.script.postEffectOutline.enabled = false;
        }

        if (this.playerCam && this.playerCam.script && this.playerCam.script.vignette) {
            this.playerCam.script.vignette.offset = this.offset;
            this.playerCam.script.vignette.darkness = this.darkness;
        }
        this.entity.script.thermalVison.enabled = true;
        //  this.entity.script.fireballAttack.enabled = true; // 🔥 disable fireball

        this.boost_EXP2.enabled = true;

    }
    this.applyDirectionalVelocity(dt);
    this.applyRotation(dt);

};

// Reset movement
ControllerAlpha.prototype.resetMotion = function () {
    this.shiftDown = false;
    this.velocityX = this.velocityY = this.velocityZ = 0;
    this.speed = 0.0435;
};

// Fire event when boostDisabledOP changes
ControllerAlpha.prototype.updateBoostDisabledOP = function () {
    if (this.boostDisabledOPPrev === undefined) this.boostDisabledOPPrev = this.boostDisabledOP;

    if (this.boostDisabledOP !== this.boostDisabledOPPrev) {
        if (this.boostDisabledOP) {
            this.app.fire('boostDisabledOP:active');
        } else {
            this.app.fire('boostDisabledOP:end');
        }
        this.boostDisabledOPPrev = this.boostDisabledOP;
    }
};

ControllerAlpha.prototype.updateBerserker = function () {
    if (this.berserkerOPPrev === undefined) this.berserkerOPPrev = this.bersekbooster;

    if (this.bersekbooster !== this.berserkerOPPrev) {
        if (this.bersekbooster) {
            this.app.fire('bersekboost:active');
        } else {
            this.app.fire('bersekboost:end');
        }
        this.berserkerOPPrev = this.bersekbooster;
    }
};

// Apply directional velocity
ControllerAlpha.prototype.applyDirectionalVelocity = function () {
    if (this.isWDown && !this.isSDown) {
        this.Forward_EXP.particlesystem.reset();
        this.Forward_EXP.particlesystem.play();
        //   this.entity.sound.play('up');
        this.velocityX = Math.max(this.velocityX - 0.01, -1);
    } else if (this.isSDown && !this.isWDown) {
        this.velocityX = Math.min(this.velocityX + 0.01, 1);
        //    this.entity.sound.play('up');
    } else {
        this.velocityX *= 0.935;
        //    this.entity.sound.stop('up');
    }

    if (this.isDDown && !this.isADown) {
        //    this.entity.sound.play('zoom');
        this.velocityZ = Math.min(this.velocityZ + 0.1, 3);
    } else if (this.isADown && !this.isDDown) {
        //    this.entity.sound.play('zoom');
        this.velocityZ = Math.max(this.velocityZ - 0.1, -3);
    } else {
        this.velocityZ *= 0.935;
        //     this.entity.sound.stop('zoom');

    }

    if (this.isqdown && !this.isedown) {
        //    this.entity.sound.play('zoom');
        this.velocityY = Math.min(this.velocityY + 0.3, 0.3);
    } else if (this.isedown && !this.isqdown) {
        //    this.entity.sound.play('zoom');
        this.velocityY = Math.max(this.velocityY - 0.3, -0.3);
    } else {
        this.velocityY *= 0.935;
        //     this.entity.sound.stop('zoom');

    }
};

// Apply pitch/roll rotation
ControllerAlpha.prototype.applyRotation = function () {
    const entity = this.entity;
    if (this.isSpaceDown && !this.isXDown) {
        entity.rigidbody.teleport(entity.getPosition(), entity.rotateLocal(-1.45, 0, 0));
        //    this.entity.sound.play('zoom');
    } else if (this.isXDown && !this.isSpaceDown) {
        entity.rigidbody.teleport(entity.getPosition(), entity.rotateLocal(1.65, 0, 0));
        //    this.entity.sound.play('zoom');
    } else {
        //    this.entity.sound.stop('zoom');
    }

    entity.rigidbody.teleport(entity.getPosition(this.entity.rotateLocal(this.velocityX, this.velocityY, this.velocityZ)));
    this.entity.rigidbody.teleport(entity.getPosition(), entity.translateLocal(0, this.force_gravity, 0));
    entity.rigidbody.teleport(entity.getPosition(this.entity.translateLocal(0, 0, this.speed / 7)));
};

// UI feedback
ControllerAlpha.prototype.updateUI = function (io) {
    this.txtas.element.text = 'SPATIAL METER: ' + Math.floor(this.speed * 50000);
    this.txtas.element.color = (this.speed < 1) ? new pc.Color(1, 0, 0) : new pc.Color(0, 1, 0);
    if (this.entity.getPosition().y > 100000 || this.entity.getPosition().x > 100000 || this.entity.getPosition().z > 100000) {
        this.airsp.element.text = 'LIMIT_BREAKER';
    } else {
        this.airsp.element.text = 'IN-BOUND';
    }

};

Not sure if it helps much but let me know!

Thanks for the reply!

I think the problem I have is because I’m using Typescript and not Javascript. I’m also not using the PlayCanvas Editor, I’m just using the engine.

Everyframe you get the gamepad 0 to validate if the player is using the gamepad and you store a reference to this.gamepad.

I’m going like this:

const canvas = document.getElementById('application') as  HTMLCanvasElement | OffscreenCanvas;
const gamepads = new pc.GamePads();
const app = new pc.Application(canvas, {
        gamepads: gamepads
    });
const gamepad = gamepads.findByIndex(pc.PAD_1);

I would like to pass a typed reference to another function with the gamepad instead of getting from gamepads on every function.

1 Like