This commit is contained in:
vesta 2025-09-08 20:37:22 +02:00
parent 746f92557c
commit 7fdcba3f7b

View file

@ -14,31 +14,31 @@ document.addEventListener('DOMContentLoaded', () => {
SWAMP: { sprite:null, design: { frames: 4,duration: 300, drawer: drawSwampFrame}, acceptStructure:false, movements:['fly'],affinities:[('water',0.6),('earth',0.2),('dark',0.2)],name: 'Marais', winterColor: '#0b2e10ff', fallColor: '#0b2e10ff', summerColor: '#0b2e10ff', autumnColor: '#0b2e10ff',maxElevation:1,minElevation:1 } SWAMP: { sprite:null, design: { frames: 4,duration: 300, drawer: drawSwampFrame}, acceptStructure:false, movements:['fly'],affinities:[('water',0.6),('earth',0.2),('dark',0.2)],name: 'Marais', winterColor: '#0b2e10ff', fallColor: '#0b2e10ff', summerColor: '#0b2e10ff', autumnColor: '#0b2e10ff',maxElevation:1,minElevation:1 }
} }
const JOB = { const JOB = {
VILLAGER: { VILLAGER: {
name: "Habitant", name: "Habitant",
dialogues: [ dialogues: [
"Bien le bonjour, étranger.", "Bien le bonjour, étranger.",
"J'espère que la récolte sera bonne cette année.", "J'espère que la récolte sera bonne cette année.",
"Faites attention aux loups dans la forêt.", "Faites attention aux loups dans la forêt.",
"Le forgeron a de nouvelles marchandises, je crois." "Le forgeron a de nouvelles marchandises, je crois."
] ]
}, FARMER: { }, FARMER: {
name: "Fermier", name: "Fermier",
dialogues: [ dialogues: [
"Le temps est parfait pour les cultures.", "Le temps est parfait pour les cultures.",
"Ces sangliers n'arrêtent pas de saccager mes champs !", "Ces sangliers n'arrêtent pas de saccager mes champs !",
"Une bonne terre, c'est tout ce qui compte." "Une bonne terre, c'est tout ce qui compte."
] ]
}, },
BANDIT: { BANDIT: {
name: "Bandit", name: "Bandit",
dialogues: [ dialogues: [
"Qu'est-ce que tu regardes ?", "Qu'est-ce que tu regardes ?",
"Dégage d'ici avant que je me fâche.", "Dégage d'ici avant que je me fâche.",
"Ta bourse ou la vie !" "Ta bourse ou la vie !"
] ]
} }
}; };
const Affinities = ['water','fire','sand','rock','dark','life','ice','wood','wind','metal','time','space','lava','light','spirit']; const Affinities = ['water','fire','sand','rock','dark','life','ice','wood','wind','metal','time','space','lava','light','spirit'];
@ -103,9 +103,9 @@ document.addEventListener('DOMContentLoaded', () => {
}; };
const ANIMAL_TYPES = { const ANIMAL_TYPES = {
BIRD: { name: 'Oiseau', svgAsset: () => birdSVG, hp: 10, strength: 4, xp: 15, loot: { 'Cuir': 1, 'Os': 1 }, biomes: [Biome.FOREST, Biome.MOUNTAIN, Biome.SNOWMOUNTAIN], spawnChance: 0.01, size: { w: 40, h: 40 }, offset: { x: -20, y: -35 } }, WOLF: { name: 'Loup', movement: 'walk', svgAsset: () => wolfPackSVG, hp: 20, strength: 4, xp: 15, loot: { 'Cuir': 1, 'Os': 1 }, biomes: [Biome.FOREST, Biome.MOUNTAIN, Biome.SNOWLAND], spawnChance: 0.01, size: { w: 40, h: 40 }, offset: { x: -20, y: -35 } },
WOLF: { name: 'Loup', svgAsset: () => wolfPackSVG, hp: 20, strength: 4, xp: 15, loot: { 'Cuir': 1, 'Os': 1 }, biomes: [Biome.FOREST, Biome.MOUNTAIN, Biome.SNOWLAND], spawnChance: 0.01, size: { w: 40, h: 40 }, offset: { x: -20, y: -35 } }, BOAR: { name: 'Sanglier', movement: 'walk', svgAsset: () => boarSVG, hp: 25, strength: 5, xp: 20, loot: { 'Cuir': 2 }, biomes: [Biome.FOREST, Biome.GRASSLAND], spawnChance: 0.02, size: { w: 30, h: 30 }, offset: { x: -15, y: -28 } },
BOAR: { name: 'Sanglier', svgAsset: () => boarSVG, hp: 25, strength: 5, xp: 20, loot: { 'Cuir': 2 }, biomes: [Biome.FOREST, Biome.GRASSLAND], spawnChance: 0.02, size: { w: 30, h: 30 }, offset: { x: -15, y: -28 } }, BIRD: { name: 'Aigle', movement: 'fly', svgAsset: () => birdSVG, hp: 10, strength: 1, xp: 5, loot: { 'Plume': 1 }, biomes: [Biome.FOREST, Biome.GRASSLAND, Biome.MOUNTAIN, Biome.BEACH], spawnChance: 0.03, size: { w: 15, h: 12 }, offset: { x: -22, y: -45 }, flightHeight: 40 },
}; };
// --- Global Asset Variables --- // --- Global Asset Variables ---
@ -329,10 +329,12 @@ document.addEventListener('DOMContentLoaded', () => {
this.position = new Position(x, y); this.position = new Position(x, y);
this.biome = null; this.biome = null;
this.structure = null; this.structure = null;
this.animal = null;
this.visibility = 0; // 0: Unseen, 1: Seen, 2: Visible this.visibility = 0; // 0: Unseen, 1: Seen, 2: Visible
this.setBiome(); this.setBiome();
this.setElevation(); this.setElevation();
this.setStructure(); this.setStructure();
this.setEntity();
} }
setBiome() { setBiome() {
@ -428,6 +430,31 @@ document.addEventListener('DOMContentLoaded', () => {
this.structure=new structure(this.position); this.structure=new structure(this.position);
} }
} }
setEntity(){
// a changer!
if(this.structure) {
const structureType = this.structure.type;
let job = JOB.VILLAGER;
if(structureType === STRUCTURE_TYPE.FARM) job = JOB.FARMER;
if(structureType === STRUCTURE_TYPE.CAMP) job = JOB.BANDIT;
for(let i = 0; i < structureType.population; i++) {
this.npc.push(new Npc(job,new Creature(job.name,null,1,null,null,this.position,'HUMAN',null,10,null),this,null ));
}
}
else {
if (this.biome) {
for (const key in ANIMAL_TYPES) {
const animalType = ANIMAL_TYPES[key];
if (animalType.biomes.includes(this.biome) && Math.random() < animalType.spawnChance) {
if( this.biome.movements.includes(animalType.movement)) {
this.animal.push(new Animal(animalType, this.position));
}
}
}
}
}
}
} }
class Map { class Map {
constructor(size) { constructor(size) {
@ -499,7 +526,7 @@ document.addEventListener('DOMContentLoaded', () => {
} }
class Creature { class Creature {
constructor(name,attributes,level,affinities,alignments,tile,species,race,hp,items) { constructor(name,attributes,level,affinities,alignments,position,species,race,hp,items) {
this.name = name; this.name = name;
this.attributes = attributes; this.attributes = attributes;
this.level = level; this.level = level;
@ -508,7 +535,7 @@ document.addEventListener('DOMContentLoaded', () => {
this.alignments = alignments; this.alignments = alignments;
this.species = species; this.species = species;
this.race = race; this.race = race;
this.tile=tile; this.position=position;
this.items=items; this.items=items;
this.hp=hp; this.hp=hp;
} }
@ -598,16 +625,13 @@ document.addEventListener('DOMContentLoaded', () => {
this.creature=creature; this.creature=creature;
this.equipments=equipments; this.equipments=equipments;
} }
get position() {
return this.creature.tile.position;
}
setDesign(ctx) { setDesign(ctx) {
const tile = this.creature.tile const position = this.creature.position
if(!tile) return; if(!position) return;
const screenPos = tile.position.cartToIso(); const screenPos = position.cartToIso();
const elevationHeight = tile.position.h * ELEVATION_STEP; const elevationHeight = position.h * ELEVATION_STEP;
ctx.save(); ctx.save();
ctx.translate(screenPos.x, screenPos.y - elevationHeight); ctx.translate(screenPos.x, screenPos.y - elevationHeight);
@ -620,12 +644,12 @@ document.addEventListener('DOMContentLoaded', () => {
ctx.restore(); ctx.restore();
} }
move(dx, dy, gameMap) { move(dx, dy, gameMap) {
const newX = this.position.x + dx; const newX = this.creature.position.x + dx;
const newY = this.position.y + dy; const newY = this.creature.position.y + dy;
if (newX >= 0 && newX < gameMap.size && newY >= 0 && newY < gameMap.size) { if (newX >= 0 && newX < gameMap.size && newY >= 0 && newY < gameMap.size) {
const targetTile = gameMap.tiles[newY][newX]; const targetTile = gameMap.tiles[newY][newX].position;
if (targetTile.biome && targetTile.biome.movements.includes('walk')) { if (targetTile.biome && targetTile.biome.movements.includes('walk')) {
this.creature.tile = targetTile; this.creature.position = targetTile;
} }
} }
} }
@ -637,48 +661,9 @@ document.addEventListener('DOMContentLoaded', () => {
this.map = new Map(200); this.map = new Map(200);
this.currentTime=new Time(); this.currentTime=new Time();
this.animals = []; this.animals = [];
this.npcs = []; this.npcs = [];
this.spawnEntities();
} }
spawnEntities() {
console.time('Entity Spawning');
for (let y = 0; y < this.map.size; y++) {
for (let x = 0; x < this.map.size; x++) {
const tile = this.map.tiles[y][x];
// Spawn NPCs in structures
if(tile.structure) {
const structureType = tile.structure.type;
let job = JOB.VILLAGER;
if(structureType === STRUCTURE_TYPE.FARM) job = JOB.FARMER;
if(structureType === STRUCTURE_TYPE.CAMP) job = JOB.BANDIT;
for(let i = 0; i < structureType.population; i++) {
this.npcs.push(new Npc(job,new Creature(job.name,null,1,null,null,tile,'HUMAN',null,10,null),tile,null ));
}
}
// Spawn Animals
if (tile.biome) {
for (const key in ANIMAL_TYPES) {
const animalType = ANIMAL_TYPES[key];
if (animalType.biomes.includes(tile.biome) && Math.random() < animalType.spawnChance) {
if(animalType.movementClass === 'ground' && tile.biome.movements.includes('walk')) {
this.animals.push(new Animal(animalType, tile));
} else if (animalType.movementClass === 'fly') {
this.animals.push(new Animal(animalType, tile));
}
}
}
}
}
}
console.log(`Spawned ${this.animals.length} animals and ${this.npcs.length} NPCs.`);
console.timeEnd('Entity Spawning');
}
} }
class Camera { class Camera {
constructor(x=0,y=0,canvas) { constructor(x=0,y=0,canvas) {
@ -712,11 +697,11 @@ document.addEventListener('DOMContentLoaded', () => {
update(currentTime) { update(currentTime) {
this.handleMovement(currentTime); this.handleMovement(currentTime);
this.updateVisibility(); this.updateVisibility();
// a changer!
this.world.animals.forEach(animal => animal.update(currentTime, this.world.map)); this.world.animals.forEach(animal => animal.update(currentTime, this.world.map));
this.world.npcs.forEach(npc => npc.update(currentTime, this.world.map)); this.world.npcs.forEach(npc => npc.update(currentTime, this.world.map));
this.camera.setCamera(this.player.position); this.camera.setCamera(this.player.creature.position);
// Update all biome sprites // Update all biome sprites
for (const key in Biome) { for (const key in Biome) {
@ -730,8 +715,8 @@ document.addEventListener('DOMContentLoaded', () => {
updateVisibility() { updateVisibility() {
const map = this.world.map; const map = this.world.map;
const px = this.player.position.x; const px = this.player.creature.position.x;
const py = this.player.position.y; const py = this.player.creature.position.y;
const radius = VISION_RADIUS; const radius = VISION_RADIUS;
const radiusSq = radius * radius; const radiusSq = radius * radius;
@ -763,7 +748,7 @@ document.addEventListener('DOMContentLoaded', () => {
spawnX = Math.floor(Math.random() * this.world.map.size); spawnX = Math.floor(Math.random() * this.world.map.size);
spawnY = Math.floor(Math.random() * this.world.map.size); spawnY = Math.floor(Math.random() * this.world.map.size);
} while (!this.world.map.tiles[spawnY][spawnX].biome || !this.world.map.tiles[spawnY][spawnX].biome.movements.includes('walk') ); } while (!this.world.map.tiles[spawnY][spawnX].biome || !this.world.map.tiles[spawnY][spawnX].biome.movements.includes('walk') );
this.player = new Player(new Creature('player',new Attributes(RACE.HUMAN),1,null,null,this.world.map.tiles[spawnY][spawnX],'human',RACE.HUMAN,10,null),); this.player = new Player(new Creature('player',new Attributes(RACE.HUMAN),1,null,null,this.world.map.tiles[spawnY][spawnX].position,'human',RACE.HUMAN,10,null),);
this.updateVisibility(); this.updateVisibility();
} }
setControls() { setControls() {
@ -849,40 +834,40 @@ document.addEventListener('DOMContentLoaded', () => {
if (controls.right) { this.player.move(1, 0,this.world.map); moved = true; } if (controls.right) { this.player.move(1, 0,this.world.map); moved = true; }
if(moved) lastMoveTime = currentTime; if(moved) lastMoveTime = currentTime;
} }
handleInteraction() { handleInteraction() {
if (!controls.interact) return; if (!controls.interact) return;
controls.interact = false; // Consume the action controls.interact = false; // Consume the action
const px = this.player.position.x; const px = this.player.creature.position.x;
const py = this.player.position.y; const py = this.player.creature.position.y;
let targetNpc = null; let targetNpc = null;
for (const npc of this.world.npcs) { for (const npc of this.world.npcs) {
const dx = Math.abs(npc.tile.position.x - px); const dx = Math.abs(npc.tile.position.x - px);
const dy = Math.abs(npc.tile.position.y - py); const dy = Math.abs(npc.tile.position.y - py);
if (dx <= 1 && dy <= 1) { // Check adjacent tiles if (dx <= 1 && dy <= 1) { // Check adjacent tiles
targetNpc = npc; targetNpc = npc;
break; break;
}
} }
}
if(targetNpc) { if(targetNpc) {
const dialogueData = targetNpc.interact(); const dialogueData = targetNpc.interact();
this.showDialogue(dialogueData.name, dialogueData.text); this.showDialogue(dialogueData.name, dialogueData.text);
} }
} }
showDialogue(name, text) { showDialogue(name, text) {
const dialogueBox = document.getElementById('dialogue-box'); const dialogueBox = document.getElementById('dialogue-box');
document.getElementById('dialogue-name').textContent = name; document.getElementById('dialogue-name').textContent = name;
document.getElementById('dialogue-text').textContent = text; document.getElementById('dialogue-text').textContent = text;
dialogueBox.classList.remove('hidden'); dialogueBox.classList.remove('hidden');
this.isDialogueActive = true; this.isDialogueActive = true;
} }
hideDialogue() { hideDialogue() {
document.getElementById('dialogue-box').classList.add('hidden'); document.getElementById('dialogue-box').classList.add('hidden');
this.isDialogueActive = false; this.isDialogueActive = false;
} }
} }
@ -1067,12 +1052,12 @@ document.addEventListener('DOMContentLoaded', () => {
if (Biome[key].design) { Biome[key].sprite = new Sprite(Biome[key]);} if (Biome[key].design) { Biome[key].sprite = new Sprite(Biome[key]);}
} }
const assetIds = ['forest-svg', 'village-svg', 'city-svg', 'player-svg', 'enchanted-forest-svg', 'swamp-svg', 'wolf-pack-svg', 'boar-svg', 'bird-svg', 'farm-svg', 'camp-svg', 'npc-svg','house-svg','cult-svg','market-svg','mine-svg']; const assetIds = ['forest-svg', 'village-svg', 'city-svg', 'player-svg', 'enchanted-forest-svg', 'swamp-svg', 'wolf-pack-svg', 'boar-svg', 'bird-svg', 'farm-svg', 'camp-svg', 'npc-svg','house-svg','cult-svg','market-svg','mine-svg'];
const assetElements = assetIds.map(id => document.getElementById(id)); const assetElements = assetIds.map(id => document.getElementById(id));
[forestSVG, villageSVG, citySVG, playerSVG, enchantedForestSVG, swampSVG, wolfPackSVG, boarSVG, birdSVG, farmSVG, campSVG, npcSVG,houseSVG,cultSVG,marketSVG,mineSVG] = await Promise.all( [forestSVG, villageSVG, citySVG, playerSVG, enchantedForestSVG, swampSVG, wolfPackSVG, boarSVG, birdSVG, farmSVG, campSVG, npcSVG,houseSVG,cultSVG,marketSVG,mineSVG] = await Promise.all(
assetElements.map(el => loadSvgAsImage(el)) assetElements.map(el => loadSvgAsImage(el))
); );
console.log("All assets loaded."); console.log("All assets loaded.");