:0
This commit is contained in:
parent
7f1140f997
commit
64d99d7476
7
TODO.md
Normal file
7
TODO.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
## Plan
|
||||||
|
- [ ] - fog (draw distance)
|
||||||
|
- [ ] - покачивание камеры
|
||||||
|
## Complete
|
||||||
|
- [ ] `...`
|
||||||
|
## Dropped
|
||||||
|
- [ ] `...`
|
16
src/game.js
16
src/game.js
@ -1,19 +1,19 @@
|
|||||||
var raycast = raycast || {};
|
var raycast = raycast || {};
|
||||||
|
|
||||||
window.requestAnimFrame = (function(){
|
window.requestAnimFrame = (function(){
|
||||||
return window.requestAnimationFrame ||
|
return window.requestAnimationFrame ||
|
||||||
window.webkitRequestAnimationFrame ||
|
window.webkitRequestAnimationFrame ||
|
||||||
window.mozRequestAnimationFrame ||
|
window.mozRequestAnimationFrame ||
|
||||||
window.oRequestAnimationFrame ||
|
window.oRequestAnimationFrame ||
|
||||||
window.msRequestAnimationFrame ||
|
window.msRequestAnimationFrame ||
|
||||||
function(callback, element){
|
function(callback, element) {
|
||||||
window.setTimeout(callback, 1000 / 60);
|
window.setTimeout(callback, 1000 / 60);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
document.onkeyup = raycast.keyhandler.onKeyup;
|
document.onkeyup = raycast.keyHandler.onKeyup;
|
||||||
document.onkeydown = raycast.keyhandler.onKeydown;
|
document.onkeydown = raycast.keyHandler.onKeydown;
|
||||||
var textureFiles = ["img/brick.png", "img/ground.png", "img/sky.png"];
|
var textureFiles = ["img/brick.png", "img/ground.png", "img/sky.png"];
|
||||||
raycast.texture.initiateLoad(textureFiles, raycast.engine.start);
|
raycast.texture.initiateLoad(textureFiles, raycast.engine.start);
|
||||||
};
|
};
|
||||||
|
@ -4,13 +4,15 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>JSRay</title>
|
<title>JSRay</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="999999">
|
<body>
|
||||||
<div id="canvasdiv">
|
<div class="container">
|
||||||
<canvas id="viewport" width="800" height="600"></canvas>
|
<canvas id="canvas" width="600" height="400"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="keyhandler.js"></script>
|
<script src="worldMap.js"></script>
|
||||||
|
<script src="keyHandler.js"></script>
|
||||||
<script src="texture.js"></script>
|
<script src="texture.js"></script>
|
||||||
<script src="raycast.js"></script>
|
<script src="raycast.js"></script>
|
||||||
<script src="game.js"></script>
|
<script src="game.js"></script>
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
var raycast = raycast || {};
|
var raycast = raycast || {};
|
||||||
|
|
||||||
raycast.keyhandler = (function () {
|
raycast.keyHandler = (function() {
|
||||||
var codes = {
|
var codes = {
|
||||||
|
// forward
|
||||||
up: 38,
|
up: 38,
|
||||||
w: 87,
|
w: 87,
|
||||||
|
// backward
|
||||||
down: 40,
|
down: 40,
|
||||||
|
s: 83,
|
||||||
|
// turn left
|
||||||
left: 37,
|
left: 37,
|
||||||
a: 65,
|
a: 65,
|
||||||
|
// turn right
|
||||||
right: 39,
|
right: 39,
|
||||||
d: 68,
|
d: 68,
|
||||||
|
// special
|
||||||
space: 32,
|
space: 32,
|
||||||
ctrl: 17,
|
ctrl: 17, // change filtering type
|
||||||
esc: 27
|
esc: 27
|
||||||
};
|
};
|
||||||
|
|
@ -1,13 +1,10 @@
|
|||||||
// http://lodev.org/cgtutor/raycasting.html
|
|
||||||
var raycast = raycast || {};
|
var raycast = raycast || {};
|
||||||
|
|
||||||
raycast.engine = (function () {
|
raycast.engine = (function() {
|
||||||
var canvas = document.getElementById("viewport");
|
var canvas = document.getElementById("canvas");
|
||||||
var g = canvas.getContext("2d");
|
var g = canvas.getContext("2d");
|
||||||
var filtering = false;
|
var filtering = false;
|
||||||
var mapWidth = 24,
|
let texHeight = 64, // mapWidth = 24, mapHeight = 24
|
||||||
mapHeight = 24,
|
|
||||||
texHeight = 64,
|
|
||||||
texWidth = 64;
|
texWidth = 64;
|
||||||
|
|
||||||
var texture;
|
var texture;
|
||||||
@ -24,24 +21,14 @@ raycast.engine = (function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
texture[0] = raycast.texture.load("ground");
|
texture[0] = raycast.texture.load("...");
|
||||||
texture[1] = raycast.texture.load("brick");
|
texture[1] = raycast.texture.load("brick");
|
||||||
texture[2] = raycast.texture.load("sky");
|
texture[2] = raycast.texture.load("ground");
|
||||||
|
texture[3] = raycast.texture.load("sky");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var worldMap = [
|
|
||||||
[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,1,0,0,1,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,1,0,0,1],
|
|
||||||
[1,0,0,0,0,0,0,0,0,1],
|
|
||||||
[1,0,0,0,0,0,0,0,0,1],
|
|
||||||
[1,1,1,1,1,1,1,1,1,1]
|
|
||||||
];
|
|
||||||
|
|
||||||
var posX = 2, posY = 2,
|
var posX = 2, posY = 2,
|
||||||
dirX = -1, dirY = 0,
|
dirX = -1, dirY = 0,
|
||||||
@ -54,7 +41,6 @@ raycast.engine = (function () {
|
|||||||
h = canvas.height;
|
h = canvas.height;
|
||||||
|
|
||||||
function verLine(arr, x, yStart, yEnd, color){
|
function verLine(arr, x, yStart, yEnd, color){
|
||||||
//console.log(x, yStart, yEnd);
|
|
||||||
for (var y = yStart | 0; y < yEnd | 0; y++) {
|
for (var y = yStart | 0; y < yEnd | 0; y++) {
|
||||||
var i = 4 * (w * y) + 4 * x;
|
var i = 4 * (w * y) + 4 * x;
|
||||||
arr[i + 0] = color[0];
|
arr[i + 0] = color[0];
|
||||||
@ -67,20 +53,21 @@ raycast.engine = (function () {
|
|||||||
imagedata = g.getImageData(0,0,w,h);
|
imagedata = g.getImageData(0,0,w,h);
|
||||||
var buffer = imagedata.data;
|
var buffer = imagedata.data;
|
||||||
|
|
||||||
var keys = raycast.keyhandler;
|
var keys = raycast.keyHandler;
|
||||||
|
|
||||||
function input() {
|
function input() {
|
||||||
if (keys.isKeydown("up")) {
|
// player move forward
|
||||||
|
if (keys.isKeydown("up") || keys.isKeydown("w")) {
|
||||||
if(worldMap[(posX + dirX * moveSpeed) | 0][posY | 0] == 0) posX += dirX * moveSpeed;
|
if(worldMap[(posX + dirX * moveSpeed) | 0][posY | 0] == 0) posX += dirX * moveSpeed;
|
||||||
if(worldMap[posX | 0][(posY + dirY * moveSpeed) | 0] == 0) posY += dirY * moveSpeed;
|
if(worldMap[posX | 0][(posY + dirY * moveSpeed) | 0] == 0) posY += dirY * moveSpeed;
|
||||||
}
|
}
|
||||||
//move backwards if no wall behind you
|
// player move backwards if no wall behind you
|
||||||
if (keys.isKeydown("down")) {
|
if (keys.isKeydown("down") || keys.isKeydown("s")) {
|
||||||
if(worldMap[(posX - dirX * moveSpeed) | 0][posY | 0] == 0) posX -= dirX * moveSpeed;
|
if(worldMap[(posX - dirX * moveSpeed) | 0][posY | 0] == 0) posX -= dirX * moveSpeed;
|
||||||
if(worldMap[posX | 0][(posY - dirY * moveSpeed) | 0] == 0) posY -= dirY * moveSpeed;
|
if(worldMap[posX | 0][(posY - dirY * moveSpeed) | 0] == 0) posY -= dirY * moveSpeed;
|
||||||
}
|
}
|
||||||
if (keys.isKeydown("right")) {
|
if (keys.isKeydown("right") || keys.isKeydown("d")) {
|
||||||
//both camera direction and camera plane must be rotated
|
// both camera direction and camera plane must be rotated
|
||||||
var oldDirX = dirX;
|
var oldDirX = dirX;
|
||||||
dirX = dirX * Math.cos(-rotSpeed) - dirY * Math.sin(-rotSpeed);
|
dirX = dirX * Math.cos(-rotSpeed) - dirY * Math.sin(-rotSpeed);
|
||||||
dirY = oldDirX * Math.sin(-rotSpeed) + dirY * Math.cos(-rotSpeed);
|
dirY = oldDirX * Math.sin(-rotSpeed) + dirY * Math.cos(-rotSpeed);
|
||||||
@ -88,8 +75,8 @@ raycast.engine = (function () {
|
|||||||
planeX = planeX * Math.cos(-rotSpeed) - planeY * Math.sin(-rotSpeed);
|
planeX = planeX * Math.cos(-rotSpeed) - planeY * Math.sin(-rotSpeed);
|
||||||
planeY = oldPlaneX * Math.sin(-rotSpeed) + planeY * Math.cos(-rotSpeed);
|
planeY = oldPlaneX * Math.sin(-rotSpeed) + planeY * Math.cos(-rotSpeed);
|
||||||
}
|
}
|
||||||
if (keys.isKeydown("left")) {
|
if (keys.isKeydown("left") || keys.isKeydown("a")) {
|
||||||
//both camera direction and camera plane must be rotated
|
// both camera direction and camera plane must be rotated
|
||||||
var oldDirX = dirX;
|
var oldDirX = dirX;
|
||||||
dirX = dirX * Math.cos(rotSpeed) - dirY * Math.sin(rotSpeed);
|
dirX = dirX * Math.cos(rotSpeed) - dirY * Math.sin(rotSpeed);
|
||||||
dirY = oldDirX * Math.sin(rotSpeed) + dirY * Math.cos(rotSpeed);
|
dirY = oldDirX * Math.sin(rotSpeed) + dirY * Math.cos(rotSpeed);
|
||||||
@ -97,7 +84,7 @@ raycast.engine = (function () {
|
|||||||
planeX = planeX * Math.cos(rotSpeed) - planeY * Math.sin(rotSpeed);
|
planeX = planeX * Math.cos(rotSpeed) - planeY * Math.sin(rotSpeed);
|
||||||
planeY = oldPlaneX * Math.sin(rotSpeed) + planeY * Math.cos(rotSpeed);
|
planeY = oldPlaneX * Math.sin(rotSpeed) + planeY * Math.cos(rotSpeed);
|
||||||
}
|
}
|
||||||
if (keys.isKeypress("d"))
|
if (keys.isKeypress("ctrl"))
|
||||||
filtering = !filtering;
|
filtering = !filtering;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,10 +145,10 @@ raycast.engine = (function () {
|
|||||||
else
|
else
|
||||||
perpWallDist = Math.abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
|
perpWallDist = Math.abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
|
||||||
|
|
||||||
//Calculate height of line to draw on screen
|
// calculate height of line to draw on screen
|
||||||
var lineHeight = Math.abs((h / perpWallDist) | 0);
|
var lineHeight = Math.abs((h / perpWallDist) | 0);
|
||||||
|
|
||||||
//calculate lowest and highest pixel to fill in current stripe
|
// calculate lowest and highest pixel to fill in current stripe
|
||||||
var drawStart = ((h - lineHeight) / 2) | 0;
|
var drawStart = ((h - lineHeight) / 2) | 0;
|
||||||
if(drawStart < 0)
|
if(drawStart < 0)
|
||||||
drawStart = 0;
|
drawStart = 0;
|
||||||
@ -247,7 +234,7 @@ raycast.engine = (function () {
|
|||||||
var ceilTex = texture[2];
|
var ceilTex = texture[2];
|
||||||
var floorTex = texture[1];
|
var floorTex = texture[1];
|
||||||
|
|
||||||
//draw the floor from drawEnd to the bottom of the screen
|
// draw the floor from drawEnd to the bottom of the screen
|
||||||
for(var y = drawEnd; y < h; y++)
|
for(var y = drawEnd; y < h; y++)
|
||||||
{
|
{
|
||||||
currentDist = h / (2.0 * y - h); //you could make a small lookup table for this instead
|
currentDist = h / (2.0 * y - h); //you could make a small lookup table for this instead
|
||||||
@ -286,7 +273,7 @@ raycast.engine = (function () {
|
|||||||
color = floorTex[texWidth * (floorTexY|0) + (floorTexX|0)];
|
color = floorTex[texWidth * (floorTexY|0) + (floorTexX|0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
//floor
|
// floor
|
||||||
i = 4 * (w * y) + 4 * x;
|
i = 4 * (w * y) + 4 * x;
|
||||||
|
|
||||||
buffer[i+0] = (color[0])/2;
|
buffer[i+0] = (color[0])/2;
|
||||||
@ -308,7 +295,7 @@ raycast.engine = (function () {
|
|||||||
color = ceilTex[texWidth * (floorTexY|0) + (floorTexX|0)];
|
color = ceilTex[texWidth * (floorTexY|0) + (floorTexX|0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
//ceiling (symmetrical!)
|
// ceiling (symmetrical!)
|
||||||
i = 4 * (w * (h - y - 1)) + 4 * x;
|
i = 4 * (w * (h - y - 1)) + 4 * x;
|
||||||
|
|
||||||
buffer[i+0] = color[0]/2;
|
buffer[i+0] = color[0]/2;
|
||||||
@ -327,8 +314,8 @@ raycast.engine = (function () {
|
|||||||
rotSpeed = frameTime * 3.0; //the constant value is in radians/second
|
rotSpeed = frameTime * 3.0; //the constant value is in radians/second
|
||||||
|
|
||||||
g.putImageData(imagedata, 0, 0);
|
g.putImageData(imagedata, 0, 0);
|
||||||
g.font = "bold 30pt Monospace";
|
g.font = "14pt Monospace";
|
||||||
g.fillText(""+((1000 / (time - oldTime))|0), 0, 30);
|
g.fillText("FPS: " + ((1000 / (time - oldTime)) | 0), 5, 20);
|
||||||
};
|
};
|
||||||
|
|
||||||
function tick() {
|
function tick() {
|
||||||
@ -337,7 +324,6 @@ raycast.engine = (function () {
|
|||||||
keys.tick();
|
keys.tick();
|
||||||
|
|
||||||
window.requestAnimFrame(tick);
|
window.requestAnimFrame(tick);
|
||||||
//window.setTimeout(tick, 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
|
20
src/styles.css
Normal file
20
src/styles.css
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
* { margin: 0; padding: 0; outline: 0; }
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
border: 2px solid #000;
|
||||||
|
}
|
31
src/worldMap.js
Normal file
31
src/worldMap.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*let worldMap = [
|
||||||
|
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
|
||||||
|
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,0,0,1,1,1,0,0,0,0,0,0,0,0,1,0,0,1],
|
||||||
|
[1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1],
|
||||||
|
[1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1],
|
||||||
|
[1,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,1],
|
||||||
|
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,1,1,1,0,1,0,0,0,0,0,0,0,0,1,1,1,1],
|
||||||
|
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1],
|
||||||
|
[1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1],
|
||||||
|
[1,1,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,1],
|
||||||
|
[1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,1],
|
||||||
|
[1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,1,1],
|
||||||
|
[1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1],
|
||||||
|
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
|
||||||
|
];*/
|
||||||
|
|
||||||
|
let worldMap = [
|
||||||
|
[1,1,1,1,1,1,1,1,1,1,1,1],
|
||||||
|
[1,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,0,0,1,1,1,0,0,1,0,0,1],
|
||||||
|
[1,0,0,0,0,0,0,0,0,0,0,1],
|
||||||
|
[1,1,1,1,1,1,1,1,1,1,1,1]
|
||||||
|
];
|
Loading…
Reference in New Issue
Block a user