Skip to content

Commit 7da9480

Browse files
committed
feat: change color of large objects
1 parent 132bbd1 commit 7da9480

File tree

10 files changed

+80
-34
lines changed

10 files changed

+80
-34
lines changed
-6.97 KB
Binary file not shown.

public/assets/block-large.png

606 Bytes
Loading

src/ability.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export function copy(cx: Context) {
9393

9494
History.record(cx);
9595

96+
cx.dynamic.isInventoryBlockLarge = movableObject.relativePositions.length >= 2;
9697
cx.dynamic.player.activated = true;
9798
}
9899
export function paste(cx: Context) {
@@ -156,6 +157,7 @@ export function cut(cx: Context) {
156157
printCells(createSnapshot(cx).game.cells, "cut");
157158
History.record(cx);
158159

160+
cx.dynamic.isInventoryBlockLarge = movableObject.relativePositions.length >= 2;
159161
cx.dynamic.player.activated = true;
160162
}
161163

@@ -192,13 +194,20 @@ export function placeMovableObject(cx: Context, x: number, y: number, object: Mo
192194
return;
193195
}
194196
const newObjectId = Math.random().toString();
197+
const isBlockLarge = object.relativePositions.length >= 2;
195198
for (const rel of object.relativePositions) {
196199
const positionX = x + rel.x;
197200
const positionY = y + rel.y;
198-
grid.setBlock(cx, positionX, positionY, {
199-
block: object.block,
200-
objectId: newObjectId,
201-
switchId: undefined,
202-
});
201+
grid.setBlock(
202+
cx,
203+
positionX,
204+
positionY,
205+
{
206+
block: object.block,
207+
objectId: newObjectId,
208+
switchId: undefined,
209+
},
210+
isBlockLarge,
211+
);
203212
}
204213
}

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const elapsedTimePerFrame = 30;
1919

2020
export const laserWidth = 0.3;
2121

22+
export const LARGE_BLOCK_COLOR = 0xff00a0; // 大きなブロックは別の色で表示する
2223
export enum Block {
2324
block = "block",
2425
movable = "movable",

src/grid.ts

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,15 @@ export class Grid {
118118
case Block.fallable:
119119
case Block.goal:
120120
case Block.switchBase: {
121-
const sprite = createSprite(cellSize, dblock, x, y, this.marginY);
121+
const objectId = stageDefinition.blockGroups.find((g) => g.x === x && g.y === y)?.objectId || undefined;
122+
let movableBlockColor: number | undefined = undefined;
123+
if (
124+
dblock === Block.movable &&
125+
stageDefinition.blockGroups.filter((b) => b.objectId === objectId).length >= 2
126+
) {
127+
movableBlockColor = consts.LARGE_BLOCK_COLOR;
128+
}
129+
const sprite = createSprite(cellSize, dblock, x, y, this.marginY, movableBlockColor);
122130
stage.addChild(sprite);
123131
vspriteRow.push({ sprite, block: dblock, dy: 0, vy: 0 });
124132
break;
@@ -211,7 +219,10 @@ export class Grid {
211219
const vsom = this.__vsom[y][x];
212220
const newCell = newGrid[y][x];
213221
if (vsom?.block !== newCell.block) {
214-
this.setBlock(cx, x, y, newCell);
222+
// TODO:this uses a lot of memory
223+
const isBlockLarge =
224+
newGrid.flatMap((row) => row.filter((cell) => cell.objectId === newCell.objectId)).length >= 2;
225+
this.setBlock(cx, x, y, newCell, isBlockLarge);
215226
}
216227
}
217228
}
@@ -345,6 +356,7 @@ export class Grid {
345356
x: number,
346357
y: number,
347358
cNewCell: GridCell,
359+
isLargeBlock?: boolean, // todo: please fix shitty code this someone please
348360
) {
349361
const stage = cx._stage_container;
350362
const cells = get(cx.state).cells;
@@ -363,6 +375,8 @@ export class Grid {
363375
assert(cNewCell.objectId == null, "Cell is not movable but has an objectId");
364376
}
365377

378+
const movableBlockColor = isLargeBlock ? consts.LARGE_BLOCK_COLOR : undefined;
379+
366380
if (vprev?.block === Block.switch && cNewCell.block === Block.switchPressed) {
367381
// switchがプレイヤーに押されるとき
368382
assert(
@@ -409,7 +423,7 @@ export class Grid {
409423
console.log("cell.block", cNewCell.block);
410424
return;
411425
}
412-
const movableSprite = createSprite(blockSize, cNewCell.block, x, y, marginY);
426+
const movableSprite = createSprite(blockSize, cNewCell.block, x, y, marginY, movableBlockColor);
413427
stage.addChild(movableSprite);
414428
assert(cNewCell.objectId !== undefined, "movable block must have objectId");
415429
assert(
@@ -551,7 +565,8 @@ export class Grid {
551565
break;
552566
}
553567
case Block.movable: {
554-
const movableSprite = createSprite(blockSize, cNewCell.block, x, y, marginY);
568+
const movableSprite = createSprite(blockSize, cNewCell.block, x, y, marginY, movableBlockColor);
569+
console.log(movableBlockColor);
555570
stage.addChild(movableSprite);
556571
assert(cNewCell.objectId !== undefined, "movable block must have objectId");
557572
cells[y][x] = {
@@ -666,7 +681,6 @@ export class Grid {
666681
vSwapCell.vy = vcell.vy;
667682
vcell.dy = 0;
668683
vcell.vy = 0;
669-
// また抽象化失敗してる...
670684
vSwapCell.sprite.y = (y + swapDiff) * blockSize + marginY + vSwapCell.dy;
671685
console.log("dy", vSwapCell.dy, "vy", vSwapCell.vy);
672686
}
@@ -908,7 +922,8 @@ function createSprite(
908922
x: number,
909923
y: number,
910924
marginY: number,
911-
switchColor?: number, // 例: #ffa500
925+
// 使われたり使われなかったりするので注意
926+
color?: number, // 例: #ffa500
912927
) {
913928
switch (block) {
914929
case Block.block: {
@@ -918,10 +933,14 @@ function createSprite(
918933
return sprite;
919934
}
920935
case Block.movable: {
921-
const movableSprite = new Sprite(rockTexture);
922-
movableSprite.tint = 0xff0000;
923-
updateSprite(movableSprite, blockSize, x, y, marginY, 0);
924-
return movableSprite;
936+
const sprite = new Sprite(rockTexture);
937+
if (color) {
938+
sprite.tint = color;
939+
} else {
940+
sprite.tint = 0xff0000;
941+
}
942+
updateSprite(sprite, blockSize, x, y, marginY, 0);
943+
return sprite;
925944
}
926945
case Block.fallable: {
927946
const movableSprite = new Sprite(fallableTexture);
@@ -931,7 +950,7 @@ function createSprite(
931950
}
932951
case Block.switch: {
933952
const switchSprite = new Sprite(switchTexture);
934-
if (switchColor) switchSprite.tint = switchColor;
953+
if (color) switchSprite.tint = color;
935954
updateSprite(switchSprite, blockSize, x, y, marginY, 0);
936955
return switchSprite;
937956
}
@@ -943,23 +962,23 @@ function createSprite(
943962
case Block.inverseSwitchingBlockON:
944963
case Block.switchingBlockOFF: {
945964
const sprite = new Sprite(rockTexture);
946-
if (switchColor) sprite.tint = switchColor;
965+
if (color) sprite.tint = color;
947966
else sprite.tint = 0xffa500;
948967
updateSprite(sprite, blockSize, x, y, marginY, 0);
949968
return sprite;
950969
}
951970
case Block.inverseSwitchingBlockOFF:
952971
case Block.switchingBlockON: {
953972
const sprite = new Sprite(rockTexture);
954-
if (switchColor) sprite.tint = switchColor;
973+
if (color) sprite.tint = color;
955974
else sprite.tint = 0xffa500;
956975
sprite.alpha = 0.3;
957976
updateSprite(sprite, blockSize, x, y, marginY, 0);
958977
return sprite;
959978
}
960979
case Block.switchPressed: {
961980
const sprite = new Sprite(switchPressedTexture);
962-
if (switchColor) sprite.tint = switchColor;
981+
if (color) sprite.tint = color;
963982
else sprite.tint = 0xffa500;
964983
updateSprite(sprite, blockSize, x, y, marginY, 0);
965984
return sprite;

src/history.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ function restore(cx: Context, ss: StateSnapshot) {
109109
cx.dynamic.player.x = ss.playerX;
110110
cx.dynamic.player.y = ss.playerY;
111111
cx.dynamic.player.facing = ss.playerFacing;
112+
cx.dynamic.isInventoryBlockLarge = (ss.game.inventory?.relativePositions.length ?? 0) >= 2;
112113
cx.grid.diffAndUpdateTo(cx, ss.game.cells);
113114
cx.grid.clearFallableSprites(cx);
114115
cx.grid.clearLaser(cx);
115-
printCells(ss.game.cells, "restore");
116116
}
117117
function stash(cx: Context) {
118118
cx.history.update((prev) => {

src/main.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export async function setup(
9494
const initialDynamic = {
9595
focus: null,
9696
player: null,
97+
isInventoryBlockLarge: false,
9798
} satisfies GameDynamic;
9899
const state = writable<GameState>(structuredClone(initialGameState));
99100
const grid = new Grid(
@@ -116,7 +117,7 @@ export async function setup(
116117
state: state,
117118
history,
118119
config,
119-
elapsed: 0, // does this need to be writable? like is anyone listening to this/
120+
elapsed: 0,
120121
};
121122

122123
function reset() {
@@ -214,7 +215,7 @@ export async function setup(
214215
};
215216

216217
const uiContext = derived([state, history], ([$state, $history]) => {
217-
return useUI($state, $history);
218+
return useUI($state, $history, cx.dynamic);
218219
});
219220
uiContext.subscribe((uiInfo) => {
220221
bindings.uiInfo = uiInfo;

src/public-types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export type GameHistory = {
5858
export type GameDynamic = {
5959
focus: Coords | null; // current focus coordinates
6060
player: Player | null;
61+
isInventoryBlockLarge: boolean; // please forgive me
6162
};
6263

6364
export type Context = {
@@ -81,6 +82,7 @@ export type Context = {
8182

8283
export type UIInfo = {
8384
inventory: MovableObject | null;
85+
inventoryIsLarge: boolean;
8486
inventoryIsInfinite: boolean;
8587
copy: number;
8688
paste: number;

src/ui-components/Game.svelte

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,19 @@ onDestroy(() => bindings.destroy());
6363
// if this isn't working well, we can use window.location.reload(); instead
6464
bindings.reset();
6565
}}
66-
stageNum={stageNum}
66+
{stageNum}
6767
/>
6868
<GoalMenu
6969
goaled={uiContext.goaled}
7070
{nextStage}
7171
reset={() => bindings.reset()}
72-
stageNum={stageNum}
72+
{stageNum}
73+
/>
74+
<GameOverMenu
75+
gameover={uiContext.gameover}
76+
reset={() => bindings.reset()}
77+
{stageNum}
7378
/>
74-
<GameOverMenu gameover={uiContext.gameover} reset={() => bindings.reset()} stageNum={stageNum} />
7579
<div
7680
class="uiBackground"
7781
style="position: fixed; left: 0; top: 0; right: 0; display: flex; align-items: end; "
@@ -85,13 +89,22 @@ onDestroy(() => bindings.destroy());
8589
<span style="">Clipboard:</span>
8690
<div class="inventory">
8791
{#if uiContext.inventory?.block === Block.movable}
88-
<!-- todo: tint 0xff0000 をする必要があるが、そもそもこの画像は仮なのか本当に赤色にするのか -->
89-
<img
90-
src="/assets/block-red.png"
91-
alt="inventory"
92-
width="100%"
93-
height="100%"
94-
/>
92+
{#if uiContext.inventoryIsLarge}
93+
<img
94+
src="/assets/block-large.png"
95+
alt="inventory"
96+
width="100%"
97+
height="100%"
98+
/>
99+
{:else}
100+
<!-- todo: tint 0xff0000 をする必要があるが、そもそもこの画像は仮なのか本当に赤色にするのか -->
101+
<img
102+
src="/assets/block-red.png"
103+
alt="inventory"
104+
width="100%"
105+
height="100%"
106+
/>
107+
{/if}
95108
{:else if uiContext.inventory?.block === Block.fallable}
96109
<img
97110
src="/assets/woodenbox.png"

src/ui-info.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import type { GameHistory, GameState, UIInfo } from "./public-types.ts";
1+
import type { GameDynamic, GameHistory, GameState, UIInfo } from "./public-types.ts";
22

3-
export function useUI(state: GameState, history: GameHistory): UIInfo {
3+
export function useUI(state: GameState, history: GameHistory, dynamic: GameDynamic): UIInfo {
44
return {
55
inventory: state.inventory,
6+
inventoryIsLarge: dynamic.isInventoryBlockLarge,
67
inventoryIsInfinite: state.inventoryIsInfinite,
78
copy: state.usage.copy,
89
paste: state.usage.paste,

0 commit comments

Comments
 (0)