<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Blocksnips Demo</title>
<script src='https://cdn.jsdelivr.net/npm/phaser@3/dist/phaser.min.js'></script>
</head>
<body>
<script>
let game;
window.onload = function() {
const config = {
type: Phaser.AUTO,
width: 160, // 10 tiles * 16px
height: 160, // 10 tiles * 16px
pixelArt: true,
physics: {
default: 'arcade',
arcade: { debug: false }
},
scene: { preload, create, update }
};
game = new Phaser.Game(config);
};
let hero, enemy, coins, cursors, coinCount, text;
const HERO_SPEED = 160;
const ENEMY_SPEED = 100;
const COIN_GOAL = 10;
function preload() {
// Load assets from manifest
this.load.spritesheet('hero', 'https://labs.phaser.io/assets/sprites/dude.png', { frameWidth: 32, frameHeight: 48 });
this.load.image('badguy', 'https://labs.phaser.io/assets/sprites/baddie.png');
this.load.image('tiles', 'https://cdn.phaserfiles.com/v385/assets/tilemaps/tiles/platformer_tiles.png');
this.load.audio('theme', [
'https://cdn.phaserfiles.com/v385/assets/audio/oedipus_wizball_highscore.ogg',
'https://cdn.phaserfiles.com/v385/assets/audio/oedipus_wizball_highscore.mp3'
]);
this.load.audio('coin', 'https://labs.phaser.io/assets/audio/coin.wav'); // Assuming a coin sound
}
function create() {
// Play background music
this.sound.play('theme', { loop: true });
// Create tilemap
const mapData = [
[2,2,2,2,2,2,2,2,2,2],
[2,5,1,1,1,1,1,1,4,2],
[2,1,2,2,1,2,2,1,1,2],
[2,1,1,1,1,1,1,1,1,2],
[2,1,2,1,2,1,2,1,1,2],
[2,1,1,1,1,1,1,1,1,2],
[2,1,2,2,1,2,2,1,6,2],
[2,4,1,1,1,1,1,1,1,2],
[2,1,1,1,1,1,1,1,1,2],
[2,2,2,2,2,2,2,2,2,2]
];
const map = this.make.tilemap({ data: mapData, tileWidth: 16, tileHeight: 16 });
const tileset = map.addTilesetImage('tiles', 'tiles');
const layer = map.createLayer(0, tileset, 0, 0);
layer.setCollisionByProperty({ collides: true });
map.setTileIndexCallback([2], () => true, 'collides');
// Hero animations
this.anims.create({
key: 'idle',
frames: this.anims.generateFrameNumbers('hero', { frames: [4] }),
frameRate: 4,
repeat: -1
});
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('hero', { frames: [0,1,2,3,4,5,6,7,8] }),
frameRate: 12,
repeat: -1
});
// Spawn hero
const heroTile = map.findByIndex(5);
hero = this.physics.add.sprite(heroTile.x * 16 + 8, heroTile.y * 16 + 8, 'hero')
.setOrigin(0.5, 0.5)
.play('idle');
map.removeTileAt(heroTile.x, heroTile.y);
// Spawn enemy
const enemyTile = map.findByIndex(6);
enemy = this.physics.add.sprite(enemyTile.x * 16 + 8, enemyTile.y * 16 + 8, 'badguy')
.setOrigin(0.5, 0.5);
enemy.setVelocityX(ENEMY_SPEED); // Start moving right
map.removeTileAt(enemyTile.x, enemyTile.y);
// Spawn coins
coins = this.physics.add.group();
map.filterTiles(tile => tile.index === 4).forEach(tile => {
coins.create(tile.x * 16 + 8, tile.y * 16 + 8, 'badguy'); // Using badguy sprite as placeholder for coin
map.removeTileAt(tile.x, tile.y);
});
// Initialize coin counter
coinCount = 0;
text = this.add.text(10, 10, `Coins: ${coinCount}/${COIN_GOAL}`, { fontSize: '12px', color: '#fff' });
// Collisions
this.physics.add.collider(hero, layer);
this.physics.add.collider(enemy, layer, () => {
enemy.setVelocityX(-enemy.body.velocity.x); // Reverse direction on wall hit
});
this.physics.add.overlap(hero, enemy, () => this.scene.restart());
this.physics.add.overlap(hero, coins, collectCoin, null, this);
// Input
cursors = this.input.keyboard.createCursorKeys();
}
function update() {
// Hero movement
hero.setVelocity(0);
let moving = false;
if (cursors.left.isDown) {
hero.setVelocityX(-HERO_SPEED);
hero.setFlipX(true);
moving = true;
} else if (cursors.right.isDown) {
hero.setVelocityX(HERO_SPEED);
hero.setFlipX(false);
moving = true;
}
if (cursors.up.isDown) {
hero.setVelocityY(-HERO_SPEED);
moving = true;
} else if (cursors.down.isDown) {
hero.setVelocityY(HERO_SPEED);
moving = true;
}
// Hero animation
hero.play(moving ? 'walk' : 'idle', true);
// Enemy patrol boundaries
if (enemy.x <= 16 || enemy.x >= 144) {
enemy.setVelocityX(-enemy.body.velocity.x);
}
}
function collectCoin(hero, coin) {
coin.destroy();
this.sound.play('coin');
coinCount++;
text.setText(`Coins: ${coinCount}/${COIN_GOAL}`);
if (coinCount >= COIN_GOAL) {
this.add.text(80, 80, 'You Win!', { fontSize: '16px', color: '#fff' }).setOrigin(0.5);
this.physics.pause();
}
}
</script>
</body>
</html>