Zdravím, podařilo se mi naprogramovat docela dobrý raycaster v JavaScriptu. Vzhled kódu jsem tak neřešil, takže se omlouvám předem za to, že to vypadá jak od 10 letého děcka Je to můj první raycaster a rozhodně ho vylepším a kód zkrátím. Problémem je ale fish-eye efekt, s kterým si absolutně nevím rady, jak opravit.Pokud někdo bude vědět, tak předem moc díky.Kód:var c = document.getElementById("board");var ctx = c.getContext("2d");window.addEventListener("keydown", control);window.addEventListener("keyup", controlUp);var w = c.clientWidth, h = c.clientHeight;var playerX = w/2;var playerY = h/2;var playerAngle = Math.PI*0.5 + 0.000001;var playerGo = false;var playerTurn = false;var time = 0;var mapS = 80;var vision = [];var rays = [];function ray(a){ rays.push({ x: playerX, y: playerY, run: true, x2: playerX, y2: playerY, run2: true, offsetX: w/2, offsetY: h/2, angle: playerAngle + a, diffX: 0, diffY: 0, diff: 0, diffX2: 0, diffY2: 0, diff2: 0, })}function vis(x){ vision.push({ x: x, y: 0, sx: w/rays.length, sy: 0, })}var map = [ 1,1,1,1,1,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,1,0,1, 1,0,0,1,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,1,0,0,0,0,0,1, 1,0,0,0,0,1,0,0,0,1, 1,1,1,1,1,1,1,1,1,1,]for… (i = 0, a = -0.7; i < 100; i++, a += 0.7/50){ ray(a);}for (i = 0; i < w; i += w/rays.length){ vis(i);}function draw(){ ctx.clearRect(0, 0, w, h); time++; for (i = 0, j = 0, c = 0; c < map.length; i += mapS, c++){ if (i > w - mapS){ i = 0; j += mapS; } if (map[c] == 3){ ctx.fillStyle = "#1F6BC7"; } if (map[c] == 2){ ctx.fillStyle = "red"; } if (map[c] == 1){ ctx.fillStyle = "white"; } if (map[c] == 0){ ctx.fillStyle = "black"; } /*ctx.fillRect(i, j, mapS, mapS); ctx.lineWidth = 1; ctx.strokeStyle = "gray"; ctx.strokeRect(i, j, mapS, mapS);*/ for (r = 0; r < rays.length; r++){ if ((((rays[r].y == j || rays[r].y == j+mapS) && rays[r].x >= i && rays[r].x <= i+mapS) || ((rays[r].x == i || rays[r].x == i+mapS) && rays[r].y >= j && rays[r].y <= j+mapS)) && map[c] != 0){ rays[r].run = false; } if ((((rays[r].y2 == j || rays[r].y2 == j+mapS) && rays[r].x2 >= i && rays[r].x2 <= i+mapS) || ((rays[r].x2 == i || rays[r].x2 == i+mapS) && rays[r].y2 >= j && rays[r].y2 <= j+mapS)) && map[c] != 0){ rays[r].run2 = false; } if (rays[r].x < 0 || rays[r].x > w || rays[r].y < 0 || rays[r].y > h){ rays[r].run = false; } if (rays[r].x2 < 0 || rays[r].x2 > w || rays[r].y2 < 0 || rays[r].y2 > h){ rays[r].run2 = false; } } } player(); for (i = 0; i < rays.length; i++){ raysFun(rays[i]); } for (i = 0, j = 0; i < vision.length, j < rays.length; i++, j++){ visionFun(vision[i], rays[j]); }}setInterval(draw, 0);function raysFun(o){ o.diffX = playerX-o.x; o.diffY = playerY-o.y; o.diff = Math.sqrt(o.diffX*o.diffX+o.diffY*o.diffY); o.diffX2 = playerX-o.x2; o.diffY2 = playerY-o.y2; o.diff2 = Math.sqrt(o.diffX2*o.diffX2+o.diffY2*o.diffY2); //offsetX if ((o.angle > Math.PI*1.5 || o.angle < Math.PI*0.5) && o.offsetX <= playerX){ o.offsetX += mapS; } if ((o.angle < Math.PI*1.5 && o.angle > Math.PI*0.5) && o.offsetX >= playerX){ o.offsetX -= mapS; } //offsetY if ((o.angle > Math.PI && o.angle < Math.PI*2) && o.offsetY >= playerY){ o.offsetY -= mapS; } if ((o.angle < Math.PI && o.angle > 0) && o.offsetY <= playerY){ o.offsetY += mapS; } //look up if (o.angle > Math.PI && o.angle < Math.PI*2 && o.run){ if (o.x == playerX && o.y == playerY){ o.y -= playerY-o.offsetY; o.x += Math.tan(o.angle + Math.PI*1.5) * (playerY-o.offsetY); } else { o.y -= mapS; o.x += Math.tan(o.angle + Math.PI*1.5) * mapS; } } //look down if (o.angle < Math.PI && o.angle > 0 && o.run){ if (o.x == playerX && o.y == playerY){ o.y += o.offsetY-playerY; o.x -= Math.tan(o.angle - Math.PI*0.5) * (o.offsetY-playerY); } else { o.y += mapS; o.x -= Math.tan(o.angle - Math.PI*0.5) * mapS; } } //look left if (o.angle < Math.PI*1.5 && o.angle > Math.PI*0.5 && o.run2){ if (o.x2 == playerX && o.y2 == playerY){ o.x2 -= playerX-o.offsetX; o.y2 -= Math.tan(o.angle) * (playerX-o.offsetX); } else { o.x2 -= mapS; o.y2 -= Math.tan(o.angle) * mapS; } } //look right if ((o.angle > Math.PI*1.5 || o.angle < Math.PI*0.5) && o.run2){ if (o.x2 == playerX && o.y2 == playerY){ o.x2 += o.offsetX-playerX; o.y2 += Math.tan(o.angle) * (o.offsetX-playerX); } else { o.x2 += mapS; o.y2 += Math.tan(o.angle) * mapS; } } if (o.run == false && o.run2 == false){ if (o.diff < o.diff2){ o.x2 = o.x; o.y2 = o.y; } else { o.x = o.x2; o.y = o.y2; } //line(playerX, playerY, o.x, o.y, "red", 2); }}function visionFun(o, p){ ctx.fillStyle = "white"; ctx.fillRect(o.x, o.y, o.sx, o.sy); let diff = Math.abs(w/2 - o.x + o.sx); if (time >= 14){ o.sy = h/p.diff * 45; o.y = h/2 - o.sy/2; }}function player(){ /*ctx.fillStyle = "gold"; ctx.beginPath(); ctx.arc(playerX, playerY, 8, 0, Math.PI*2); ctx.fill(); line(playerX, playerY, playerX + 20*Math.cos(playerAngle), playerY + 20*Math.sin(playerAngle), "gold", 3);*/ if (time >= 15){ //player go forward if (playerGo){ playerX += 10*Math.cos(playerAngle); playerY += 10*Math.sin(playerAngle); } //player turn left if (playerTurn == "left"){ playerAngle -= Math.PI/18; for (i of rays){ i.angle -= Math.PI/18; if (i.angle <= 0){ i.angle += Math.PI*2 } } if (playerAngle <= 0){ playerAngle += Math.PI*2 } } //player turn right if (playerTurn == "right"){ playerAngle += Math.PI/18; for (i of rays){ i.angle += Math.PI/18; if (i.angle > Math.PI*2){ i.angle -= Math.PI*2 } } if (playerAngle > Math.PI*2){ playerAngle -= Math.PI*2 } } for (i of rays){ i.x = playerX; i.y = playerY; i.run = true; i.x2 = playerX; i.y2 = playerY; i.run2 = true; } time = 0; }}function control(e){ if (e.code == "KeyA"){ playerTurn = "left" } if (e.code == "KeyD"){ playerTurn = "right" } if (e.code == "KeyW"){ playerGo = true }}function controlUp(e){ if (e.code == "KeyW"){ playerGo = false } if (e.code == "KeyA" || e.code == "KeyD"){ playerTurn = false }}function line(x1, y1, x2, y2, c, s = 2){ ctx.beginPath(); ctx.lineWidth = s; ctx.strokeStyle = c; ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke();} Ukázat celý příspěvek