Skip to content

API Reference

Complete API documentation for Phaser Virtual Joystick.

The main class for creating and managing virtual joysticks.

new VirtualJoystick(config: VirtualJoystickParams)

Parameters:

  • config - Configuration object (see VirtualJoystickParams below)
interface VirtualJoystickParams {
scene: Phaser.Scene; // Required: The Phaser scene
deadZone?: Partial<StyleConfig>; // Optional: Dead zone styling
baseArea?: Partial<StyleConfig>; // Optional: Base area styling
stick?: Partial<StyleConfig>; // Optional: Stick styling
stickIcon?: Phaser.GameObjects.Text; // Optional: Icon on the stick
bounds?: { // Optional: Activation area
topLeft: { x: number; y: number };
bottomRight: { x: number; y: number };
};
enableWithoutTouch?: boolean; // Optional: Enable on non-touch devices
}

Each visual component (deadZone, baseArea, stick) can be customized:

interface StyleConfig {
alpha: number; // Transparency (0-1)
strokeColor: number; // Stroke color (hex)
strokeAlpha: number; // Stroke transparency (0-1)
strokeWidth: number; // Stroke width in pixels
radius: number; // Circle radius in pixels
fillColor: number; // Fill color (hex)
}

Updates the joystick state. Must be called in your scene’s update method for smooth following behavior.

update() {
this.joystick?.update();
}

Destroys the joystick and cleans up resources.

joystick.destroy();

The joystick provides the following events:

Fired when the joystick knob is moved.

joystick.on('move', (data: { x: number, y: number }) => {
console.log('Joystick moved:', data.x, data.y);
});

Event Data:

  • x - Normalized X value (-1 to 1)
  • y - Normalized Y value (-1 to 1)

Fired when the joystick is first pressed.

joystick.on('press', () => {
console.log('Joystick pressed');
});

Fired when the joystick is released.

joystick.on('release', () => {
console.log('Joystick released');
});
const joystick = new VirtualJoystick({
scene: this
});
this.add.existing(joystick);
joystick.on('move', (data) => {
player.setVelocity(data.x * 200, data.y * 200);
});
joystick.on('release', () => {
player.setVelocity(0, 0);
});
const joystick = new VirtualJoystick({
scene: this,
deadZone: {
radius: 20,
fillColor: 0xFF6B6B, // Red
alpha: 0.3,
strokeColor: 0xFF5252,
strokeWidth: 3
},
baseArea: {
radius: 80,
fillColor: 0x4ECDC4, // Teal
alpha: 0.1,
strokeColor: 0x26A69A,
strokeWidth: 4
},
stick: {
radius: 35,
fillColor: 0xFFE66D, // Yellow
alpha: 0.9,
strokeColor: 0xFFD54F,
strokeWidth: 2
}
});
const joystick = new VirtualJoystick({
scene: this,
bounds: {
topLeft: { x: 0, y: 100 },
bottomRight: { x: 400, y: 600 }
}
});
const stickIcon = this.add.text(0, 0, '🎮', {
fontSize: '24px',
color: '#ffffff'
});
const joystick = new VirtualJoystick({
scene: this,
stickIcon: stickIcon
});
const joystick = new VirtualJoystick({
scene: this,
enableWithoutTouch: true // Allows mouse interaction on desktop
});
// Left joystick for movement
const moveJoystick = new VirtualJoystick({
scene: this,
bounds: {
topLeft: { x: 0, y: 0 },
bottomRight: { x: this.cameras.main.width / 2, y: this.cameras.main.height }
}
});
// Right joystick for aiming
const aimJoystick = new VirtualJoystick({
scene: this,
bounds: {
topLeft: { x: this.cameras.main.width / 2, y: 0 },
bottomRight: { x: this.cameras.main.width, y: this.cameras.main.height }
},
stick: {
fillColor: 0xFF6B6B, // Red for aiming
radius: 30
}
});
this.add.existing(moveJoystick);
this.add.existing(aimJoystick);
interface VirtualJoystickParams {
scene: Phaser.Scene;
deadZone?: Partial<StyleConfig>;
baseArea?: Partial<StyleConfig>;
stick?: Partial<StyleConfig>;
stickIcon?: Phaser.GameObjects.Text;
bounds?: {
topLeft: { x: number; y: number };
bottomRight: { x: number; y: number };
};
enableWithoutTouch?: boolean;
}
interface StyleConfig {
alpha: number;
strokeColor: number;
strokeAlpha: number;
strokeWidth: number;
radius: number;
fillColor: number;
}
interface JoystickData {
x: number;
y: number;
}
type JoystickEvent = 'move' | 'press' | 'release';
  • Activation Area: Left half of the screen (with 20% top padding)
  • Visual Style: Blue-themed with subtle transparency
  • Dead Zone: 16px radius - no input registered in this area
  • Base Area: 64px radius - maximum joystick movement range
  • Stick: 40px radius - follows your finger with smooth following behavior
  • Touch Only: Only works on touch devices by default
  • iOS Safari 10+
  • Android Chrome 50+
  • All modern mobile browsers with touch support
  • Automatically detects touch capability
  • The joystick is optimized for 60fps gaming
  • Event handlers are called once per frame when active
  • Memory is automatically cleaned up when destroyed
  • Touch detection is cached for performance
  • Important: Always call joystick.update() in your scene’s update method