<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Phaser 3 Game - Binary Scoring</title>
<script src="https://cdn.jsdelivr.net/npm/phaser@3.80.1/dist/phaser.js"></script>
<style type="text/css">
body {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
background: #000;
}
.phaser-container {
text-align: center;
width: 100%;
max-width: 800px;
margin: 0 auto;
}
canvas {
display: block !important;
max-width: 100%;
height: auto;
margin: 0 auto;
border: 2px solid #fff;
}
#star-grid {
display: grid;
grid-template-columns: repeat(3, 50px);
grid-template-rows: repeat(4, 50px);
gap: 5px;
margin: 10px 0;
}
#star-grid img {
width: 50px;
height: 50px;
object-fit: contain;
}
</style>
</head>
<body>
<div id="star-grid"></div>
<div class="phaser-container" id="game-container"></div>

<script type="text/javascript">
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
},
parent: 'game-container'
};

var player;
var stars;
var bombs;
var platforms;
var cursors;
var score = 0;
var starsCollected = 0;
var gameOver = false;
var scoreText;
var starsText;

var game = new Phaser.Game(config);

function preload() {
this.load.image('sky', 'sky.png');
this.load.image('ground', 'platform.png');
this.load.image('star', 'star.png');
this.load.image('bomb', 'bomb.png');
this.load.spritesheet('dude', 'dude.png', { frameWidth: 32, frameHeight: 48 });
}

function create() {
// Populate star grid
var starGrid = document.getElementById('star-grid');
for (var i = 0; i < 12; i++) {
var img = document.createElement('img');
img.src = 'star.png';
starGrid.appendChild(img);
}

// Background
this.add.image(400, 300, 'sky');

// Platforms
platforms = this.physics.add.staticGroup();
platforms.create(400, 568, 'ground').setScale(2).refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');

// Player
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);

// Animations
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'turn',
frames: [{ key: 'dude', frame: 4 }],
frameRate: 20
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
frameRate: 10,
repeat: -1
});

// Input
cursors = this.input.keyboard.createCursorKeys();
this.spaceKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);

// Stars
stars = this.physics.add.group({
key: 'star',
repeat: 11,
setXY: { x: 12, y: 0, stepX: 70 }
});

stars.children.iterate(function(child) {
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});

bombs = this.physics.add.group();

// UI
scoreText = this.add.text(16, 16, 'Score: 0', { fontSize: '32px', fill: '#fff' });
starsText = this.add.text(16, 48, 'Stars: 0', { fontSize: '32px', fill: '#fff' });

// Collisions
this.physics.add.collider(player, platforms);
this.physics.add.collider(stars, platforms);
this.physics.add.collider(bombs, platforms);
this.physics.add.overlap(player, stars, collectStar, null, this);
this.physics.add.collider(player, bombs, hitBomb, null, this);
}

function update() {
if (gameOver) {
if (this.spaceKey.isDown) {
// Restart game
gameOver = false;
score = 0;
starsCollected = 0;
scoreText.setText('Score: 0');
starsText.setText('Stars: 0');
player.clearTint();
player.setPosition(100, 450);
this.physics.resume();
bombs.clear(true, true);
stars.children.iterate(child => {
child.enableBody(true, child.x, 0, true, true);
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
}
return;
}

if (cursors.left.isDown) {
player.setVelocityX(-160);
player.anims.play('left', true);
} else if (cursors.right.isDown) {
player.setVelocityX(160);
player.anims.play('right', true);
} else {
player.setVelocityX(0);
player.anims.play('turn');
}

if (cursors.up.isDown && player.body.touching.down) {
player.setVelocityY(-330);
}
}

function collectStar(player, star) {
star.disableBody(true, true);

// Binary score
score += 1;
starsCollected += 1;
scoreText.setText('Score: ' + score.toString(2));
starsText.setText('Stars: ' + starsCollected);

if (stars.countActive(true) === 0) {
stars.children.iterate(function(child) {
child.enableBody(true, child.x, 0, true, true);
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});

var x = (player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
var bomb = bombs.create(x, 16, 'bomb');
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-300, 300), 20);
bomb.setAngularVelocity(Phaser.Math.Between(-200, 200));
bomb.allowGravity = false;
}
}

function hitBomb(player, bomb) {
this.physics.pause();
player.setTint(0xff0000);
player.anims.play('turn');
gameOver = true;
}
</script>
</body>
</html>