Non-grid-based movement
This commit is contained in:
		| @@ -84,6 +84,13 @@ export class Point { | ||||
|     return new Point(this.x * other.w, this.y * other.h); | ||||
|   } | ||||
|  | ||||
|   unscale(other: Point | Size) { | ||||
|     if (other instanceof Point) { | ||||
|       return new Point(this.x / other.x, this.y / other.y); | ||||
|     } | ||||
|     return new Point(this.x / other.w, this.y / other.h); | ||||
|   } | ||||
|  | ||||
|   subtract(top: Point): Size { | ||||
|     return new Size(this.x - top.x, this.y - top.y); | ||||
|   } | ||||
| @@ -91,6 +98,13 @@ export class Point { | ||||
|   manhattan(other: Point) { | ||||
|     return Math.abs(this.x - other.x) + Math.abs(this.y - other.y); | ||||
|   } | ||||
|  | ||||
|   snap(x: number, y: number) { | ||||
|     return new Point( | ||||
|       lerp(x, Math.floor(this.x), Math.ceil(this.x)), | ||||
|       lerp(y, Math.floor(this.y), Math.ceil(this.y)) | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| export class Size { | ||||
| @@ -118,12 +132,16 @@ export class Size { | ||||
| export class Rect { | ||||
|   readonly top: Point; | ||||
|   readonly size: Size; | ||||
|  | ||||
|   constructor(top: Point, size: Size) { | ||||
|     this.top = top; | ||||
|     this.size = size; | ||||
|   } | ||||
|  | ||||
|   toString(): string { | ||||
|     return `Rect(${this.top},${this.size})`; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   offset(offset: Point) { | ||||
|     return new Rect(this.top.offset(offset), this.size); | ||||
|   } | ||||
| @@ -137,6 +155,28 @@ export class Rect { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   overlappedCells(size: Size) { | ||||
|     let x0 = this.top.x; | ||||
|     let y0 = this.top.y; | ||||
|     let x1 = x0 + this.size.w; | ||||
|     let y1 = y0 + this.size.w; | ||||
|  | ||||
|     let cx0 = Math.floor(x0 / size.w); | ||||
|     let cy0 = Math.floor(y0 / size.h); | ||||
|     let cx1 = Math.ceil(x1 / size.w); | ||||
|     let cy1 = Math.ceil(y1 / size.h); | ||||
|  | ||||
|     let cells = []; | ||||
|     for (let cy = cy0; cy < cy1; cy++) { | ||||
|       for (let cx = cx0; cx < cx1; cx++) { | ||||
|         let px0 = cx * size.w; | ||||
|         let py0 = cy * size.h; | ||||
|         cells.push(new Rect(new Point(px0, py0), size)); | ||||
|       } | ||||
|     } | ||||
|     return cells; | ||||
|   } | ||||
|  | ||||
|   overlaps(other: Rect) { | ||||
|     let ax0 = this.top.x; | ||||
|     let ay0 = this.top.y; | ||||
| @@ -254,3 +294,13 @@ export enum AlignY { | ||||
|   Middle = 1, | ||||
|   Bottom = 2, | ||||
| } | ||||
|  | ||||
| export function lerp(amt: number, lo: number, hi: number) { | ||||
|   if (amt <= 0) { | ||||
|     return lo; | ||||
|   } | ||||
|   if (amt >= 1) { | ||||
|     return hi; | ||||
|   } | ||||
|   return lo + (hi - lo) * amt; | ||||
| }; | ||||
|   | ||||
							
								
								
									
										130
									
								
								src/gridart.ts
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								src/gridart.ts
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ export const CENTER = new Point(192, 192); | ||||
| export const MOULDING_SZ = new Size(1, 1); | ||||
|  | ||||
| export class GridArt { | ||||
|   #at: Point; | ||||
|   #atPixel: Point; | ||||
|  | ||||
|   #floorCenter: Point; | ||||
|   #ceilingCenter: Point; | ||||
| @@ -17,27 +17,29 @@ export class GridArt { | ||||
|   #floorBr: Point; | ||||
|   #ceilingBr: Point; | ||||
|  | ||||
|   constructor(at: Point) { | ||||
|     this.#at = at; | ||||
|     this.#floorCenter = at.scale(FLOOR_CELL_SIZE).offset(CENTER); | ||||
|   constructor(atPixel: Point) { | ||||
|     this.#atPixel = atPixel; | ||||
|     let at = atPixel.unscale(FLOOR_CELL_SIZE); | ||||
|     this.#floorCenter = atPixel.offset(CENTER); | ||||
|     this.#ceilingCenter = at.scale(CEILING_CELL_SIZE).offset(CENTER); | ||||
|  | ||||
|     this.#floorTl = at | ||||
|       .offset(new Point(-0.5, -0.5)) | ||||
|       .scale(FLOOR_CELL_SIZE) | ||||
|     this.#floorTl = atPixel.offset(new Point(-FLOOR_CELL_SIZE.w / 2, -FLOOR_CELL_SIZE.h / 2)) | ||||
|       .offset(CENTER); | ||||
|     this.#ceilingTl = at | ||||
|       .offset(new Point(-0.5, -0.5)) | ||||
|       .scale(CEILING_CELL_SIZE) | ||||
|       .offset(CENTER); | ||||
|     this.#floorBr = at | ||||
|       .offset(new Point(0.5, 0.5)) | ||||
|       .scale(FLOOR_CELL_SIZE) | ||||
|       .offset(CENTER) | ||||
|       .snap(0, 0) | ||||
|     this.#floorBr = atPixel.offset(new Point(FLOOR_CELL_SIZE.w / 2, FLOOR_CELL_SIZE.h / 2)) | ||||
|       .offset(CENTER); | ||||
|     this.#ceilingBr = at | ||||
|       .offset(new Point(0.5, 0.5)) | ||||
|       .scale(CEILING_CELL_SIZE) | ||||
|       .offset(CENTER); | ||||
|       .offset(CENTER) | ||||
|       .snap(0, 0) | ||||
|  | ||||
|     // console.log(`floorTl: ${this.#floorTl}`) | ||||
|     // console.log(`floorBr: ${this.#floorBr}`) | ||||
|   } | ||||
|  | ||||
|   get floorRect(): Rect { | ||||
| @@ -83,84 +85,134 @@ export class GridArt { | ||||
|   } | ||||
|  | ||||
|   drawWallTop(color: Color) { | ||||
|     if (this.#at.y > 0) { | ||||
|     if (this.#atPixel.y > FLOOR_CELL_SIZE.h / 2) { | ||||
|       return; | ||||
|     } | ||||
|     this.#drawWallTop(color); | ||||
|   } | ||||
|  | ||||
|   drawWallLeft(color: Color) { | ||||
|     if (this.#at.x > 0) { | ||||
|     if (this.#atPixel.x > FLOOR_CELL_SIZE.w / 2) { | ||||
|       return; | ||||
|     } | ||||
|     this.#drawWallLeft(color); | ||||
|   } | ||||
|  | ||||
|   drawWallBottom(color: Color) { | ||||
|     if (this.#at.y < 0) { | ||||
|     if (this.#atPixel.y < -FLOOR_CELL_SIZE.h / 2) { | ||||
|       return; | ||||
|     } | ||||
|     new GridArt(this.#at.offset(new Point(0, 1))).#drawWallTop(color); | ||||
|     new GridArt(this.#atPixel.offset(new Point(0, FLOOR_CELL_SIZE.h))).#drawWallTop(color); | ||||
|   } | ||||
|  | ||||
|   drawWallRight(color: Color) { | ||||
|     if (this.#at.x < 0) { | ||||
|     if (this.#atPixel.x < -FLOOR_CELL_SIZE.w / 2) { | ||||
|       return; | ||||
|     } | ||||
|     new GridArt(this.#at.offset(new Point(1, 0))).#drawWallLeft(color); | ||||
|     new GridArt(this.#atPixel.offset(new Point(FLOOR_CELL_SIZE.w, 0))).#drawWallLeft(color); | ||||
|   } | ||||
|  | ||||
|   drawMouldingTop(color: Color) { | ||||
|     let lhs = this.#ceilingTl.offset(new Point(0, -MOULDING_SZ.h)); | ||||
|     D.fillRect(lhs, new Size(CEILING_CELL_SIZE.w, MOULDING_SZ.h), color); | ||||
|     let x0 = this.#ceilingTl.x; | ||||
|     let y0 = this.#ceilingTl.y - MOULDING_SZ.h; | ||||
|     let x1 = this.#ceilingBr.x; | ||||
|     let y1 = this.#ceilingTl.y; | ||||
|  | ||||
|     D.fillRect( | ||||
|       new Point(x0, y0), | ||||
|       new Size(x1 - x0, y1 - y0), | ||||
|       color | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   drawMouldingTopLeft(color: Color) { | ||||
|     let x0 = this.#ceilingTl.x - MOULDING_SZ.w; | ||||
|     let y0 = this.#ceilingTl.y - MOULDING_SZ.h; | ||||
|     let x1 = this.#ceilingTl.x; | ||||
|     let y1 = this.#ceilingTl.y; | ||||
|  | ||||
|     D.fillRect( | ||||
|       this.#ceilingTl.offset(new Point(-MOULDING_SZ.w, -MOULDING_SZ.h)), | ||||
|       MOULDING_SZ, | ||||
|       color, | ||||
|       new Point(x0, y0), | ||||
|       new Size(x1 - x0, y1 - y0), | ||||
|       color | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   drawMouldingLeft(color: Color) { | ||||
|     let lhs = this.#ceilingTl.offset(new Point(-MOULDING_SZ.w, 0)); | ||||
|     D.fillRect(lhs, new Size(MOULDING_SZ.w, CEILING_CELL_SIZE.h), color); | ||||
|     let x0 = this.#ceilingTl.x - MOULDING_SZ.w; | ||||
|     let y0 = this.#ceilingTl.y; | ||||
|     let x1 = this.#ceilingTl.x; | ||||
|     let y1 = this.#ceilingBr.y; | ||||
|  | ||||
|     D.fillRect( | ||||
|       new Point(x0, y0), | ||||
|       new Size(x1 - x0, y1 - y0), | ||||
|       color | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   drawMouldingTopRight(color: Color) { | ||||
|     let x0 = this.#ceilingBr.x; | ||||
|     let y0 = this.#ceilingTl.y - MOULDING_SZ.h; | ||||
|     let x1 = this.#ceilingBr.x + MOULDING_SZ.w; | ||||
|     let y1 = this.#ceilingTl.y; | ||||
|  | ||||
|     D.fillRect( | ||||
|       this.#ceilingTl.offset(new Point(CEILING_CELL_SIZE.w, -MOULDING_SZ.h)), | ||||
|       MOULDING_SZ, | ||||
|       color, | ||||
|       new Point(x0, y0), | ||||
|       new Size(x1 - x0, y1 - y0), | ||||
|       color | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   drawMouldingBottom(color: Color) { | ||||
|     let lhs = this.#ceilingTl.offset(new Point(0, CEILING_CELL_SIZE.h)); | ||||
|     D.fillRect(lhs, new Size(CEILING_CELL_SIZE.w, MOULDING_SZ.h), color); | ||||
|     let x0 = this.#ceilingTl.x; | ||||
|     let y0 = this.#ceilingBr.y; | ||||
|     let x1 = this.#ceilingBr.x; | ||||
|     let y1 = this.#ceilingBr.y + MOULDING_SZ.h; | ||||
|  | ||||
|     D.fillRect( | ||||
|       new Point(x0, y0), | ||||
|       new Size(x1 - x0, y1 - y0), | ||||
|       color | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   drawMouldingBottomLeft(color: Color) { | ||||
|     let x0 = this.#ceilingTl.x - MOULDING_SZ.w; | ||||
|     let y0 = this.#ceilingBr.y; | ||||
|     let x1 = this.#ceilingTl.x; | ||||
|     let y1 = this.#ceilingBr.y + MOULDING_SZ.h; | ||||
|  | ||||
|     D.fillRect( | ||||
|       this.#ceilingTl.offset(new Point(-MOULDING_SZ.w, CEILING_CELL_SIZE.h)), | ||||
|       MOULDING_SZ, | ||||
|       new Point(x0, y0), | ||||
|       new Size(x1 - x0, y1 - y0), | ||||
|       color, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   drawMouldingRight(color: Color) { | ||||
|     let lhs = this.#ceilingTl.offset(new Point(CEILING_CELL_SIZE.w, 0)); | ||||
|     D.fillRect(lhs, new Size(MOULDING_SZ.w, CEILING_CELL_SIZE.h), color); | ||||
|     let x0 = this.#ceilingBr.x; | ||||
|     let y0 = this.#ceilingTl.y; | ||||
|     let x1 = this.#ceilingBr.x + MOULDING_SZ.w; | ||||
|     let y1 = this.#ceilingBr.y; | ||||
|  | ||||
|     D.fillRect( | ||||
|       new Point(x0, y0), | ||||
|       new Size(x1 - x0, y1 - y0), | ||||
|       color | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   drawMouldingBottomRight(color: Color) { | ||||
|     let x0 = this.#ceilingBr.x; | ||||
|     let y0 = this.#ceilingBr.y; | ||||
|     let x1 = this.#ceilingBr.x + MOULDING_SZ.w; | ||||
|     let y1 = this.#ceilingBr.y + MOULDING_SZ.h; | ||||
|  | ||||
|     D.fillRect( | ||||
|       this.#ceilingTl.offset( | ||||
|         new Point(CEILING_CELL_SIZE.w, CEILING_CELL_SIZE.h), | ||||
|       ), | ||||
|       MOULDING_SZ, | ||||
|       color, | ||||
|       new Point(x0, y0), | ||||
|       new Size(x1 - x0, y1 - y0), | ||||
|       color | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   | ||||
							
								
								
									
										158
									
								
								src/huntmode.ts
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								src/huntmode.ts
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| import { Point, Size } from "./engine/datatypes.ts"; | ||||
| import { DrawPile } from "./drawpile.ts"; | ||||
| import { D } from "./engine/public.ts"; | ||||
| import { sprThrallLore } from "./sprites.ts"; | ||||
| import {Point, Rect, Size} from "./engine/datatypes.ts"; | ||||
| import {DrawPile} from "./drawpile.ts"; | ||||
| import {D, I} from "./engine/public.ts"; | ||||
| import {sprThrallLore} from "./sprites.ts"; | ||||
| import { | ||||
|   BG_INSET, | ||||
|   BG_WALL_OR_UNREVEALED, | ||||
| @@ -11,16 +11,16 @@ import { | ||||
|   FG_TEXT_ENDORSED, | ||||
|   FG_TOO_EXPENSIVE, | ||||
| } from "./colors.ts"; | ||||
| import { getPlayerProgress } from "./playerprogress.ts"; | ||||
| import { Architecture, LoadedNewMap } from "./newmap.ts"; | ||||
| import { FLOOR_CELL_SIZE, GridArt } from "./gridart.ts"; | ||||
| import { shadowcast } from "./shadowcast.ts"; | ||||
| import { getCheckModal } from "./checkmodal.ts"; | ||||
| import { withCamera } from "./layout.ts"; | ||||
| import {getPlayerProgress} from "./playerprogress.ts"; | ||||
| import {Architecture, LoadedNewMap} from "./newmap.ts"; | ||||
| import {FLOOR_CELL_SIZE, GridArt} from "./gridart.ts"; | ||||
| import {shadowcast} from "./shadowcast.ts"; | ||||
| import {withCamera} from "./layout.ts"; | ||||
|  | ||||
| export class HuntMode { | ||||
|   map: LoadedNewMap; | ||||
|   player: Point; | ||||
|   floatingPlayer: Point; | ||||
|   velocity: Point; | ||||
|   faceLeft: boolean; | ||||
|  | ||||
|   drawpile: DrawPile; | ||||
| @@ -29,7 +29,8 @@ export class HuntMode { | ||||
|  | ||||
|   constructor(depth: number, map: LoadedNewMap) { | ||||
|     this.map = map; | ||||
|     this.player = map.entrance; | ||||
|     this.floatingPlayer = map.entrance.offset(new Point(0.5, 0.5)); | ||||
|     this.velocity = new Point(0, 0); | ||||
|     this.faceLeft = false; | ||||
|  | ||||
|     this.drawpile = new DrawPile(); | ||||
| @@ -39,13 +40,27 @@ export class HuntMode { | ||||
|     // getCheckModal().show(standardVaultTemplates[5].checks[1], null) | ||||
|   } | ||||
|  | ||||
|   get gridifiedPlayer(): Point { | ||||
|     return new Point( | ||||
|       Math.floor(this.floatingPlayer.x), | ||||
|       Math.floor(this.floatingPlayer.y), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   get pixelPlayer(): Point { | ||||
|     return new Point( | ||||
|       Math.floor(this.floatingPlayer.x * FLOOR_CELL_SIZE.w - FLOOR_CELL_SIZE.w / 2), | ||||
|       Math.floor(this.floatingPlayer.y * FLOOR_CELL_SIZE.h - FLOOR_CELL_SIZE.h / 2), | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   getDepth() { | ||||
|     return this.depth; | ||||
|   } | ||||
|  | ||||
|   // == update logic == | ||||
|   #collectResources() { | ||||
|     let cell = this.map.get(this.player); | ||||
|     let cell = this.map.get(this.gridifiedPlayer); | ||||
|  | ||||
|     let pickup = cell.pickup; | ||||
|     if (pickup != null) { | ||||
| @@ -61,11 +76,11 @@ export class HuntMode { | ||||
|     } | ||||
|  | ||||
|     let dist = Math.max( | ||||
|       Math.abs(mapPosition.x - this.player.x), | ||||
|       Math.abs(mapPosition.y - this.player.y), | ||||
|       Math.abs(mapPosition.x - this.gridifiedPlayer.x), | ||||
|       Math.abs(mapPosition.y - this.gridifiedPlayer.y), | ||||
|     ); | ||||
|  | ||||
|     if (dist != 1) { | ||||
|     if (dist > 1) { | ||||
|       return null; | ||||
|     } | ||||
|  | ||||
| @@ -76,6 +91,7 @@ export class HuntMode { | ||||
|     return pickup.computeCostToClick(); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|   movePlayerTo(newPosition: Point) { | ||||
|     let oldX = this.player.x; | ||||
|     let newX = newPosition.x; | ||||
| @@ -88,9 +104,10 @@ export class HuntMode { | ||||
|     } | ||||
|     this.#collectResources(); | ||||
|   } | ||||
|    */ | ||||
|  | ||||
|   getZoneLabel(): string | null { | ||||
|     return this.map.get(this.player).zoneLabel; | ||||
|     return this.map.get(this.gridifiedPlayer).zoneLabel; | ||||
|   } | ||||
|  | ||||
|   // draw | ||||
| @@ -109,18 +126,20 @@ export class HuntMode { | ||||
|     this.frame += 1; | ||||
|     this.drawpile.clear(); | ||||
|  | ||||
|     let globalOffset = new Point( | ||||
|       this.player.x * FLOOR_CELL_SIZE.w, | ||||
|       this.player.y * FLOOR_CELL_SIZE.h, | ||||
|     ).offset(new Point(-192, -192)); | ||||
|     let globalOffset = this.pixelPlayer.offset( | ||||
|       new Point(-192, -192) | ||||
|     ); | ||||
|  | ||||
|     this.#updatePlayer(); | ||||
|     this.#updateFov(); | ||||
|     this.#updatePickups(); | ||||
|  | ||||
|     for (let y = 0; y < this.map.size.h; y += 1) { | ||||
|       for (let x = 0; x < this.map.size.w; x += 1) { | ||||
|         let offsetInCells = new Point(x - this.player.x, y - this.player.y); | ||||
|         this.#drawMapCell(offsetInCells, new Point(x, y)); | ||||
|         let offsetInPixels = new Point(x, y).scale(FLOOR_CELL_SIZE).offset( | ||||
|           this.pixelPlayer.negate() | ||||
|         ); | ||||
|         this.#drawMapCell(offsetInPixels, new Point(x, y)); | ||||
|       } | ||||
|     } | ||||
|     this.#drawPlayer(globalOffset); | ||||
| @@ -130,6 +149,60 @@ export class HuntMode { | ||||
|     this.drawpile.executeOnClick(); | ||||
|   } | ||||
|  | ||||
|   #updatePlayer() { | ||||
|     let dx = this.velocity.x; | ||||
|     let dy = this.velocity.y; | ||||
|  | ||||
|     let amt = 0.005; | ||||
|  | ||||
|     if (I.isKeyDown("w")) { dy -= amt; } | ||||
|     if (I.isKeyDown("s")) { dy += amt; } | ||||
|     if (I.isKeyDown("a")) { dx -= amt; } | ||||
|     if (I.isKeyDown("d")) { dx += amt; } | ||||
|  | ||||
|     dx *= 0.9; | ||||
|     dy *= 0.9; | ||||
|  | ||||
|     this.velocity = new Point(dx, dy); | ||||
|     let nSteps = 40; | ||||
|     let szX = 0.5; | ||||
|     let szY = 0.5; | ||||
|  | ||||
|     for (let i = 0; i < nSteps; i++) { | ||||
|       let oldXy = this.floatingPlayer; | ||||
|       let newXy = oldXy.offset(new Point(this.velocity.x / nSteps, 0)); | ||||
|  | ||||
|       let bbox = new Rect( | ||||
|         newXy.offset(new Point(-szX / 2, -szY / 2)), | ||||
|         new Size(szX, szY) | ||||
|       ) | ||||
|  | ||||
|       for (let cell of bbox.overlappedCells(new Size(1, 1)).values()) { | ||||
|         if (this.#blocksMovement(cell.top)) { | ||||
|           this.velocity = new Point(0, this.velocity.y); | ||||
|           newXy = oldXy; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       oldXy = newXy; | ||||
|       newXy = oldXy.offset(new Point(0, this.velocity.y / nSteps)); | ||||
|  | ||||
|       bbox = new Rect( | ||||
|         newXy.offset(new Point(-szX / 2, -szY / 2)), | ||||
|         new Size(szX, szY) | ||||
|       ) | ||||
|  | ||||
|       for (let cell of bbox.overlappedCells(new Size(1, 1)).values()) { | ||||
|         if (this.#blocksMovement(cell.top)) { | ||||
|           this.velocity = new Point(this.velocity.x, 0); | ||||
|           newXy = oldXy; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       this.floatingPlayer = newXy; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   #updateFov() { | ||||
|     for (let y = 0; y < this.map.size.h; y += 1) { | ||||
|       for (let x = 0; x < this.map.size.w; x += 1) { | ||||
| @@ -137,15 +210,15 @@ export class HuntMode { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this.map.get(new Point(this.player.x, this.player.y)).revealed = true; | ||||
|     this.map.get(this.gridifiedPlayer).revealed = true; | ||||
|     shadowcast( | ||||
|       [this.player.x, this.player.y], | ||||
|       [this.gridifiedPlayer.x, this.gridifiedPlayer.y], | ||||
|       ([x, y]: [number, number]): boolean => { | ||||
|         let cell = this.map.get(new Point(x, y)); | ||||
|         let pickup = cell.pickup; | ||||
|         return ( | ||||
|           cell.architecture == Architecture.Wall || | ||||
|           (pickup != null && pickup.isObstructive()) | ||||
|           (pickup != null && pickup.obstructsVision()) | ||||
|         ); | ||||
|       }, | ||||
|       ([x, y]: [number, number]) => { | ||||
| @@ -167,8 +240,8 @@ export class HuntMode { | ||||
|   } | ||||
|  | ||||
|   #inVisibilityRange(x: number, y: number): boolean { | ||||
|     let dx = x - this.player.x; | ||||
|     let dy = y - this.player.y; | ||||
|     let dx = x - this.gridifiedPlayer.x; | ||||
|     let dy = y - this.gridifiedPlayer.y; | ||||
|     return dx * dx + dy * dy < 13; | ||||
|   } | ||||
|  | ||||
| @@ -176,14 +249,14 @@ export class HuntMode { | ||||
|     this.drawpile.draw(); | ||||
|   } | ||||
|  | ||||
|   #drawMapCell(offsetInCells: Point, mapPosition: Point) { | ||||
|   #drawMapCell(offsetInPixels: Point, mapPosition: Point) { | ||||
|     const OFFSET_UNDER_FLOOR = -512 + mapPosition.y; | ||||
|     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(offsetInCells); | ||||
|     const gridArt = new GridArt(offsetInPixels); | ||||
|  | ||||
|     let cellData = this.map.get(mapPosition); | ||||
|  | ||||
| @@ -240,8 +313,10 @@ export class HuntMode { | ||||
|           } | ||||
|  | ||||
|           getPlayerProgress().spendBlood(cost); | ||||
|           this.movePlayerTo(mapPosition); | ||||
|           getCheckModal().show(null, null); | ||||
|  | ||||
|           // TODO: This isn't a thing anymore | ||||
|           // this.movePlayerTo(mapPosition); | ||||
|           // getCheckModal().show(null, null); | ||||
|         }, | ||||
|         onSqueeze: () => { | ||||
|           // the cost _gates_ squeezes | ||||
| @@ -320,10 +395,7 @@ export class HuntMode { | ||||
|   } | ||||
|  | ||||
|   #drawPlayer(globalOffset: Point) { | ||||
|     let cellOffset = new Point( | ||||
|       this.player.x * FLOOR_CELL_SIZE.w, | ||||
|       this.player.y * FLOOR_CELL_SIZE.h, | ||||
|     ).offset(globalOffset.negate()); | ||||
|     let cellOffset = this.pixelPlayer.offset(globalOffset.negate()); | ||||
|     this.drawpile.add(0, () => { | ||||
|       D.drawSprite(sprThrallLore, cellOffset, 1, { | ||||
|         xScale: this.faceLeft ? -2 : 2, | ||||
| @@ -379,6 +451,20 @@ export class HuntMode { | ||||
|       ); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   #blocksMovement(xy: Point) { | ||||
|     let cell = this.map.get(xy); | ||||
|     if (cell.architecture == Architecture.Wall) { | ||||
|       return true; | ||||
|     } | ||||
|  | ||||
|     if (cell.pickup?.blocksMovement()) { | ||||
|       return true; | ||||
|     } | ||||
|  | ||||
|     // TODO: Other cases | ||||
|     return false; | ||||
|   } | ||||
| } | ||||
|  | ||||
| let active: HuntMode | null = null; | ||||
|   | ||||
| @@ -44,7 +44,11 @@ export class LockPickup { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   isObstructive() { | ||||
|   blocksMovement() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   obstructsVision() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -90,7 +94,11 @@ export class BreakableBlockPickup { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   isObstructive() { | ||||
|   blocksMovement() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   obstructsVision() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -175,7 +183,11 @@ export class LadderPickup { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   isObstructive() { | ||||
|   blocksMovement() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   obstructsVision() { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
| @@ -217,7 +229,11 @@ export class ThrallPickup { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   isObstructive() { | ||||
|   blocksMovement() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   obstructsVision() { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
| @@ -263,7 +279,11 @@ export class ThrallPosterPickup { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   isObstructive() { | ||||
|   blocksMovement() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   obstructsVision() { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
| @@ -310,7 +330,11 @@ export class ThrallRecruitedPickup { | ||||
|     return !this.bitten; | ||||
|   } | ||||
|  | ||||
|   isObstructive() { | ||||
|   blocksMovement() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   obstructsVision() { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
| @@ -425,7 +449,11 @@ export class ThrallCollectionPlatePickup { | ||||
|     return !this.rewarded; | ||||
|   } | ||||
|  | ||||
|   isObstructive() { | ||||
|   blocksMovement() { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   obstructsVision() { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
| @@ -530,7 +558,10 @@ export class ThrallItemPickup { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   isObstructive() { | ||||
|   blocksMovement() { | ||||
|     return true; | ||||
|   } | ||||
|   obstructsVision() { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user