diff --git a/js/script.js b/js/script.js index 2c3843c..7056cb3 100644 --- a/js/script.js +++ b/js/script.js @@ -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 }, 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 }, - 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 }, - 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 }, 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 } @@ -107,29 +107,26 @@ document.addEventListener('DOMContentLoaded', () => { class Tile { - constructor(position) { - this.position = position; + constructor(x, y) { + this.position = new Position(x, y); this.biome = null; this.structure = null; - this.explored = false; - this.design=null; this.setBiome(); this.setElevation(); this.setStructure(); - this.setDesign(); + //this.setDesign(ctx); } // Méthode de l'objet setBiome() { let scale = 0.05; - let simplex = new SimplexNoise(); 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 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; else if (eRaw < 0.3) this.biome = Biome.WATER_SHALLOW; 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 (tRaw < 0.3) this.biome = Biome.DESERT; @@ -137,7 +134,7 @@ document.addEventListener('DOMContentLoaded', () => { else this.biome = Biome.GRASSLAND; } } - setDesign(){ + setDesign(ctx){ if (!this.biome) return; const screenPos = this.position.cartToIso(); const elevationHeight = this.position.h * 8; @@ -219,7 +216,8 @@ document.addEventListener('DOMContentLoaded', () => { initializeMap(){ 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 { @@ -229,11 +227,13 @@ document.addEventListener('DOMContentLoaded', () => { this.day = 13; this.season = 'winter'; this.hour = 12; - this.day = true; + this.daylight = true; + this.minute=2 } 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.day==1) {this.month=(this.month+1) % 12;} if (this.month==1) {this.year=(this.year+1); } @@ -248,6 +248,27 @@ document.addEventListener('DOMContentLoaded', () => { 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 } @@ -312,10 +333,12 @@ document.addEventListener('DOMContentLoaded', () => { constructor(creature,equipments) { this.creature=creature; this.equipments=equipments; - this.color = '#E53E3E'; - this.position=creature.tile.position + this.color = '#E53E3E'; } - draw(ctx) { + get position() { + return this.creature.tile.position; + } + setDesign(ctx) { const tile = this.creature.tile if(!tile) return; @@ -324,28 +347,18 @@ document.addEventListener('DOMContentLoaded', () => { ctx.save(); ctx.translate(screenPos.x, screenPos.y - elevationHeight); - ctx.fillStyle = 'rgba(0, 0, 0, 0.4)'; - ctx.beginPath(); - ctx.ellipse(0, 16 + 2, 6, 3, 0, 0, Math.PI * 2); - 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.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.fillStyle = this.color; ctx.beginPath(); ctx.arc(0, TILE_HEIGHT / 2 - 6, 8, 0, Math.PI * 2); ctx.fill(); + ctx.strokeStyle = shadeColor(this.color, -30); ctx.lineWidth = 2; ctx.stroke(); ctx.restore(); } - move(dx, dy) { + move(dx, dy, gameMap) { const newX = this.position.x + dx; const newY = this.position.y + dy; if (newX >= 0 && newX < gameMap.size && newY >= 0 && newY < gameMap.size) { const targetTile = gameMap.tiles[newY][newX]; if (targetTile.biome && targetTile.biome.movements.includes('walk')) { - this.position.x = newX; - this.position.y = newY; - centerCameraOnPlayer(this.position); + this.creature.tile = targetTile; } } } @@ -462,14 +475,97 @@ document.addEventListener('DOMContentLoaded', () => { spawnY = Math.floor(Math.random() * this.map.size); } 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); - centerCameraOnPlayer(this.player.position); + this.currentTime=new Time(); } // Méthode de l'objet 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 simplex = new SimplexNoise(); @@ -488,54 +584,8 @@ document.addEventListener('DOMContentLoaded', () => { 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) { 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); @@ -545,12 +595,10 @@ document.addEventListener('DOMContentLoaded', () => { function initializeGame() { canvas.width = canvas.parentElement.clientWidth; canvas.height = canvas.parentElement.clientHeight; - setupControls(); - let world=new World('1sttest'); + let session=new Session(); isGameReady = true; - centerCameraOnPlayer(world.player.position) loadingScreen.style.display = 'none'; - gameLoop(world); + session.loop(); } initializeGame(); }) \ No newline at end of file