Skip to content

Commit

Permalink
Attempted sprite casting
Browse files Browse the repository at this point in the history
  • Loading branch information
rachitkakkar committed May 21, 2024
1 parent 9344369 commit 08b85b3
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 17 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
- Features textures, a mini-map, procedural/maze generation, doors, fully implemented first person controller (including strafe and up/down mouselook), and more!
- Uses modern javascript and browser features such as classes, modules, JSDoc (mostly), PointerLock API, etc.

*This project started as a quest to improve a much older raycaster I made a long time ago, and the original code plus its README can be found in the `Version 1` directory.*
<!--*This project started as a quest to improve a much older raycaster I made a long time ago, and the original code plus its README can be found in the `Version 1` directory.*-->

# Credits
Much of the work here is inspired by Lode Vandevenne's excellent tutorials on raycasting.
Expand Down
102 changes: 88 additions & 14 deletions raycaster.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Timer } from "./src/Timer.js";
import { MiniMap } from "./src/MiniMap.js";
import { OptionsHandler } from "./src/OptionsHandler.js";
import { Player } from "./src/Player.js";
import { Sprite } from "./src/Sprite.js";

import * as Utils from "./src/Utils.js";

Expand Down Expand Up @@ -45,6 +46,13 @@ var playerSize = Utils.castToInt(padding * 4/5);

var miniMap = new MiniMap(blockSize, playerSize, padding);

// Sprite setup
var sprites = [new Sprite(new Utils.Vector2(2, 1.5), barrelTexture)];
var zBuffer = []
for (let z = 0; z < screenWidth; z++) {
zBuffer.push(0);
}

// Main loop
function main() {
// Calculate delta time
Expand Down Expand Up @@ -254,12 +262,12 @@ function main() {
let dimFactor = 0.9 + (0.2 * (currentDistance));
let fogPercentage = (optionsHandler.getOption("fog")) ? 0.1 * currentDistance : 0;

let pixelindex = (ceilingTex.y * textureWidth + ceilingTex.x) * 4;
red = ceilingTexture.data[pixelindex] / dimFactor;
let pixelIndex = (ceilingTex.y * textureWidth + ceilingTex.x) * 4;
red = ceilingTexture.data[pixelIndex] / dimFactor;
red = red * (1 - fogPercentage) + fogPercentage * 0.1;
green = ceilingTexture.data[pixelindex+1] / dimFactor;
green = ceilingTexture.data[pixelIndex+1] / dimFactor;
green = green * (1 - fogPercentage) + fogPercentage * 0.1;
blue = ceilingTexture.data[pixelindex+2] / dimFactor;
blue = ceilingTexture.data[pixelIndex+2] / dimFactor;
blue = blue * (1 - fogPercentage) + fogPercentage * 0.1;
}

Expand All @@ -276,26 +284,88 @@ function main() {

let weight = currentDistance / perpendicularWallDistance;

let currentFloor = new Utils.Vector2(weight * floorCeilingWallPos.x + (1.0 - weight) * player.position.x,
weight * floorCeilingWallPos.y + (1.0 - weight) * player.position.y)
let currentFloor = new Utils.Vector2(
weight * floorCeilingWallPos.x + (1.0 - weight) * player.position.x,
weight * floorCeilingWallPos.y + (1.0 - weight) * player.position.y
);

let floorTex = new Utils.Vector2(Utils.castToInt(currentFloor.x * textureWidth) % textureWidth,
Utils.castToInt(currentFloor.y * textureHeight) % textureHeight);
let floorTex = new Utils.Vector2(
Utils.castToInt(currentFloor.x * textureWidth) % textureWidth,
Utils.castToInt(currentFloor.y * textureHeight) % textureHeight
);

let dimFactor = 0.9 + (0.2 * (currentDistance));
let fogPercentage = (optionsHandler.getOption("fog")) ? 0.1 * currentDistance : 0;

let pixelindex = (floorTex.y * textureWidth + floorTex.x) * 4;
red = groundTexture.data[pixelindex] / dimFactor;
let pixelIndex = (floorTex.y * textureWidth + floorTex.x) * 4;
red = groundTexture.data[pixelIndex] / dimFactor;
red = red * (1 - fogPercentage) + fogPercentage * 0.1;
green = groundTexture.data[pixelindex+1] / dimFactor;
green = groundTexture.data[pixelIndex+1] / dimFactor;
green = green * (1 - fogPercentage) + fogPercentage * 0.1;
blue = groundTexture.data[pixelindex+2] / dimFactor;
blue = groundTexture.data[pixelIndex+2] / dimFactor;
blue = blue * (1 - fogPercentage) + fogPercentage * 0.1;
}

renderer.drawPixel(x, y, red, green, blue);
}

// Set zBuffer for sprite casting
zBuffer[x] = perpendicularWallDistance;
for (const sprite of sprites) {
sprite.distance = ((player.position.x - sprite.position.x) * (player.position.x - sprite.position.x) + (player.position.y - sprite.position.y) * (player.position.y - sprite.position.y));
}
sprites.sort((a, b) => a.distance - b.distance);
}

for (const sprite of sprites) {
let relSpritePosition = new Utils.Vector2(
sprite.position.x - player.position.x,
sprite.position.y - player.position.y
);

let invDet = 1.0 / (player.plane.x * player.direction.y - player.direction.x * player.plane.y);
let transformPosition = new Utils.Vector2(
invDet * (player.direction.y * relSpritePosition.x - player.direction.x * relSpritePosition.y),
invDet * (-player.plane.y * relSpritePosition.x + player.plane.x * relSpritePosition.y)
);

let spriteScreenX = Utils.castToInt((screenWidth / 2) * (1 + transformPosition.x / transformPosition.y));

let spriteHeight = Math.abs(Utils.castToInt(screenHeight / (transformPosition.y)));
let drawStartY = -spriteHeight / 2 + screenHeight / 2;
if (drawStartY < 0) drawStartY = 0;
let drawEndY = spriteHeight / 2 + screenHeight / 2;
if (drawEndY >= screenHeight) drawEndY = screenHeight - 1;

let spriteWidth = Math.abs(Utils.castToInt(screenHeight / (transformPosition.y)));
let drawStartX = -spriteWidth / 2 + spriteScreenX;
if (drawStartX < 0) drawStartX = 0;
let drawEndX = spriteWidth / 2 + spriteScreenX;
if (drawEndX >= screenWidth) drawEndX = screenWidth - 1;

for (let stripe = drawStartX; stripe < drawEndX; stripe++) {
let texX = Utils.castToInt((stripe - (-spriteWidth / 2 + spriteScreenX)) * textureWidth / spriteWidth);
// the conditions in the if are:
// 1) it's in front of camera plane so you don't see things behind you
// 2) it's on the screen (left)
// 3) it's on the screen (right)
// 4) ZBuffer, with perpendicular distance
if (transformPosition.y > 0 && stripe > 0 && stripe < screenWidth && transformPosition.y < zBuffer[stripe]) {
for (let y = drawStartY; y < drawEndY; y++) {
let d = (y) - screenHeight + spriteHeight;
let texY = ((d * textureHeight) / spriteHeight);
let pixelIndex = (textureWidth * texY + texX) * 4;
let red = barrelTexture.data[pixelIndex] / 1;
// red = red * (1 - fogPercentage) + fogPercentage * 0.1;
let green = barrelTexture.data[pixelIndex+1] / 1;
// green = green * (1 - fogPercentage) + fogPercentage * 0.1;
let blue = barrelTexture.data[pixelIndex+2] / 1;
// blue = blue * (1 - fogPercentage) + fogPercentage * 0.1;
if (Utils.castToInt(red) != 0 && Utils.castToInt(green) != 0 && Utils.castToInt(blue) != 0) // Transparency for black
renderer.drawPixel(stripe, y, red, green, blue);
}
}
}
}

// Render minimap
Expand All @@ -319,12 +389,13 @@ function main() {
// Textures
const textureWidth = 64;
const textureHeight = 64;
const textureUrls = ["textures/bricks.png", "textures/tiles.png", "textures/tiles.png", "textures/door.png"];
const textureUrls = ["textures/bricks.png", "textures/tiles.png", "textures/tiles.png", "textures/door.png", "textures/barrel 2.png"];

var wallTexture;
var groundTexture;
var ceilingTexture;
var doorTexture;
var barrelTexture;

Utils.loadImages(textureUrls).then(textures => {
ctx.drawImage(textures[0], 0, 0);
Expand All @@ -338,6 +409,9 @@ Utils.loadImages(textureUrls).then(textures => {

ctx.drawImage(textures[3], 0, 0);
doorTexture = ctx.getImageData(0, 0, textureWidth, textureHeight);


ctx.drawImage(textures[4], 0, 0);
barrelTexture = ctx.getImageData(0, 0, textureWidth, textureHeight);

requestAnimationFrame(main);
});
4 changes: 2 additions & 2 deletions src/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class Player {
* Creates an instance of Player.
*/
constructor() {
this.position = new Utils.Vector2(1.5, 1.5);
this.position = new Utils.Vector2(3.5, 1.5);
this.direction = new Utils.Vector2(1, 0);
this.plane = new Utils.Vector2(0, 0.66);
this.walkTime = 0.0;
Expand Down Expand Up @@ -78,7 +78,7 @@ export class Player {

if (moved) {
this.walkTime += timer.getDeltaTime();
this.pitch += (Math.cos(10 * this.walkTime) / 2 * 8);
this.pitch += (Math.cos(10 * this.walkTime) / 2 * 7);
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/Sprite.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class Sprite {
constructor(position, texture) {
this.distance = 0.0;

this.position = position;
this.texture = texture;
}
}
Binary file added textures/barrel 2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added textures/barrel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 08b85b3

Please sign in to comment.