feat: init

This commit is contained in:
tiennm99 committed 2025-04-26 23:07:35 +07:00
1 parent a878bdc6b5
commit 361f558e19
18 files changed
+2175

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
.
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+17
View File
@@ -0,0 +1,17 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/style.css">
<title>Phaser - Template</title>
</head>
<body>
<div id="app">
<div id="game-container"></div>
</div>
<script type="module" src="src/main.js"></script>
</body>
</html>
+36
View File
@@ -0,0 +1,36 @@
import * as fs from 'fs';
import * as https from 'https';
const main = async () => {
const args = process.argv.slice(2);
const packageData = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
const event = args[0] || 'unknown';
const phaserVersion = packageData.dependencies.phaser;
const options = {
hostname: 'gryzor.co',
port: 443,
path: `/v/${event}/${phaserVersion}/${packageData.name}`,
method: 'GET'
};
try {
const req = https.request(options, (res) => {
res.on('data', () => {});
res.on('end', () => {
process.exit(0);
});
});
req.on('error', (error) => {
process.exit(1);
});
req.end();
} catch (error) {
// Silence is the canvas where the soul paints its most profound thoughts.
process.exit(1);
}
}
main();
+1159
View File
File diff suppressed because it is too large. Load diff
+30
View File
@@ -0,0 +1,30 @@
{
"name": "template-vite",
"description": "A Phaser 3 template using Vite.",
"version": "1.4.0",
"type": "module",
"repository": {
"type": "git",
"url": "git+https://github.com/phaserjs/template-vite.git"
},
"author": "Phaser Studio <support@phaser.io> (https://phaser.io/)",
"license": "MIT",
"licenseUrl": "http://www.opensource.org/licenses/mit-license.php",
"bugs": {
"url": "https://github.com/phaserjs/template-vite/issues"
},
"homepage": "https://github.com/phaserjs/template-vite#readme",
"scripts": {
"dev": "node log.js dev & vite --config vite/config.dev.mjs",
"build": "node log.js build & vite build --config vite/config.prod.mjs",
"dev-nolog": "vite --config vite/config.dev.mjs",
"build-nolog": "vite build --config vite/config.prod.mjs"
},
"devDependencies": {
"terser": "^5.39.0",
"vite": "^6.3.1"
},
"dependencies": {
"phaser": "^3.88.2"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

+14
View File
@@ -0,0 +1,14 @@
{
"width": 8,
"height": 8,
"tiles": [
["W", "W", "W", "W", "W", "W", "W", "W"],
["W", ".", ".", ".", ".", ".", ".", "W"],
["W", ".", ".", ".", ".", ".", ".", "W"],
["W", ".", "W", "W", ".", ".", ".", "W"],
["W", ".", ".", "B", ".", "T", ".", "W"],
["W", ".", "P", ".", ".", ".", ".", "W"],
["W", ".", ".", ".", ".", ".", ".", "W"],
["W", "W", "W", "W", "W", "W", "W", "W"]
]
}
+14
View File
@@ -0,0 +1,14 @@
{
"width": 8,
"height": 8,
"tiles": [
["W", "W", "W", "W", "W", "W", "W", "W"],
["W", ".", ".", ".", ".", ".", ".", "W"],
["W", ".", "P", ".", ".", ".", ".", "W"],
["W", ".", "B", ".", "W", ".", ".", "W"],
["W", ".", "B", ".", "T", ".", ".", "W"],
["W", ".", ".", ".", "T", ".", ".", "W"],
["W", ".", ".", ".", ".", ".", ".", "W"],
["W", "W", "W", "W", "W", "W", "W", "W"]
]
}
+16
View File
@@ -0,0 +1,16 @@
{
"width": 10,
"height": 10,
"tiles": [
["W", "W", "W", "W", "W", "W", "W", "W", "W", "W"],
["W", ".", ".", ".", ".", ".", ".", ".", ".", "W"],
["W", ".", ".", ".", "W", "W", ".", ".", ".", "W"],
["W", ".", "P", ".", ".", ".", ".", ".", ".", "W"],
["W", ".", ".", "B", ".", ".", "W", ".", ".", "W"],
["W", ".", "W", ".", "B", ".", ".", ".", ".", "W"],
["W", ".", ".", ".", ".", "B", ".", ".", ".", "W"],
["W", ".", ".", "T", "T", "T", ".", ".", ".", "W"],
["W", ".", ".", ".", ".", ".", ".", ".", ".", "W"],
["W", "W", "W", "W", "W", "W", "W", "W", "W", "W"]
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

+15
View File
@@ -0,0 +1,15 @@
body {
margin: 0;
padding: 0;
color: rgba(255, 255, 255, 0.87);
background-color: #000000;
}
#app {
width: 100%;
height: 100vh;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
+34
View File
@@ -0,0 +1,34 @@
import {Game, AUTO} from 'phaser';
import MenuScene from './scenes/MenuScene';
import LevelScene from './scenes/LevelScene';
import MainScene from './scenes/MainScene';
// Game configuration
const config = {
type: AUTO,
width: 800,
height: 600,
parent: 'game-container',
backgroundColor: '#f9f9f9',
scene: [MenuScene, LevelScene, MainScene],
physics: {
default: 'arcade',
arcade: {
gravity: {y: 0},
debug: false
}
},
pixelArt: true
};
// Create the game instance
const game = new Game(config);
// Global game variables
game.globals = {
currentLevel: 0,
totalLevels: 3, // We'll create 3 levels for now
levelCompleted: [false, false, false]
};
export default game;
+113
View File
@@ -0,0 +1,113 @@
import Phaser from 'phaser';
import game from '../main.js';
class LevelScene extends Phaser.Scene {
constructor() {
super({ key: 'LevelScene' });
}
preload() {
// Load any assets needed for the level selection
}
create() {
// Add background
this.cameras.main.setBackgroundColor('#f0f0f0');
// Add title text
const title = this.add.text(
this.cameras.main.centerX,
100,
'SELECT LEVEL',
{
fontSize: '48px',
fill: '#000',
fontStyle: 'bold'
}
);
title.setOrigin(0.5);
// Add back button
const backButton = this.add.text(
100,
50,
'< BACK',
{
fontSize: '24px',
fill: '#000',
backgroundColor: '#f0f0f0',
padding: { left: 15, right: 15, top: 5, bottom: 5 }
}
);
backButton.setInteractive({ useHandCursor: true });
// Add hover effect
backButton.on('pointerover', () => {
backButton.setStyle({ fill: '#555' });
});
backButton.on('pointerout', () => {
backButton.setStyle({ fill: '#000' });
});
// Add click event
backButton.on('pointerdown', () => {
this.scene.start('MenuScene');
});
// Create level buttons
this.createLevelButtons();
}
createLevelButtons() {
const buttonWidth = 150;
const buttonHeight = 100;
const padding = 20;
const startX = this.cameras.main.centerX - buttonWidth - padding / 2;
const startY = this.cameras.main.centerY - buttonHeight / 2;
for (let i = 0; i < game.globals.totalLevels; i++) {
const x = startX + (i % 3) * (buttonWidth + padding);
const y = startY + Math.floor(i / 3) * (buttonHeight + padding);
// Create button background
const buttonBg = this.add.rectangle(
x + buttonWidth / 2,
y + buttonHeight / 2,
buttonWidth,
buttonHeight,
game.globals.levelCompleted[i] ? 0x4CAF50 : 0x3498db
);
buttonBg.setInteractive({ useHandCursor: true });
// Add level number
const levelText = this.add.text(
x + buttonWidth / 2,
y + buttonHeight / 2,
`LEVEL ${i + 1}`,
{
fontSize: '24px',
fill: '#fff',
align: 'center'
}
);
levelText.setOrigin(0.5);
// Add click event
buttonBg.on('pointerdown', () => {
game.globals.currentLevel = i;
this.scene.start('MainScene');
});
// Add hover effect
buttonBg.on('pointerover', () => {
buttonBg.setFillStyle(game.globals.levelCompleted[i] ? 0x45a049 : 0x2980b9);
});
buttonBg.on('pointerout', () => {
buttonBg.setFillStyle(game.globals.levelCompleted[i] ? 0x4CAF50 : 0x3498db);
});
}
}
}
export default LevelScene;
+569
View File
@@ -0,0 +1,569 @@
import Phaser from 'phaser';
import game from '../main.js';
class MainScene extends Phaser.Scene {
constructor() {
super({ key: 'MainScene' });
// Game objects
this.player = null;
this.walls = null;
this.boxes = null;
this.targets = null;
// Controls
this.cursors = null;
this.keyState = {
up: false,
down: false,
left: false,
right: false
};
// Level data
this.levelData = null;
// Game state
this.isMoving = false;
this.moveDirection = { x: 0, y: 0 };
// Tile size
this.tileSize = 64;
}
preload() {
// Load level data
this.load.json('level1', 'public/assets/levels/level1.json');
this.load.json('level2', 'public/assets/levels/level2.json');
this.load.json('level3', 'public/assets/levels/level3.json');
}
create() {
// Set up controls
this.cursors = this.input.keyboard.createCursorKeys();
// Reset key state
this.keyState = {
up: false,
down: false,
left: false,
right: false
};
// Set up key release listeners
this.input.keyboard.on('keyup', (event) => {
switch (event.keyCode) {
case 37: // Left
this.keyState.left = false;
break;
case 38: // Up
this.keyState.up = false;
break;
case 39: // Right
this.keyState.right = false;
break;
case 40: // Down
this.keyState.down = false;
break;
}
});
try {
// Load level data
const levelNumber = game.globals.currentLevel + 1;
this.levelData = this.cache.json.get(`level${levelNumber}`);
if (!this.levelData || !this.levelData.tiles) {
console.error(`Failed to load level data for level ${levelNumber}`);
this.showErrorMessage(`Failed to load level ${levelNumber}`);
return;
}
// Create game objects
this.createLevel();
// Add UI elements
this.createUI();
} catch (error) {
console.error('Error creating level:', error);
this.showErrorMessage('Error loading level');
}
}
showErrorMessage(message) {
// Add error message
const errorText = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY,
message,
{
fontSize: '32px',
fill: '#FF0000',
backgroundColor: '#000000',
padding: { left: 20, right: 20, top: 10, bottom: 10 }
}
);
errorText.setOrigin(0.5);
// Add back button
const backButton = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY + 80,
'BACK TO MENU',
{
fontSize: '24px',
fill: '#FFFFFF',
backgroundColor: '#333333',
padding: { left: 15, right: 15, top: 5, bottom: 5 }
}
);
backButton.setOrigin(0.5);
backButton.setInteractive({ useHandCursor: true });
// Add hover effect
backButton.on('pointerover', () => {
backButton.setStyle({ backgroundColor: '#555555' });
});
backButton.on('pointerout', () => {
backButton.setStyle({ backgroundColor: '#333333' });
});
// Add click event
backButton.on('pointerdown', () => {
this.scene.start('MenuScene');
});
}
update() {
// Skip if player is already moving or player is not defined
if (this.isMoving || !this.player) return;
// Handle player movement with key state tracking
if (this.cursors.left.isDown && !this.keyState.left) {
this.keyState.left = true;
this.movePlayer(-1, 0);
} else if (this.cursors.right.isDown && !this.keyState.right) {
this.keyState.right = true;
this.movePlayer(1, 0);
} else if (this.cursors.up.isDown && !this.keyState.up) {
this.keyState.up = true;
this.movePlayer(0, -1);
} else if (this.cursors.down.isDown && !this.keyState.down) {
this.keyState.down = true;
this.movePlayer(0, 1);
}
// Check win condition
this.checkWinCondition();
}
createLevel() {
// Create groups for game objects
this.walls = this.physics.add.staticGroup();
this.boxes = this.physics.add.group();
this.targets = this.physics.add.staticGroup();
// Calculate level offset to center it
const levelWidth = this.levelData.width * this.tileSize;
const levelHeight = this.levelData.height * this.tileSize;
const offsetX = (this.cameras.main.width - levelWidth) / 2;
const offsetY = (this.cameras.main.height - levelHeight) / 2;
// Create floor tiles (light gray background)
this.add.rectangle(
offsetX + levelWidth / 2,
offsetY + levelHeight / 2,
levelWidth,
levelHeight,
0xeeeeee
);
// Create grid lines
const graphics = this.add.graphics();
graphics.lineStyle(1, 0xcccccc, 0.5);
// Draw horizontal grid lines
for (let y = 0; y <= this.levelData.height; y++) {
graphics.moveTo(offsetX, offsetY + y * this.tileSize);
graphics.lineTo(offsetX + levelWidth, offsetY + y * this.tileSize);
}
// Draw vertical grid lines
for (let x = 0; x <= this.levelData.width; x++) {
graphics.moveTo(offsetX + x * this.tileSize, offsetY);
graphics.lineTo(offsetX + x * this.tileSize, offsetY + levelHeight);
}
graphics.strokePath();
// Create level objects based on level data
for (let y = 0; y < this.levelData.height; y++) {
for (let x = 0; x < this.levelData.width; x++) {
const tileX = offsetX + x * this.tileSize + this.tileSize / 2;
const tileY = offsetY + y * this.tileSize + this.tileSize / 2;
const tile = this.levelData.tiles[y][x];
switch (tile) {
case 'W': // Wall (dark gray rectangle)
const wall = this.add.rectangle(tileX, tileY, this.tileSize - 4, this.tileSize - 4, 0x555555);
this.walls.add(wall);
break;
case 'B': // Box (brown rectangle)
const box = this.add.rectangle(tileX, tileY, this.tileSize - 10, this.tileSize - 10, 0x8B4513);
this.physics.add.existing(box);
box.setData('onTarget', false);
this.boxes.add(box);
break;
case 'P': // Player (blue circle)
this.player = this.add.circle(tileX, tileY, this.tileSize / 2 - 5, 0x0000FF);
this.physics.add.existing(this.player);
this.player.setData('gridX', x);
this.player.setData('gridY', y);
break;
case 'T': // Target (red circle outline)
const target = this.add.circle(tileX, tileY, this.tileSize / 3, 0xFF0000, 0.2);
target.setStrokeStyle(2, 0xFF0000);
this.targets.add(target);
break;
case 'BT': // Box on target (brown rectangle with red outline)
const targetBox = this.add.rectangle(tileX, tileY, this.tileSize - 10, this.tileSize - 10, 0x8B4513);
targetBox.setStrokeStyle(3, 0xFF0000);
this.physics.add.existing(targetBox);
targetBox.setData('onTarget', true);
this.boxes.add(targetBox);
const boxTarget = this.add.circle(tileX, tileY, this.tileSize / 3, 0xFF0000, 0.2);
boxTarget.setStrokeStyle(2, 0xFF0000);
this.targets.add(boxTarget);
break;
case '.': // Empty space - do nothing
break;
default:
console.warn(`Unknown tile type: ${tile} at position (${x}, ${y})`);
break;
}
}
}
// Set up collisions
this.physics.add.collider(this.player, this.walls);
this.physics.add.collider(this.boxes, this.walls);
this.physics.add.collider(this.boxes, this.boxes);
}
createUI() {
// Add level text
const levelText = this.add.text(
20,
20,
`LEVEL ${game.globals.currentLevel + 1}`,
{
fontSize: '24px',
fill: '#000'
}
);
// Add restart button
const restartButton = this.add.text(
this.cameras.main.width - 20,
20,
'RESTART',
{
fontSize: '24px',
fill: '#000',
backgroundColor: '#f0f0f0',
padding: { left: 15, right: 15, top: 5, bottom: 5 }
}
);
restartButton.setOrigin(1, 0);
restartButton.setInteractive({ useHandCursor: true });
// Add hover effect
restartButton.on('pointerover', () => {
restartButton.setStyle({ fill: '#555' });
});
restartButton.on('pointerout', () => {
restartButton.setStyle({ fill: '#000' });
});
// Add click event
restartButton.on('pointerdown', () => {
this.scene.restart();
});
// Add back button
const backButton = this.add.text(
20,
this.cameras.main.height - 20,
'BACK TO MENU',
{
fontSize: '24px',
fill: '#000',
backgroundColor: '#f0f0f0',
padding: { left: 15, right: 15, top: 5, bottom: 5 }
}
);
backButton.setOrigin(0, 1);
backButton.setInteractive({ useHandCursor: true });
// Add hover effect
backButton.on('pointerover', () => {
backButton.setStyle({ fill: '#555' });
});
backButton.on('pointerout', () => {
backButton.setStyle({ fill: '#000' });
});
// Add click event
backButton.on('pointerdown', () => {
this.scene.start('MenuScene');
});
}
movePlayer(dx, dy) {
// Set moving flag
this.isMoving = true;
// Get player's current grid position
const gridX = this.player.getData('gridX');
const gridY = this.player.getData('gridY');
// Calculate new position
const newX = gridX + dx;
const newY = gridY + dy;
// Check if the new position is valid
if (this.isValidMove(newX, newY, dx, dy)) {
// Update player's grid position
this.player.setData('gridX', newX);
this.player.setData('gridY', newY);
// Calculate pixel position
const levelWidth = this.levelData.width * this.tileSize;
const levelHeight = this.levelData.height * this.tileSize;
const offsetX = (this.cameras.main.width - levelWidth) / 2;
const offsetY = (this.cameras.main.height - levelHeight) / 2;
const pixelX = offsetX + newX * this.tileSize + this.tileSize / 2;
const pixelY = offsetY + newY * this.tileSize + this.tileSize / 2;
// Move player
this.tweens.add({
targets: this.player,
x: pixelX,
y: pixelY,
duration: 100,
onComplete: () => {
this.isMoving = false;
}
});
} else {
this.isMoving = false;
}
}
isValidMove(newX, newY, dx, dy) {
// Check if the new position is out of bounds
if (newX < 0 || newX >= this.levelData.width || newY < 0 || newY >= this.levelData.height) {
return false;
}
// Calculate level offset
const levelWidth = this.levelData.width * this.tileSize;
const levelHeight = this.levelData.height * this.tileSize;
const offsetX = (this.cameras.main.width - levelWidth) / 2;
const offsetY = (this.cameras.main.height - levelHeight) / 2;
// Calculate pixel position
const pixelX = offsetX + newX * this.tileSize + this.tileSize / 2;
const pixelY = offsetY + newY * this.tileSize + this.tileSize / 2;
// Check if there's a wall at the new position
let wallAtPosition = false;
this.walls.getChildren().forEach(wall => {
if (wall.x === pixelX && wall.y === pixelY) {
wallAtPosition = true;
}
});
if (wallAtPosition) {
return false;
}
// Check if there's a box at the new position
let boxAtPosition = null;
this.boxes.getChildren().forEach(box => {
if (box.x === pixelX && box.y === pixelY) {
boxAtPosition = box;
}
});
if (boxAtPosition) {
// Calculate the position behind the box
const behindX = newX + dx;
const behindY = newY + dy;
// Check if the position behind the box is valid
if (this.isValidBoxMove(behindX, behindY)) {
// Calculate pixel position behind the box
const behindPixelX = offsetX + behindX * this.tileSize + this.tileSize / 2;
const behindPixelY = offsetY + behindY * this.tileSize + this.tileSize / 2;
// Move the box
this.tweens.add({
targets: boxAtPosition,
x: behindPixelX,
y: behindPixelY,
duration: 100,
onComplete: () => {
// Check if the box is on a target
let onTarget = false;
this.targets.getChildren().forEach(target => {
if (target.x === behindPixelX && target.y === behindPixelY) {
onTarget = true;
}
});
// Update box appearance
if (onTarget) {
boxAtPosition.setStrokeStyle(3, 0xFF0000);
boxAtPosition.setData('onTarget', true);
} else {
boxAtPosition.setStrokeStyle(0);
boxAtPosition.setData('onTarget', false);
}
}
});
return true;
} else {
return false;
}
}
return true;
}
isValidBoxMove(x, y) {
// Check if the position is out of bounds
if (x < 0 || x >= this.levelData.width || y < 0 || y >= this.levelData.height) {
return false;
}
// Calculate level offset
const levelWidth = this.levelData.width * this.tileSize;
const levelHeight = this.levelData.height * this.tileSize;
const offsetX = (this.cameras.main.width - levelWidth) / 2;
const offsetY = (this.cameras.main.height - levelHeight) / 2;
// Calculate pixel position
const pixelX = offsetX + x * this.tileSize + this.tileSize / 2;
const pixelY = offsetY + y * this.tileSize + this.tileSize / 2;
// Check if there's a wall at the position
let wallAtPosition = false;
this.walls.getChildren().forEach(wall => {
if (wall.x === pixelX && wall.y === pixelY) {
wallAtPosition = true;
}
});
if (wallAtPosition) {
return false;
}
// Check if there's a box at the position
let boxAtPosition = false;
this.boxes.getChildren().forEach(box => {
if (box.x === pixelX && box.y === pixelY) {
boxAtPosition = true;
}
});
if (boxAtPosition) {
return false;
}
return true;
}
checkWinCondition() {
// Check if all boxes are on targets
let allBoxesOnTargets = true;
this.boxes.getChildren().forEach(box => {
if (!box.getData('onTarget')) {
allBoxesOnTargets = false;
}
});
if (allBoxesOnTargets && this.boxes.getChildren().length > 0) {
// Mark level as completed
game.globals.levelCompleted[game.globals.currentLevel] = true;
// Show win message
const winText = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY,
'LEVEL COMPLETE!',
{
fontSize: '48px',
fill: '#000',
backgroundColor: '#4CAF50',
padding: { left: 30, right: 30, top: 15, bottom: 15 }
}
);
winText.setOrigin(0.5);
// Add continue button
const continueButton = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY + 100,
'CONTINUE',
{
fontSize: '32px',
fill: '#000',
backgroundColor: '#f0f0f0',
padding: { left: 20, right: 20, top: 10, bottom: 10 }
}
);
continueButton.setOrigin(0.5);
continueButton.setInteractive({ useHandCursor: true });
// Add hover effect
continueButton.on('pointerover', () => {
continueButton.setStyle({ fill: '#555' });
});
continueButton.on('pointerout', () => {
continueButton.setStyle({ fill: '#000' });
});
// Add click event
continueButton.on('pointerdown', () => {
this.scene.start('LevelScene');
});
// Disable player movement
this.isMoving = true;
}
}
shutdown() {
// Clean up event listeners
this.input.keyboard.off('keyup');
// Reset key state
this.keyState = {
up: false,
down: false,
left: false,
right: false
};
}
}
export default MainScene;
+70
View File
@@ -0,0 +1,70 @@
class MenuScene extends Phaser.Scene {
constructor() {
super({ key: 'MenuScene' });
}
preload() {
// No assets to preload
}
create() {
// Add background
this.cameras.main.setBackgroundColor('#f0f0f0');
// Add title text
const title = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY - 100,
'SOKOBAN',
{
fontSize: '64px',
fill: '#000',
fontStyle: 'bold'
}
);
title.setOrigin(0.5);
// Add play button
const playButton = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY,
'PLAY',
{
fontSize: '32px',
fill: '#000',
backgroundColor: '#4CAF50',
padding: { left: 30, right: 30, top: 10, bottom: 10 }
}
);
playButton.setOrigin(0.5);
playButton.setInteractive({ useHandCursor: true });
// Add hover effect
playButton.on('pointerover', () => {
playButton.setStyle({ fill: '#fff' });
});
playButton.on('pointerout', () => {
playButton.setStyle({ fill: '#000' });
});
// Add click event
playButton.on('pointerdown', () => {
this.scene.start('LevelScene');
});
// Add instructions
const instructions = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY + 100,
'Use arrow keys to move\nPush boxes to the targets',
{
fontSize: '24px',
fill: '#000',
align: 'center'
}
);
instructions.setOrigin(0.5);
}
}
export default MenuScene;
+17
View File
@@ -0,0 +1,17 @@
import { defineConfig } from 'vite';
export default defineConfig({
base: './',
build: {
rollupOptions: {
output: {
manualChunks: {
phaser: ['phaser']
}
}
},
},
server: {
port: 8080
}
});
+47
View File
@@ -0,0 +1,47 @@
import { defineConfig } from 'vite';
const phasermsg = () => {
return {
name: 'phasermsg',
buildStart() {
process.stdout.write(`Building for production...\n`);
},
buildEnd() {
const line = "---------------------------------------------------------";
const msg = `❤️❤️❤️ Tell us about your game! - games@phaser.io ❤️❤️❤️`;
process.stdout.write(`${line}\n${msg}\n${line}\n`);
process.stdout.write(`✨ Done ✨\n`);
}
}
}
export default defineConfig({
base: './',
logLevel: 'warn',
build: {
rollupOptions: {
output: {
manualChunks: {
phaser: ['phaser']
}
}
},
minify: 'terser',
terserOptions: {
compress: {
passes: 2
},
mangle: true,
format: {
comments: false
}
}
},
server: {
port: 8080
},
plugins: [
phasermsg()
]
});