Jump to content

Problems with a class for virtual controls


ylluminarious
 Share

Recommended Posts

In my game, I need some buttons that will work on mobile devices (buttons that you can press and/or hold in the game). I saw this example (note that the version of Phaser being used here is old, however, it still works) and was able to temporarily have some working buttons. Here's the source code for that example.

 

However, one thing bothered me about this example's code for the creation of these virtual gamepad buttons: the buttons' code wasn't DRY (Don't Repeat Yourself). You can see how these buttons keep getting created in the same fashion here over and over again:

 



// create our virtual game controller buttons
buttonjump = game.add.button(660, 340, 'buttonjump', null, this, 0, 1, 0, 1); //game, x, y, key, callback, callbackContext, overFrame, outFrame, downFrame, upFrame
buttonjump.anchor.setTo(0.5, 0.5);
buttonjump.fixedToCamera = true; //our buttons should stay on the same place
buttonjump.events.onInputOver.add(function(){jump=true;});
buttonjump.events.onInputOut.add(function(){jump=false;});
buttonjump.events.onInputDown.add(function(){jump=true;});
buttonjump.events.onInputUp.add(function(){jump=false;});

buttonfire = game.add.button(750, 340, 'buttonfire', null, this, 0, 1, 0, 1);
buttonfire.anchor.setTo(0.5, 0.5);
buttonfire.fixedToCamera = true;
buttonfire.events.onInputOver.add(function(){fire=true;});
buttonfire.events.onInputOut.add(function(){fire=false;});
buttonfire.events.onInputDown.add(function(){fire=true;});
buttonfire.events.onInputUp.add(function(){fire=false;});

buttonleft = game.add.button(40, 312, 'buttonhorizontal', null, this, 0, 1, 0, 1);
buttonleft.anchor.setTo(0.5, 0.5);
buttonleft.fixedToCamera = true;
buttonleft.events.onInputOver.add(function(){left=true;});
buttonleft.events.onInputOut.add(function(){left=false;});
buttonleft.events.onInputDown.add(function(){left=true;});
buttonleft.events.onInputUp.add(function(){left=false;});

buttonbottomleft = game.add.button(48, 352, 'buttondiagonal', null, this, 6, 4, 6, 4);
buttonbottomleft.anchor.setTo(0.5, 0.5);
buttonbottomleft.fixedToCamera = true;
buttonbottomleft.events.onInputOver.add(function(){left=true;duck=true;});
buttonbottomleft.events.onInputOut.add(function(){left=false;duck=false;});
buttonbottomleft.events.onInputDown.add(function(){left=true;duck=true;});
buttonbottomleft.events.onInputUp.add(function(){left=false;duck=false;});

buttonright = game.add.button(136, 312, 'buttonhorizontal', null, this, 0, 1, 0, 1);
buttonright.anchor.setTo(0.5, 0.5);
buttonright.fixedToCamera = true;
buttonright.events.onInputOver.add(function(){right=true;});
buttonright.events.onInputOut.add(function(){right=false;});
buttonright.events.onInputDown.add(function(){right=true;});
buttonright.events.onInputUp.add(function(){right=false;});

buttonbottomright = game.add.button(128, 352, 'buttondiagonal', null, this, 7, 5, 7, 5);
buttonbottomright.anchor.setTo(0.5, 0.5);
buttonbottomright.fixedToCamera = true;
buttonbottomright.events.onInputOver.add(function(){right=true;duck=true;});
buttonbottomright.events.onInputOut.add(function(){right=false;duck=false;});
buttonbottomright.events.onInputDown.add(function(){right=true;duck=true;});
buttonbottomright.events.onInputUp.add(function(){right=false;duck=false;});

buttondown = game.add.button(88, 360, 'buttonvertical', null, this, 0, 1, 0, 1);
buttondown.anchor.setTo(0.5, 0.5);
buttondown.fixedToCamera = true;
buttondown.events.onInputOver.add(function(){duck=true;});
buttondown.events.onInputOut.add(function(){duck=false;});
buttondown.events.onInputDown.add(function(){duck=true;});
buttondown.events.onInputUp.add(function(){duck=false;});


Because they were created in such a non-DRY and, what I feel to be, inefficient way, I decided that my buttons should have a gamepad button class that they all inherit from. Unfortunately, I've been running into lots of problems trying to make this button class work.

 

I have an example here that models what I'm trying to do in my game.

 

(Here's the source code for my example)



// Global constants
var GAME_WIDTH = 800;
var GAME_HEIGHT = 600;

var ORIGIN = 0;

var TEXT_X_POS = 50;
var TEXT_Y_POS = 100;
var TEXT_STYLE = { fontSize: "16px" };

var RIGHT_BUTTON_X_POS = 600;
var RIGHT_BUTTON_Y_POS = 400;

var LEFT_BUTTON_X_POS = 100;
var LEFT_BUTTON_Y_POS = 400;

var PHASER_DUDE_Y_POS = 300;
var PHASER_DUDE_GRAVITY = 300;
var PHASER_DUDE_RIGHT_VELOCITY = 100;
var PHASER_DUDE_LEFT_VELOCITY = -100;

var STOPPED = 0;

// Global variables
var background;

var rightButton;
var movingRight;
var rightButtonDown;

var leftButton;
var movingLeft;
var leftButtonDown;

var phaserDude;

var rightKey;
var leftKey;

// New instance of Phaser.Game
var game = new Phaser.Game(GAME_WIDTH, GAME_HEIGHT, Phaser.AUTO, "game", {preload: preload, create: create, update: update});

// Mobile button class
var MobileButton = function (button, movingInADirection, isTheButtonDown, pressedMethod) {
button.events.onInputOver.add(function () {
if (isTheButtonDown === true) {
movingInADirection = true;
}
});
button.events.onInputDown.add(function () {
isTheButtonDown = true;
movingInADirection = true;
});
button.events.onInputUp.add(function () {
movingInADirection = false;
});
};

function preload () {
game.load.image("background", "sprites/sky.png");
game.load.image("left arrow", "sprites/left_arrow.png");
game.load.image("right arrow", "sprites/right_arrow.png");
game.load.image("phaser dude", "sprites/phaser_dude.png");
}

function create () {
background = game.add.image(ORIGIN, ORIGIN, "background");

game.add.text(TEXT_X_POS, TEXT_Y_POS, "Use the arrow keys or the arrow buttons below to move", TEXT_STYLE);

rightButton = game.add.button(RIGHT_BUTTON_X_POS, RIGHT_BUTTON_Y_POS, "right arrow", moveRight);

leftButtonDown = game.add.button(LEFT_BUTTON_X_POS, LEFT_BUTTON_Y_POS, "left arrow", moveLeft);

phaserDude = game.add.sprite(game.world.centerX, PHASER_DUDE_Y_POS, "phaser dude");
game.physics.arcade.enable(phaserDude);
phaserDude.body.collideWorldBounds = true;
phaserDude.body.gravity.y = PHASER_DUDE_GRAVITY;

rightKey = game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
leftKey = game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
}

function update () {
stopMoving();

if (leftKey.isDown || movingLeft === true) {
moveLeft();
}
if (rightKey.isDown || movingRight === true) {
moveRight();
}
}

function moveRight () {
phaserDude.body.velocity.x = PHASER_DUDE_RIGHT_VELOCITY;
}

function moveLeft () {
phaserDude.body.velocity.x = PHASER_DUDE_LEFT_VELOCITY;
}
function stopMoving () {
phaserDude.body.velocity.x = STOPPED;
}


As you can see, the arrow keys work fine for moving the sprite, but the mobile buttons do not work well; they only move the sprite for a frame, and then it stops moving again. I'm not sure why the keys work, yet the mobile buttons don't. The problem seems to be that the code in the class is not being run the way that I am thinking it should run (i.e., it seems like all of the code concerning the `onInputOver`, `onInputDown`, and `onInputUp` events is not being correctly run and the class is only paying attention to the method to run when a button is pressed). Can anyone figure out what the problem is with my button class?

Link to comment
Share on other sites

Ok, someone came up with a solution to this on Stack Overflow:

 

Your problem is that the onInputDown of Phaser.Button only fires once each time the button is pressed.

What you need to do is set an isDown property on the button something like this:

 

 

button.events.onInputDown.add(function () {    button.isDown = true;});button.events.onInputUp.add(function () {    button.isDown = false;});
And the in your update method check for that property:

 

function update () {    stopMoving();        if (leftKey.isDown || leftButton.isDown) {        moveLeft();    }        // Other stuff in the update method}
Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...