From 27459787c1d3402a4f32d530c969c0c7653b8c52 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Sat, 22 Feb 2025 19:22:06 -0800 Subject: [PATCH] Blockify collectibles --- src/art/pickups/collectibles.png | Bin 0 -> 605 bytes src/art/pickups/collectibles_silhouettes.png | Bin 0 -> 471 bytes src/art/pickups/resources.png | Bin 455 -> 0 bytes src/art/pickups/stats.png | Bin 431 -> 0 bytes src/colors.ts | 34 +++ src/huntmode.ts | 130 ++++------ src/pickups.ts | 238 ++++++++++++------- src/sprites.ts | 20 +- src/world3d.ts | 140 +++++++++++ 9 files changed, 384 insertions(+), 178 deletions(-) create mode 100644 src/art/pickups/collectibles.png create mode 100644 src/art/pickups/collectibles_silhouettes.png delete mode 100644 src/art/pickups/resources.png delete mode 100644 src/art/pickups/stats.png create mode 100644 src/world3d.ts diff --git a/src/art/pickups/collectibles.png b/src/art/pickups/collectibles.png new file mode 100644 index 0000000000000000000000000000000000000000..cc1c22c450d72e4ab08d5235dff6f48720c1794a GIT binary patch literal 605 zcmV-j0;2tiP)001Be1^@s6m49>f00001b5ch_0Itp) z=>Px%7fD1xRCt{2*uP4{KpY3~U!-(!C=Q~iAQrWh4n9CBMQLB4dk2TQ_yoGS`39W= zc5wFv3`nVY01=TEO%*D%I+P9$BAkP!=5L#5?%Jf^50oakgx@v!^>=q60ssI200000 z0002sNSbs9AbdU!=b3T8bGt%BM9KOC@(ILXKbq|xYqon#%WtyrSJ@$BeLBvbjJ(mO z>Ph79X^<7r_XTdjb)w2}y4*1J2iaKNJ68+!kX=v((iDK=azWZcAkmY+E4y&KfMy|rA+Oq zjU`{P=lpgcUVV2BAfo!|$wx$_e;eC)$2U^?o#BT!r{v48Ur>Ji!qd6aDwGv4ro51~ z0!GMq@~Qd$Kl$ilsUJZBM+L2EYOpxvQr7N7E(|U zF-g&gIifQEp2D@`%l_Q{|NsBL&j)^8+wpb5^cPvhd%R{>S~WNr2dgNVD9K0}X=@ZZ zTJJ7(zr7^+%cVKD9=zJT^J4ep^|__JULi@wmX1y;#?gireL+FHO0!;WUHtgj|DF4P zx6FPL(Yw#RwpBUZ&!{COc75-pJG;()fAr+is^c5F7qlf+riVuPxj0#xnAuCt0s6(E zB*-tA0q7J;fUx#FL!eoeo-U3d5v^~hIC32@;9%MO|9{ECDU+OEdAaU66LbBD;k0$E z3=9+8%rA@exjC-v19{Zos3>hYxmE*(v>Ze|NdHYVT2*Wfky5})r=|gTxa|SI)cH| L)z4*}Q$iB}!ZGSJ literal 0 HcmV?d00001 diff --git a/src/art/pickups/resources.png b/src/art/pickups/resources.png deleted file mode 100644 index bc989aa97f5ab1dc339e22af9214f84ef9047864..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 455 zcmV;&0XY7NP)Px$fk{L`RA_-?U>F6XU=)mkQ801=<3Kxr9PlfP>pwF8=@m%^1_lNO#Y1<8q<_c) z|DoX4gIE7=J$Uv1zMb-a!n!cQkPI^68$2ST1k*xd(i>8 z=8gCiK#~S*4q(~)3`5Yj(M8IC!SZ$A??95s{y$tgf}!F^N%(6WF=%#r`J$^x_iL^~8c z|DoqQY=D%!NRAtDxrL@>05Uk{um`6cwabEESzP}a`j4ZC!D^q==!)%>{}WpyQ4|1! z0sLNc97Bwhz#lSM0KM(Oz<@{r*Z{F9fFuWEa|AZPHtict3PD=5Lr8Y$tp~601_CYH z0V?zF{l{pBP-y>%ZwHKK0SetjH$baGct}@+)M$r{_%dKfrvR%1E;!{x7U=yaCJPLi xGJt`BHihtz3IGNM>bFBid>JsLQUEQo000&o+%8IVcAo$M002ovPDHLkV1jKSx!eE% diff --git a/src/art/pickups/stats.png b/src/art/pickups/stats.png deleted file mode 100644 index 7301deb037ab571450a8e3910610fce8e8865adf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 431 zcmV;g0Z{&lP)Px$X-PyuRCt{2*s*HDKp4RBFGV_ZkZz?d2o44D5ky?_1n!PbeS>apeS=Pp?mj`5 zAbEmPgi-=R3fZJXhf+wVlUy6Emzpz4|347n&Uhd9eRsJ;1ONa400000P;<_)1E`w2 z-Xz)8e;-ULHK)eGe%zjE6A(RKYW;2h#mWS9Mhh*D<*Z-$xW6S|DY^)r-o}}6bemJ- zaT|XR$G*;Jk$k#W((qojHXB8d=AK{wX!F)lVdHH}{P%v7LO3xE;`HHt>z~_L{VMq) zBI-NcSM>O4-a6WRik6l9L2E99)_kwuZev^kWuR7mdIzX8lZ2XHldAx-b^%-Wex;1b zx3Lo(S|xXY|0d7jZr^Ki7eIO!u(|qo9rSD;0+p=8;GuP!QzwW+t<7Hz#a|7zwjd6T z3Z{}z0n1t6ImTn4Vk6;M#y6fLA~Jn;lio#J>kHy=({G|uFD=TTZZCoW000000002B Z_XUM7du#jK&Yu7P002ovPDHLkV1l>Ry9odQ diff --git a/src/colors.ts b/src/colors.ts index b980880..7e6215b 100644 --- a/src/colors.ts +++ b/src/colors.ts @@ -1,4 +1,5 @@ import { Color } from "./engine/datatypes.ts"; +import { Stat } from "./datatypes.ts"; export const BG_OUTER = Color.parseHexCode("#143464"); export const BG_WALL_OR_UNREVEALED = Color.parseHexCode("#143464"); @@ -10,3 +11,36 @@ export const FG_TEXT_ENDORSED = Color.parseHexCode("#80ff80"); export const FG_BOLD = Color.parseHexCode("#ffffff"); export const BG_CEILING = Color.parseHexCode("#143464"); export const FG_MOULDING = FG_TEXT; + +// stat colors +export const SWATCH_EXP: [Color, Color] = [ + Color.parseHexCode("#b9bffb"), + Color.parseHexCode("#e3e6ff"), +]; + +export const SWATCH_AGI: [Color, Color] = [ + Color.parseHexCode("#df3e23"), + Color.parseHexCode("#fa6a0a"), +]; + +export const SWATCH_INT: [Color, Color] = [ + Color.parseHexCode("#285cc4"), + Color.parseHexCode("#249fde"), +]; + +export const SWATCH_CHA: [Color, Color] = [ + Color.parseHexCode("#793a80"), + Color.parseHexCode("#bc4a9b"), +]; + +export const SWATCH_PSI: [Color, Color] = [ + Color.parseHexCode("#9cdb43"), + Color.parseHexCode("#d6f264"), +]; + +export const SWATCH_STAT: Record = { + AGI: SWATCH_AGI, + INT: SWATCH_INT, + CHA: SWATCH_CHA, + PSI: SWATCH_PSI, +}; diff --git a/src/huntmode.ts b/src/huntmode.ts index b45b14e..0137c0c 100644 --- a/src/huntmode.ts +++ b/src/huntmode.ts @@ -4,9 +4,6 @@ import { D, I } from "./engine/public.ts"; import { sprThrallLore } from "./sprites.ts"; import { BG_INSET, - BG_WALL_OR_UNREVEALED, - FG_BOLD, - FG_MOULDING, FG_TEXT, FG_TEXT_ENDORSED, FG_TOO_EXPENSIVE, @@ -18,6 +15,7 @@ import { shadowcast } from "./shadowcast.ts"; import { withCamera } from "./layout.ts"; import { getCheckModal } from "./checkmodal.ts"; import { CARDINAL_DIRECTIONS } from "./mapgen.ts"; +import { Block3D, Floor3D, World3D } from "./world3d.ts"; export class HuntMode { map: LoadedNewMap; @@ -113,14 +111,22 @@ export class HuntMode { this.#updateFov(); this.#updatePickups(); + let world3d = new World3D(this.map.size); + for (let y = 0; y < this.map.size.h; y += 1) { + for (let x = 0; x < this.map.size.w; x += 1) { + this.#writeMapCellToWorld(world3d, new Point(x, y)); + } + } + for (let y = 0; y < this.map.size.h; y += 1) { for (let x = 0; x < this.map.size.w; x += 1) { let offsetInPixels = new Point(x, y) .scale(FLOOR_CELL_SIZE) .offset(this.pixelPlayer.negate()); - this.#drawMapCell(offsetInPixels, new Point(x, y)); + this.#drawMapCell(offsetInPixels, world3d, new Point(x, y)); } } + this.#drawPlayer(globalOffset); this.#drawBadges(globalOffset); @@ -181,8 +187,8 @@ export class HuntMode { } let nSteps = 40; - let szX = 0.75; - let szY = 0.75; + let szX = 0.5; + let szY = 0.5; this.velocity = new Point(dx, dy); @@ -190,7 +196,7 @@ export class HuntMode { for (let offset of CARDINAL_DIRECTIONS.values()) { let bigBbox = new Rect( this.floatingPlayer - .offset(offset.scale(new Size(0.02, 0.02))) + .offset(offset.scale(new Size(0.12, 0.12))) .offset(new Point(-szX / 2, -szY / 2)), new Size(szX, szY), ); @@ -293,26 +299,14 @@ export class HuntMode { this.drawpile.draw(); } - #drawMapCell(offsetInPixels: Point, mapPosition: Point) { - const OFFSET_UNDER_FLOOR = -512 + mapPosition.y; + #drawMapCell(offsetInPixels: Point, world3d: World3D, mapPosition: Point) { const OFFSET_FLOOR = -256 + mapPosition.y; - const OFFSET_AIR = 0 + mapPosition.y; - const OFFSET_TOP = 256 + mapPosition.y; - const OFFSET_TOP_OF_TOP = 512 + mapPosition.y; const gridArt = new GridArt(offsetInPixels); - let cellData = this.map.get(mapPosition); + world3d.drawCell(this.drawpile, gridArt, mapPosition); - this.drawpile.add(OFFSET_UNDER_FLOOR, () => { - gridArt.drawCeiling(BG_WALL_OR_UNREVEALED); - }); - if (cellData.architecture == Architecture.Wall || !cellData.revealed) { - this.drawpile.add(OFFSET_TOP, () => { - gridArt.drawCeiling(BG_WALL_OR_UNREVEALED); - }); - return; - } + let cellData = this.map.get(mapPosition); if (!cellData.revealed) { return; @@ -343,7 +337,6 @@ export class HuntMode { } gridArt.drawFloor(color); - pickup?.drawFloor(gridArt); }, gridArt.floorRect, true, @@ -369,70 +362,32 @@ export class HuntMode { ); if (pickup != null) { - this.drawpile.add(OFFSET_AIR, () => { - pickup.drawInAir(gridArt); - }); - } - - const isRevealedBlock = (dx: number, dy: number) => { - let other = this.map.get(mapPosition.offset(new Point(dx, dy))); - return other.revealed && other.architecture == Architecture.Wall; - }; - if (isRevealedBlock(0, -1) && isRevealedBlock(-1, 0)) { - this.drawpile.add(OFFSET_TOP_OF_TOP, () => { - gridArt.drawMouldingTopLeft(FG_MOULDING); - }); - } - if (isRevealedBlock(0, -1)) { - this.drawpile.add(OFFSET_AIR, () => { - gridArt.drawWallTop(FG_TEXT); - }); - this.drawpile.add(OFFSET_TOP_OF_TOP, () => { - gridArt.drawMouldingTop(FG_MOULDING); - }); - } - if (isRevealedBlock(0, -1) && isRevealedBlock(1, 0)) { - this.drawpile.add(OFFSET_TOP_OF_TOP, () => { - gridArt.drawMouldingTopRight(FG_MOULDING); - }); - } - if (isRevealedBlock(-1, 0)) { - this.drawpile.add(OFFSET_AIR, () => { - gridArt.drawWallLeft(FG_TEXT); - }); - this.drawpile.add(OFFSET_TOP_OF_TOP, () => { - gridArt.drawMouldingLeft(FG_MOULDING); - }); - } - if (isRevealedBlock(0, 1) && isRevealedBlock(-1, 0)) { - this.drawpile.add(OFFSET_TOP_OF_TOP, () => { - gridArt.drawMouldingBottomLeft(FG_MOULDING); - }); - } - if (isRevealedBlock(0, 1)) { - this.drawpile.add(OFFSET_AIR, () => { - gridArt.drawWallBottom(FG_BOLD); - }); - this.drawpile.add(OFFSET_TOP_OF_TOP, () => { - gridArt.drawMouldingBottom(FG_MOULDING); - }); - } - if (isRevealedBlock(0, 1) && isRevealedBlock(1, 0)) { - this.drawpile.add(OFFSET_TOP_OF_TOP, () => { - gridArt.drawMouldingBottomRight(FG_MOULDING); - }); - } - if (isRevealedBlock(1, 0)) { - this.drawpile.add(OFFSET_AIR, () => { - gridArt.drawWallRight(FG_BOLD); - }); - this.drawpile.add(OFFSET_TOP_OF_TOP, () => { - gridArt.drawMouldingRight(FG_MOULDING); - }); + pickup.draw(this.drawpile, gridArt); } } - #drawPlayer(globalOffset: Point) { + #writeMapCellToWorld(world3d: World3D, mapPosition: Point) { + let cellData = this.map.get(mapPosition); + if (!cellData.revealed) { + return; + } + + let pickupBlock = cellData.pickup?.getBlock(); + if (pickupBlock) { + world3d.set(mapPosition, pickupBlock); + return; + } + + if (cellData.architecture == Architecture.Wall) { + world3d.set(mapPosition, Block3D.standardWall()); + return; + } + + world3d.set(mapPosition, new Floor3D()); + } + + #drawPlayer(_globalOffset: Point) { + /* let cellOffset = this.pixelPlayer.offset(globalOffset.negate()); this.drawpile.add(1024, () => { D.drawSprite(sprThrallLore, cellOffset, 1, { @@ -440,6 +395,13 @@ export class HuntMode { yScale: 2, }); }); + */ + this.drawpile.add(1024, () => { + D.drawSprite(sprThrallLore, new Point(192, 192), 1, { + xScale: this.faceLeft ? -2 : 2, + yScale: 2, + }); + }); } #drawBadges(globalOffset: Point) { diff --git a/src/pickups.ts b/src/pickups.ts index 5847aaa..95ffa7c 100644 --- a/src/pickups.ts +++ b/src/pickups.ts @@ -6,16 +6,24 @@ import { generateMap } from "./mapgen.ts"; import { ALL_STATS, Stat } from "./datatypes.ts"; import { D } from "./engine/public.ts"; import { + sprCollectibles, + sprCollectiblesSilhouettes, sprLadder, sprLock, - sprResourcePickup, - sprStatPickup, } from "./sprites.ts"; import { GridArt } from "./gridart.ts"; import { getCheckModal } from "./checkmodal.ts"; import { Point, Size } from "./engine/datatypes.ts"; import { choose } from "./utils.ts"; -import { FG_TEXT } from "./colors.ts"; +import { + BG_CEILING, + FG_BOLD, + FG_TEXT, + SWATCH_EXP, + SWATCH_STAT, +} from "./colors.ts"; +import { Block3D } from "./world3d.ts"; +import { DrawPile } from "./drawpile.ts"; export type Pickup = | LockPickup @@ -52,14 +60,19 @@ export class LockPickup { return true; } - drawFloor() {} - drawInAir(gridArt: GridArt) { - for (let z = 0; z < 5; z += 0.25) { - D.drawSprite(sprLock, gridArt.project(z), 0, { - xScale: 2.0, - yScale: 2.0, - }); - } + draw(drawpile: DrawPile, gridArt: GridArt) { + drawpile.add(0, () => { + for (let z = 0; z < 5; z += 0.25) { + D.drawSprite(sprLock, gridArt.project(z), 0, { + xScale: 2.0, + yScale: 2.0, + }); + } + }); + } + + getBlock(): Block3D | null { + return null; } update() {} @@ -102,23 +115,32 @@ export class BreakableBlockPickup { return true; } - drawFloor() {} - drawInAir(gridArt: GridArt) { - let progress = Math.pow(this.breakProgress, 2.15); - let extraMult = 1.0; - let angleRange = 0; - if (progress != 0) { - extraMult = 1.2; - angleRange = 10; - } + get #adjustedProgress(): number { + return Math.pow(this.breakProgress, 2.15); + } - this.callbacks.draw(gridArt.project(5), { - xScale: 2 * (1.0 - progress * 0.7) * extraMult, - yScale: 2 * (1.0 - progress * 0.7) * extraMult, - angle: (2 * progress - 1) * angleRange, + draw(drawpile: DrawPile, gridArt: GridArt) { + drawpile.add(384, () => { + let progress = this.#adjustedProgress; + let extraMult = 1.0; + let angleRange = 0; + if (progress != 0) { + extraMult = 1.2; + angleRange = 10; + } + + this.callbacks.draw(gridArt, { + xScale: 2 * (1.0 - progress * 0.7) * extraMult, + yScale: 2 * (1.0 - progress * 0.7) * extraMult, + angle: (2 * progress - 1) * angleRange, + }); }); } + getBlock(): Block3D | null { + return this.callbacks.getBlock(this.breakProgress); + } + update(cellData: CellView) { if (this.breakProgress >= 1.0) { getPlayerProgress().spendBlood(this.callbacks.cost); @@ -157,8 +179,16 @@ export class StatPickupCallbacks { getPlayerProgress().purloinItem(); } + getBlock(progress: number) { + return new Block3D( + progress > 0.6 ? FG_BOLD : SWATCH_STAT[this.#stat][1], + progress > 0.6 ? FG_TEXT : SWATCH_STAT[this.#stat][0], + progress > 0.6 ? FG_BOLD : SWATCH_STAT[this.#stat][1], + ); + } + draw( - at: Point, + gridArt: GridArt, options: { xScale?: number; yScale?: number; angle?: number }, ) { let statIndex = ALL_STATS.indexOf(this.#stat); @@ -166,7 +196,8 @@ export class StatPickupCallbacks { return; } - D.drawSprite(sprStatPickup, at, statIndex, options); + let at = gridArt.project(100); + D.drawSprite(sprCollectiblesSilhouettes, at, statIndex, options); } } @@ -182,11 +213,20 @@ export class ExperiencePickupCallbacks { getPlayerProgress().purloinItem(); } + getBlock(progress: number) { + return new Block3D( + progress > 0.6 ? FG_BOLD : SWATCH_EXP[1], + progress > 0.6 ? FG_TEXT : SWATCH_EXP[0], + progress > 0.6 ? FG_BOLD : SWATCH_EXP[1], + ); + } + draw( - at: Point, + gridArt: GridArt, options: { xScale?: number; yScale?: number; angle?: number }, ) { - D.drawSprite(sprResourcePickup, at, 0, options); + let at = gridArt.project(100); + D.drawSprite(sprCollectiblesSilhouettes, at, 0, options); } } @@ -211,13 +251,18 @@ export class LadderPickup { return false; } - drawFloor(gridArt: GridArt) { - D.drawSprite(sprLadder, gridArt.project(0.0), 0, { - xScale: 2.0, - yScale: 2.0, + draw(drawpile: DrawPile, gridArt: GridArt) { + drawpile.add(-128, () => { + D.drawSprite(sprLadder, gridArt.project(0.0), 0, { + xScale: 2.0, + yScale: 2.0, + }); }); } - drawInAir() {} + + getBlock(): Block3D | null { + return null; + } update() {} @@ -257,15 +302,20 @@ export class ThrallPickup { return false; } - drawFloor() {} - drawInAir(gridArt: GridArt) { - let data = getThralls().get(this.thrall); - D.drawSprite(data.sprite, gridArt.project(0.0), 0, { - xScale: 2.0, - yScale: 2.0, + draw(drawpile: DrawPile, gridArt: GridArt) { + drawpile.add(0, () => { + let data = getThralls().get(this.thrall); + D.drawSprite(data.sprite, gridArt.project(0.0), 0, { + xScale: 2.0, + yScale: 2.0, + }); }); } + getBlock(): Block3D | null { + return null; + } + update() {} onClick(cell: CellView): boolean { @@ -307,15 +357,20 @@ export class ThrallPosterPickup { return false; } - drawFloor() {} - drawInAir(gridArt: GridArt) { - let data = getThralls().get(this.thrall); - D.drawSprite(data.sprite, gridArt.project(0.0), 2, { - xScale: 2.0, - yScale: 2.0, + draw(drawpile: DrawPile, gridArt: GridArt) { + drawpile.add(0, () => { + let data = getThralls().get(this.thrall); + D.drawSprite(data.sprite, gridArt.project(0.0), 2, { + xScale: 2.0, + yScale: 2.0, + }); }); } + getBlock(): Block3D | null { + return null; + } + update() {} onClick(cell: CellView): boolean { @@ -358,27 +413,32 @@ export class ThrallRecruitedPickup { return false; } - drawFloor() {} - drawInAir(gridArt: GridArt) { - let data = getThralls().get(this.thrall); - let lifeStage = getPlayerProgress().getThrallLifeStage(this.thrall); - let ix = 0; - let rot = 0; + draw(drawpile: DrawPile, gridArt: GridArt) { + drawpile.add(0, () => { + let data = getThralls().get(this.thrall); + let lifeStage = getPlayerProgress().getThrallLifeStage(this.thrall); + let ix = 0; + let rot = 0; - if (lifeStage == LifeStage.Vampirized) { - ix = 1; - } - if (lifeStage == LifeStage.Dead) { - ix = 1; - rot = 270; - } - D.drawSprite(data.sprite, gridArt.project(0.0), ix, { - xScale: 2.0, - yScale: 2.0, - angle: rot, + if (lifeStage == LifeStage.Vampirized) { + ix = 1; + } + if (lifeStage == LifeStage.Dead) { + ix = 1; + rot = 270; + } + D.drawSprite(data.sprite, gridArt.project(0.0), ix, { + xScale: 2.0, + yScale: 2.0, + angle: rot, + }); }); } + getBlock(): Block3D | null { + return null; + } + update() {} onClick(_cell: CellView): boolean { @@ -477,23 +537,28 @@ export class ThrallCollectionPlatePickup { return false; } - drawFloor() {} - drawInAir(gridArt: GridArt) { - let itemStage = getPlayerProgress().getThrallItemStage(this.thrall); - let data = getThralls().get(this.thrall); + draw(drawpile: DrawPile, gridArt: GridArt) { + drawpile.add(0, () => { + let itemStage = getPlayerProgress().getThrallItemStage(this.thrall); + let data = getThralls().get(this.thrall); - if (itemStage != ItemStage.Delivered) { - D.drawRect( - gridArt.project(0).offset(new Point(-18, -18)), - new Size(36, 36), - FG_TEXT, - ); - } else { - D.drawSprite(data.sprite, gridArt.project(2), 3, { - xScale: 2.0, - yScale: 2.0, - }); - } + if (itemStage != ItemStage.Delivered) { + D.drawRect( + gridArt.project(0).offset(new Point(-18, -18)), + new Size(36, 36), + FG_TEXT, + ); + } else { + D.drawSprite(data.sprite, gridArt.project(2), 3, { + xScale: 2.0, + yScale: 2.0, + }); + } + }); + } + + getBlock(): Block3D | null { + return null; } update() {} @@ -585,16 +650,21 @@ export class ThrallItemPickup { return false; } - drawFloor() {} - drawInAir(gridArt: GridArt) { - let data = getThralls().get(this.thrall); + draw(drawpile: DrawPile, gridArt: GridArt) { + drawpile.add(0, () => { + let data = getThralls().get(this.thrall); - D.drawSprite(data.sprite, gridArt.project(2), 3, { - xScale: 2.0, - yScale: 2.0, + D.drawSprite(data.sprite, gridArt.project(2), 3, { + xScale: 2.0, + yScale: 2.0, + }); }); } + getBlock(): Block3D | null { + return null; + } + update() {} onClick(cell: CellView): boolean { diff --git a/src/sprites.ts b/src/sprites.ts index 54b897d..6c903d3 100644 --- a/src/sprites.ts +++ b/src/sprites.ts @@ -1,7 +1,7 @@ import { Sprite } from "./engine/internal/sprite.ts"; -import imgResourcePickup from "./art/pickups/resources.png"; -import imgStatPickup from "./art/pickups/stats.png"; +import imgCollectibles from "./art/pickups/collectibles.png"; +import imgCollectiblesSilhouettes from "./art/pickups/collectibles_silhouettes.png"; import imgLadder from "./art/pickups/ladder.png"; import imgLock from "./art/pickups/lock.png"; import { Point, Size } from "./engine/datatypes.ts"; @@ -13,20 +13,20 @@ import imgThrallParty from "./art/thralls/thrall_party.png"; import imgThrallStare from "./art/thralls/thrall_stare.png"; import imgThrallStealth from "./art/thralls/thrall_stealth.png"; -export let sprResourcePickup = new Sprite( - imgResourcePickup, +export let sprCollectibles = new Sprite( + imgCollectibles, new Size(32, 32), new Point(16, 16), - new Size(1, 1), - 1, + new Size(5, 1), + 5, ); -export let sprStatPickup = new Sprite( - imgStatPickup, +export let sprCollectiblesSilhouettes = new Sprite( + imgCollectiblesSilhouettes, new Size(32, 32), new Point(16, 16), - new Size(4, 1), - 4, + new Size(5, 1), + 5, ); export let sprLadder = new Sprite( diff --git a/src/world3d.ts b/src/world3d.ts new file mode 100644 index 0000000..13074d0 --- /dev/null +++ b/src/world3d.ts @@ -0,0 +1,140 @@ +import { Color, Grid, Point, Rect, Size } from "./engine/datatypes.ts"; +import { DrawPile } from "./drawpile.ts"; +import { GridArt } from "./gridart.ts"; +import { + BG_CEILING, + BG_WALL_OR_UNREVEALED, + FG_BOLD, + FG_TEXT, +} from "./colors.ts"; + +export class World3D { + #grid: Grid; + + constructor(size: Size) { + this.#grid = new Grid(size, () => null); + } + + set(at: Point, value: Element3D) { + this.#grid.set(at, value); + } + + drawCell(drawpile: DrawPile, gridArt: GridArt, xy: Point) { + const OFFSET_AIR = 0; + const OFFSET_TOP = 256; + const OFFSET_TOP_OF_TOP = 512; + let here = this.#grid.get(xy); + + if (here == null) { + drawpile.add(OFFSET_TOP, () => { + gridArt.drawCeiling(BG_CEILING); + }); + return; + } + + const getRevealedBlock = (dx: number, dy: number): Block3D | null => { + let xy2 = xy.offset(new Point(dx, dy)); + if (!new Rect(new Point(0, 0), this.#grid.size).contains(xy2)) { + return null; + } + + let other = this.#grid.get(xy.offset(new Point(dx, dy))); + if (other instanceof Block3D) { + return other; + } + return null; + }; + + let center = getRevealedBlock(0, 0); + if (center) { + drawpile.add(OFFSET_TOP, () => { + gridArt.drawCeiling(center.ceiling); + }); + return; + } + + let west = getRevealedBlock(-1, 0); + let east = getRevealedBlock(1, 0); + let north = getRevealedBlock(0, -1); + let south = getRevealedBlock(0, 1); + + if (north && west) { + drawpile.add(OFFSET_TOP_OF_TOP, () => { + gridArt.drawMouldingTopLeft(north.moulding); + }); + } + if (north) { + drawpile.add(OFFSET_AIR, () => { + gridArt.drawWallTop(north.dark); + }); + drawpile.add(OFFSET_TOP_OF_TOP, () => { + gridArt.drawMouldingTop(north.moulding); + }); + } + if (north && east) { + drawpile.add(OFFSET_TOP_OF_TOP, () => { + gridArt.drawMouldingTopRight(north.moulding); + }); + } + if (west) { + drawpile.add(OFFSET_AIR, () => { + gridArt.drawWallLeft(west.dark); + }); + drawpile.add(OFFSET_TOP_OF_TOP, () => { + gridArt.drawMouldingLeft(west.moulding); + }); + } + if (south && west) { + drawpile.add(OFFSET_TOP_OF_TOP, () => { + gridArt.drawMouldingBottomLeft(south.moulding); + }); + } + if (south) { + drawpile.add(OFFSET_AIR, () => { + gridArt.drawWallBottom(south.bright); + }); + drawpile.add(OFFSET_TOP_OF_TOP, () => { + gridArt.drawMouldingBottom(south.moulding); + }); + } + if (south && east) { + drawpile.add(OFFSET_TOP_OF_TOP, () => { + gridArt.drawMouldingBottomRight(south.moulding); + }); + } + if (east) { + drawpile.add(OFFSET_AIR, () => { + gridArt.drawWallRight(east.bright); + }); + drawpile.add(OFFSET_TOP_OF_TOP, () => { + gridArt.drawMouldingRight(east.moulding); + }); + } + } +} + +export type Element3D = Floor3D | Block3D | null; + +export class Floor3D { + constructor() {} +} + +export class Block3D { + readonly bright: Color; + readonly dark: Color; + readonly ceiling: Color; + + get moulding(): Color { + return this.dark; + } + + constructor(bright: Color, dark: Color, ceiling: Color) { + this.bright = bright; + this.dark = dark; + this.ceiling = ceiling; + } + + static standardWall(): Block3D { + return new Block3D(FG_BOLD, FG_TEXT, BG_WALL_OR_UNREVEALED); + } +}