Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions ray_casting_3d/SBS - Tiny Texture Pack - 128x128/License.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
All Screaming Brain Studios assets have been released
under the CC0/Public Domain License. You are free to
use these assets in any and all projects, commercial
or non-commercial, with no restrictions, and can be
released with or without credit.

--------------------------------------------------
CC0 1.0 Universal (CC0 1.0)
Public Domain
https://creativecommons.org/publicdomain/zero/1.0/
--------------------------------------------------


|| A Very Special Thanks to all my Patrons ||

Dwayne Jarvis
Peardox
Caleb Ralph
Heruca
Binary file added ray_casting_3d/bricks.png
10 changes: 6 additions & 4 deletions ray_casting_3d/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function intersects(L1, L2) {
((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));

if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
return point(x1 + t * (x2 - x1), y1 + t * (y2 - y1));
return [point(x1 + t * (x2 - x1), y1 + t * (y2 - y1)), t];
}

return null;
Expand All @@ -43,9 +43,11 @@ function distance(p1, p2) {
);
}

function getLineByAngle(x, y, angle, WIDTH) {
const k = 2 * WIDTH * Math.cos(angle);
const z = 2 * WIDTH * Math.sin(angle);
// given a start coordinate, angle and length of the line segment,
// this function returns the start and end coords of that line segment
function getLineByAngle(x, y, angle, lineWidth) {
const k = lineWidth * Math.cos(angle);
const z = lineWidth * Math.sin(angle);

const a = x + k;
const b = y + z;
Expand Down
2 changes: 2 additions & 0 deletions ray_casting_3d/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

<canvas id="mini-canvas"></canvas>

<img src="bricks.png" style="display: none;" id="brick"/>

<script src="./functions.js"></script>
<script src="./main.js"></script>
</body>
Expand Down
115 changes: 81 additions & 34 deletions ray_casting_3d/main.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
const VERTICAL_LINES = 510;
const VERTICAL_LINES = 1020;

const HEIGHT = 573.75;
const WIDTH = 1020;
const STEP = WIDTH / VERTICAL_LINES;

const ROTATION_ANGLE_STEP = 0.05
const PLAYER_MOVEMENT_STEP = 0.001

const worldCanvas = document.getElementById("canvas");
worldCanvas.height = HEIGHT;
worldCanvas.width = WIDTH;

const BRICK_IMG = document.getElementById("brick");

const CELL_TO_COLOR = [
"grey",
"black",
Expand All @@ -16,14 +21,28 @@ const CELL_TO_COLOR = [
"green"
];

// const COLOR_TO_RGB_INTENSITY = {
// "red": intensity => `rgb(${intensity}, 11, 11)`,
// "black": intensity => `rgb(${intensity}, 11, 11)`,
// "green": intensity => `rgb(11, ${intensity}, 11)`,
// "blue": intensity => `rgb(11, 11, ${intensity})`,
// }

const COLOR_TO_RGB_INTENSITY = {
"red": t => `rgb(${t * 255}, 0, 0)`,
"black": t => `rgb(${t * 255}, 0, 0)`,
"green": t => `rgb(0, ${t * 255}, 0)`,
"blue": t => `rgb(0, 0, ${t * 255})`,
}

const GAME_WORLD = [
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
];

Expand All @@ -32,11 +51,18 @@ const ALL_LINES = getAllLines();
const PLAYER = {
x: 100,
y: 200,
rotationAngle: 20,
fixedAngle: Math.PI / 3,
keys: {}
rotationAngle: 0,
fieldOfView: Math.PI / 3,
keys: {
"ArrowRight": false,
"ArrowLeft": false,
"ArrowUp": false,
"ArrowDown": false,
}
};

let lastRenderTime = 0

function getAllLines() {
const STEP = 50;

Expand Down Expand Up @@ -99,20 +125,25 @@ function drawMiniMap() {

function drawRays() {
const HIT_BOX = [];
const step = PLAYER.fixedAngle / VERTICAL_LINES;
for (let radian = -PLAYER.fixedAngle / 2; radian < PLAYER.fixedAngle / 2; radian += step) {
const step = PLAYER.fieldOfView / VERTICAL_LINES;
for (let radian = -PLAYER.fieldOfView / 2; radian < PLAYER.fieldOfView / 2; radian += step) {
const radianRotated = radian + PLAYER.rotationAngle;
const line = getLineByAngle(PLAYER.x, PLAYER.y, radianRotated, WIDTH);
const line = getLineByAngle(PLAYER.x, PLAYER.y, radianRotated, WIDTH * 2);

const arr = ALL_LINES
.map(target => {
let result = intersects(target.line, line)
return {
intersection: result,
color: target.color
if (result !== null) {
const [point, t] = result;
return {
intersection: point,
t: t,
color: target.color
}
}
return null
})
.filter(result => result.intersection !== null)
.filter(result => result !== null)
.map(result => {
return {
...result,
Expand All @@ -122,6 +153,10 @@ function drawMiniMap() {

arr.sort((a, b) => a.distance - b.distance);

if (arr.length == 0) {
continue;
}

const closest = arr[0].intersection;
arr[0].distance *= Math.cos(radian);

Expand Down Expand Up @@ -151,23 +186,32 @@ function updateWorldView(HIT_BOX) {

let verticalStripe = 0;

for (let { distance } of HIT_BOX) {
for (let { distance, color, t } of HIT_BOX) {
const height = (HEIGHT / distance) * 40;
let x = verticalStripe * STEP;
let y = (HEIGHT - height) / 2;

let red = Math.max(255 - Math.min(distance, 255), 30);

ctx.fillStyle = `rgb(${red}, 11, 11)`;
ctx.fillRect(x, y, STEP, height);

let intensity = Math.max(255 - Math.min(distance, 255), 30);

// ctx.fillStyle = COLOR_TO_RGB_INTENSITY[color](t)
// ctx.fillRect(x, y, STEP, height);
// drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
ctx.drawImage(
BRICK_IMG,
t*128, 0,
50 / 128, 128, // swidth is not right
x, y,
STEP, height
)
verticalStripe++;
}
}

const HIT_BOX = drawMiniMap()
updateWorldView(HIT_BOX);

function nextPoint(p0, p1, t) {
// linear interpolation
function lerp(p0, p1, t) {
const btx = p0.x + t * (p1.x - p0.x);
const bty = p0.y + t * (p1.y - p0.y);
return point(btx, bty);
Expand All @@ -181,19 +225,21 @@ document.addEventListener('keyup', ({key}) => {
PLAYER.keys[key] = !(key && key.startsWith("Arrow"));
});

function updateAndRender(time) {
if (PLAYER.keys["ArrowRight"]) {
PLAYER.rotationAngle += 0.005;
}
function gameloop(timePassed) {
const deltaTimeMs = timePassed - lastRenderTime;

if (PLAYER.keys["ArrowLeft"]) {
PLAYER.rotationAngle -= 0.005;
}
// lock the framerate to 60
if (deltaTimeMs < (1000 / 60)) {
window.requestAnimationFrame(gameloop)
return;
}

PLAYER.rotationAngle += (PLAYER.keys["ArrowRight"] - PLAYER.keys["ArrowLeft"]) * ROTATION_ANGLE_STEP

if (PLAYER.keys["ArrowUp"] || PLAYER.keys["ArrowDown"]) {
const forwardLine = getLineByAngle(PLAYER.x, PLAYER.y, PLAYER.rotationAngle, WIDTH * 2);
const t = PLAYER.keys["ArrowUp"] ? 0.00005 : -0.00005;
const {x, y} = nextPoint(forwardLine.p1, forwardLine.p2, t);
const t = PLAYER.keys["ArrowUp"] ? PLAYER_MOVEMENT_STEP : -PLAYER_MOVEMENT_STEP;
const {x, y} = lerp(forwardLine.p1, forwardLine.p2, t);

const blockX = Math.floor(x / 50);
const blockY = Math.floor(y / 50);
Expand All @@ -205,8 +251,9 @@ function updateAndRender(time) {

const HIT_BOX = drawMiniMap()
updateWorldView(HIT_BOX);
window.requestAnimationFrame(updateAndRender)
lastRenderTime = timePassed
window.requestAnimationFrame(gameloop)
}

window.requestAnimationFrame(updateAndRender);
window.requestAnimationFrame(gameloop);