Blockify collectibles
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								src/art/pickups/collectibles.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/art/pickups/collectibles.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 605 B | 
							
								
								
									
										
											BIN
										
									
								
								src/art/pickups/collectibles_silhouettes.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/art/pickups/collectibles_silhouettes.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 471 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 455 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 431 B | 
| @@ -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<Stat, [Color, Color]> = { | ||||
|   AGI: SWATCH_AGI, | ||||
|   INT: SWATCH_INT, | ||||
|   CHA: SWATCH_CHA, | ||||
|   PSI: SWATCH_PSI, | ||||
| }; | ||||
|   | ||||
							
								
								
									
										130
									
								
								src/huntmode.ts
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								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) { | ||||
|   | ||||
							
								
								
									
										238
									
								
								src/pickups.ts
									
									
									
									
									
								
							
							
						
						
									
										238
									
								
								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 { | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
							
								
								
									
										140
									
								
								src/world3d.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/world3d.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -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<Element3D>; | ||||
|  | ||||
|   constructor(size: Size) { | ||||
|     this.#grid = new Grid<Element3D>(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); | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user