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); 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) { public heal(player: Player) {
player.health += this.healingAmount; player.health += this.healingAmount;
} }
@ -77,11 +85,11 @@ export default class Player extends Character {
return false; return false;
} }
public hasItem(item: Item | null | undefined): boolean { public hasItem(item: Item | ItemTypeImage | null | undefined): boolean {
if (!item) { if (!item) {
return false; return false;
} }
const itemIndex = this.inventory.findIndex(i => i === item); const itemIndex = this.inventory.findIndex(i => i === item || i.type === item);
return itemIndex >= 0; return itemIndex >= 0;
} }

View File

@ -1,7 +1,6 @@
import Entity from "./entity"; import Entity from "./entity";
import type Item from "./item"; import type Item from "./item";
import { ItemType } from "./item";
import planks from './assets/items/planks.jpg';
export enum TileType { export enum TileType {
NORMAL, NORMAL,
@ -69,7 +68,7 @@ export default class Tile extends Entity {
y += (Number(this.top < doorway.top) - Number(doorway.top < this.top)) * 0.5; 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 state = GameState.NORMAL;
private availableTiles: Tile[] = []; private availableTiles: Tile[] = [];
public keysFound = false;
public fuelFound = false;
public bossKilled = false;
public readonly foundPlayers: Set<Player>;
constructor( constructor(
position: [number, number], position: [number, number],
private mapSize: number, private mapSize: number,
@ -29,6 +34,7 @@ export default class TileMap extends Entity {
) { ) {
super(position, [mapSize * tileSize, mapSize * tileSize]); super(position, [mapSize * tileSize, mapSize * tileSize]);
this.players = shuffle(Object.values(Players)).slice(0, numPlayers); this.players = shuffle(Object.values(Players)).slice(0, numPlayers);
this.foundPlayers = new Set(this.players);
this.startTile = this.createMap(); this.startTile = this.createMap();
this.findAvailableTiles(); this.findAvailableTiles();
} }
@ -237,8 +243,10 @@ export default class TileMap extends Entity {
} else if (item instanceof Player) { } else if (item instanceof Player) {
tile.removeItem(item); tile.removeItem(item);
this.players.push(item); this.players.push(item);
this.foundPlayers.add(item);
} else if (item.isBoss && this.player.removeItem(this.player.rocketLauncher)) { } else if (item.isBoss && this.player.removeItem(this.player.rocketLauncher)) {
tile.killEnemy(); tile.killEnemy();
this.bossKilled = true;
} else if (item.isEnemy) { } else if (item.isEnemy) {
this.state = GameState.FIGHT; this.state = GameState.FIGHT;
break; break;
@ -246,6 +254,14 @@ export default class TileMap extends Entity {
alert(`Unknown item found: ${item}`); 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) { if (this.state === GameState.NORMAL) {
this.nextPlayer(); this.nextPlayer();
} }
@ -325,6 +341,18 @@ export default class TileMap extends Entity {
private nextPlayer() { private nextPlayer() {
this.spinner.stop(); this.spinner.stop();
this.currentPlayerIdx = (this.currentPlayerIdx + 1) % this.players.length; 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() { private killEnemy() {
@ -339,6 +367,28 @@ export default class TileMap extends Entity {
this.setNormalState(); 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 { protected draw(ctx: CanvasRenderingContext2D): void {
ctx.scale(1 / this.width, 1 / this.height); ctx.scale(1 / this.width, 1 / this.height);
@ -363,6 +413,46 @@ export default class TileMap extends Entity {
ctx.strokeStyle = 'yellow'; ctx.strokeStyle = 'yellow';
ctx.strokeRect(this.player.tile.centerX - w / 2, this.player.tile.centerY - w / 2, w, w); 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) { public update(dt: number) {