1
0
Fork 0

Win checking

This commit is contained in:
Pabloader 2025-06-27 15:31:49 +00:00
parent d2df62cdbe
commit 9c0aad2e75
3 changed files with 106 additions and 9 deletions

View File

@ -59,6 +59,14 @@ export default class Player extends Character {
return this.inventory.find(i => i.type === ItemType.WEAPON_ROCKET_LAUNCHER);
}
get keys() {
return this.inventory.find(i => i.type === ItemType.ITEM_KEYS);
}
get fuel() {
return this.inventory.find(i => i.type === ItemType.ITEM_FUEL);
}
public heal(player: Player) {
player.health += this.healingAmount;
}
@ -77,11 +85,11 @@ export default class Player extends Character {
return false;
}
public hasItem(item: Item | null | undefined): boolean {
public hasItem(item: Item | ItemTypeImage | null | undefined): boolean {
if (!item) {
return false;
}
const itemIndex = this.inventory.findIndex(i => i === item);
const itemIndex = this.inventory.findIndex(i => i === item || i.type === item);
return itemIndex >= 0;
}

View File

@ -1,7 +1,6 @@
import Entity from "./entity";
import type Item from "./item";
import planks from './assets/items/planks.jpg';
import { ItemType } from "./item";
export enum TileType {
NORMAL,
@ -69,7 +68,7 @@ export default class Tile extends Entity {
y += (Number(this.top < doorway.top) - Number(doorway.top < this.top)) * 0.5;
}
ctx.drawImage(planks, x - 0.2, y - 0.2, 0.4, 0.4);
ctx.drawImage(ItemType.ITEM_PLANKS, x - 0.2, y - 0.2, 0.4, 0.4);
}
}

View File

@ -20,6 +20,11 @@ export default class TileMap extends Entity {
private state = GameState.NORMAL;
private availableTiles: Tile[] = [];
public keysFound = false;
public fuelFound = false;
public bossKilled = false;
public readonly foundPlayers: Set<Player>;
constructor(
position: [number, number],
private mapSize: number,
@ -29,6 +34,7 @@ export default class TileMap extends Entity {
) {
super(position, [mapSize * tileSize, mapSize * tileSize]);
this.players = shuffle(Object.values(Players)).slice(0, numPlayers);
this.foundPlayers = new Set(this.players);
this.startTile = this.createMap();
this.findAvailableTiles();
}
@ -237,8 +243,10 @@ export default class TileMap extends Entity {
} else if (item instanceof Player) {
tile.removeItem(item);
this.players.push(item);
this.foundPlayers.add(item);
} else if (item.isBoss && this.player.removeItem(this.player.rocketLauncher)) {
tile.killEnemy();
this.bossKilled = true;
} else if (item.isEnemy) {
this.state = GameState.FIGHT;
break;
@ -246,6 +254,14 @@ export default class TileMap extends Entity {
alert(`Unknown item found: ${item}`);
}
}
if (tile.type === TileType.END) {
if (this.player.removeItem(this.player.fuel)) {
this.fuelFound = true;
}
if (this.player.removeItem(this.player.keys)) {
this.keysFound = true;
}
}
if (this.state === GameState.NORMAL) {
this.nextPlayer();
}
@ -325,6 +341,18 @@ export default class TileMap extends Entity {
private nextPlayer() {
this.spinner.stop();
this.currentPlayerIdx = (this.currentPlayerIdx + 1) % this.players.length;
if (this.win) {
const endTile = this.tiles.findLast(t => t.type === TileType.END);
if (endTile) {
for (const player of this.players) {
const path = Pathfinding.findPath(player.tile, endTile);
player.moveTo(endTile, path);
}
}
setTimeout(alert, 2000, "🎉🎉🎉 ПОБЕДА! 🚗 🎉🎉🎉");
} else if (this.currentPlayerIdx === 0) {
// TODO zombies turn
}
}
private killEnemy() {
@ -339,6 +367,28 @@ export default class TileMap extends Entity {
this.setNormalState();
}
private get win() {
if (!this.keysFound || !this.fuelFound || !this.bossKilled) {
return false;
}
const endTiles = this.tiles.filter(t => t.type === TileType.END);
for (const tile of endTiles) {
if (tile.items.length !== 0) return false;
}
for (const player of Object.values(Players)) {
if (!this.foundPlayers.has(player)) return false;
if (player.isDead) continue;
if (endTiles.every((tile) => {
const path = Pathfinding.findPath(player.tile, tile);
return path.length === 0;
})) {
return false;
}
}
return true;
}
protected draw(ctx: CanvasRenderingContext2D): void {
ctx.scale(1 / this.width, 1 / this.height);
@ -363,6 +413,46 @@ export default class TileMap extends Entity {
ctx.strokeStyle = 'yellow';
ctx.strokeRect(this.player.tile.centerX - w / 2, this.player.tile.centerY - w / 2, w, w);
let x = this.width + this.tileSize / 2 + 10;
let y = this.height - this.tileSize / 2;
for (const player of Object.values(Players)) {
this.drawItem(ctx, player.type, x, y, w, this.foundPlayers.has(player));
x += this.tileSize;
}
x = this.width + this.tileSize / 2 + 10;
y = this.height - 3 * this.tileSize / 2;
for (const [item, found] of zip(
[ItemType.ITEM_KEYS, ItemType.ITEM_FUEL, ItemType.ENEMY_BOSS],
[this.keysFound, this.fuelFound, this.bossKilled],
)) {
this.drawItem(ctx, item, x, y, w, found);
x += this.tileSize;
}
x = this.width + this.tileSize / 2 + 10;
y = this.height - 5 * this.tileSize / 2;
for (const tile of this.tiles) {
if (tile.type !== TileType.END) continue;
this.drawItem(ctx, ItemType.ENEMY_ZOMBIE, x, y, w, tile.items.length === 0);
x += this.tileSize;
}
}
private drawItem(
ctx: CanvasRenderingContext2D,
img: HTMLImageElement,
x: number, y: number, w: number,
found: boolean,
) {
ctx.drawImage(img, x - w / 2, y - w / 2, w, w);
if (!found) {
ctx.fillStyle = `rgba(255, 255, 255, 0.6)`;
ctx.fillRect(x - w / 2, y - w / 2, w, w);
}
}
public update(dt: number) {