p5.raycaster
Version:
a simple p5js library for semi 3d rendering with ray casting
152 lines (137 loc) • 4.5 kB
JavaScript
let canvas;
let world, camera, controller, textureMap;
let mapData = [
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
]
let sprites = [];
// advance animation control over the sprite
// there's a lots of way to do that here is just one example
let guardMoveTrail = [[{x:7.5, y: 7.5}, 120], [{x:1.5, y:1.5}, 120]];
let guardMoveSpeed = 0.5;
let guardMoving = false;
let guardMovingCurrent = 0;
let guardMovingTarget = 1;
let guardCounter = 0;
function preload() {
star = loadImage("./assets/star.png");
guard = loadImage("./assets/guard.png");
}
function setup() {
canvas = createCanvas(600, 600);
frameRate(30);
// star sprite
sprites.push(RayCaster.createSprite(star, { x: 7.5, y: 7.5 }, 100, 100));
sprites[0].setYAdjustment(0.1);
sprites[0].setAnimationGap(15);
sprites[0].scale(0.5);
// guard sprite
sprites.push(RayCaster.createSprite(guard, { x: 1.5, y: 1.5 }, 128, 128, - Math.PI));
sprites[1].setYAdjustment(0);
sprites[1].setAnimationGap(6);
sprites[1].setAnimationGroups([[0],[1,2,3]]); // idle & moving
sprites[1].setCurrentAnimationGroup(0);
background(0);
world = RayCaster.createWorld(9, 9);
world.loadMap(mapData);
textureMap = RayCaster.createTextureMap(1, "red");
world.loadTextureMap(textureMap);
sprites.forEach(sprite => world.addSprite(sprite));
camera = RayCaster.createCamera({ x: 1.5, y: 7.5 }, { x: 1, y: -1 }, 0.5, world, canvas);
keyboardController = RayCaster.initKeyboardControl();
pointerLockController = RayCaster.initPointerLockControl(camera, canvas.canvas);
keyboardController.addItem("showMiniMap", ["m"], "up", false);
camera.renderFrame();
}
function draw() {
camera.renderFrame();
toggleMiniMap();
cameraMove()
doorInteraction();
worldUpdate();
}
function toggleMiniMap() {
if (keyboardController.showMiniMap) {
camera.renderMiniMap({ x: 7, y: 7 }, 0, 0, 200, 200);
}
}
function cameraMove() {
const MOVE_SPEED = 0.04, TURN_SPEED = 0.02;
let movement = { x: 0, y: 0 };
if (keyboardController.forward) {
movement.x += camera.dir.x * MOVE_SPEED;
movement.y += camera.dir.y * MOVE_SPEED;
}
if (keyboardController.backward) {
movement.x -= camera.dir.x * MOVE_SPEED;
movement.y -= camera.dir.y * MOVE_SPEED;
}
if (keyboardController.goLeft) {
movement.x -= camera.plane.x * MOVE_SPEED;
movement.y -= camera.plane.y * MOVE_SPEED;
}
if (keyboardController.goRight) {
movement.x += camera.plane.x * MOVE_SPEED;
movement.y += camera.plane.y * MOVE_SPEED;
}
camera.move(movement);
if (keyboardController.turnLeft) {
camera.rotate(TURN_SPEED);
}
if (keyboardController.turnRight) {
camera.rotate(-TURN_SPEED);
}
if (keyboardController.tiltUp) {
camera.tilt(TURN_SPEED);
}
if (keyboardController.tiltDown) {
camera.tilt(-TURN_SPEED);
}
}
function doorInteraction() {
if (keyboardController.moveDoor) {
camera.moveDoor();
}
}
function worldUpdate() {
world.update();
sprites.forEach(s => s.update(frameCount));
guardMove();
}
function guardMove(){
if(!guardMoving) {
guardCounter ++;
if(guardCounter > guardMoveTrail[guardMovingCurrent][1]) {
guardCounter = 0;
guardMoving = true;
sprites[1].setCurrentAnimationGroup(1);
}
} else {
let dirX = guardMoveTrail[guardMovingTarget][0].x - sprites[1].pos.x;
let dirY = guardMoveTrail[guardMovingTarget][0].y - sprites[1].pos.y;
sprites[1].rotateTo(Math.PI + Math.atan2(dirY, dirX));
let m = dirX * dirX + dirY * dirY;
if (m < 0.01) {
guardMoving = false;
guardMovingCurrent = guardMovingTarget;
guardMovingTarget = (guardMovingTarget + 1) % guardMoveTrail.length;
sprites[1].setCurrentAnimationGroup(0)
} else {
m = Math.sqrt(m);
dirX /= m;
dirY /= m;
sprites[1].pos.x += dirX * (guardMoveSpeed / 30);
sprites[1].pos.y += dirY * (guardMoveSpeed / 30);
}
}
}
function mouseClicked() {
if (!pointerLockController.pointerLocked) pointerLockController.lock();
}