version movement

This commit is contained in:
vesta 2025-08-30 11:45:03 +02:00
parent 5dcb18fe66
commit 1489f28899

View file

@ -6,9 +6,9 @@ document.addEventListener('DOMContentLoaded', () => {
GRASSLAND: { acceptStructure:true, movements:['walk','ride','fly'],affinities:[('life',0.6),('earth',0.2)],name: 'Plaine', winterColor: '#ecf1e3ff', fallColor: '#98C159', summerColor: '#a5a450ff', autumnColor: '#455e21ff',maxElevation:3,minElevation:2 }, GRASSLAND: { acceptStructure:true, movements:['walk','ride','fly'],affinities:[('life',0.6),('earth',0.2)],name: 'Plaine', winterColor: '#ecf1e3ff', fallColor: '#98C159', summerColor: '#a5a450ff', autumnColor: '#455e21ff',maxElevation:3,minElevation:2 },
FOREST: { acceptStructure:true,movements:['walk','ride','fly'],affinities:[('wood',0.6),('earth',0.4)], name: 'Forêt', winterColor: '#92ac83ff', fallColor: '#21a32cff', summerColor: '#6A994E', autumnColor: '#b88a28ff',maxElevation:3,minElevation:2 }, FOREST: { acceptStructure:true,movements:['walk','ride','fly'],affinities:[('wood',0.6),('earth',0.4)], name: 'Forêt', winterColor: '#92ac83ff', fallColor: '#21a32cff', summerColor: '#6A994E', autumnColor: '#b88a28ff',maxElevation:3,minElevation:2 },
ENCHANTED_FOREST: { acceptStructure:true,movements:['walk','ride','fly'],affinities:[('wood',0.8),('dark',0.2),('life',0.2)], name: 'Forêt Enchantée', winterColor: '#7B6094', fallColor: '#7B6094', summerColor: '#7B6094', autumnColor: '#7B6094',maxElevation:3,minElevation:2 }, ENCHANTED_FOREST: { acceptStructure:true,movements:['walk','ride','fly'],affinities:[('wood',0.8),('dark',0.2),('life',0.2)], name: 'Forêt Enchantée', winterColor: '#7B6094', fallColor: '#7B6094', summerColor: '#7B6094', autumnColor: '#7B6094',maxElevation:3,minElevation:2 },
MOUNTAIN: { acceptStructure:false, movements:['climb','fly'],affinities:[('rock',0.6),('wind',0.4)],name: 'Montagne', winterColor: '#F7F7F7', fallColor: '#A9A9A9', summerColor: '#A9A9A9', autumnColor: '#A9A9A9',maxElevation:4,minElevation:3 }, MOUNTAIN: { acceptStructure:false, movements:['climb','fly'],affinities:[('rock',0.6),('wind',0.4)],name: 'Montagne', winterColor: '#F7F7F7', fallColor: '#A9A9A9', summerColor: '#A9A9A9', autumnColor: '#A9A9A9',maxElevation:5,minElevation:3 },
SNOWLAND: { acceptStructure:true,movements:['walk','ride','fly'], affinities:[('ice',0.8),('earth',0.2)],name: 'Toundra', winterColor: '#F7F7F7', fallColor: '#F7F7F7', summerColor: '#F7F7F7', autumnColor: '#F7F7F7',maxElevation:2,minElevation:2 }, SNOWLAND: { acceptStructure:true,movements:['walk','ride','fly'], affinities:[('ice',0.8),('earth',0.2)],name: 'Toundra', winterColor: '#F7F7F7', fallColor: '#F7F7F7', summerColor: '#F7F7F7', autumnColor: '#F7F7F7',maxElevation:2,minElevation:2 },
SNOWMOUNTAIN: { acceptStructure:false, movements:['climb','fly'],affinities:[('ice',0.4),('rock',0.4),('wind',0.2)],name: 'Mont enneigé', winterColor: '#F7F7F7', fallColor: '#F7F7F7', summerColor: '#F7F7F7', autumnColor: '#F7F7F7',maxElevation:4,minElevation:3 }, SNOWMOUNTAIN: { acceptStructure:false, movements:['climb','fly'],affinities:[('ice',0.4),('rock',0.4),('wind',0.2)],name: 'Mont enneigé', winterColor: '#F7F7F7', fallColor: '#F7F7F7', summerColor: '#F7F7F7', autumnColor: '#F7F7F7',maxElevation:8,minElevation:4 },
DESERT: { acceptStructure:true,movements:['walk','ride','fly'],affinities:[('sand',0.8),('life',0.1),('fire',0.1)], name: 'Désert', winterColor: '#D4A373', fallColor: '#D4A373', summerColor: '#D4A373', autumnColor: '#D4A373',maxElevation:2,minElevation:2 }, DESERT: { acceptStructure:true,movements:['walk','ride','fly'],affinities:[('sand',0.8),('life',0.1),('fire',0.1)], name: 'Désert', winterColor: '#D4A373', fallColor: '#D4A373', summerColor: '#D4A373', autumnColor: '#D4A373',maxElevation:2,minElevation:2 },
RIVER: { acceptStructure:false,movements:['navigate','swim','fly'],affinities:[('water',0.6),('earth',0.2),('life',0.2)],name: 'Rivière', winterColor: '#97aabdff', fallColor: '#5A8AB8', summerColor: '#5A8AB8', autumnColor: '#5A8AB8',maxElevation:2,minElevation:2 }, RIVER: { acceptStructure:false,movements:['navigate','swim','fly'],affinities:[('water',0.6),('earth',0.2),('life',0.2)],name: 'Rivière', winterColor: '#97aabdff', fallColor: '#5A8AB8', summerColor: '#5A8AB8', autumnColor: '#5A8AB8',maxElevation:2,minElevation:2 },
SWAMP: { 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: { 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 }
@ -107,29 +107,26 @@ document.addEventListener('DOMContentLoaded', () => {
class Tile { class Tile {
constructor(position) { constructor(x, y) {
this.position = position; this.position = new Position(x, y);
this.biome = null; this.biome = null;
this.structure = null; this.structure = null;
this.explored = false;
this.design=null;
this.setBiome(); this.setBiome();
this.setElevation(); this.setElevation();
this.setStructure(); this.setStructure();
this.setDesign(); //this.setDesign(ctx);
} }
// Méthode de l'objet // Méthode de l'objet
setBiome() { setBiome() {
let scale = 0.05; let scale = 0.05;
let simplex = new SimplexNoise();
let eRaw = (simplex.noise2D(this.position.x * scale, this.position.y * scale) + 1) / 2; let eRaw = (simplex.noise2D(this.position.x * scale, this.position.y * scale) + 1) / 2;
let tRaw = (simplex.noise2D(this.position.x * scale * 0.8, this.position.y * scale * 0.8) + 1) / 2; let tRaw = (simplex.noise2D(this.position.x * scale * 0.8, this.position.y * scale * 0.8) + 1) / 2;
let mRaw = (simplex.noise2D(this.position.x * scale * 1.5, this.position.y * scale * 1.5) + 1) / 2; let mRaw = (simplex.noise2D(this.position.x * scale * 1.5, this.position.y * scale * 1.5) + 1) / 2;
if (eRaw < 0.25) this.biome = Biome.WATER_DEEP; if (eRaw < 0.25) this.biome = Biome.WATER_DEEP;
else if (eRaw < 0.3) this.biome = Biome.WATER_SHALLOW; else if (eRaw < 0.3) this.biome = Biome.WATER_SHALLOW;
else if (eRaw < 0.35) this.biome = Biome.BEACH; else if (eRaw < 0.35) this.biome = Biome.BEACH;
else if (eRaw > 0.85) this.biome = Biome.SNOWLAND; else if (eRaw > 0.85) this.biome = Biome.SNOWMOUNTAIN;
else if (eRaw > 0.75) this.biome = Biome.MOUNTAIN; else if (eRaw > 0.75) this.biome = Biome.MOUNTAIN;
else { else {
if (tRaw < 0.3) this.biome = Biome.DESERT; if (tRaw < 0.3) this.biome = Biome.DESERT;
@ -137,7 +134,7 @@ document.addEventListener('DOMContentLoaded', () => {
else this.biome = Biome.GRASSLAND; else this.biome = Biome.GRASSLAND;
} }
} }
setDesign(){ setDesign(ctx){
if (!this.biome) return; if (!this.biome) return;
const screenPos = this.position.cartToIso(); const screenPos = this.position.cartToIso();
const elevationHeight = this.position.h * 8; const elevationHeight = this.position.h * 8;
@ -219,7 +216,8 @@ document.addEventListener('DOMContentLoaded', () => {
initializeMap(){ initializeMap(){
console.time('Map Generation'); console.time('Map Generation');
this.tiles=Array(this.size).fill(null).map((_, y) => Array(this.size).fill(null).map((_, x) => new Tile(new Position(y, x)))); this.tiles = Array(this.size).fill(null).map((_, y) => Array(this.size).fill(null).map((_, x) => new Tile(x, y)));
console.timeEnd('Map Generation');
} }
} }
class Time { class Time {
@ -229,11 +227,13 @@ document.addEventListener('DOMContentLoaded', () => {
this.day = 13; this.day = 13;
this.season = 'winter'; this.season = 'winter';
this.hour = 12; this.hour = 12;
this.day = true; this.daylight = true;
this.minute=2
} }
tick(){ tick(){
this.hour=(this.hour+1) % 24 this.minute=(this.minute+1) % 60
if (this.minute==1) this.hour=(this.hour+1) % 24
if (this.hour==1) this.day=(this.day+1) % 30 if (this.hour==1) this.day=(this.day+1) % 30
if (this.day==1) {this.month=(this.month+1) % 12;} if (this.day==1) {this.month=(this.month+1) % 12;}
if (this.month==1) {this.year=(this.year+1); } if (this.month==1) {this.year=(this.year+1); }
@ -248,6 +248,27 @@ document.addEventListener('DOMContentLoaded', () => {
this.tick(); this.tick();
} }
} }
setDesign(){
let overlayColor = 'rgba(0,0,0,0)';
let opacity = 0;
if (this.hour > 20 || this.hour < 6) { // Nuit (20h -> 6h)
overlayColor = '#000033';
opacity = 0.5;
} else if (this.hour > 18) { // Soir (18h -> 20h)
overlayColor = '#FF8C00';
opacity = 0.3 * ( ((this.hour/24) - 0.75) / 0.08 );
} else if (this.hour < 8) { // Matin (6h -> 8h)
overlayColor = '#FFD700';
opacity = 0.3 * ( (0.33 - (this.hour/24) ) / 0.08 );
}
ctx.fillStyle = overlayColor;
ctx.globalAlpha = opacity;
document.getElementById('time-display').textContent = `Jour ${this.day}, ${this.hour}:${this.minute}`;
document.getElementById('season-display').textContent = this.season;
}
// Méthode de l'objet // Méthode de l'objet
} }
@ -313,9 +334,11 @@ document.addEventListener('DOMContentLoaded', () => {
this.creature=creature; this.creature=creature;
this.equipments=equipments; this.equipments=equipments;
this.color = '#E53E3E'; this.color = '#E53E3E';
this.position=creature.tile.position
} }
draw(ctx) { get position() {
return this.creature.tile.position;
}
setDesign(ctx) {
const tile = this.creature.tile const tile = this.creature.tile
if(!tile) return; if(!tile) return;
@ -324,28 +347,18 @@ document.addEventListener('DOMContentLoaded', () => {
ctx.save(); ctx.save();
ctx.translate(screenPos.x, screenPos.y - elevationHeight); ctx.translate(screenPos.x, screenPos.y - elevationHeight);
ctx.fillStyle = 'rgba(0, 0, 0, 0.4)'; ctx.fillStyle = 'rgba(0, 0, 0, 0.4)'; ctx.beginPath(); ctx.ellipse(0, TILE_HEIGHT / 2 + 2, 6, 3, 0, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(0, TILE_HEIGHT / 2 - 6, 8, 0, Math.PI * 2); ctx.fill();
ctx.ellipse(0, 16 + 2, 6, 3, 0, 0, Math.PI * 2); ctx.strokeStyle = shadeColor(this.color, -30); ctx.lineWidth = 2; ctx.stroke();
ctx.fill();
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(0, 16 - 6, 8, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = shadeColor(this.color, -30);
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore(); ctx.restore();
} }
move(dx, dy) { move(dx, dy, gameMap) {
const newX = this.position.x + dx; const newX = this.position.x + dx;
const newY = this.position.y + dy; const newY = this.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];
if (targetTile.biome && targetTile.biome.movements.includes('walk')) { if (targetTile.biome && targetTile.biome.movements.includes('walk')) {
this.position.x = newX; this.creature.tile = targetTile;
this.position.y = newY;
centerCameraOnPlayer(this.position);
} }
} }
} }
@ -462,14 +475,97 @@ document.addEventListener('DOMContentLoaded', () => {
spawnY = Math.floor(Math.random() * this.map.size); spawnY = Math.floor(Math.random() * this.map.size);
} while (!this.map.tiles[spawnY][spawnX].biome || !this.map.tiles[spawnY][spawnX].biome.movements.includes('walk') ); } while (!this.map.tiles[spawnY][spawnX].biome || !this.map.tiles[spawnY][spawnX].biome.movements.includes('walk') );
this.player = new Player(new Creature('player',new Attributes(RACE.HUMAN),1,null,null,this.map.tiles[spawnY][spawnX],'human',RACE.HUMAN,10,null),null); this.player = new Player(new Creature('player',new Attributes(RACE.HUMAN),1,null,null,this.map.tiles[spawnY][spawnX],'human',RACE.HUMAN,10,null),null);
centerCameraOnPlayer(this.player.position); this.currentTime=new Time();
} }
// Méthode de l'objet // Méthode de l'objet
save() { save() {
// delete after x Tick
} }
} }
class Camera {
constructor(x=0,y=0,canvas) {
this.x=x;
this.y=y;
this.canvas = canvas;
}
// Méthode de l'objet
setCamera(position) {
var target = position.cartToIso();
var perspective = position.h * ELEVATION_STEP;
this.x = this.canvas.width / 2 - target.x;
this.y = this.canvas.height / 2 - (target.y - perspective);
}
}
class Session {
constructor() {
this.world = new World('Defiance');
this.camera = new Camera(0,0, canvas);
this.setControls();
this.loop = this.loop.bind(this);
}
// Méthode de l'objet
loop(currentTime) {
this.handleMovement(currentTime);
this.camera.setCamera(this.world.player.position);
this.setDesign();
requestAnimationFrame(this.loop);
}
setControls() {
document.addEventListener('keydown', e => {
const key = e.key.toLowerCase();
if (key.startsWith('arrow')) { controls[key.replace('arrow', '')] = true; }
else if (['w', 'z'].includes(key)) { controls.up = true; }
else if (['s'].includes(key)) { controls.down = true; }
else if (['a', 'q'].includes(key)) { controls.left = true; }
else if (['d'].includes(key)) { controls.right = true; }
});
document.addEventListener('keyup', e => {
const key = e.key.toLowerCase();
if (key.startsWith('arrow')) { controls[key.replace('arrow', '')] = false; }
else if (['w', 'z'].includes(key)) { controls.up = false; }
else if (['s'].includes(key)) { controls.down = false; }
else if (['a', 'q'].includes(key)) { controls.left = false; }
else if (['d'].includes(key)) { controls.right = false; }
});
const controlMap = { 'btn-up': 'up', 'btn-down': 'down', 'btn-left': 'left', 'btn-right': 'right' };
for (const [id, dir] of Object.entries(controlMap)) {
const btn = document.getElementById(id);
btn.addEventListener('touchstart', e => { e.preventDefault(); controls[dir] = true; }, { passive: false });
btn.addEventListener('touchend', e => { e.preventDefault(); controls[dir] = false; });
}
}
setDesign(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(this.camera.x, this.camera.y);
for (let y = 0; y < this.world.map.size; y++) for (let x = 0; x < this.world.map.size; x++) this.world.map.tiles[y][x].setDesign(ctx);
this.world.player.setDesign(ctx);
this.world.currentTime.setDesign(ctx);
ctx.fillRect(this.camera.x * -1, this.camera.y * -1, canvas.width, canvas.height);
ctx.globalAlpha = 1.0;
//drawFloatingTexts();
ctx.restore();
this.world.currentTime.tick();
}
handleMovement(currentTime) {
if (currentTime - lastMoveTime < 150) return;
let moved = false;
if (controls.up) { this.world.player.move(0, -1,this.world.map); moved = true; }
if (controls.down) { this.world.player.move(0, 1,this.world.map); moved = true; }
if (controls.left) { this.world.player.move(-1, 0,this.world.map); moved = true; }
if (controls.right) { this.world.player.move(1, 0,this.world.map); moved = true; }
if(moved) lastMoveTime = currentTime;
}
}
const controls = { up: false, down: false, left: false, right: false }; const controls = { up: false, down: false, left: false, right: false };
const simplex = new SimplexNoise(); const simplex = new SimplexNoise();
@ -488,54 +584,8 @@ document.addEventListener('DOMContentLoaded', () => {
return () => { s = (s * 9301 + 49297) % 233280; return s / 233280.0; }; return () => { s = (s * 9301 + 49297) % 233280; return s / 233280.0; };
} }
function centerCameraOnPlayer(position) {
const camera = { x: 0, y: 0 };
const playerScreenPos = position.cartToIso();
const elevationHeight = position.h * ELEVATION_STEP;
camera.x = canvas.width / 2 - playerScreenPos.x;
camera.y = canvas.height / 2 - (playerScreenPos.y - elevationHeight);
}
function handleMovement(player,currentTime) {
if (currentTime - lastMoveTime < 150) return;
let moved = false;
if (controls.up) { player.move(0, -1); moved = true; }
if (controls.down) { player.move(0, 1); moved = true; }
if (controls.left) { player.move(-1, 0); moved = true; }
if (controls.right) { player.move(1, 0); moved = true; }
if(moved) lastMoveTime = currentTime;
}
function gameLoop(world,currentTime) {
handleMovement(world.player,currentTime);
//draw(currentTime);
requestAnimationFrame(gameLoop);
}
function setupControls() {
document.addEventListener('keydown', e => {
const key = e.key.toLowerCase();
if (key.startsWith('arrow')) { controls[key.replace('arrow', '')] = true; }
else if (['w', 'z'].includes(key)) { controls.up = true; }
else if (['s'].includes(key)) { controls.down = true; }
else if (['a', 'q'].includes(key)) { controls.left = true; }
else if (['d'].includes(key)) { controls.right = true; }
});
document.addEventListener('keyup', e => {
const key = e.key.toLowerCase();
if (key.startsWith('arrow')) { controls[key.replace('arrow', '')] = false; }
else if (['w', 'z'].includes(key)) { controls.up = false; }
else if (['s'].includes(key)) { controls.down = false; }
else if (['a', 'q'].includes(key)) { controls.left = false; }
else if (['d'].includes(key)) { controls.right = false; }
});
const controlMap = { 'btn-up': 'up', 'btn-down': 'down', 'btn-left': 'left', 'btn-right': 'right' };
for (const [id, dir] of Object.entries(controlMap)) {
const btn = document.getElementById(id);
btn.addEventListener('touchstart', e => { e.preventDefault(); controls[dir] = true; }, { passive: false });
btn.addEventListener('touchend', e => { e.preventDefault(); controls[dir] = false; });
}
}
function shadeColor(c, p) { function shadeColor(c, p) {
let R=parseInt(c.substring(1,3),16),G=parseInt(c.substring(3,5),16),B=parseInt(c.substring(5,7),16);R=parseInt(R*(100+p)/100);G=parseInt(G*(100+p)/100);B=parseInt(B*(100+p)/100);R=(R<255)?R:255;G=(G<255)?G:255;B=(B<255)?B:255; let R=parseInt(c.substring(1,3),16),G=parseInt(c.substring(3,5),16),B=parseInt(c.substring(5,7),16);R=parseInt(R*(100+p)/100);G=parseInt(G*(100+p)/100);B=parseInt(B*(100+p)/100);R=(R<255)?R:255;G=(G<255)?G:255;B=(B<255)?B:255;
return "#"+("0"+R.toString(16)).slice(-2)+("0"+G.toString(16)).slice(-2)+("0"+B.toString(16)).slice(-2); return "#"+("0"+R.toString(16)).slice(-2)+("0"+G.toString(16)).slice(-2)+("0"+B.toString(16)).slice(-2);
@ -545,12 +595,10 @@ document.addEventListener('DOMContentLoaded', () => {
function initializeGame() { function initializeGame() {
canvas.width = canvas.parentElement.clientWidth; canvas.width = canvas.parentElement.clientWidth;
canvas.height = canvas.parentElement.clientHeight; canvas.height = canvas.parentElement.clientHeight;
setupControls(); let session=new Session();
let world=new World('1sttest');
isGameReady = true; isGameReady = true;
centerCameraOnPlayer(world.player.position)
loadingScreen.style.display = 'none'; loadingScreen.style.display = 'none';
gameLoop(world); session.loop();
} }
initializeGame(); initializeGame();
}) })