Skip to content

Commit 976f43a

Browse files
committed
Merge branch 'main' into fallable
2 parents 31431ca + bf3a1df commit 976f43a

28 files changed

+679
-676
lines changed

biome.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"formatter": {
1212
"enabled": true,
1313
"indentStyle": "space",
14-
"indentWidth": 2
14+
"indentWidth": 2,
15+
"lineWidth": 120
1516
},
1617
"linter": {
1718
"enabled": true,

index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
<head>
55
<meta charset="utf-8" />
66
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
7+
<link href="https://fonts.cdnfonts.com/css/fleftex-mono" rel="stylesheet">
78
<meta name="viewport" content="width=device-width, initial-scale=1" />
89
%sveltekit.head%
910
</head>
1011

11-
<body data-sveltekit-preload-data="hover" style="margin: 0px; overflow: hidden;" data-theme="light">
12+
<body data-sveltekit-preload-data="hover" style="margin: 0px; overflow: hidden; font-family: 'Fleftex'; font-size: 1.5rem;" data-theme="light">
1213
<div style="display: contents">%sveltekit.body%</div>
1314
</body>
1415

public/assets/goal.png

219 KB
Loading

public/assets/tutorial1.png

147 KB
Loading

public/assets/tutorial2.png

190 KB
Loading

public/assets/tutorial3.png

191 KB
Loading

routes/+page.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313
<a href="/game?stage=8">Stage 8</a>
1414

1515
<p>
16-
<a href="/game?stage=3-1">Stage 3-1</a>
17-
<a href="/game?stage=3-2">Stage 3-2</a>
16+
<a href="/game?stage=3-1">Stage 3-1</a>
17+
<a href="/game?stage=3-2">Stage 3-2</a>
1818
</p>

routes/game/+page.svelte

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ import { page } from "$app/state";
44
import { stages } from "@/stages";
55
import GameLoader from "@/ui-components/GameLoader.svelte";
66
7-
const stageNum = $derived(
8-
browser ? (page.url.searchParams.get("stage") ?? "") : "",
9-
);
7+
const stageNum = $derived(browser ? (page.url.searchParams.get("stage") ?? "") : "");
108
const stageDefinition = $derived(stages.get(stageNum));
9+
const stageNames = $derived(Array.from(stages.keys()));
1110
</script>
1211

13-
<GameLoader stage={stageDefinition} {stageNum}>
12+
<GameLoader stage={stageDefinition} {stageNum} {stageNames}>
1413
{#snippet children(loadingState)}
1514
{loadingState}...
1615
{/snippet}

src/ability.ts

Lines changed: 34 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@ import { Block, Facing } from "./constants.ts";
33
import { printCells } from "./grid.ts";
44
import { createSnapshot } from "./history.ts";
55
import * as History from "./history.ts";
6-
import type {
7-
AbilityInit,
8-
Context,
9-
Coords,
10-
MovableObject,
11-
} from "./public-types.ts";
6+
import type { AbilityInit, Context, Coords, MovableObject } from "./public-types.ts";
127

138
export function init(cx: Context, options?: AbilityInit) {
149
cx.state.update((prev) => ({
@@ -65,8 +60,7 @@ export function copy(cx: Context) {
6560
const x = focus.x;
6661
const y = focus.y;
6762
const target = cx.grid.getBlock(cx, x, y);
68-
if (!target || (target !== Block.movable && target !== Block.fallable))
69-
return;
63+
if (!target || (target !== Block.movable && target !== Block.fallable)) return;
7064
const movableObject = cx.grid.getMovableObject(cx, x, y);
7165
if (!movableObject) return;
7266

@@ -83,35 +77,19 @@ export function copy(cx: Context) {
8377
}
8478
export function paste(cx: Context) {
8579
const state = get(cx.state);
86-
const { focus } = cx.dynamic;
80+
const { focus, player } = cx.dynamic;
8781
const { inventory } = state;
8882
if (!focus) return;
8983
if (!inventory) return;
9084
if (state.usage.paste <= 0) return;
9185

92-
// 左向きのときにブロックを配置する位置を変更するのに使用
93-
const width =
94-
inventory.relativePositions.reduce((acc, i) => Math.max(acc, i.x), 0) -
95-
inventory.relativePositions.reduce((acc, i) => Math.min(acc, i.x), 1000) +
96-
1;
97-
98-
const facing = cx.dynamic.player.facing;
99-
const x = focus.x - (facing === Facing.left ? width - 1 : 0);
100-
const y = focus.y;
101-
102-
for (const i of inventory.relativePositions) {
103-
const positionX = x + i.x;
104-
const positionY = y + i.y;
105-
const target = cx.grid.getBlock(cx, positionX, positionY);
106-
if (target !== Block.air && target !== Block.switch) {
107-
// すでに何かある場合は、ペーストできない
108-
return;
109-
}
86+
const { x, y } = findSafeObjectPlace(player.facing, focus.x, focus.y, inventory);
87+
if (!canPlaceMovableObject(cx, x, y, inventory)) {
88+
return;
11089
}
111-
11290
History.record(cx);
11391
placeMovableObject(cx, x, y, inventory);
114-
if (!get(cx.state).inventoryIsInfinite) {
92+
if (!state.inventoryIsInfinite) {
11593
cx.state.update((prev) => {
11694
prev.inventory = null;
11795
return prev;
@@ -129,8 +107,7 @@ export function cut(cx: Context) {
129107
const y = focus.y;
130108
const target = cx.grid.getBlock(cx, x, y);
131109
// removable 以外はカットできない
132-
if (!target || (target !== Block.movable && target !== Block.fallable))
133-
return;
110+
if (!target || (target !== Block.movable && target !== Block.fallable)) return;
134111
const movableObject = cx.grid.getMovableObject(cx, x, y);
135112
if (!movableObject) return;
136113

@@ -142,35 +119,47 @@ export function cut(cx: Context) {
142119
});
143120
cx.grid.update(cx, (prev) => {
144121
if (prev.objectId !== movableObject.objectId) return prev;
145-
if (
146-
(prev.block === Block.movable || prev.block === Block.fallable) &&
147-
prev.switchId !== undefined
148-
)
122+
if ((prev.block === Block.movable || prev.block === Block.fallable) && prev.switchId !== undefined)
149123
return { block: Block.switch, switchId: prev.switchId };
150-
return { block: Block.air };
124+
return { block: null };
151125
});
152126

153127
printCells(createSnapshot(cx).game.cells, "cut");
154128
History.record(cx);
155129
}
156130

157-
export function placeMovableObject(
158-
cx: Context,
159-
x: number,
160-
y: number,
161-
object: MovableObject,
162-
) {
163-
const grid = cx.grid;
131+
// 左向きのときにブロックを配置する位置を変更するのに使用
132+
function findSafeObjectPlace(facing: Facing, x: number, y: number, obj: MovableObject) {
133+
const width =
134+
obj.relativePositions.reduce((acc, i) => Math.max(acc, i.x), 0) -
135+
obj.relativePositions.reduce((acc, i) => Math.min(acc, i.x), 1000) +
136+
1;
164137

138+
return {
139+
x: x - (facing === Facing.left ? width - 1 : 0),
140+
y: y,
141+
};
142+
}
143+
export function canPlaceMovableObject(cx: Context, x: number, y: number, object: MovableObject) {
144+
const grid = cx.grid;
165145
for (const i of object.relativePositions) {
166146
const positionX = x + i.x;
167147
const positionY = y + i.y;
168148
const target = grid.getBlock(cx, positionX, positionY);
169-
if (target !== Block.air && target !== Block.switch) {
149+
if (target && target !== Block.switch) {
170150
// すでに何かある場合は、ペーストできない
171-
return;
151+
return false;
172152
}
173153
}
154+
return true;
155+
}
156+
export function placeMovableObject(cx: Context, x: number, y: number, object: MovableObject) {
157+
const grid = cx.grid;
158+
159+
if (!canPlaceMovableObject(cx, x, y, object)) {
160+
console.error("[placeMovableObject] cannot place object");
161+
return;
162+
}
174163
for (const rel of object.relativePositions) {
175164
const positionX = x + rel.x;
176165
const positionY = y + rel.y;
@@ -181,20 +170,3 @@ export function placeMovableObject(
181170
});
182171
}
183172
}
184-
185-
export function removeMovableObject(
186-
cx: Context,
187-
x: number,
188-
y: number,
189-
): MovableObject | undefined {
190-
const grid = cx.grid;
191-
const obj = grid.getMovableObject(cx, x, y);
192-
if (!obj) return undefined;
193-
194-
for (const i of obj.relativePositions) {
195-
const positionX = x + i.x;
196-
const positionY = y + i.y;
197-
grid.setBlock(cx, positionX, positionY, { block: Block.air });
198-
}
199-
return obj;
200-
}

src/constants.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ export const moveVX = 0.1;
55
export const jumpVY = 0.12;
66
export const jumpFrames = 10;
77
export const gravity = 0.02;
8+
export const maxObjectFallSpeed = 2;
89

910
export enum Block {
10-
air = "air",
1111
block = "block",
1212
movable = "movable",
1313
fallable = "fallable",
@@ -16,6 +16,7 @@ export enum Block {
1616
switchingBlockOFF = "switching-block-off",
1717
switchingBlockON = "switching-block-on",
1818
switchPressed = "switch-pressed",
19+
goal = "goal",
1920
}
2021
export enum Facing {
2122
left = "left",
@@ -27,3 +28,14 @@ export enum Inputs {
2728
Up = 2,
2829
Ctrl = 3,
2930
}
31+
32+
export const BlockDefinitionMap = new Map<string, Block | null>([
33+
[".", null],
34+
["b", Block.block],
35+
["m", Block.movable],
36+
["f", Block.fallable],
37+
["s", Block.switch],
38+
["S", Block.switchBase],
39+
["w", Block.switchingBlockOFF],
40+
["g", Block.goal],
41+
]);

0 commit comments

Comments
 (0)