diff --git a/src/actors/baddie.ts b/src/actors/baddie.ts index d0a85c5..774e40d 100644 --- a/src/actors/baddie.ts +++ b/src/actors/baddie.ts @@ -1,5 +1,10 @@ import * as ex from "excalibur"; -import { baddieSpriteSheet, Resources, tileSize } from "../core/resources"; +import { + baddieSpriteSheet, + gridSpace, + Resources, + tileSize, +} from "../core/resources"; import { Player } from "./player"; import { stats } from "../core/stats"; import { Ground } from "./ground"; @@ -21,7 +26,7 @@ export class Baddie extends SceneActor { constructor(args: iLocation) { super({ name: "Baddie", - pos: new ex.Vector(args.x * tileSize, args.y * tileSize), + pos: gridSpace(args), anchor: new ex.Vector(0.5, 1), collisionGroup: ex.CollisionGroupManager.groupByName("enemy"), collisionType: ex.CollisionType.Active, diff --git a/src/actors/gate.ts b/src/actors/gate.ts index 6a1deb9..d0ebed5 100644 --- a/src/actors/gate.ts +++ b/src/actors/gate.ts @@ -3,6 +3,7 @@ import { gateOpenSpriteSheet, gateClosedSpriteSheet, tileSize, + gridSpace, } from "../core/resources"; import { Player } from "./player"; import { stats } from "../core/stats"; @@ -28,7 +29,7 @@ export class Gate extends GameActor implements iArtifact { constructor(args: GateArgs) { super({ name: "Gate", - pos: new ex.Vector(args.x * tileSize, args.y * tileSize), + pos: gridSpace(args), scale: new ex.Vector(0.5, 0.5), anchor: ex.Vector.Down, collider: ex.Shape.Box( diff --git a/src/actors/ground.ts b/src/actors/ground.ts index c2e1a1a..6b2bb0f 100644 --- a/src/actors/ground.ts +++ b/src/actors/ground.ts @@ -1,5 +1,10 @@ import * as ex from "excalibur"; -import { grassFlatSprite, grassBelowSprite, tileSize } from "../core/resources"; +import { + grassFlatSprite, + grassBelowSprite, + tileSize, + gridSpace, +} from "../core/resources"; import { iBox, iFloor, iWall } from "../core/location"; /** @@ -7,27 +12,27 @@ import { iBox, iFloor, iWall } from "../core/location"; */ export class Ground extends ex.Actor { constructor(args: iBox) { - const scale = (args.scale !== undefined ? args.scale : 1) * tileSize; + const scale = args.scale !== undefined ? args.scale : 1; super({ name: "Ground", - pos: new ex.Vector(args.x * scale, args.y * scale), + pos: gridSpace(args), scale: new ex.Vector( - scale / grassFlatSprite.width, - scale / grassFlatSprite.width, + (scale * tileSize) / grassFlatSprite.width, + (scale * tileSize) / grassFlatSprite.width, ), anchor: ex.Vector.Zero, collider: ex.Shape.Box( - 4 * tileSize * args.right, - 4 * tileSize * args.down, + (4 * tileSize * args.right) / scale, + (4 * tileSize * args.down) / scale, ex.Vector.Zero, ), collisionType: ex.CollisionType.Fixed, collisionGroup: ex.CollisionGroupManager.groupByName("floor"), }); - for (let i = 0; i < args.right; i++) { + for (let i = 0; i < args.right / scale; i++) { let sprite = grassFlatSprite; - for (let j = 0; j < args.down; j++) { + for (let j = 0; j < args.down / scale; j++) { this.graphics.show(sprite, { anchor: ex.Vector.Zero, offset: ex.vec(i * sprite.width, j * sprite.height), @@ -46,6 +51,6 @@ export class Floor extends Ground { export class Wall extends Ground { constructor(args: iWall) { - super({ right: 1, ...args }); + super({ x: args.x, y: args.y + args.up - 1, right: 1, down: args.up }); } } diff --git a/src/actors/lift.ts b/src/actors/lift.ts index 57f146c..135be9b 100644 --- a/src/actors/lift.ts +++ b/src/actors/lift.ts @@ -1,5 +1,5 @@ import * as ex from "excalibur"; -import { sandHalfSprite, tileSize } from "../core/resources"; +import { gridSpace, sandHalfSprite, tileSize } from "../core/resources"; import { iLocation } from "../core/location"; export interface LiftArgs { @@ -16,15 +16,11 @@ export class Lift extends ex.Actor implements LiftArgs { constructor(args: LiftArgs) { super({ - pos: new ex.Vector( - args.startPos.x * tileSize, - args.startPos.y * tileSize + 3, - ), - scale: new ex.Vector(0.25, 0.25), + pos: gridSpace(args.startPos), anchor: ex.Vector.Down, collisionType: ex.CollisionType.Fixed, collisionGroup: ex.CollisionGroupManager.groupByName("floor"), - collider: ex.Shape.Box(tileSize * 4, tileSize * 2, ex.Vector.Down), + collider: ex.Shape.Box(tileSize, tileSize / 2, ex.Vector.Down), }); this.startPos = args.startPos; this.endPos = args.endPos; @@ -37,8 +33,8 @@ export class Lift extends ex.Actor implements LiftArgs { if (!(window as any).__TESTING) { this.actions.repeatForever((ctx) => ctx - .moveTo(this.endPos.x * tileSize, this.endPos.y * tileSize, 100) - .moveTo(this.startPos.x * tileSize, this.startPos.y * tileSize, 100), + .moveTo(gridSpace(this.endPos), 100) + .moveTo(gridSpace(this.startPos), 100), ); } } diff --git a/src/actors/npc.ts b/src/actors/npc.ts index b27f363..9497bec 100644 --- a/src/actors/npc.ts +++ b/src/actors/npc.ts @@ -1,5 +1,5 @@ import * as ex from "excalibur"; -import { girl, npcSprite, tileSize } from "../core/resources"; +import { girl, gridSpace, npcSprite, tileSize } from "../core/resources"; import { Player } from "./player"; import { iLocation } from "../core/location"; @@ -10,7 +10,7 @@ export class NPC extends ex.Actor { public hurtTime: number = 0; constructor(args: iLocation) { super({ - pos: new ex.Vector(args.x * tileSize, args.y * tileSize + 3), + pos: gridSpace(args), anchor: new ex.Vector(0.5, 1), collisionType: ex.CollisionType.Passive, collisionGroup: ex.CollisionGroupManager.groupByName("enemy"), diff --git a/src/actors/player.ts b/src/actors/player.ts index a07c5c5..8b76927 100644 --- a/src/actors/player.ts +++ b/src/actors/player.ts @@ -5,6 +5,7 @@ import { Resources, tileSize, playerCharacters, + gridSpace, } from "../core/resources"; import { Baddie } from "./baddie"; import { stats } from "../core/stats"; @@ -50,7 +51,7 @@ export class Player extends GameActor { constructor(x: number, y: number) { super({ name: "Player", - pos: new ex.Vector(x * tileSize, y * tileSize), + pos: gridSpace({ x: x, y: y }), anchor: new ex.Vector(0.5, 1), collisionType: ex.CollisionType.Active, collisionGroup: ex.CollisionGroupManager.groupByName("player"), diff --git a/src/core/artifact.ts b/src/core/artifact.ts index 1856fd0..21712be 100644 --- a/src/core/artifact.ts +++ b/src/core/artifact.ts @@ -2,7 +2,7 @@ import * as ex from "excalibur"; import { Actor } from "./actor"; import { iArtifact } from "./iartifact"; import { iLocation } from "./location"; -import { tileSize } from "./resources"; +import { gridSpace, tileSize } from "./resources"; import { Player } from "../actors/player"; export interface ArtifactArgs extends iLocation { @@ -13,7 +13,7 @@ export class Artifact extends Actor implements iArtifact { constructor(args: ArtifactArgs) { super({ name: args.name, - pos: new ex.Vector(args.x * tileSize, args.y * tileSize), + pos: gridSpace(args), scale: new ex.Vector(0.5, 0.5), anchor: ex.Vector.Down, collider: ex.Shape.Box(tileSize, tileSize, ex.vec(0, 1)), diff --git a/src/core/levelLayout.ts b/src/core/levelLayout.ts index 60dac93..552836d 100644 --- a/src/core/levelLayout.ts +++ b/src/core/levelLayout.ts @@ -95,6 +95,8 @@ export abstract class LevelLayout extends ex.Scene implements iSceneNode { background.graphics.show("poly"); engine.add(background); + this.camera.pos = this.player.pos.clone(); + // For the test harness to be predicable if (!(window as any).__TESTING) { this.initCamera(this.player); @@ -103,22 +105,22 @@ export abstract class LevelLayout extends ex.Scene implements iSceneNode { this.camera.strategy.limitCameraBounds( new ex.BoundingBox( 0, - 0, + -this.levelSize.y * tileSize, this.levelSize.x * tileSize, - this.levelSize.y * tileSize, + 0, ), ); - engine.add(new Floor({ x: -1, y: -1, right: this.levelSize.x + 2 })); + engine.add(new Floor({ x: -1, y: 0, right: this.levelSize.x + 2 })); engine.add( new Floor({ x: -1, - y: this.levelSize.y, + y: this.levelSize.y + 1, right: this.levelSize.x + 2, }), ); - engine.add(new Wall({ x: -1, y: 0, down: this.levelSize.y })); + engine.add(new Wall({ x: -1, y: 0, up: this.levelSize.y + 1 })); engine.add( - new Wall({ x: this.levelSize.x, y: 0, down: this.levelSize.y }), + new Wall({ x: this.levelSize.x, y: 0, up: this.levelSize.y + 1 }), ); } } diff --git a/src/core/location.ts b/src/core/location.ts index 1df6b74..e9ff339 100644 --- a/src/core/location.ts +++ b/src/core/location.ts @@ -4,7 +4,7 @@ export interface iLocation { scale?: number; } export interface iWall extends iLocation { - down: number; + up: number; } export interface iFloor extends iLocation { right: number; diff --git a/src/core/resources.ts b/src/core/resources.ts index b5c73e4..0660324 100644 --- a/src/core/resources.ts +++ b/src/core/resources.ts @@ -1,5 +1,6 @@ import * as ex from "excalibur"; import { iCharacter } from "./icharacter"; +import { iLocation } from "./location"; const botFile = require("../../res/excalibot.png"); const girlIdleFile = require("../../res/girl-idle.png"); @@ -63,7 +64,7 @@ const girl: iCharacter = { columns: 10, rows: 1, spriteWidth: 641, - spriteHeight: 542, + spriteHeight: 510, }, }), run: ex.SpriteSheet.fromImageSource({ @@ -72,7 +73,7 @@ const girl: iCharacter = { columns: 8, rows: 1, spriteWidth: 641, - spriteHeight: 542, + spriteHeight: 510, }, }), hurt: ex.SpriteSheet.fromImageSource({ @@ -81,7 +82,7 @@ const girl: iCharacter = { columns: 1, rows: 1, spriteWidth: 641, - spriteHeight: 542, + spriteHeight: 510, }, }), jump: ex.SpriteSheet.fromImageSource({ @@ -90,7 +91,7 @@ const girl: iCharacter = { columns: 10, rows: 1, spriteWidth: 641, - spriteHeight: 542, + spriteHeight: 510, }, }), }; @@ -182,6 +183,7 @@ const gateOpenSpriteSheet = ex.SpriteSheet.fromImageSource({ spriteHeight: 227, }, }); + const potionPurpleSprite = Resources.potionPurple.toSprite(); const potionYellowSprite = Resources.potionYellow.toSprite(); const blockSprite = Resources.block.toSprite(); @@ -190,10 +192,16 @@ const grassBelowSprite = Resources.grassBelow.toSprite(); const sandHalfSprite = Resources.sandHalf.toSprite(); const npcSprite = Resources.npc.toSprite(); +sandHalfSprite.scale = ex.vec(0.25, 0.25); + for (const res in Resources) { loader.addResource((Resources as any)[res]); } +export function gridSpace(loc: iLocation): ex.Vector { + return ex.vec(loc.x, -loc.y).scale(tileSize); +} + export { Resources, loader, diff --git a/src/main.ts b/src/main.ts index de6d715..ce9bb59 100644 --- a/src/main.ts +++ b/src/main.ts @@ -43,13 +43,13 @@ function addNode(node: iSceneNode & ex.Scene) { const playerSelect = new PlayerSelect(); addNode(playerSelect); -addNode(new Example()); addNode(new BeforeLevel1()); addNode(new Level1()); addNode(new BeforeLevel2()); addNode(new Level2()); addNode(new BeforeLevel3()); addNode(new Level3()); +addNode(new Example()); addNode(new Finish()); addNode(new GameOver()); @@ -68,6 +68,7 @@ engine.on("preupdate", () => { stats.nextScene = true; } else if (engine.input.keyboard.wasPressed(ex.Input.Keys.KeyR)) { stats.currentNode = "playerSelect"; + stats.reset(); engine.goToScene(nodes[stats.currentNode].thisScene); window.localStorage.setItem("stats", JSON.stringify(stats)); } diff --git a/src/scenes/example.ts b/src/scenes/example.ts index 1c1e12b..9dd635a 100644 --- a/src/scenes/example.ts +++ b/src/scenes/example.ts @@ -17,31 +17,31 @@ export class Example extends LevelLayout implements iSceneNode { levelSize = new ex.Vector(22, 22); layoutLevel(engine: ex.Engine) { - engine.add(new Floor({ x: 0, y: 19, right: 17 })); + engine.add(new Floor({ x: 0, y: 3, right: 17 })); - engine.add(new Floor({ x: 1, y: 17, right: 3 })); - engine.add(new Floor({ x: 2, y: 15, right: 2 })); - engine.add(new Floor({ x: 2, y: 13, right: 2 })); + engine.add(new Floor({ x: 1, y: 5, right: 3 })); + engine.add(new Floor({ x: 2, y: 7, right: 2 })); + engine.add(new Floor({ x: 2, y: 9, right: 2 })); engine.add(new Floor({ x: 3, y: 11, right: 1 })); - engine.add(new Floor({ x: 3, y: 9, right: 1 })); - engine.add(new Floor({ x: 3, y: 7, right: 1 })); - engine.add(new Potion({ x: 3, y: 7, potionColor: "yellow" })); + engine.add(new Floor({ x: 3, y: 13, right: 1 })); + engine.add(new Floor({ x: 3, y: 15, right: 1 })); + engine.add(new Potion({ x: 3, y: 15, potionColor: "yellow" })); + engine.add(new Ground({ x: 4, y: 19, down: 15.5, right: 1, scale: 0.5 })); + + engine.add(new Floor({ x: 5, y: 9, right: 2 })); + engine.add(new Floor({ x: 5, y: 6, right: 1 })); + engine.add(new Potion({ x: 5, y: 6, potionColor: "purple" })); engine.add( - new Ground({ x: 4 * 2, y: 3 * 2, down: 15.5 * 2, right: 2, scale: 0.5 }), + new Lift({ startPos: { x: 5, y: 16 }, endPos: { x: 16, y: 22 - 6 } }), ); - engine.add(new Floor({ x: 5, y: 13, right: 2 })); - engine.add(new Floor({ x: 5, y: 16, right: 1 })); - engine.add(new Potion({ x: 5, y: 16, potionColor: "purple" })); - engine.add(new Lift({ startPos: { x: 5, y: 6 }, endPos: { x: 16, y: 6 } })); - - this.playerStartsAt({ x: 6, y: 12 }); - engine.add(new Baddie({ x: 6, y: 15 })); - engine.add(new Baddie({ x: 10, y: 15 })); + this.playerStartsAt({ x: 6, y: 10 }); + engine.add(new Baddie({ x: 6, y: 7 })); + engine.add(new Baddie({ x: 10, y: 7 })); engine.add(new Floor({ x: 13, y: 11, right: 4 })); engine.add(new Gate({ x: 14, y: 11, goal: 2 })); - engine.add(new Floor({ x: 16, y: 16, right: 1 })); - engine.add(new Wall({ x: 17, y: 0, down: 20 })); + engine.add(new Floor({ x: 16, y: 6, right: 1 })); + engine.add(new Wall({ x: 17, y: 3, up: 20 })); } } diff --git a/src/scenes/level1.ts b/src/scenes/level1.ts index 2c9d4fb..8221a7e 100644 --- a/src/scenes/level1.ts +++ b/src/scenes/level1.ts @@ -10,23 +10,23 @@ export class Level1 extends LevelLayout implements iSceneNode { layoutLevel(engine: ex.Engine) { this.playerStartsAt({ x: 2, y: 2 }); - engine.add(new Wall({ x: 0, y: 0, down: 6 })); - engine.add(new Floor({ x: 1, y: 5, right: 2 })); + engine.add(new Wall({ x: 0, y: 0, up: 6 })); + engine.add(new Floor({ x: 1, y: 0, right: 2 })); - // --- - // Deze vloer staat te hoog. Zorg dat hij lager staat. + // // --- + // // Deze vloer staat te hoog. Zorg dat hij lager staat. engine.add( new Floor({ x: 3, - y: 0, + y: 5, right: 6, }), ); - // LET OP: Na de aanpassing moet je het spel herladen! - // --- + // // LET OP: Na de aanpassing moet je het spel herladen! + // // --- - engine.add(new Floor({ x: 9, y: 5, right: 2 })); - engine.add(new Gate({ x: 9, y: 5, goal: 0 })); - engine.add(new Wall({ x: 11, y: 0, down: 6 })); + engine.add(new Floor({ x: 9, y: 0, right: 2 })); + engine.add(new Gate({ x: 9, y: 0, goal: 0 })); + engine.add(new Wall({ x: 11, y: 0, up: 6 })); } } diff --git a/src/scenes/level2.ts b/src/scenes/level2.ts index 7910b27..d6551c1 100644 --- a/src/scenes/level2.ts +++ b/src/scenes/level2.ts @@ -9,24 +9,24 @@ export class Level2 extends LevelLayout implements iSceneNode { nextScene = "beforeLevel3"; layoutLevel(engine: ex.Engine) { - this.playerStartsAt({ x: 2, y: 2 }); - engine.add(new Wall({ x: 0, y: 0, down: 6 })); - engine.add(new Floor({ x: 1, y: 5, right: 2 })); + this.playerStartsAt({ x: 2, y: 3 }); + engine.add(new Wall({ x: 0, y: 2, up: 6 })); + engine.add(new Floor({ x: 1, y: 2, right: 2 })); // --- // Deze vloer is niet lang genoeg. Kan jij het oplossen? engine.add( new Floor({ x: 3, - y: 7, + y: 0, right: 1, }), ); // LET OP: Na de aanpassing moet je het spel herladen! // --- - engine.add(new Floor({ x: 11, y: 5, right: 2 })); - engine.add(new Gate({ x: 11, y: 5, goal: 0 })); - engine.add(new Wall({ x: 13, y: 0, down: 6 })); + engine.add(new Floor({ x: 11, y: 2, right: 2 })); + engine.add(new Gate({ x: 11, y: 2, goal: 0 })); + engine.add(new Wall({ x: 13, y: 2, up: 6 })); } } diff --git a/src/scenes/level3.ts b/src/scenes/level3.ts index 1d8776f..cbab959 100644 --- a/src/scenes/level3.ts +++ b/src/scenes/level3.ts @@ -15,8 +15,8 @@ export class Level3 extends LevelLayout implements iSceneNode { levelSize = new ex.Vector(22, 22); layoutLevel(engine: ex.Engine) { - this.playerStartsAt({ x: 2, y: 22 }); - engine.add(new Gate({ x: 20, y: 22, goal: 0 })); + this.playerStartsAt({ x: 2, y: 0 }); + engine.add(new Gate({ x: 20, y: 0, goal: 0 })); // ----- // Hier zijn een paar voorbeelden van dingen die je aan je level kan toevoegen. diff --git a/src/scenes/playerSelect.ts b/src/scenes/playerSelect.ts index 722f2b6..e1c4768 100644 --- a/src/scenes/playerSelect.ts +++ b/src/scenes/playerSelect.ts @@ -72,7 +72,7 @@ function sequence(scene: ex.Scene, actors: ex.Actor[]): void { export class PlayerSelect extends ex.Scene implements iSceneNode { thisScene: string = "playerSelect"; - nextScene: string = "level1"; + nextScene: string = "beforeLevel1"; onInitialize(engine: ex.Engine) { engine.add( diff --git a/src/tests/artifact.test.ts b/src/tests/artifact.test.ts index f88654d..4bb7fc9 100644 --- a/src/tests/artifact.test.ts +++ b/src/tests/artifact.test.ts @@ -3,10 +3,10 @@ import { Artifact } from "../core/artifact"; import { tileSize } from "../core/resources"; describe("Artifact", () => { - it("uses tile space for positioning in construction", () => { + it("uses tile size for positioning in construction", () => { let subject = new Artifact({ x: 1, y: 4, name: "test" }); expect(subject.pos.x).toBe(1 * tileSize); - expect(subject.pos.y).toBe(4 * tileSize); + expect(subject.pos.y).toBe(-4 * tileSize); expect(subject.name).toBe("test"); }); });