brick-engine-cli 1.0.8 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ function run() {
12
12
  commander_1.program
13
13
  .name("brick-engine-cli")
14
14
  .description("CLI to scaffold Brick Engine projects")
15
- .version("1.0.0");
15
+ .version("1.0.8");
16
16
  commander_1.program
17
17
  .command("init <name>")
18
18
  .description("Initialize a new Brick Engine project")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brick-engine-cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "CLI to scaffold Brick Game projects",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@types/inquirer": "^8.2.12",
16
- "brick-engine-js": "^1.0.20",
16
+ "brick-engine-js": "^1.0.22",
17
17
  "chalk": "^4.1.2",
18
18
  "commander": "^11.1.0",
19
19
  "dotenv": "^17.3.1",
package/src/index.ts CHANGED
@@ -2,12 +2,13 @@ import { program } from "commander";
2
2
  import { initCommand } from "./commands/init";
3
3
  import { publishCommand } from "./commands/publish";
4
4
  import chalk from "chalk";
5
+ import { readFileSync } from "fs";
5
6
 
6
7
  export function run() {
7
8
  program
8
9
  .name("brick-engine-cli")
9
10
  .description("CLI to scaffold Brick Engine projects")
10
- .version("1.0.0");
11
+ .version("1.0.8");
11
12
 
12
13
  program
13
14
  .command("init <name>")
@@ -1,100 +1,169 @@
1
- import { Game, FontSize, ControlKey, ControlEventType, Sound, FontAlign, FontVerticalAlign, Color } from 'brick-engine-js';
1
+ import { Game, FontSize, ControlKey, ControlEventType, Sound, FontAlign, FontVerticalAlign, Color, Coordinate, StateProperty } from 'brick-engine-js';
2
2
 
3
3
  export default class MyGame extends Game {
4
- y = 0;
5
- x = 5;
4
+ private playerX = 5;
5
+ private enemies: Coordinate[] = [];
6
+ private spawnRate = 5; // Ticks between spawns
7
+ private initTickInterval = 200;
6
8
 
7
9
  /**
8
10
  * Called once after the engine and its modules are fully initialized.
9
- * Ideal for setting initial state, text sizes, and subscribing to controls.
10
11
  */
11
12
  setupGame(): void {
12
- const { grid, control, sound } = this.modules;
13
-
14
- // Example: Subscriber to ACTION button
15
- control.subscribeForPlayingScreen(ControlKey.ACTION, ControlEventType.PRESSED, () => {
16
- sound.play(Sound.ACTION_1);
17
- grid.stampCell({
18
- coordinate: { x: this.x, y: this.y },
19
- color: Color.CYAN,
20
- value: 1,
21
- });
22
- this.modules.time.decrementTickInterval(this.y);
23
- this.y++;
24
- });
25
-
26
- this.modules.session.register({
27
- serialId: 'coords',
28
- deserialize: data => {
29
- const { x, y } = JSON.parse(data);
30
- this.x = x;
31
- this.y = y;
13
+ const { control, session } = this.modules;
14
+
15
+ // Register how game data should be serialized and deserialized for the session
16
+ session.register({
17
+ // Unique identifier for the session data
18
+ serialId: 'game-data',
19
+ // Recieves from LocalStorage and restore the game state
20
+ deserialize: (data: string) => {
21
+ if (!data) return;
22
+ const { playerX, enemies } = JSON.parse(data);
23
+ this.playerX = playerX;
24
+ this.enemies = enemies;
32
25
  },
26
+ // Prepare data to be saved to LocalStorage
33
27
  serialize: () => {
34
- return JSON.stringify({ x: this.x, y: this.y });
28
+ return JSON.stringify({
29
+ playerX: this.playerX,
30
+ enemies: this.enemies,
31
+ });
35
32
  },
36
33
  });
34
+
35
+ this.onStart();
36
+
37
+ // Move Left
38
+ control.subscribeForPlayingScreen(ControlKey.LEFT, ControlEventType.PRESSED, () => {
39
+ this.movePlayer(-1);
40
+ });
41
+
42
+ // Move Right
43
+ control.subscribeForPlayingScreen(ControlKey.RIGHT, ControlEventType.PRESSED, () => {
44
+ this.movePlayer(1);
45
+ });
46
+ }
47
+
48
+ private movePlayer(dx: number): void {
49
+ const { grid, sound } = this.modules;
50
+
51
+ const newX = this.playerX + dx;
52
+
53
+ if (grid.isCoordinateValid({ x: newX, y: grid.bottomRow })) {
54
+ this.playerX = newX;
55
+ sound.play(Sound.KEY_PRESS);
56
+ }
37
57
  }
38
58
 
39
59
  /**
40
- * Called on every logic "tick". The frequency is defined by the game's tickInterval.
41
- * This is where movement, collision, and state updates should happen.
42
- * Logic here ONLY runs when the game is in the PLAYING state.
60
+ * Logic update on every game "tick".
43
61
  */
44
- update(deltaTime: number): void {
45
- const actualCoordinate = { x: this.x, y: this.y };
62
+ update(): void {
63
+ const { grid, state, score, sound, time } = this.modules;
64
+
65
+ // 1. Move enemies down
66
+ this.enemies = this.enemies.map(enemy => ({ x: enemy.x, y: enemy.y + 1 })).filter(enemy => grid.isCoordinateValid({ x: enemy.x, y: enemy.y }));
46
67
 
47
- if (!this.modules.grid.isValidCoordinate(actualCoordinate)) {
48
- this.modules.state.triggerGameOver();
68
+ // 2. Spawn new enemy
69
+ if (time.isTickEvery(this.spawnRate)) {
70
+ const spawnX = Math.floor(Math.random() * grid.width);
71
+ this.enemies.push({ x: spawnX, y: grid.topRow });
49
72
  }
50
73
 
51
- this.modules.score.increaseScore(1);
74
+ // 3. Check collisions
75
+ const playerY = grid.bottomRow;
76
+ const collision = this.enemies.find(enemy => enemy.x === this.playerX && enemy.y === playerY);
77
+
78
+ if (collision) {
79
+ sound.play(Sound.EXPLOSION);
80
+ state.triggerGameOver();
81
+ return;
82
+ }
83
+
84
+ // 4. Update Grid
85
+ grid.resetGrid();
86
+
87
+ // Draw Player
88
+ grid.stampCell({
89
+ coordinate: { x: this.playerX, y: playerY },
90
+ color: Color.CYAN,
91
+ value: 1,
92
+ });
93
+
94
+ // Draw Enemies
95
+ this.enemies.forEach(enemy => {
96
+ grid.stampCell({
97
+ coordinate: enemy,
98
+ color: Color.RED,
99
+ value: 2,
100
+ });
101
+ });
102
+
103
+ // 5. Increase score and difficulty
104
+ score.increaseScore(1);
105
+
106
+ // Increase speed every 50 points
107
+ if (score.score > 0 && score.score % 50 === 0 && score.level < score.maxLevel) {
108
+ time.setTickInterval(this.initTickInterval - 15 * score.level);
109
+
110
+ score.increaseLevel(1);
111
+
112
+ if (score.level < 6) {
113
+ sound.play(Sound.SCORE_2);
114
+ } else {
115
+ sound.play(Sound.SCORE_3);
116
+ }
117
+ }
52
118
  }
53
119
 
54
120
  /**
55
- * Called every rendering frame (60fps).
56
- * Used for visual-only effects that don't impact game state (e.g. animations).
57
- * Runs during PLAYING and PAUSED states.
121
+ * Visual-only rendering (HUD elements).
58
122
  */
59
- render(): void {
60
- const { text } = this.modules;
61
-
62
- text.setTextSize(FontSize.EXTRA_SMALL);
63
- text.setTextAlign(FontAlign.LEFT, FontVerticalAlign.TOP);
64
- text.textOnDisplay('press', { x: 0.05, y: 0.05 });
65
- text.textOnDisplay('action', { x: 0.05, y: 0.1 });
66
- }
123
+ render(): void {}
67
124
 
68
125
  /**
69
- * Rendered every frame when the device is ON but the game hasn't started.
70
- * Usually displays the title and "Press Start" instructions.
126
+ * Title Screen Layout.
71
127
  */
72
128
  drawTitleScreen(): void {
73
129
  const { text } = this.modules;
74
130
 
75
131
  text.setTextSize(FontSize.MEDIUM);
76
132
  text.setTextAlign(FontAlign.CENTER, FontVerticalAlign.CENTER);
77
- text.textOnDisplay('MY GAME', { x: 0.5, y: 0.2 });
133
+ text.textOnDisplay('DODGE BRICK', { x: 0.5, y: 0.3 });
78
134
 
79
135
  text.setTextSize(FontSize.SMALL);
80
- text.textOnDisplay('running on', { x: 0.5, y: 0.48 });
81
- text.textOnDisplay('drawTitleScreen', { x: 0.5, y: 0.55 });
136
+ text.textOnDisplay('USE ARROWS TO MOVE', { x: 0.5, y: 0.5 });
82
137
 
83
138
  text.setTextSize(FontSize.MEDIUM);
84
139
  text.textOnDisplay('PRESS START', { x: 0.5, y: 0.8 });
85
140
  }
86
141
 
87
142
  /**
88
- * Rendered every frame when the game state reaches GAME OVER.
89
- * Replaces standard `render()` calls to show scores or restart messages.
90
- * Usually displays the game over message and "Press START to restart" instructions, and the final score.
143
+ * Game Over Screen Layout.
91
144
  */
92
145
  drawGameOverScreen(): void {
93
- this.modules.text.setTextAlign(FontAlign.CENTER, FontVerticalAlign.CENTER);
146
+ const { text, score } = this.modules;
94
147
 
95
- this.modules.text.textOnDisplay('GAME OVER', { x: 0.5, y: 0.5 });
148
+ text.setTextAlign(FontAlign.CENTER, FontVerticalAlign.CENTER);
149
+ text.setTextSize(FontSize.MEDIUM);
150
+ text.textOnDisplay('GAME OVER', { x: 0.5, y: 0.4 });
151
+
152
+ text.setTextSize(FontSize.SMALL);
153
+ text.textOnDisplay(`FINAL SCORE: ${score.score}`, { x: 0.5, y: 0.55 });
154
+
155
+ text.setTextSize(FontSize.MEDIUM);
156
+ text.textOnDisplay('PRESS START', { x: 0.5, y: 0.8 });
157
+ }
158
+
159
+ /**
160
+ * Reset game local state when starting/restarting.
161
+ */
162
+ onStart(): void {
163
+ const { score, time } = this.modules;
96
164
 
97
- this.modules.text.setTextSize(FontSize.MEDIUM);
98
- this.modules.text.textOnDisplay('PRESS START', { x: 0.5, y: 0.8 });
165
+ this.playerX = 5;
166
+ this.enemies = [];
167
+ time.setTickInterval(this.initTickInterval - 15 * score.level);
99
168
  }
100
169
  }