Skip to content

Commit cfb9d85

Browse files
committed
new 2D ship game 2
1 parent ac8fc99 commit cfb9d85

File tree

3 files changed

+164
-1
lines changed

3 files changed

+164
-1
lines changed

client/ship.html

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Ship Game - Time Helm</title>
7+
<style>
8+
* {
9+
margin: 0;
10+
padding: 0;
11+
box-sizing: border-box;
12+
}
13+
body {
14+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
15+
overflow: hidden;
16+
background: #000;
17+
}
18+
#ship-game-container {
19+
width: 100vw;
20+
height: 100vh;
21+
}
22+
</style>
23+
</head>
24+
<body>
25+
<div id="ship-game-container"></div>
26+
<script type="module" src="/src/ship.ts"></script>
27+
</body>
28+
</html>
29+
30+

client/src/commit_time.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2026-01-28T19:57:20.090Z
1+
2026-01-28T19:57:36.233Z

client/src/ship.ts

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/**
2+
* Ship Game - A 2D Phaser game
3+
*
4+
* Entry point for the ship game accessible at /ship
5+
*/
6+
7+
import Phaser from 'phaser';
8+
9+
/**
10+
* Main game scene for the ship game
11+
*/
12+
class ShipScene extends Phaser.Scene {
13+
private ship: Phaser.GameObjects.Sprite | null = null;
14+
private cursors: Phaser.Types.Input.Keyboard.CursorKeys | null = null;
15+
private wasdKeys: Record<string, Phaser.Input.Keyboard.Key> | null = null;
16+
private readonly shipSpeed = 200;
17+
18+
constructor() {
19+
super({ key: 'ShipScene' });
20+
}
21+
22+
create(): void {
23+
// Set background color
24+
this.cameras.main.setBackgroundColor('#1a1a2e');
25+
26+
// Create a simple ship sprite (using a rectangle for now)
27+
// In a real game, you'd load an image asset
28+
const graphics = this.add.graphics();
29+
graphics.fillStyle(0x00ff00);
30+
graphics.fillTriangle(0, -20, -15, 15, 15, 15);
31+
graphics.generateTexture('ship', 30, 30);
32+
graphics.destroy();
33+
34+
// Create ship sprite at center
35+
this.ship = this.add.sprite(400, 300, 'ship');
36+
this.ship.setOrigin(0.5, 0.5);
37+
38+
// Set up keyboard input
39+
this.cursors = this.input.keyboard?.createCursorKeys() || null;
40+
41+
// Add WASD keys as alternative
42+
if (this.input.keyboard) {
43+
this.wasdKeys = this.input.keyboard.addKeys('W,S,A,D') as Record<string, Phaser.Input.Keyboard.Key>;
44+
}
45+
46+
// Add instructions text
47+
const instructions = this.add.text(10, 10, 'Ship Game\nArrow Keys or WASD to move', {
48+
fontSize: '16px',
49+
color: '#ffffff',
50+
backgroundColor: '#000000',
51+
padding: { x: 10, y: 5 }
52+
});
53+
instructions.setScrollFactor(0);
54+
}
55+
56+
update(): void {
57+
if (!this.ship || !this.cursors) {
58+
return;
59+
}
60+
61+
const delta = this.game.loop.delta;
62+
63+
// Calculate movement
64+
let velocityX = 0;
65+
let velocityY = 0;
66+
67+
// Check arrow keys or WASD
68+
const left = this.cursors.left?.isDown || this.wasdKeys?.A?.isDown || false;
69+
const right = this.cursors.right?.isDown || this.wasdKeys?.D?.isDown || false;
70+
const up = this.cursors.up?.isDown || this.wasdKeys?.W?.isDown || false;
71+
const down = this.cursors.down?.isDown || this.wasdKeys?.S?.isDown || false;
72+
73+
if (left) {
74+
velocityX = -this.shipSpeed;
75+
} else if (right) {
76+
velocityX = this.shipSpeed;
77+
}
78+
79+
if (up) {
80+
velocityY = -this.shipSpeed;
81+
} else if (down) {
82+
velocityY = this.shipSpeed;
83+
}
84+
85+
// Normalize diagonal movement
86+
if (velocityX !== 0 && velocityY !== 0) {
87+
const length = Math.sqrt(velocityX * velocityX + velocityY * velocityY);
88+
velocityX = (velocityX / length) * this.shipSpeed;
89+
velocityY = (velocityY / length) * this.shipSpeed;
90+
}
91+
92+
// Update ship position
93+
const deltaSeconds = delta / 1000;
94+
this.ship.x += velocityX * deltaSeconds;
95+
this.ship.y += velocityY * deltaSeconds;
96+
97+
// Rotate ship to face movement direction
98+
if (velocityX !== 0 || velocityY !== 0) {
99+
const angle = Math.atan2(velocityY, velocityX) * (180 / Math.PI) + 90;
100+
this.ship.rotation = Phaser.Math.DegToRad(angle);
101+
}
102+
103+
// Keep ship within bounds
104+
const width = this.cameras.main.width;
105+
const height = this.cameras.main.height;
106+
this.ship.x = Phaser.Math.Clamp(this.ship.x, 0, width);
107+
this.ship.y = Phaser.Math.Clamp(this.ship.y, 0, height);
108+
}
109+
}
110+
111+
/**
112+
* Phaser game configuration
113+
*/
114+
const config: Phaser.Types.Core.GameConfig = {
115+
type: Phaser.AUTO,
116+
width: 800,
117+
height: 600,
118+
parent: 'ship-game-container',
119+
backgroundColor: '#1a1a2e',
120+
scene: ShipScene,
121+
physics: {
122+
default: 'arcade',
123+
arcade: {
124+
gravity: { x: 0, y: 0 },
125+
debug: false
126+
}
127+
}
128+
};
129+
130+
// Initialize the game
131+
new Phaser.Game(config);
132+
133+

0 commit comments

Comments
 (0)