Refactor screen layout code, start player progress code
This commit is contained in:
		| @@ -91,6 +91,10 @@ export class Rect { | ||||
|     this.size = size; | ||||
|   } | ||||
|  | ||||
|   offset(offset: Point) { | ||||
|     return new Rect(this.top.offset(offset), this.size); | ||||
|   } | ||||
|  | ||||
|   contains(other: Point) { | ||||
|     return (other.x >= this.top.x && other.y >= this.top.y && other.x < this.top.x + this.size.w && other.y < this.top.y + this.size.h); | ||||
|   } | ||||
| @@ -186,5 +190,5 @@ export enum AlignX { | ||||
| export enum AlignY { | ||||
|   Top = 0, | ||||
|   Middle = 1, | ||||
|   Right = 2, | ||||
|   Bottom = 2, | ||||
| } | ||||
|   | ||||
| @@ -28,8 +28,10 @@ class Screen { | ||||
|  | ||||
|  | ||||
| let active: Screen | undefined = undefined | ||||
| export let desiredWidth = 384; | ||||
| export let desiredHeight = 384; | ||||
|  | ||||
| // TODO: Move these to Game? | ||||
| export let desiredWidth = 400; | ||||
| export let desiredHeight = 400; | ||||
|  | ||||
| export function pollAndTouch(canvas: HTMLCanvasElement) { | ||||
|   let realWidth = canvas.offsetWidth; | ||||
|   | ||||
							
								
								
									
										47
									
								
								src/game.ts
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								src/game.ts
									
									
									
									
									
								
							| @@ -1,8 +1,9 @@ | ||||
| import {desiredHeight, desiredWidth, getScreen} from "./engine/internal/screen.ts"; | ||||
| import {getScreen} from "./engine/internal/screen.ts"; | ||||
| import {BG_OUTER} from "./colors.ts"; | ||||
| import {D, I} from "./engine/public.ts"; | ||||
| import {IGame, Point, Size} from "./engine/datatypes.ts"; | ||||
| import {IGame, Point, Rect, Size} from "./engine/datatypes.ts"; | ||||
| import {HuntMode} from "./huntmode.ts"; | ||||
| import {getLayoutRect} from "./layout.ts"; | ||||
|  | ||||
| class MenuCamera { | ||||
|   // measured in whole screens | ||||
| @@ -43,7 +44,6 @@ export class Game implements IGame { | ||||
|   camera: MenuCamera; | ||||
|   state: GameState; | ||||
|   huntMode: HuntMode; | ||||
|   frame: number; | ||||
|  | ||||
|   constructor() { | ||||
|     this.camera = new MenuCamera({ | ||||
| @@ -53,11 +53,9 @@ export class Game implements IGame { | ||||
|     this.state = "Gameplay"; | ||||
|  | ||||
|     this.huntMode = HuntMode.generate({depth: 1}); | ||||
|     this.frame = 0; | ||||
|   } | ||||
|  | ||||
|   update() { | ||||
|     this.frame += 1; | ||||
|     if (I.isKeyPressed("w")) { | ||||
|       this.state = "Gameplay" | ||||
|     } | ||||
| @@ -93,37 +91,32 @@ export class Game implements IGame { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   getPaneRegionForGameState(gameState: GameState) { | ||||
|   getGameStateRect(gameState: GameState): Rect { | ||||
|     let baseRect: Rect; | ||||
|     switch(gameState) { | ||||
|       case "Gameplay": | ||||
|       case "Thralls": | ||||
|         baseRect = getLayoutRect(new Size(384, 384)); | ||||
|         break; | ||||
|       default: | ||||
|         throw `not sure what base rect to use: ${gameState}` | ||||
|     } | ||||
|  | ||||
|     // now move that base to a reasonable screen location | ||||
|     let screen = getScreen(); | ||||
|     let {w, h} = screen.size; | ||||
|     let overallScreenLocation = getScreenLocation(gameState); | ||||
|  | ||||
|     let bigPaneX = overallScreenLocation.x * w; | ||||
|     let bigPaneY = overallScreenLocation.y * h; | ||||
|     let bigPaneW = w; | ||||
|     let bigPaneH = h; | ||||
|     let offsetX = overallScreenLocation.x * w; | ||||
|     let offsetY = overallScreenLocation.y * h; | ||||
|  | ||||
|     let smallPaneW = desiredWidth; | ||||
|     let smallPaneH = desiredHeight; | ||||
|     let smallPaneX = Math.floor(bigPaneX + (bigPaneW - smallPaneW) / 2) | ||||
|     let smallPaneY = Math.floor(bigPaneY + (bigPaneH - smallPaneH) / 2) | ||||
|  | ||||
|     return { | ||||
|       big: { | ||||
|         position: new Point(bigPaneX, bigPaneY), | ||||
|         size: new Size(bigPaneW, bigPaneH), | ||||
|       }, | ||||
|       small: { | ||||
|         position: new Point(smallPaneX, smallPaneY), | ||||
|         size: new Size(smallPaneW, smallPaneH), | ||||
|       } | ||||
|     } | ||||
|     return baseRect.offset(new Point(offsetX, offsetY)); | ||||
|   } | ||||
|  | ||||
|   #withHuntModeCamera(cb: () => void) { | ||||
|     let region = this.getPaneRegionForGameState("Gameplay") | ||||
|     let region = this.getGameStateRect("Gameplay") | ||||
|  | ||||
|     D.withCamera(D.camera.offset(region.small.position.negate()), cb) | ||||
|     D.withCamera(D.camera.offset(region.top.negate()), cb) | ||||
|   } | ||||
|  | ||||
|   updateGameplay() { | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import {DrawPile} from "./drawpile.ts"; | ||||
| import {D} from "./engine/public.ts"; | ||||
| import {sprDrips, sprRaccoonWalking, sprStatPickup} from "./sprites.ts"; | ||||
| import {BG_INSET, FG_TEXT} from "./colors.ts"; | ||||
| import {getPlayerProgress} from "./playerprogress.ts"; | ||||
|  | ||||
| export type MapCellContent = | ||||
|   {type: "statPickup", stat: Stat} | | ||||
| @@ -142,7 +143,10 @@ export class HuntMode { | ||||
|   #collectResources() { | ||||
|     let present = this.cells.get(this.player); | ||||
|     if (present.content.type == "statPickup") { | ||||
|       let stat = present.content.stat; | ||||
|       let amount = 1; | ||||
|       present.content = {type: "empty"}; | ||||
|       getPlayerProgress().add(stat, amount); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -152,7 +156,7 @@ export class HuntMode { | ||||
|     this.#collectResources(); | ||||
|   } | ||||
|  | ||||
|   // draw: | ||||
|   // draw | ||||
|   update() { | ||||
|     this.frame += 1; | ||||
|     this.drawpile.clear(); | ||||
|   | ||||
							
								
								
									
										43
									
								
								src/layout.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/layout.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| import {AlignX, AlignY, Point, Rect, Size} from "./engine/datatypes.ts"; | ||||
| import {D} from "./engine/public.ts"; | ||||
|  | ||||
| let margin = 8; | ||||
|  | ||||
| export function getLayoutRect( | ||||
|   size: Size, | ||||
|   options?: {alignX?: AlignX, alignY?: AlignY} | ||||
| ): Rect { | ||||
|   let {w: screenW, h: screenH} = D.size; | ||||
|  | ||||
|   // first of all: place the _internal_ screen inside the real screen | ||||
|   let marginalScreenW = screenW - margin * 2; | ||||
|   let marginalScreenH = screenH - margin * 2; | ||||
|   let marginalScreenX = margin; | ||||
|   let marginalScreenY = margin; | ||||
|  | ||||
|   // NOTE: If the screen is too small, remainingSpace will be negative | ||||
|   // This is fine -- it actually results in reasonable outcomes except | ||||
|   // that the size of the box is exceeded in the opposite of the align direction. | ||||
|   let {w: innerW, h: innerH} = size; | ||||
|   let remainingSpaceX = marginalScreenW - innerW; | ||||
|   let remainingSpaceY = marginalScreenH - innerH; | ||||
|  | ||||
|   let alignXCoef = | ||||
|     options?.alignX == AlignX.Left ? 0.0 : | ||||
|     options?.alignX == AlignX.Center ? 0.5 : | ||||
|     options?.alignX == AlignX.Right ? 1.0 : | ||||
|     0.5; | ||||
|   let alignYCoef = | ||||
|     options?.alignY == AlignY.Top ? 0.0 : | ||||
|     options?.alignY == AlignY.Middle ? 0.5 : | ||||
|     options?.alignY == AlignY.Bottom ? 1.0 : | ||||
|     0.5; | ||||
|  | ||||
|   let x = marginalScreenX + alignXCoef * remainingSpaceX; | ||||
|   let y = marginalScreenY + alignYCoef * remainingSpaceY; | ||||
|  | ||||
|   return new Rect( | ||||
|     new Point(Math.floor(x), Math.floor(y)), | ||||
|     size | ||||
|   ) | ||||
| } | ||||
							
								
								
									
										34
									
								
								src/playerprogress.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/playerprogress.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| import {Stat} from "./datatypes.ts"; | ||||
|  | ||||
| export class PlayerProgress { | ||||
|   #stats: Record<Stat, number> | ||||
|  | ||||
|   constructor() { | ||||
|     this.#stats = { | ||||
|       AGI: 10, | ||||
|       INT: 10, | ||||
|       CHA: 10, | ||||
|       PSI: 10, | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   add(stat: Stat, amount: number) { | ||||
|     if (amount != Math.floor(amount)) { | ||||
|       throw `stat increment must be integer: ${amount}` | ||||
|     } | ||||
|     if (amount <= 0) { | ||||
|       throw `stat increment must be >0: ${amount}` | ||||
|     } | ||||
|     this.#stats[stat] += amount; | ||||
|   } | ||||
|  | ||||
|   get(stat: Stat): number { | ||||
|     return this.#stats[stat] | ||||
|   } | ||||
| } | ||||
|  | ||||
| let active: PlayerProgress = new PlayerProgress(); | ||||
|  | ||||
| export function getPlayerProgress(): PlayerProgress { | ||||
|   return active | ||||
| } | ||||
		Reference in New Issue
	
	Block a user