Make ladders work
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								src/art/pickups/ladder.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/art/pickups/ladder.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 179 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 240 B After Width: | Height: | Size: 216 B | 
| @@ -1,7 +1,7 @@ | ||||
| import {BG_OUTER} from "./colors.ts"; | ||||
| import {D, I} from "./engine/public.ts"; | ||||
| import {IGame, Point, Size} from "./engine/datatypes.ts"; | ||||
| import {HuntMode} from "./huntmode.ts"; | ||||
| import {getHuntMode} from "./huntmode.ts"; | ||||
| import {getPageLocation, Page, withCamera} from "./layout.ts"; | ||||
| import {getHud} from "./hud.ts"; | ||||
| import {getHotbar, Hotbar} from "./hotbar.ts"; | ||||
| @@ -32,7 +32,6 @@ class MenuCamera { | ||||
| export class Game implements IGame { | ||||
|   camera: MenuCamera; | ||||
|   page: Page; | ||||
|   huntMode: HuntMode; | ||||
|   #bottomThing: SkillsModal | SleepModal | Hotbar | null; | ||||
|  | ||||
|   constructor() { | ||||
| @@ -42,7 +41,6 @@ export class Game implements IGame { | ||||
|     }); | ||||
|     this.page = "Gameplay"; | ||||
|  | ||||
|     this.huntMode = HuntMode.generate({depth: 1}); | ||||
|     this.#bottomThing = null; | ||||
|   } | ||||
|  | ||||
| @@ -86,7 +84,7 @@ export class Game implements IGame { | ||||
|     this.#chooseBottomThing(); | ||||
|  | ||||
|     withCamera("Gameplay", () => { | ||||
|       this.huntMode.update(); | ||||
|       getHuntMode().update(); | ||||
|     }); | ||||
|     withCamera("HUD", () => { getHud().update() }) | ||||
|     this.#bottomThing?.update(); | ||||
| @@ -94,7 +92,7 @@ export class Game implements IGame { | ||||
|  | ||||
|   drawGameplay() { | ||||
|     withCamera("Gameplay", () => { | ||||
|       this.huntMode.draw(); | ||||
|       getHuntMode().draw(); | ||||
|     }); | ||||
|     withCamera("HUD", () => { getHud().draw() }) | ||||
|     this.#bottomThing?.draw() | ||||
|   | ||||
| @@ -3,6 +3,7 @@ import {Point, Size} from "./engine/datatypes.ts"; | ||||
| import {FG_BOLD, FG_TEXT} from "./colors.ts"; | ||||
| import {ALL_STATS} from "./datatypes.ts"; | ||||
| import {getPlayerProgress} from "./playerprogress.ts"; | ||||
| import {getHuntMode} from "./huntmode.ts"; | ||||
|  | ||||
| export class Hud { | ||||
|   get size(): Size { | ||||
| @@ -14,7 +15,7 @@ export class Hud { | ||||
|   draw() { | ||||
|     // D.fillRect(new Point(-4, -4), this.size.add(new Size(8, 8)), BG_INSET) | ||||
|     D.drawText("Pyrex", new Point(0, 0), FG_BOLD) | ||||
|     D.drawText("Level 1", new Point(0, 16), FG_TEXT) | ||||
|     D.drawText(`Level ${getHuntMode().getDepth()}`, new Point(0, 16), FG_TEXT) | ||||
|  | ||||
|     let y = 48; | ||||
|     let prog = getPlayerProgress(); | ||||
|   | ||||
							
								
								
									
										163
									
								
								src/huntmode.ts
									
									
									
									
									
								
							
							
						
						
									
										163
									
								
								src/huntmode.ts
									
									
									
									
									
								
							| @@ -1,11 +1,11 @@ | ||||
| import {Grid, Point, Rect, Size} from "./engine/datatypes.ts"; | ||||
| import {ConceptualCell, maps} from "./maps.ts"; | ||||
| import {ALL_STATS, Resource, Stat} from "./datatypes.ts"; | ||||
| import {DrawPile} from "./drawpile.ts"; | ||||
| import {D} from "./engine/public.ts"; | ||||
| import {sprDrips, sprRaccoonWalking, sprResourcePickup, sprStatPickup} from "./sprites.ts"; | ||||
| import {sprDrips, sprLadder, sprRaccoonWalking, sprResourcePickup, sprStatPickup} from "./sprites.ts"; | ||||
| import {BG_INSET, FG_TEXT} from "./colors.ts"; | ||||
| import {getPlayerProgress} from "./playerprogress.ts"; | ||||
| import {generate} from "./mapgen.ts"; | ||||
|  | ||||
| export type MapCellContent = | ||||
|   {type: "statPickup", stat: Stat} | | ||||
| @@ -21,122 +21,53 @@ export type MapCell = { | ||||
|   nextMoveAccessible: boolean, | ||||
| } | ||||
|  | ||||
| export class HuntMode { | ||||
|   depth: number | ||||
|   cells: Grid<MapCell> | ||||
| export type LoadedMap = { | ||||
|   cells: Grid<MapCell>, | ||||
|   player: Point | ||||
| } | ||||
|  | ||||
| export class HuntMode { | ||||
|   map: LoadedMap | ||||
|   drawpile: DrawPile | ||||
|   frame: number | ||||
|   depth: number | ||||
|  | ||||
|   constructor({depth, cells, player}: {depth: number, cells: Grid<MapCell>, player: Point }) { | ||||
|     this.depth = depth; | ||||
|     this.cells = cells; | ||||
|     this.player = player; | ||||
|   constructor() { | ||||
|     this.map = null!; // initialized in replaceMap | ||||
|  | ||||
|     this.drawpile = new DrawPile(); | ||||
|     this.frame = 0; | ||||
|     this.depth = 1; | ||||
|     this.replaceMap(); | ||||
|   } | ||||
|  | ||||
|   // == map generator == | ||||
|   static generate({depth}: {depth: number}) { | ||||
|     let mapNames: Array<string> = Object.keys(maps); | ||||
|     let mapName = mapNames[Math.floor(Math.random() * mapNames.length)]; | ||||
|     let map = maps[mapName]; | ||||
|   replaceMap(deeper?: boolean) { | ||||
|     this.map = generate(); | ||||
|     this.#updateVisibilityAndPossibleMoves(); | ||||
|  | ||||
|     let baseCells = map.map((ccell, _xy) => { | ||||
|       return this.#generateCell(ccell); | ||||
|     }) | ||||
|  | ||||
|     let cells = new Grid( | ||||
|       new Size(baseCells.size.w + 2, baseCells.size.h + 2), (xy) => { | ||||
|         let offset = xy.offset(new Point(-1, -1)); | ||||
|         if (offset.x == -1 || offset.y == -1 || offset.x == baseCells.size.w || offset.y == baseCells.size.h) { | ||||
|           return this.#generateBoundaryCell(); | ||||
|         } | ||||
|         return baseCells.get(offset) | ||||
|       } | ||||
|     ) | ||||
|  | ||||
|     let validSpawns = []; | ||||
|     for (let x = 0; x < cells.size.w; x++) { | ||||
|       for (let y = 0; y < cells.size.h; y++) { | ||||
|         let position = new Point(x, y); | ||||
|         if (cells.get(position).isValidSpawn)  { | ||||
|           validSpawns.push(position); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     let player = choose(validSpawns); | ||||
|     cells.get(player).content = {type: "empty"}; | ||||
|  | ||||
|     if (Math.random() < 0.75) { | ||||
|       while (true) { | ||||
|         let x = Math.floor(Math.random() * cells.size.w); | ||||
|         let y = Math.floor(Math.random() * cells.size.h); | ||||
|         let xy = new Point(x, y); | ||||
|  | ||||
|         let item = cells.get(new Point(x, y)); | ||||
|         if (player.equals(xy)) { | ||||
|           continue; | ||||
|         } | ||||
|         if (item.content.type == "block") { | ||||
|           continue; | ||||
|         } | ||||
|         item.content = {type: "stairs"} | ||||
|         break; | ||||
|     if (deeper) { | ||||
|       this.depth += 1; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|     let hm = new HuntMode({depth, cells, player}) | ||||
|     hm.#updateVisibilityAndPossibleMoves(); | ||||
|     return hm; | ||||
|   } | ||||
|  | ||||
|   static #generateCell(conceptual: ConceptualCell): MapCell { | ||||
|     switch (conceptual) { | ||||
|       case "X": | ||||
|         return { content: {type: "block"}, revealed: false, isValidSpawn: false, nextMoveAccessible: false}; | ||||
|       case " ": | ||||
|         return { content: HuntMode.#generateContent(), revealed: false, isValidSpawn: false, nextMoveAccessible: false }; | ||||
|       case ".": | ||||
|         return { content: HuntMode.#generateContent(), revealed: false, isValidSpawn: true, nextMoveAccessible: false }; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static #generateBoundaryCell() { | ||||
|     return this.#generateCell("X"); | ||||
|   } | ||||
|  | ||||
|   static #generateContent(): MapCellContent { | ||||
|     // stat pickup | ||||
|     let gsp = (): MapCellContent => { | ||||
|       return {type: "statPickup", stat: choose(ALL_STATS)} | ||||
|     }; | ||||
|     let exp = (): MapCellContent => { | ||||
|       return {type: "resourcePickup", resource: "EXP"} | ||||
|     } | ||||
|     // TODO: Other objects? | ||||
|     return choose([ | ||||
|       gsp, gsp, gsp, gsp, | ||||
|       exp, | ||||
|     ])(); | ||||
|   getDepth() { | ||||
|     return this.depth; | ||||
|   } | ||||
|  | ||||
|   // == update logic == | ||||
|   #updateVisibilityAndPossibleMoves() { | ||||
|     for (let x = 0; x < this.cells.size.w; x++) { | ||||
|       for (let y = 0; y < this.cells.size.h; y++) { | ||||
|     for (let x = 0; x < this.map.cells.size.w; x++) { | ||||
|       for (let y = 0; y < this.map.cells.size.h; y++) { | ||||
|         let position = new Point(x, y); | ||||
|         let data = this.cells.get(position); | ||||
|         let data = this.map.cells.get(position); | ||||
|  | ||||
|         data.nextMoveAccessible = false; | ||||
|         if ( | ||||
|           Math.abs(x - this.player.x) <= 1 && | ||||
|           Math.abs(y - this.player.y) <= 1 | ||||
|           Math.abs(x - this.map.player.x) <= 1 && | ||||
|           Math.abs(y - this.map.player.y) <= 1 | ||||
|         ) { | ||||
|           data.revealed = true; | ||||
|           if (!this.player.equals(position)) { | ||||
|           if (!this.map.player.equals(position)) { | ||||
|             data.nextMoveAccessible = true; | ||||
|           } | ||||
|         } | ||||
| @@ -146,7 +77,12 @@ export class HuntMode { | ||||
|   } | ||||
|  | ||||
|   #collectResources() { | ||||
|     let present = this.cells.get(this.player); | ||||
|     let present = this.map.cells.get(this.map.player); | ||||
|  | ||||
|     if (present.content.type == "stairs") { | ||||
|       getPlayerProgress().addBlood(1000); | ||||
|       this.replaceMap(true); | ||||
|     } | ||||
|  | ||||
|     if (present.content.type == "statPickup") { | ||||
|       let stat = present.content.stat; | ||||
| @@ -170,10 +106,13 @@ export class HuntMode { | ||||
|   } | ||||
|  | ||||
|   #computeCostToMoveTo(mapPosition: Point): number | null { | ||||
|     let present = this.cells.get(mapPosition); | ||||
|     let present = this.map.cells.get(mapPosition); | ||||
|     if (present.content.type == "statPickup" || present.content.type == "resourcePickup") { | ||||
|       return 100; | ||||
|     } | ||||
|     if (present.content.type == "stairs") { | ||||
|       return 0; | ||||
|     } | ||||
|     if (present.content.type == "empty") { | ||||
|       return 10; | ||||
|     } | ||||
| @@ -181,7 +120,7 @@ export class HuntMode { | ||||
|   } | ||||
|  | ||||
|   movePlayerTo(newPosition: Point) { | ||||
|     this.player = newPosition; | ||||
|     this.map.player = newPosition; | ||||
|     this.#updateVisibilityAndPossibleMoves(); | ||||
|     this.#collectResources(); | ||||
|   } | ||||
| @@ -192,18 +131,18 @@ export class HuntMode { | ||||
|     this.drawpile.clear(); | ||||
|  | ||||
|     let globalOffset = | ||||
|       new Point(this.player.x * MAP_CELL_ONSCREEN_SIZE.w, this.player.y * MAP_CELL_ONSCREEN_SIZE.h).offset( | ||||
|       new Point(this.map.player.x * MAP_CELL_ONSCREEN_SIZE.w, this.map.player.y * MAP_CELL_ONSCREEN_SIZE.h).offset( | ||||
|         new Point(-192, -192) | ||||
|       ) | ||||
|  | ||||
|     let map = this.cells; | ||||
|     let map = this.map.cells; | ||||
|     for (let y = 0; y < map.size.h; y += 1) { | ||||
|       for (let x = 0; x < map.size.w; x += 1) { | ||||
|         let cellOffset = new Point(x * MAP_CELL_ONSCREEN_SIZE.w, y * MAP_CELL_ONSCREEN_SIZE.h).offset(globalOffset.negate()); | ||||
|         let cellData = this.cells.get(new Point(x, y)) | ||||
|         let cellData = this.map.cells.get(new Point(x, y)) | ||||
|         let belowIsBlock = true; | ||||
|         if (y < map.size.h - 1) { | ||||
|           let below = this.cells.get(new Point(x, y + 1)); | ||||
|           let below = this.map.cells.get(new Point(x, y + 1)); | ||||
|           belowIsBlock = !below.revealed || below.content.type == "block"; | ||||
|         } | ||||
|  | ||||
| @@ -241,7 +180,7 @@ export class HuntMode { | ||||
|     if (cellData.content.type == "block") { | ||||
|       if (!belowIsBlock) { | ||||
|         this.drawpile.add(inAir, () => { | ||||
|           D.drawSprite(sprDrips, cellOffset.offset(new Point(0, -cellSize.h)), 1, {xScale: 3, yScale: 3}) | ||||
|           D.drawSprite(sprDrips, cellOffset.offset(new Point(0, -cellSize.h / 2)), 1, {xScale: 3, yScale: 3}) | ||||
|         }) | ||||
|       } | ||||
|       return; | ||||
| @@ -252,6 +191,11 @@ export class HuntMode { | ||||
|     this.drawpile.addClickable(onFloor, | ||||
|       (hover: boolean) => { | ||||
|         D.fillRect(cellTopLeft, cellSize, hover ? FG_TEXT : BG_INSET) | ||||
|  | ||||
|         if (cellData.content.type == "stairs") { | ||||
|           // draw ladder if applicable | ||||
|           D.drawSprite(sprLadder, cellTopLeft, 0, {xScale: 3, yScale: 3}); | ||||
|         } | ||||
|       }, | ||||
|       new Rect(cellTopLeft, cellSize), | ||||
|       cellData.nextMoveAccessible && cost != null && cost <= getPlayerProgress().getBlood(), | ||||
| @@ -263,6 +207,7 @@ export class HuntMode { | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|  | ||||
|     if (belowIsBlock) { | ||||
|       // draw the underhang | ||||
|       this.drawpile.add(onFloor, () => { | ||||
| @@ -304,10 +249,10 @@ export class HuntMode { | ||||
|  | ||||
|   #drawPlayer(globalOffset: Point) { | ||||
|     let cellOffset = new Point( | ||||
|       this.player.x * MAP_CELL_ONSCREEN_SIZE.w, | ||||
|       this.player.y * MAP_CELL_ONSCREEN_SIZE.h | ||||
|       this.map.player.x * MAP_CELL_ONSCREEN_SIZE.w, | ||||
|       this.map.player.y * MAP_CELL_ONSCREEN_SIZE.h | ||||
|     ).offset(globalOffset.negate()) | ||||
|     this.drawpile.add(this.player.y, () => { | ||||
|     this.drawpile.add(this.map.player.y, () => { | ||||
|       D.drawSprite( | ||||
|         sprRaccoonWalking, | ||||
|         cellOffset.offset(new Point(0, 22)), | ||||
| @@ -322,9 +267,7 @@ export class HuntMode { | ||||
|  | ||||
| const MAP_CELL_ONSCREEN_SIZE: Size = new Size(96, 48) | ||||
|  | ||||
| function choose<T>(array: Array<T>): T  { | ||||
|   if (array.length == 0) { | ||||
|     throw `array cannot have length 0 for choose` | ||||
|   } | ||||
|   return array[Math.floor(Math.random() * array.length)] | ||||
| let active = new HuntMode(); | ||||
| export function getHuntMode() { | ||||
|   return active; | ||||
| } | ||||
|   | ||||
							
								
								
									
										97
									
								
								src/mapgen.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/mapgen.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| import {ConceptualCell, maps} from "./maps.ts"; | ||||
| import {Grid, Point, Size} from "./engine/datatypes.ts"; | ||||
| import {ALL_STATS} from "./datatypes.ts"; | ||||
| import {LoadedMap, MapCell, MapCellContent} from "./huntmode.ts"; | ||||
|  | ||||
| export function generate(): LoadedMap { | ||||
|   let mapNames: Array<string> = Object.keys(maps); | ||||
|   let mapName = mapNames[Math.floor(Math.random() * mapNames.length)]; | ||||
|   let map = maps[mapName]; | ||||
|  | ||||
|   let baseCells = map.map((ccell, _xy) => { | ||||
|     return generateCell(ccell); | ||||
|   }) | ||||
|  | ||||
|   let cells = new Grid( | ||||
|     new Size(baseCells.size.w + 2, baseCells.size.h + 2), (xy) => { | ||||
|       let offset = xy.offset(new Point(-1, -1)); | ||||
|       if (offset.x == -1 || offset.y == -1 || offset.x == baseCells.size.w || offset.y == baseCells.size.h) { | ||||
|         return generateBoundaryCell(); | ||||
|       } | ||||
|       return baseCells.get(offset) | ||||
|     } | ||||
|   ) | ||||
|  | ||||
|   let validSpawns = []; | ||||
|   for (let x = 0; x < cells.size.w; x++) { | ||||
|     for (let y = 0; y < cells.size.h; y++) { | ||||
|       let position = new Point(x, y); | ||||
|       if (cells.get(position).isValidSpawn)  { | ||||
|         validSpawns.push(position); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   let player = choose(validSpawns); | ||||
|   cells.get(player).content = {type: "empty"}; | ||||
|  | ||||
|   let nStairs = choose([1, 1, 1, 0]); | ||||
|   for (let i = 0; i < nStairs; i++) { | ||||
|     while (true) { | ||||
|       let x = Math.floor(Math.random() * cells.size.w); | ||||
|       let y = Math.floor(Math.random() * cells.size.h); | ||||
|       let xy = new Point(x, y); | ||||
|  | ||||
|       let item = cells.get(new Point(x, y)); | ||||
|       if (player.equals(xy)) { | ||||
|         continue; | ||||
|       } | ||||
|       if (item.content.type == "block" || item.content.type == "stairs") { | ||||
|         continue; | ||||
|       } | ||||
|       item.content = {type: "stairs"} | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return { | ||||
|     cells, | ||||
|     player, | ||||
|   } | ||||
| } | ||||
|  | ||||
| function generateCell(conceptual: ConceptualCell): MapCell { | ||||
|   switch (conceptual) { | ||||
|     case "X": | ||||
|       return { content: {type: "block"}, revealed: false, isValidSpawn: false, nextMoveAccessible: false}; | ||||
|     case " ": | ||||
|       return { content: generateContent(), revealed: false, isValidSpawn: false, nextMoveAccessible: false }; | ||||
|     case ".": | ||||
|       return { content: generateContent(), revealed: false, isValidSpawn: true, nextMoveAccessible: false }; | ||||
|   } | ||||
| } | ||||
|  | ||||
| function generateBoundaryCell() { | ||||
|   return generateCell("X"); | ||||
| } | ||||
|  | ||||
| function generateContent(): MapCellContent { | ||||
|   // stat pickup | ||||
|   let gsp = (): MapCellContent => { | ||||
|     return {type: "statPickup", stat: choose(ALL_STATS)} | ||||
|   }; | ||||
|   let exp = (): MapCellContent => { | ||||
|     return {type: "resourcePickup", resource: "EXP"} | ||||
|   } | ||||
|   // TODO: Other objects? | ||||
|   return choose([ | ||||
|     gsp, gsp, gsp, gsp, | ||||
|     exp, | ||||
|   ])(); | ||||
| } | ||||
|  | ||||
| function choose<T>(array: Array<T>): T  { | ||||
|   if (array.length == 0) { | ||||
|     throw `array cannot have length 0 for choose` | ||||
|   } | ||||
|   return array[Math.floor(Math.random() * array.length)] | ||||
| } | ||||
| @@ -107,6 +107,11 @@ export class PlayerProgress { | ||||
|     return Math.floor(Math.max(this.#blood, 0)); | ||||
|   } | ||||
|  | ||||
|   addBlood(amt: number) { | ||||
|     this.#blood += amt; | ||||
|     this.#blood = Math.min(this.#blood, 5000) | ||||
|   } | ||||
|  | ||||
|   spendBlood(amt: number) { | ||||
|     this.#blood -= amt; | ||||
|   } | ||||
| @@ -127,7 +132,6 @@ export class PlayerProgress { | ||||
|     }); | ||||
|     return skillsAvailable.slice(0, 6) | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| let active: PlayerProgress = new PlayerProgress(); | ||||
|   | ||||
| @@ -79,7 +79,7 @@ function governing(track: Track, difficulty: Difficulty): SkillGoverning { | ||||
|   let cost: number | ||||
|   switch(difficulty) { | ||||
|     case 0: underTarget = 5; target = 15; cost = 50; break; | ||||
|     case 1: underTarget = 50; target = 100; cost = 100; break; | ||||
|     case 1: underTarget = 15; target = 40; cost = 100; break; | ||||
|     case 2: underTarget = 100; target = 150; cost = 250; break; | ||||
|     case 3: underTarget = 175; target = 250; cost = 500; break; | ||||
|   } | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import {D} from "./engine/public.ts"; | ||||
| import {BG_INSET} from "./colors.ts"; | ||||
| import {getSkillsModal} from "./skillsmodal.ts"; | ||||
| import {getPlayerProgress} from "./playerprogress.ts"; | ||||
| import {getHuntMode} from "./huntmode.ts"; | ||||
|  | ||||
| export class SleepModal { | ||||
|   #drawpile: DrawPile; | ||||
| @@ -60,10 +61,10 @@ export class SleepModal { | ||||
|  | ||||
|     let remainingWidth = size.w - 160; | ||||
|     let nextRect = new Rect(new Point(160, 96), new Size(remainingWidth, 32)); | ||||
|     addButton(this.#drawpile, "Sleep All Day", nextRect, true, () => { | ||||
|     addButton(this.#drawpile, "Sleep (Next Day)", nextRect, true, () => { | ||||
|       getPlayerProgress().refill(); | ||||
|       getHuntMode().replaceMap(); | ||||
|       getSleepModal().setShown(false); | ||||
|       // TODO: Advance huntmode | ||||
|     }); | ||||
|  | ||||
|     this.#drawpile.executeOnClick(); | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import imgRaccoon from "./art/characters/raccoon.png"; | ||||
| import imgRaccoonWalking from "./art/characters/raccoon_walking.png"; | ||||
| import imgResourcePickup from "./art/pickups/resources.png"; | ||||
| import imgStatPickup from "./art/pickups/stats.png"; | ||||
| import imgLadder from "./art/pickups/ladder.png"; | ||||
| import imgDrips from "./art/tilesets/drips.png"; | ||||
| import {Point, Size} from "./engine/datatypes.ts"; | ||||
|  | ||||
| @@ -40,6 +41,11 @@ export let sprStatPickup = new Sprite( | ||||
| ); | ||||
|  | ||||
| export let sprDrips = new Sprite( | ||||
|   imgDrips, new Size(32, 24), new Point(16, 0), | ||||
|   imgDrips, new Size(32, 16), new Point(16, 0), | ||||
|   new Size(2, 1), 2 | ||||
| ); | ||||
|  | ||||
| export let sprLadder = new Sprite( | ||||
|   imgLadder, new Size(32, 24), new Point(0, 0), | ||||
|   new Size(1, 1), 1 | ||||
| ); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user