Files
arch_agent 3890395885 fix: const redeclaration bug + bare ctx references
- Remove duplicate const TILE_HEIGHT/TILE_WIDTH in player.js and game.js
- Use var TILE_HEIGHT_PLAYER in player.js to avoid collision
- Fix bare ctx → this.ctx in monster render
- Fix ctx = this.ctx → const ctx = this.ctx in NPC render

This was causing a SyntaxError that prevented the entire game from loading.
2026-07-17 20:42:39 +02:00

196 lines
5.4 KiB
JavaScript

// player.js — Player character with stats
var TILE_HEIGHT_PLAYER = 32;
class Player {
constructor(x, y) {
this.x = x;
this.y = y;
this.tileX = 0;
this.tileY = 0;
this.speed = 2;
// Stats
this.name = 'Wanderer';
this.class = 'wanderer';
this.level = 1;
this.exp = 0;
this.expNeeded = 100;
this.maxHp = 100;
this.hp = 100;
this.maxSp = 50;
this.sp = 50;
this.str = 10;
this.agi = 10;
this.int = 10;
this.vit = 10;
this.dex = 10;
this.luk = 5;
this.atk = 15;
this.def = 5;
this.gold = 100;
// Movement
this.path = [];
this.targetX = null;
this.targetY = null;
this.moving = false;
// Combat
this.attackTarget = null;
this.attackRange = 1.5;
this.attackCooldown = 0;
this.attackSpeed = 30; // frames between attacks
// Visual
this.facing = 'down';
this.animFrame = 0;
this.animTimer = 0;
}
getScreenPos(map) {
const screen = map.tileToScreen(Math.floor(this.x), Math.floor(this.y));
return screen;
}
update(map) {
// Update tile position
this.tileX = Math.floor(this.x);
this.tileY = Math.floor(this.y);
// Movement along path
if (this.path.length > 0) {
const next = this.path[0];
const dx = next.x - this.x;
const dy = next.y - this.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 0.1) {
this.path.shift();
if (this.path.length === 0) {
this.moving = false;
}
} else {
this.x += (dx / dist) * this.speed * 0.1;
this.y += (dy / dist) * this.speed * 0.1;
if (Math.abs(dx) > Math.abs(dy)) {
this.facing = dx > 0 ? 'right' : 'left';
} else {
this.facing = dy > 0 ? 'down' : 'up';
}
}
}
// Animation
if (this.moving) {
this.animTimer++;
if (this.animTimer > 10) {
this.animTimer = 0;
this.animFrame = (this.animFrame + 1) % 4;
}
}
// Combat
if (this.attackCooldown > 0) this.attackCooldown--;
}
setPath(path) {
this.path = path;
this.moving = path.length > 0;
}
takeDamage(amount) {
this.hp -= amount;
if (this.hp < 0) this.hp = 0;
return this.hp <= 0;
}
heal(amount) {
this.hp = Math.min(this.maxHp, this.hp + amount);
}
gainExp(amount) {
this.exp += amount;
if (this.exp >= this.expNeeded) {
this.levelUp();
return true;
}
return false;
}
levelUp() {
this.exp -= this.expNeeded;
this.level++;
this.expNeeded = Math.floor(100 * Math.pow(this.level, 1.5));
this.maxHp += 20;
this.maxSp += 10;
this.hp = this.maxHp;
this.sp = this.maxSp;
this.str += 2;
this.agi += 2;
this.int += 1;
this.vit += 2;
this.dex += 1;
this.atk += 3;
this.def += 1;
}
render(ctx, map, camera) {
const screen = map.tileToScreen(this.x, this.y);
const drawX = screen.x - camera.x + 480;
const drawY = screen.y - camera.y + 320;
// Shadow
ctx.fillStyle = 'rgba(0,0,0,0.3)';
ctx.beginPath();
ctx.ellipse(drawX, drawY + TILE_HEIGHT_PLAYER/2 + 4, 12, 4, 0, 0, Math.PI * 2);
ctx.fill();
// Body (simple character)
const bobOffset = this.moving ? Math.sin(this.animFrame * Math.PI / 2) * 2 : 0;
// Legs
ctx.fillStyle = '#4a4a6a';
ctx.fillRect(drawX - 5, drawY + TILE_HEIGHT_PLAYER/2 - 8 + bobOffset, 4, 8);
ctx.fillRect(drawX + 1, drawY + TILE_HEIGHT_PLAYER/2 - 8 + bobOffset, 4, 8);
// Body
ctx.fillStyle = '#5566aa';
ctx.fillRect(drawX - 7, drawY + TILE_HEIGHT_PLAYER/2 - 18 + bobOffset, 14, 12);
// Head
ctx.fillStyle = '#e0b890';
ctx.beginPath();
ctx.arc(drawX, drawY + TILE_HEIGHT_PLAYER/2 - 22 + bobOffset, 7, 0, Math.PI * 2);
ctx.fill();
// Hair (black)
ctx.fillStyle = '#1a1a1a';
ctx.beginPath();
ctx.arc(drawX, drawY + TILE_HEIGHT_PLAYER/2 - 24 + bobOffset, 7, Math.PI, Math.PI * 2);
ctx.fill();
ctx.fillRect(drawX - 7, drawY + TILE_HEIGHT_PLAYER/2 - 22 + bobOffset, 14, 3);
// Name label
ctx.fillStyle = '#ffcc44';
ctx.font = '11px sans-serif';
ctx.textAlign = 'center';
ctx.fillText(this.name, drawX, drawY + TILE_HEIGHT_PLAYER/2 - 32);
// HP bar above character
const hpPercent = this.hp / this.maxHp;
const barWidth = 24;
const barX = drawX - barWidth / 2;
const barY = drawY + TILE_HEIGHT_PLAYER/2 - 38;
ctx.fillStyle = '#333';
ctx.fillRect(barX, barY, barWidth, 3);
ctx.fillStyle = hpPercent > 0.5 ? '#44dd44' : hpPercent > 0.25 ? '#ddaa44' : '#dd4444';
ctx.fillRect(barX, barY, barWidth * hpPercent, 3);
}
}