mustachio-game 1.0.0

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.
Files changed (101) hide show
  1. package/.github/workflows/pr.yaml +21 -0
  2. package/.github/workflows/push.yaml +26 -0
  3. package/eslint.config.ts +17 -0
  4. package/index.html +22 -0
  5. package/package.json +35 -0
  6. package/src/assets/Mustachio.webp +0 -0
  7. package/src/assets/Mustachio_FacingLeft.webp +0 -0
  8. package/src/assets/Mustachio_FacingLeft_Fire.webp +0 -0
  9. package/src/assets/Mustachio_FacingRight.webp +0 -0
  10. package/src/assets/Mustachio_FacingRight_Fire.webp +0 -0
  11. package/src/assets/Mustachio_Fire.webp +0 -0
  12. package/src/assets/brick.webp +0 -0
  13. package/src/assets/cannonDown.webp +0 -0
  14. package/src/assets/cannonLeft.webp +0 -0
  15. package/src/assets/cannonRight.webp +0 -0
  16. package/src/assets/cannonUp.webp +0 -0
  17. package/src/assets/fallingFloor.webp +0 -0
  18. package/src/assets/homestead.webp +0 -0
  19. package/src/assets/homesteadClosed.webp +0 -0
  20. package/src/assets/itemBlock.webp +0 -0
  21. package/src/assets/obstacleBrick.webp +0 -0
  22. package/src/assets/punchedBlock.webp +0 -0
  23. package/src/assets/stacheSeed1.webp +0 -0
  24. package/src/assets/stacheSeed2.webp +0 -0
  25. package/src/assets/stacheSeedReversed1.webp +0 -0
  26. package/src/assets/stacheSeedReversed2.webp +0 -0
  27. package/src/assets/stacheShotDown.webp +0 -0
  28. package/src/assets/stacheShotLeft.webp +0 -0
  29. package/src/assets/stacheShotRight.webp +0 -0
  30. package/src/assets/stacheShotUp.webp +0 -0
  31. package/src/assets/stacheSlinger1.webp +0 -0
  32. package/src/assets/stacheSlinger2.webp +0 -0
  33. package/src/assets/stacheStalker.webp +0 -0
  34. package/src/assets/stacheStalkerReversed.webp +0 -0
  35. package/src/assets/stacheStreaker1.webp +0 -0
  36. package/src/assets/stacheStreaker2.webp +0 -0
  37. package/src/classes/game-objects/bg-objects/background.ts +18 -0
  38. package/src/classes/game-objects/bg-objects/cloud.ts +37 -0
  39. package/src/classes/game-objects/mustachio.ts +482 -0
  40. package/src/classes/game-objects/point-objects/enemies/enemy.ts +64 -0
  41. package/src/classes/game-objects/point-objects/enemies/stache-seed.ts +124 -0
  42. package/src/classes/game-objects/point-objects/enemies/stache-shot.ts +68 -0
  43. package/src/classes/game-objects/point-objects/enemies/stache-slinger.ts +63 -0
  44. package/src/classes/game-objects/point-objects/enemies/stache-stalker.ts +41 -0
  45. package/src/classes/game-objects/point-objects/enemies/stache-streaker.ts +78 -0
  46. package/src/classes/game-objects/point-objects/items/coin.ts +72 -0
  47. package/src/classes/game-objects/point-objects/items/fire-stache.ts +48 -0
  48. package/src/classes/game-objects/point-objects/items/item.ts +27 -0
  49. package/src/classes/game-objects/point-objects/items/stacheroom.ts +48 -0
  50. package/src/classes/game-objects/point-objects/point-item.ts +10 -0
  51. package/src/classes/game-objects/projectiles/brick-debris.ts +44 -0
  52. package/src/classes/game-objects/projectiles/enemy-projectiles/enemy-projectile.ts +3 -0
  53. package/src/classes/game-objects/projectiles/enemy-projectiles/fire-ball.ts +87 -0
  54. package/src/classes/game-objects/projectiles/enemy-projectiles/fire-bar.ts +65 -0
  55. package/src/classes/game-objects/projectiles/enemy-projectiles/fire-cross.ts +67 -0
  56. package/src/classes/game-objects/projectiles/enemy-projectiles/laser.ts +41 -0
  57. package/src/classes/game-objects/projectiles/projectile.ts +3 -0
  58. package/src/classes/game-objects/projectiles/stache-ball.ts +57 -0
  59. package/src/classes/game-objects/set-pieces/flag.ts +34 -0
  60. package/src/classes/game-objects/set-pieces/obstacles/blocks/block.ts +17 -0
  61. package/src/classes/game-objects/set-pieces/obstacles/blocks/cave-wall.ts +21 -0
  62. package/src/classes/game-objects/set-pieces/obstacles/blocks/falling-floor.ts +65 -0
  63. package/src/classes/game-objects/set-pieces/obstacles/blocks/fire-bar-block.ts +31 -0
  64. package/src/classes/game-objects/set-pieces/obstacles/blocks/fire-cross-block.ts +28 -0
  65. package/src/classes/game-objects/set-pieces/obstacles/blocks/punchable-blockS/brick.ts +44 -0
  66. package/src/classes/game-objects/set-pieces/obstacles/blocks/punchable-blockS/item-block.ts +82 -0
  67. package/src/classes/game-objects/set-pieces/obstacles/blocks/punchable-blockS/punchable-block.ts +6 -0
  68. package/src/classes/game-objects/set-pieces/obstacles/blocks/stache-cannon.ts +54 -0
  69. package/src/classes/game-objects/set-pieces/obstacles/blocks/wall.ts +22 -0
  70. package/src/classes/game-objects/set-pieces/obstacles/floor.ts +27 -0
  71. package/src/classes/game-objects/set-pieces/obstacles/obstacle-types.ts +14 -0
  72. package/src/classes/game-objects/set-pieces/obstacles/obstacle.ts +3 -0
  73. package/src/classes/game-objects/set-pieces/obstacles/pipe.ts +35 -0
  74. package/src/classes/game-objects/set-pieces/obstacles/warp-pipe.ts +17 -0
  75. package/src/classes/game-objects/set-pieces/set-piece.ts +3 -0
  76. package/src/classes/game-objects/ui-objects/score-display.ts +10 -0
  77. package/src/classes/game-objects/ui-objects/timer-display.ts +15 -0
  78. package/src/classes/game-objects/ui-objects/ui-object.ts +16 -0
  79. package/src/classes/game-objects/ui-objects/win-display.ts +25 -0
  80. package/src/dev.ts +5 -0
  81. package/src/index.ts +3 -0
  82. package/src/levels/caves/cave-one.ts +90 -0
  83. package/src/levels/level-helpers.ts +101 -0
  84. package/src/levels/level-one.ts +379 -0
  85. package/src/levels/test-levels/blocks-and-items.ts +77 -0
  86. package/src/levels/test-levels/cannon-and-cross.ts +75 -0
  87. package/src/levels/test-levels/caves-and-enemies.ts +73 -0
  88. package/src/levels/test-levels/win-game.ts +24 -0
  89. package/src/main.ts +6 -0
  90. package/src/mustachi-game-context.ts +35 -0
  91. package/src/shared/app-code.ts +106 -0
  92. package/src/shared/constants.ts +1 -0
  93. package/src/shared/game-context.ts +547 -0
  94. package/src/shared/game-objects/game-object.ts +28 -0
  95. package/src/shared/game-objects/moving-game-object.ts +46 -0
  96. package/src/shared/game-objects/rotating-game-object.ts +58 -0
  97. package/src/shared/game-objects/updating-game-object.ts +7 -0
  98. package/src/shared/player.ts +73 -0
  99. package/src/shared/types.ts +21 -0
  100. package/tsconfig.json +26 -0
  101. package/vite.config.ts +13 -0
@@ -0,0 +1,17 @@
1
+ import type { GameContext } from "../../../../shared/game-context";
2
+ import { Pipe } from "./pipe";
3
+ import type { WarpPipeOptions } from "./obstacle-types";
4
+
5
+ export class WarpPipe extends Pipe {
6
+ readonly objectId = 0;
7
+ readonly setNewLevel: (gameContext: GameContext) => void;
8
+
9
+ constructor(gameContext: GameContext, options: WarpPipeOptions) {
10
+ super(gameContext, { ...options });
11
+ this.setNewLevel = options.setNewLevel;
12
+ }
13
+
14
+ enter() {
15
+ this.setNewLevel(this.gameContext);
16
+ }
17
+ }
@@ -0,0 +1,3 @@
1
+ import { GameObject } from "../../../shared/game-objects/game-object";
2
+
3
+ export abstract class SetPiece extends GameObject {}
@@ -0,0 +1,10 @@
1
+ import { UIObject } from "./ui-object";
2
+
3
+ export class ScoreDisplay extends UIObject {
4
+ draw(ctx: CanvasRenderingContext2D): void {
5
+ ctx.clearRect(0, 0, this.gameContext.gameArea.width / 2, 100);
6
+ ctx.fillStyle = "white";
7
+ ctx.font = "40px Arial";
8
+ ctx.fillText(`Score: ${this.gameContext.score}`, this.rect.x, this.rect.y);
9
+ }
10
+ }
@@ -0,0 +1,15 @@
1
+ import { UIObject } from "./ui-object";
2
+
3
+ export class TimerDisplay extends UIObject {
4
+ draw(ctx: CanvasRenderingContext2D): void {
5
+ ctx.clearRect(
6
+ this.gameContext.gameArea.width / 2,
7
+ 0,
8
+ this.gameContext.gameArea.width / 2,
9
+ 100,
10
+ );
11
+ ctx.fillStyle = "white";
12
+ ctx.font = "40px Arial";
13
+ ctx.fillText(`Time: ${this.gameContext.time}`, this.rect.x, this.rect.y);
14
+ }
15
+ }
@@ -0,0 +1,16 @@
1
+ import type { GameContext } from "../../../shared/game-context";
2
+ import { GameObject } from "../../../shared/game-objects/game-object";
3
+ import type { rectangle } from "../../../shared/types";
4
+
5
+ export abstract class UIObject extends GameObject {
6
+ constructor(gameContext: GameContext, x: number, y: number) {
7
+ const rect: rectangle = {
8
+ x,
9
+ y,
10
+ width: 0,
11
+ height: 0,
12
+ };
13
+
14
+ super(gameContext, rect);
15
+ }
16
+ }
@@ -0,0 +1,25 @@
1
+ import type { GameContext } from "../../../shared/game-context";
2
+ import { UIObject } from "./ui-object";
3
+
4
+ export class WinDisplay extends UIObject {
5
+ constructor(gameContext: GameContext) {
6
+ super(
7
+ gameContext,
8
+ gameContext.gameArea.width / 2,
9
+ gameContext.gameArea.height / 2 - 50,
10
+ );
11
+ }
12
+
13
+ draw(ctx: CanvasRenderingContext2D) {
14
+ ctx.fillStyle = "white";
15
+ ctx.font = "80px Arial";
16
+ const text = `You win! Score: ${this.gameContext.score}`;
17
+ const textWidth = ctx.measureText(text).width;
18
+
19
+ ctx.fillText(
20
+ text,
21
+ this.rect.x + this.rect.width / 2 - textWidth / 2,
22
+ this.rect.y + this.rect.height,
23
+ );
24
+ }
25
+ }
package/src/dev.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { startMustachio } from "./main";
2
+
3
+ document.addEventListener("DOMContentLoaded", () => {
4
+ startMustachio("app");
5
+ });
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { startMustachio } from "./main";
2
+
3
+ export { startMustachio };
@@ -0,0 +1,90 @@
1
+ import type { GameContext } from "../../shared/game-context";
2
+ import { CaveWall } from "../../classes/game-objects/set-pieces/obstacles/blocks/cave-wall";
3
+ import { BLOCK_SIZE } from "../../shared/constants";
4
+ import { Coin } from "../../classes/game-objects/point-objects/items/coin";
5
+ import { Pipe } from "../../classes/game-objects/set-pieces/obstacles/pipe";
6
+ import { ItemBlock } from "../../classes/game-objects/set-pieces/obstacles/blocks/punchable-blockS/item-block";
7
+ import { WarpPipe } from "../../classes/game-objects/set-pieces/obstacles/warp-pipe";
8
+ import { levelOne } from "../level-one";
9
+
10
+ export function caveOne(
11
+ gameContext: GameContext,
12
+ previousLevels: string[] = [],
13
+ ) {
14
+ gameContext.clearLevel();
15
+ gameContext.setStatic(true);
16
+
17
+ // Cave walls
18
+ gameContext.addGameObject(
19
+ new CaveWall(gameContext, {
20
+ x: 0,
21
+ y: 0,
22
+ width: BLOCK_SIZE * 4,
23
+ height: gameContext.gameArea.height,
24
+ }),
25
+ );
26
+
27
+ gameContext.addGameObject(
28
+ new CaveWall(gameContext, {
29
+ x: BLOCK_SIZE * 28,
30
+ y: 0,
31
+ width: BLOCK_SIZE * 4,
32
+ height: gameContext.gameArea.height,
33
+ }),
34
+ );
35
+
36
+ gameContext.addGameObject(
37
+ new CaveWall(gameContext, {
38
+ x: BLOCK_SIZE * 4,
39
+ y: BLOCK_SIZE * 16,
40
+ width: BLOCK_SIZE * 24,
41
+ height: BLOCK_SIZE * 2,
42
+ }),
43
+ );
44
+
45
+ gameContext.addGameObject(
46
+ new CaveWall(gameContext, {
47
+ x: BLOCK_SIZE * 4,
48
+ y: 0,
49
+ width: BLOCK_SIZE * 24,
50
+ height: BLOCK_SIZE * 2,
51
+ }),
52
+ );
53
+
54
+ gameContext.addGameObject(
55
+ new Pipe(gameContext, {
56
+ x: BLOCK_SIZE * 4,
57
+ y: BLOCK_SIZE * 2,
58
+ }),
59
+ );
60
+
61
+ gameContext.addGameObject(
62
+ new WarpPipe(gameContext, {
63
+ x: BLOCK_SIZE * 26,
64
+ y: BLOCK_SIZE * 14,
65
+ setNewLevel: (gc) => levelOne(gc, [...previousLevels, "cave-one"]),
66
+ }),
67
+ );
68
+
69
+ for (let i = 7; i < 24; i += 2) {
70
+ for (let j = 10; j < 16; j += 2) {
71
+ gameContext.addGameObject(
72
+ new Coin(gameContext, BLOCK_SIZE * i, BLOCK_SIZE * j),
73
+ );
74
+ }
75
+ }
76
+
77
+ gameContext.addGameObject(
78
+ new ItemBlock(
79
+ gameContext,
80
+ BLOCK_SIZE * 27,
81
+ BLOCK_SIZE * 9,
82
+ true,
83
+ "fire-stache",
84
+ ),
85
+ );
86
+
87
+ gameContext.setPlayerLocation(BLOCK_SIZE * 4.5, BLOCK_SIZE * 5);
88
+
89
+ gameContext.startMainLoop();
90
+ }
@@ -0,0 +1,101 @@
1
+ import { BLOCK_SIZE } from "../shared/constants";
2
+ import { Wall } from "../classes/game-objects/set-pieces/obstacles/blocks/wall";
3
+ import type { GameContext } from "../shared/game-context";
4
+ import { Coin } from "../classes/game-objects/point-objects/items/coin";
5
+ import { Brick } from "../classes/game-objects/set-pieces/obstacles/blocks/punchable-blockS/brick";
6
+ import { FallingFloor } from "../classes/game-objects/set-pieces/obstacles/blocks/falling-floor";
7
+
8
+ export type BlockType = "wall" | "brick" | "coin" | "falling-floor";
9
+
10
+ export function createBlockWall(
11
+ gameContext: GameContext,
12
+ startingX: number,
13
+ startingY: number,
14
+ numBlocksWide: number,
15
+ numBlocksHigh: number,
16
+ blockType: BlockType,
17
+ ) {
18
+ for (let i = 0; i < numBlocksWide; i++) {
19
+ for (let j = 0; j < numBlocksHigh; j++) {
20
+ const x = (startingX + i) * BLOCK_SIZE;
21
+ const y = (startingY + j) * BLOCK_SIZE;
22
+ if (blockType === "wall") {
23
+ gameContext.addGameObject(new Wall(gameContext, x, y));
24
+ } else if (blockType === "brick") {
25
+ gameContext.addGameObject(new Brick(gameContext, x, y));
26
+ } else if (blockType === "coin") {
27
+ gameContext.addGameObject(new Coin(gameContext, x, y));
28
+ } else if (blockType === "falling-floor") {
29
+ gameContext.addGameObject(new FallingFloor(gameContext, x, y));
30
+ }
31
+ }
32
+ }
33
+ }
34
+
35
+ export function createBlockPyramid(
36
+ gameContext: GameContext,
37
+ startingX: number,
38
+ startingY: number,
39
+ numBlocksWide: number,
40
+ blockType: BlockType,
41
+ ) {
42
+ while (numBlocksWide > 0) {
43
+ createBlockWall(
44
+ gameContext,
45
+ startingX,
46
+ startingY,
47
+ numBlocksWide,
48
+ 1,
49
+ blockType,
50
+ );
51
+
52
+ startingX += 1;
53
+ startingY -= 1;
54
+ numBlocksWide -= 2;
55
+ }
56
+ }
57
+
58
+ export function createBlockSquare(
59
+ gameContext: GameContext,
60
+ startingX: number,
61
+ startingY: number,
62
+ numBlocksWide: number,
63
+ numBlocksHigh: number,
64
+ blockType: BlockType,
65
+ ) {
66
+ createBlockWall(
67
+ gameContext,
68
+ startingX,
69
+ startingY,
70
+ numBlocksWide,
71
+ 1,
72
+ blockType,
73
+ );
74
+
75
+ createBlockWall(
76
+ gameContext,
77
+ startingX,
78
+ startingY + numBlocksHigh - 1,
79
+ numBlocksWide,
80
+ 1,
81
+ blockType,
82
+ );
83
+
84
+ createBlockWall(
85
+ gameContext,
86
+ startingX,
87
+ startingY + 1,
88
+ 1,
89
+ numBlocksHigh - 2,
90
+ blockType,
91
+ );
92
+
93
+ createBlockWall(
94
+ gameContext,
95
+ startingX + numBlocksWide - 1,
96
+ startingY + 1,
97
+ 1,
98
+ numBlocksHigh - 2,
99
+ blockType,
100
+ );
101
+ }
@@ -0,0 +1,379 @@
1
+ import { GameContext } from "../shared/game-context";
2
+ import {
3
+ createBlockPyramid,
4
+ createBlockSquare,
5
+ createBlockWall,
6
+ } from "./level-helpers";
7
+ import { BLOCK_SIZE } from "../shared/constants";
8
+ import { Floor } from "../classes/game-objects/set-pieces/obstacles/floor";
9
+ import { ItemBlock } from "../classes/game-objects/set-pieces/obstacles/blocks/punchable-blockS/item-block";
10
+ import { Brick } from "../classes/game-objects/set-pieces/obstacles/blocks/punchable-blockS/brick";
11
+ import { Wall } from "../classes/game-objects/set-pieces/obstacles/blocks/wall";
12
+ import { StacheStalker } from "../classes/game-objects/point-objects/enemies/stache-stalker";
13
+ import { Pipe } from "../classes/game-objects/set-pieces/obstacles/pipe";
14
+ import { WarpPipe } from "../classes/game-objects/set-pieces/obstacles/warp-pipe";
15
+ import { caveOne } from "./caves/cave-one";
16
+ import { StacheCannon } from "../classes/game-objects/set-pieces/obstacles/blocks/stache-cannon";
17
+ import { direction } from "../shared/types";
18
+ import { FireCrossBlock } from "../classes/game-objects/set-pieces/obstacles/blocks/fire-cross-block";
19
+ import { FireBarBlock } from "../classes/game-objects/set-pieces/obstacles/blocks/fire-bar-block";
20
+ import { StacheStreaker } from "../classes/game-objects/point-objects/enemies/stache-streaker";
21
+ import { Flag } from "../classes/game-objects/set-pieces/flag";
22
+
23
+ export function levelOne(
24
+ gameContext: GameContext,
25
+ previousLevels: string[] = [],
26
+ ) {
27
+ gameContext.clearLevel();
28
+
29
+ sectionOne(gameContext);
30
+ sectionTwo(gameContext);
31
+ sectionThree(gameContext, previousLevels);
32
+ sectionFour(gameContext);
33
+ sectionFive(gameContext);
34
+ sectionSix(gameContext);
35
+ sectionSeven(gameContext);
36
+
37
+ if (previousLevels[0] === "cave-one") {
38
+ gameContext.setPlayerLocation(BLOCK_SIZE * 69, BLOCK_SIZE * 8);
39
+ }
40
+
41
+ gameContext.startMainLoop();
42
+ }
43
+
44
+ function sectionOne(gameContext: GameContext) {
45
+ // Floor
46
+ gameContext.addGameObject(
47
+ new Floor(gameContext, {
48
+ x: 0,
49
+ y: BLOCK_SIZE * 17,
50
+ width: BLOCK_SIZE * 40,
51
+ height: BLOCK_SIZE,
52
+ }),
53
+ );
54
+
55
+ // First barrier
56
+ createBlockWall(gameContext, 0, 0, 1, 17, "wall");
57
+ createBlockWall(gameContext, 1, 5, 1, 11, "coin");
58
+
59
+ gameContext.addGameObject(
60
+ new ItemBlock(gameContext, BLOCK_SIZE * 6, BLOCK_SIZE * 14, false, "coin"),
61
+ );
62
+
63
+ gameContext.addGameObject(
64
+ new Brick(gameContext, BLOCK_SIZE * 7, BLOCK_SIZE * 14),
65
+ );
66
+
67
+ gameContext.addGameObject(
68
+ new ItemBlock(gameContext, BLOCK_SIZE * 8, BLOCK_SIZE * 14, true, "coin"),
69
+ );
70
+
71
+ gameContext.addGameObject(
72
+ new ItemBlock(gameContext, BLOCK_SIZE * 8, BLOCK_SIZE * 11, true, "coin"),
73
+ );
74
+
75
+ gameContext.addGameObject(
76
+ new Brick(gameContext, BLOCK_SIZE * 9, BLOCK_SIZE * 14),
77
+ );
78
+
79
+ gameContext.addGameObject(
80
+ new ItemBlock(gameContext, BLOCK_SIZE * 10, BLOCK_SIZE * 14, false, "coin"),
81
+ );
82
+
83
+ createBlockPyramid(gameContext, 16, 16, 12, "wall");
84
+
85
+ gameContext.addGameObject(
86
+ new Wall(gameContext, BLOCK_SIZE * 39, BLOCK_SIZE * 16),
87
+ );
88
+
89
+ gameContext.addGameObject(
90
+ new StacheStalker(gameContext, BLOCK_SIZE * 28, BLOCK_SIZE * 14),
91
+ );
92
+
93
+ gameContext.addGameObject(
94
+ new StacheStalker(gameContext, BLOCK_SIZE * 34, BLOCK_SIZE * 14),
95
+ );
96
+ }
97
+
98
+ function sectionTwo(gameContext: GameContext) {
99
+ gameContext.addGameObject(
100
+ new Wall(gameContext, BLOCK_SIZE * 46, BLOCK_SIZE * 16),
101
+ );
102
+
103
+ gameContext.addGameObject(
104
+ new ItemBlock(gameContext, BLOCK_SIZE * 49, BLOCK_SIZE * 13, false, "coin"),
105
+ );
106
+
107
+ gameContext.addGameObject(
108
+ new ItemBlock(
109
+ gameContext,
110
+ BLOCK_SIZE * 49,
111
+ BLOCK_SIZE * 9,
112
+ true,
113
+ "stacheroom",
114
+ ),
115
+ );
116
+
117
+ createBlockSquare(gameContext, 53, 11, 6, 4, "brick");
118
+ createBlockWall(gameContext, 54, 12, 4, 2, "coin");
119
+
120
+ gameContext.addGameObject(
121
+ new Pipe(gameContext, {
122
+ x: BLOCK_SIZE * 64,
123
+ y: BLOCK_SIZE * 15,
124
+ hasStacheSeed: true,
125
+ }),
126
+ );
127
+
128
+ // Floor
129
+ gameContext.addGameObject(
130
+ new Floor(gameContext, {
131
+ x: BLOCK_SIZE * 46,
132
+ y: BLOCK_SIZE * 17,
133
+ width: BLOCK_SIZE * 20,
134
+ height: BLOCK_SIZE,
135
+ }),
136
+ );
137
+ }
138
+
139
+ function sectionThree(gameContext: GameContext, previousLevels: string[]) {
140
+ createBlockWall(gameContext, 66, 17, 23, 1, "wall");
141
+ let pipe: Pipe;
142
+ if (previousLevels.includes("cave-one")) {
143
+ pipe = new Pipe(gameContext, {
144
+ x: BLOCK_SIZE * 73,
145
+ y: BLOCK_SIZE * 9,
146
+ });
147
+ } else {
148
+ pipe = new WarpPipe(gameContext, {
149
+ x: BLOCK_SIZE * 73,
150
+ y: BLOCK_SIZE * 9,
151
+ setNewLevel: caveOne,
152
+ });
153
+ }
154
+
155
+ createBlockWall(gameContext, 73, 11, 2, 1, "wall");
156
+
157
+ gameContext.addGameObject(pipe);
158
+
159
+ createBlockWall(gameContext, 78, 16, 1, 1, "wall");
160
+ gameContext.addGameObject(
161
+ new StacheCannon(
162
+ gameContext,
163
+ BLOCK_SIZE * 78,
164
+ BLOCK_SIZE * 15,
165
+ direction.LEFT,
166
+ ),
167
+ );
168
+
169
+ createBlockWall(gameContext, 80, 15, 1, 2, "wall");
170
+ gameContext.addGameObject(
171
+ new StacheCannon(
172
+ gameContext,
173
+ BLOCK_SIZE * 80,
174
+ BLOCK_SIZE * 14,
175
+ direction.LEFT,
176
+ ),
177
+ );
178
+
179
+ createBlockWall(gameContext, 82, 14, 1, 3, "wall");
180
+ gameContext.addGameObject(
181
+ new StacheCannon(
182
+ gameContext,
183
+ BLOCK_SIZE * 82,
184
+ BLOCK_SIZE * 13,
185
+ direction.LEFT,
186
+ ),
187
+ );
188
+
189
+ createBlockWall(gameContext, 84, 13, 1, 4, "wall");
190
+ gameContext.addGameObject(
191
+ new StacheCannon(
192
+ gameContext,
193
+ BLOCK_SIZE * 84,
194
+ BLOCK_SIZE * 12,
195
+ direction.LEFT,
196
+ ),
197
+ );
198
+ }
199
+
200
+ function sectionFour(gameContext: GameContext) {
201
+ createBlockWall(gameContext, 89, 17, 33, 1, "falling-floor");
202
+
203
+ for (let i = 0; i < 11; i++) {
204
+ gameContext.addGameObject(
205
+ new Pipe(gameContext, {
206
+ x: BLOCK_SIZE * (89 + i * 3),
207
+ y: 0,
208
+ height: BLOCK_SIZE * 14,
209
+ hasStacheSeed: true,
210
+ reversed: true,
211
+ }),
212
+ );
213
+ }
214
+
215
+ createBlockWall(gameContext, 122, 17, 5, 1, "wall");
216
+ }
217
+
218
+ function sectionFive(gameContext: GameContext) {
219
+ createBlockWall(gameContext, 126, 14, 1, 3, "wall");
220
+
221
+ gameContext.addGameObject(
222
+ new ItemBlock(
223
+ gameContext,
224
+ BLOCK_SIZE * 121,
225
+ BLOCK_SIZE * 13,
226
+ false,
227
+ "stacheroom",
228
+ ),
229
+ );
230
+
231
+ gameContext.addGameObject(
232
+ new FireCrossBlock(gameContext, BLOCK_SIZE * 126, BLOCK_SIZE * 13, [
233
+ direction.LEFT,
234
+ direction.RIGHT,
235
+ ]),
236
+ );
237
+
238
+ gameContext.addGameObject(
239
+ new FireBarBlock(gameContext, BLOCK_SIZE * 126, BLOCK_SIZE * 7),
240
+ );
241
+
242
+ createBlockWall(gameContext, 129, 13, 1, 4, "coin");
243
+ createBlockWall(gameContext, 129, 17, 1, 1, "wall");
244
+ createBlockWall(gameContext, 133, 17, 15, 1, "wall");
245
+ createBlockWall(gameContext, 132, 0, 1, 14, "wall");
246
+ createBlockWall(gameContext, 137, 5, 1, 12, "wall");
247
+
248
+ gameContext.addGameObject(
249
+ new FireCrossBlock(gameContext, BLOCK_SIZE * 132, BLOCK_SIZE * 17, [
250
+ direction.UP,
251
+ ]),
252
+ );
253
+
254
+ gameContext.addGameObject(
255
+ new FireCrossBlock(gameContext, BLOCK_SIZE * 136, BLOCK_SIZE * 14, [
256
+ direction.LEFT,
257
+ ]),
258
+ );
259
+
260
+ gameContext.addGameObject(
261
+ new FireCrossBlock(gameContext, BLOCK_SIZE * 133, BLOCK_SIZE * 11, [
262
+ direction.RIGHT,
263
+ ]),
264
+ );
265
+
266
+ gameContext.addGameObject(
267
+ new FireCrossBlock(gameContext, BLOCK_SIZE * 136, BLOCK_SIZE * 8, [
268
+ direction.LEFT,
269
+ ]),
270
+ );
271
+
272
+ gameContext.addGameObject(
273
+ new FireCrossBlock(gameContext, BLOCK_SIZE * 133, BLOCK_SIZE * 5, [
274
+ direction.RIGHT,
275
+ ]),
276
+ );
277
+
278
+ createBlockWall(gameContext, 138, 5, 4, 1, "falling-floor");
279
+ createBlockWall(gameContext, 138, 8, 4, 1, "falling-floor");
280
+ createBlockWall(gameContext, 138, 11, 4, 1, "falling-floor");
281
+ createBlockWall(gameContext, 138, 14, 4, 1, "falling-floor");
282
+
283
+ createBlockWall(gameContext, 142, 0, 1, 15, "wall");
284
+
285
+ gameContext.addGameObject(
286
+ new StacheStalker(gameContext, BLOCK_SIZE * 140, BLOCK_SIZE * 6),
287
+ );
288
+
289
+ gameContext.addGameObject(
290
+ new StacheStalker(gameContext, BLOCK_SIZE * 140, BLOCK_SIZE * 9),
291
+ );
292
+
293
+ gameContext.addGameObject(
294
+ new StacheStalker(gameContext, BLOCK_SIZE * 140, BLOCK_SIZE * 12),
295
+ );
296
+ }
297
+
298
+ function sectionSix(gameContext: GameContext) {
299
+ for (let i = 0; i < 5; i++) {
300
+ gameContext.addGameObject(
301
+ new StacheCannon(
302
+ gameContext,
303
+ BLOCK_SIZE * 143,
304
+ BLOCK_SIZE * (i * 3 + 2),
305
+ direction.RIGHT,
306
+ ),
307
+ );
308
+ }
309
+
310
+ createBlockWall(gameContext, 150, 3, 1, 1, "wall");
311
+ createBlockWall(gameContext, 150, 6, 1, 1, "wall");
312
+ createBlockWall(gameContext, 150, 9, 1, 1, "wall");
313
+ createBlockWall(gameContext, 150, 12, 1, 1, "wall");
314
+ createBlockWall(gameContext, 150, 15, 1, 1, "wall");
315
+
316
+ createBlockWall(gameContext, 153, 4, 1, 1, "wall");
317
+ createBlockWall(gameContext, 153, 7, 1, 1, "wall");
318
+ createBlockWall(gameContext, 153, 10, 1, 1, "wall");
319
+ createBlockWall(gameContext, 153, 13, 1, 1, "wall");
320
+ createBlockWall(gameContext, 153, 16, 1, 1, "wall");
321
+
322
+ createBlockWall(gameContext, 156, 2, 1, 1, "wall");
323
+ createBlockWall(gameContext, 156, 5, 1, 1, "wall");
324
+ createBlockWall(gameContext, 156, 8, 1, 1, "wall");
325
+ createBlockWall(gameContext, 156, 11, 1, 1, "wall");
326
+ createBlockWall(gameContext, 156, 14, 1, 1, "wall");
327
+
328
+ createBlockWall(gameContext, 159, 3, 1, 1, "wall");
329
+ createBlockWall(gameContext, 159, 6, 1, 1, "wall");
330
+ createBlockWall(gameContext, 159, 9, 1, 1, "wall");
331
+ createBlockWall(gameContext, 159, 12, 1, 1, "wall");
332
+ createBlockWall(gameContext, 159, 15, 1, 1, "wall");
333
+
334
+ gameContext.addGameObject(
335
+ new StacheStreaker(gameContext, BLOCK_SIZE * 155, 0),
336
+ );
337
+ const enemy = new StacheStreaker(gameContext, BLOCK_SIZE * 152, 0);
338
+ enemy.speedX *= -1;
339
+ gameContext.addGameObject(enemy);
340
+
341
+ gameContext.addGameObject(
342
+ new Pipe(gameContext, {
343
+ x: BLOCK_SIZE * 162,
344
+ y: 0,
345
+ height: BLOCK_SIZE * 4,
346
+ hasStacheSeed: true,
347
+ reversed: true,
348
+ }),
349
+ );
350
+
351
+ gameContext.addGameObject(
352
+ new Pipe(gameContext, {
353
+ x: BLOCK_SIZE * 162,
354
+ y: BLOCK_SIZE * 10,
355
+ height: BLOCK_SIZE * 8,
356
+ hasStacheSeed: true,
357
+ }),
358
+ );
359
+ }
360
+
361
+ function sectionSeven(gameContext: GameContext) {
362
+ createBlockWall(gameContext, 168, 7, 2, 1, "falling-floor");
363
+ createBlockWall(gameContext, 172, 4, 2, 1, "falling-floor");
364
+ createBlockWall(gameContext, 184, 15, 2, 1, "falling-floor");
365
+ createBlockWall(gameContext, 189, 12, 1, 1, "falling-floor");
366
+ createBlockWall(gameContext, 193, 9, 1, 1, "falling-floor");
367
+ createBlockWall(gameContext, 189, 6, 1, 1, "falling-floor");
368
+ createBlockWall(gameContext, 193, 3, 1, 1, "falling-floor");
369
+ createBlockWall(gameContext, 194, 2, 1, 15, "falling-floor");
370
+
371
+ createBlockSquare(gameContext, 198, 7, 10, 6, "falling-floor");
372
+ createBlockWall(gameContext, 199, 8, 8, 4, "coin");
373
+
374
+ createBlockWall(gameContext, 208, 17, 32, 1, "wall");
375
+ gameContext.addGameObject(
376
+ new Flag(gameContext, BLOCK_SIZE * 220, BLOCK_SIZE * 9),
377
+ true,
378
+ );
379
+ }