Skip to content

Commit 38cec7d

Browse files
committed
feat: spike
1 parent ad5a369 commit 38cec7d

File tree

6 files changed

+52
-105
lines changed

6 files changed

+52
-105
lines changed

public/assets/spike.png

8.06 KB
Loading

src/constants.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export enum Block {
2424
switchingBlockOFF = "switching-block-off",
2525
switchingBlockON = "switching-block-on",
2626
switchPressed = "switch-pressed",
27+
spike = "spike",
2728
goal = "goal",
2829
}
2930
export enum Facing {
@@ -45,5 +46,11 @@ export const BlockDefinitionMap = new Map<string, Block | null>([
4546
["s", Block.switch],
4647
["S", Block.switchBase],
4748
["w", Block.switchingBlockOFF],
49+
["^", Block.spike],
4850
["g", Block.goal],
4951
]);
52+
53+
export const ReverseBlockMap = new Map<Block | null, string>();
54+
BlockDefinitionMap.forEach((value, key) => {
55+
ReverseBlockMap.set(value, key);
56+
});

src/grid.ts

Lines changed: 25 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import { type Container, Sprite, type Ticker } from "pixi.js";
22
import { type Writable, get } from "svelte/store";
33
import { Block, BlockDefinitionMap } from "./constants.ts";
44
import * as consts from "./constants.ts";
5-
import { assert, warnIf } from "./lib.ts";
5+
import { assert } from "./lib.ts";
66
import type { Context, GameConfig, GameState, MovableObject } from "./public-types.ts";
77
import {
88
fallableTexture,
99
goalTexture,
1010
rockTexture,
11+
spikeTexture,
1112
switchBaseTexture,
1213
switchPressedTexture,
1314
switchTexture,
@@ -27,49 +28,20 @@ type VirtualSpriteCell = {
2728
type VirtualSOM = (VirtualSpriteCell | null)[][];
2829
export type GridCell =
2930
| {
30-
block: Block.block;
31+
// blocks that don't have switchId
32+
block: null | Block.block | Block.switchBase | Block.goal | Block.spike;
3133
objectId?: unknown;
3234
}
3335
| {
34-
block: Block.movable;
35-
objectId: string;
36-
switchId: string | undefined;
37-
}
38-
| {
39-
block: Block.fallable;
36+
// movable blocks (can be placed on top of switch)
37+
block: Block.movable | Block.fallable;
4038
objectId: string;
4139
switchId: string | undefined; // switchの上に置かれている場合
4240
}
4341
| {
44-
block: null; // air
45-
objectId?: unknown;
46-
}
47-
| {
48-
block: Block.switch;
49-
switchId?: string;
50-
objectId?: unknown;
51-
}
52-
| {
53-
block: Block.switchBase;
54-
objectId?: unknown;
55-
}
56-
| {
57-
block: Block.switchingBlockOFF;
58-
switchId?: string;
59-
objectId?: unknown;
60-
}
61-
| {
62-
block: Block.switchingBlockON;
63-
switchId?: string;
64-
objectId?: unknown;
65-
}
66-
| {
67-
block: Block.switchPressed;
68-
switchId?: string;
69-
objectId?: unknown;
70-
}
71-
| {
72-
block: Block.goal;
42+
// switches / triggerable blocks
43+
block: Block.switch | Block.switchingBlockOFF | Block.switchingBlockON | Block.switchPressed;
44+
switchId?: string; // optional でいいの?
7345
objectId?: unknown;
7446
};
7547

@@ -102,19 +74,12 @@ export class Grid {
10274
case null: // air
10375
vspriteRow.push(null);
10476
break;
105-
case Block.movable: {
106-
const sprite = createSprite(cellSize, dblock, x, y, this.marginY);
107-
stage.addChild(sprite);
108-
vspriteRow.push({ sprite, block: dblock, dy: 0, vy: 0 });
109-
break;
110-
}
111-
case Block.fallable: {
112-
const sprite = createSprite(cellSize, dblock, x, y, this.marginY);
113-
stage.addChild(sprite);
114-
vspriteRow.push({ sprite, block: dblock, dy: 0, vy: 0 });
115-
break;
116-
}
117-
case Block.block: {
77+
case Block.block:
78+
case Block.movable:
79+
case Block.spike:
80+
case Block.fallable:
81+
case Block.goal:
82+
case Block.switchBase: {
11883
const sprite = createSprite(cellSize, dblock, x, y, this.marginY);
11984
stage.addChild(sprite);
12085
vspriteRow.push({ sprite, block: dblock, dy: 0, vy: 0 });
@@ -139,12 +104,6 @@ export class Grid {
139104
});
140105
break;
141106
}
142-
case Block.switchBase: {
143-
const sprite = createSprite(cellSize, dblock, x, y, this.marginY);
144-
stage.addChild(sprite);
145-
vspriteRow.push({ sprite, block: dblock, dy: 0, vy: 0 });
146-
break;
147-
}
148107
case Block.switchingBlockOFF: {
149108
const switchId = (
150109
get(cx.state).cells[y][x] as {
@@ -167,15 +126,9 @@ export class Grid {
167126
});
168127
break;
169128
}
170-
case Block.goal: {
171-
const sprite = createSprite(cellSize, dblock, x, y, this.marginY);
172-
stage.addChild(sprite);
173-
vspriteRow.push({ sprite, block: dblock, dy: 0, vy: 0 });
174-
break;
175-
}
176129
case Block.switchingBlockON:
177130
case Block.switchPressed:
178-
throw new Error(`createCellsFromStageDefinition: block is not supported: ${dblock}`);
131+
throw new Error(`[Grid.constructor]: block is not supported: ${dblock}`);
179132
default:
180133
dblock satisfies never;
181134
}
@@ -204,6 +157,7 @@ export class Grid {
204157
}
205158
}
206159
}
160+
207161
/**
208162
it uses object equality internally, therefore
209163
- object should be equal if they are the same.
@@ -631,6 +585,7 @@ export function createCellsFromStageDefinition(stageDefinition: StageDefinition)
631585
case Block.block:
632586
case null:
633587
case Block.switchBase:
588+
case Block.spike:
634589
case Block.goal: {
635590
const cell: GridCell = {
636591
block,
@@ -753,6 +708,11 @@ function createSprite(
753708
updateSprite(sprite, blockSize, x, y, marginY, 0);
754709
return sprite;
755710
}
711+
case Block.spike: {
712+
const sprite = new Sprite(spikeTexture);
713+
updateSprite(sprite, blockSize, x, y, marginY, 0);
714+
return sprite;
715+
}
756716
default:
757717
block satisfies never;
758718
throw new Error("unreachable");
@@ -765,6 +725,7 @@ function updateSprite(sprite: Sprite, blockSize: number, x: number, y: number, m
765725
sprite.y = y * blockSize + marginY + dy;
766726
}
767727

728+
//ToDo: 現在の仕様では、Escメニュー表示状態でも動き続ける。
768729
export function createTutorialSprite(cx: { _stage_container: Container }, order: number) {
769730
let sprite = new Sprite(tutorialImg1);
770731
switch (order) {
@@ -781,43 +742,11 @@ export function createTutorialSprite(cx: { _stage_container: Container }, order:
781742
sprite.y = 100;
782743
cx._stage_container.addChild(sprite);
783744
}
784-
//ToDo: 現在の仕様では、Escメニュー表示状態でも動き続ける。
785745

786746
export function printCells(cells: GridCell[][], context?: string) {
787747
console.log(
788748
`${context ? context : "Grid"}:
789-
${cells
790-
.map((row) =>
791-
row
792-
.map((cell) => {
793-
switch (cell.block) {
794-
case null:
795-
return ".";
796-
case Block.block:
797-
return "b";
798-
case Block.movable:
799-
return cell.switchId !== undefined ? "M" : "m";
800-
case Block.fallable:
801-
return cell.switchId !== undefined ? "F" : "f";
802-
case Block.switch:
803-
return "s";
804-
case Block.switchBase:
805-
return "S";
806-
case Block.switchingBlockOFF:
807-
return "w";
808-
case Block.switchingBlockON:
809-
return "w";
810-
case Block.switchPressed:
811-
return "s";
812-
case Block.goal:
813-
return "g";
814-
default:
815-
cell satisfies never;
816-
}
817-
})
818-
.join(""),
819-
)
820-
.join("\n")}`,
749+
${cells.map((row) => row.map((cell) => consts.ReverseBlockMap.get(cell.block)).join("")).join("\n")}`,
821750
);
822751
}
823752

src/player.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ export function handleInput(cx: Context, event: KeyboardEvent, eventIsKeyDown: b
128128
export function tick(cx: Context, ticker: Ticker) {
129129
const { blockSize, gridX, gridY, marginY } = get(cx.config);
130130
const player = cx.dynamic.player;
131+
const grid = cx.grid;
132+
133+
// movement
131134
const accel = player.onGround ? consts.playerAccelOnGround : consts.playerAccelInAir;
132135
const decel = player.onGround ? consts.playerDecelOnGround : consts.playerDecelInAir;
133136
let playerIntent = 0; // 0 -> no intent, 1 -> wants to go right, -1 -> wants to go left
@@ -176,6 +179,7 @@ export function tick(cx: Context, ticker: Ticker) {
176179
player.jumpingBegin = null;
177180
}
178181

182+
// collision
179183
const isBlock = (x: number, y: number) =>
180184
cx.grid.getBlock(cx, Math.floor(x), Math.floor(y)) !== null &&
181185
cx.grid.getBlock(cx, Math.floor(x), Math.floor(y)) !== Block.switch &&
@@ -238,6 +242,7 @@ export function tick(cx: Context, ticker: Ticker) {
238242
gameover(cx);
239243
}
240244

245+
// switch activation
241246
if (isSwitchBase(nextX, nextBottomY)) {
242247
const switchBlock = get(cx.state).cells[Math.floor(nextBottomY - 1)][Math.floor(nextX)];
243248
if (switchBlock.block === Block.switch) {
@@ -296,20 +301,21 @@ export function tick(cx: Context, ticker: Ticker) {
296301
}
297302
}
298303

304+
// goal
299305
if (isGoal(nextX, nextTopY) && player.onGround) {
300306
cx.state.update((prev) => {
301307
prev.goaled = true;
302308
return prev;
303309
});
304310
}
305311

306-
// if (get(cx.state).gameover) {
307-
// cx.state.update((prev) => {
308-
// prev.gameover = true;
309-
// return prev;
310-
// });
311-
// };
312+
// gameover
313+
const coords = getCoords(cx);
314+
if (player.onGround && cx.grid.getBlock(cx, coords.x, coords.y + 1) === Block.spike) {
315+
gameover(cx);
316+
}
312317

318+
// movement? again?
313319
// 当たり判定結果を反映する
314320
player.x += player.vx * ticker.deltaTime;
315321
player.y += player.vy * ticker.deltaTime;

src/resources.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import { Assets } from "pixi.js";
2-
32
// assets
3+
4+
// entities
45
export const bunnyTexture = await Assets.load("/assets/bunny.png");
6+
7+
// blocks
58
export const rockTexture = await Assets.load("/assets/block.png");
69
export const fallableTexture = await Assets.load("/assets/woodenbox.png");
710
export const switchTexture = await Assets.load("/assets/switch.png");
811
export const switchBaseTexture = await Assets.load("/assets/switch-base.png");
912
export const switchPressedTexture = await Assets.load("/assets/switch-pressed.png");
1013
export const goalTexture = await Assets.load("/assets/goal.png");
11-
export const highlightTexture = await Assets.load("/assets/highlight.svg");
14+
export const spikeTexture = await Assets.load("/assets/spike.png");
1215

16+
// UI
17+
export const highlightTexture = await Assets.load("/assets/highlight.svg");
1318
export const highlightHoldTexture = await Assets.load("/assets/highlight-hold.webp");
1419
export const tutorialImg1 = await Assets.load("/assets/tutorial1.png");
1520
export const tutorialImg2 = await Assets.load("/assets/tutorial2.png");

src/stages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export const stages = new Map<string, StageDefinition>([
181181
"bb..............w.....m..",
182182
"bb..............b....mm..",
183183
"bb.w....m..s...bb...mmm..",
184-
"bbbbbbbbbbbSbbbbbbbbbbbbb",
184+
"bbbbbbbbbbbSbbbbb^bbbbbbb",
185185
],
186186
initialPlayerX: 5,
187187
initialPlayerY: 8,

0 commit comments

Comments
 (0)