diff --git a/src/main.js b/src/main.js index 59d2acf..c946be4 100644 --- a/src/main.js +++ b/src/main.js @@ -11,7 +11,8 @@ class ForestScene extends Phaser.Scene { this.acorns = 0; this.mushrooms = 0; this.totalMushrooms = 5; - this.touch = { left: false, right: false, jump: false }; + this.touch = { left: false, right: false }; + this.touchPointers = { left: new Set(), right: new Set() }; } create() { @@ -240,9 +241,12 @@ class ForestScene extends Phaser.Scene { this.add.rectangle(WORLD_WIDTH / 2, GROUND_Y + 2, WORLD_WIDTH, 20, 0x55714a); const branchPositions = [ - [520, 520], [900, 445], [1320, 525], [1680, 415], [2050, 505], - [2470, 430], [2910, 515], [3370, 405], [3800, 500], [4230, 425], - [4680, 520], [5100, 430] + [500, 545], [720, 505], [900, 465], + [1260, 545], [1480, 505], [1680, 465], + [2050, 545], [2260, 505], [2470, 465], + [2900, 545], [3140, 505], [3370, 465], + [3800, 545], [4010, 505], [4230, 465], + [4680, 545], [4890, 505], [5100, 465] ]; branchPositions.forEach(([x, y], index) => { @@ -431,8 +435,12 @@ class ForestScene extends Phaser.Scene { this.cursors = this.input.keyboard.createCursorKeys(); this.keys = this.input.keyboard.addKeys('A,D,W,SPACE'); - const makeButton = (x, y, label, onDown, onUp) => { - const circle = this.add.circle(x, y, 34, 0x15261e, 0.55) + // Phaser only tracks a limited pointer set by default. Add enough pointers + // for a movement thumb and a separate jump thumb on touch devices. + this.input.addPointer(3); + + const makeButton = (x, y, label) => { + const circle = this.add.circle(x, y, 40, 0x15261e, 0.55) .setScrollFactor(0) .setDepth(40) .setStrokeStyle(2, 0xe0eadb, 0.35) @@ -440,30 +448,45 @@ class ForestScene extends Phaser.Scene { const text = this.add.text(x, y - 2, label, { fontFamily: 'Arial, sans-serif', - fontSize: '24px', + fontSize: '26px', color: '#edf4e9' }).setOrigin(0.5).setScrollFactor(0).setDepth(41); - circle.on('pointerdown', onDown); - circle.on('pointerup', onUp); - circle.on('pointerout', onUp); return { circle, text }; }; - this.leftBtn = makeButton(68, this.scale.height - 70, '‹', - () => { this.touch.left = true; }, - () => { this.touch.left = false; } - ); + const bindHold = (button, action) => { + button.circle.on('pointerdown', pointer => { + this.touchPointers[action].add(pointer.id); + this.touch[action] = true; + }); + }; - this.rightBtn = makeButton(146, this.scale.height - 70, '›', - () => { this.touch.right = true; }, - () => { this.touch.right = false; } - ); + const releasePointer = pointer => { + for (const action of ['left', 'right']) { + this.touchPointers[action].delete(pointer.id); + this.touch[action] = this.touchPointers[action].size > 0; + } + }; - this.jumpBtn = makeButton(this.scale.width - 74, this.scale.height - 70, '↑', - () => { this.touch.jump = true; }, - () => { this.touch.jump = false; } - ); + this.leftBtn = makeButton(68, this.scale.height - 70, '‹'); + this.rightBtn = makeButton(156, this.scale.height - 70, '›'); + this.jumpBtn = makeButton(this.scale.width - 74, this.scale.height - 70, '↑'); + + bindHold(this.leftBtn, 'left'); + bindHold(this.rightBtn, 'right'); + + // Jump fires immediately for its own pointer while the movement pointer can + // remain held down at the same time. + this.jumpBtn.circle.on('pointerdown', () => this.tryJump()); + this.input.on('pointerup', releasePointer); + this.input.on('pointerupoutside', releasePointer); + this.input.on('gameout', () => { + this.touchPointers.left.clear(); + this.touchPointers.right.clear(); + this.touch.left = false; + this.touch.right = false; + }); this.input.keyboard.on('keydown-UP', () => this.tryJump()); this.input.keyboard.on('keydown-W', () => this.tryJump()); @@ -474,8 +497,8 @@ class ForestScene extends Phaser.Scene { if (!this.leftBtn) return; this.leftBtn.circle.setPosition(68, height - 70); this.leftBtn.text.setPosition(68, height - 72); - this.rightBtn.circle.setPosition(146, height - 70); - this.rightBtn.text.setPosition(146, height - 72); + this.rightBtn.circle.setPosition(156, height - 70); + this.rightBtn.text.setPosition(156, height - 72); this.jumpBtn.circle.setPosition(width - 74, height - 70); this.jumpBtn.text.setPosition(width - 74, height - 72); } @@ -483,7 +506,7 @@ class ForestScene extends Phaser.Scene { tryJump() { if (!this.player?.body) return; if (this.player.body.blocked.down || this.player.body.touching.down) { - this.player.setVelocityY(-470); + this.player.setVelocityY(-520); this.player.setAngularVelocity(this.player.flipX ? -25 : 25); this.time.delayedCall(180, () => this.player?.setAngularVelocity(0)); } @@ -562,11 +585,6 @@ class ForestScene extends Phaser.Scene { this.player.setAccelerationX(0); } - if (this.touch.jump) { - this.tryJump(); - this.touch.jump = false; - } - const grounded = this.player.body.blocked.down || this.player.body.touching.down; if (grounded) { this.player.setAngle(0);