Created
May 25, 2018 04:01
-
-
Save andiogenes/254210e82cf349cfaf73b628393a2c75 to your computer and use it in GitHub Desktop.
Haxe written Raycaster based on lodev's tutorials
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package; | |
import js.Browser; | |
import js.html.CanvasElement; | |
import js.html.CanvasRenderingContext2D; | |
import js.html.KeyboardEvent; | |
import js.Lib; | |
/** | |
* @name ОНО РАБОТАЕТ | |
* @author Wookie | |
*/ | |
class Main | |
{ | |
var worldMap : Array<Array<Int>> = [ | |
[1,1,1,1,1,1,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,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,0,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,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1], | |
[1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1], | |
[1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1], | |
[1,0,0,0,0,0,0,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,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,0,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,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,0,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,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,4,4,4,4,4,4,4,4,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,1,1,1,1,1,1] | |
]; | |
public function new() | |
{ | |
// x and y start position | |
var posX : Float = 22; | |
var posY : Float = 12; | |
// initial direction vector | |
var dirX : Float = -1; | |
var dirY : Float = 0; | |
// the 2d raycaster version of camera plane | |
var planeX : Float = 0; | |
var planeY : Float = 0.66; | |
var time : Float = 0; // time of current frame | |
var oldTime : Float = 0; // time of previous frame | |
var frameTime : Float = 0; // вынес из игрового цикла сюда, т.к. доступ к клавишам из события | |
var screen : CanvasElement = Browser.document.createCanvasElement(); | |
var w : Int = screen.width = 512; | |
var h : Int = screen.height = 384; | |
screen.style.backgroundColor = "#000"; | |
Browser.document.head.title = screen.id = "Raycaster"; | |
var ctx : CanvasRenderingContext2D = screen.getContext2d(); | |
ctx.fillStyle = "#fff"; | |
ctx.font = "12pt sans-serif"; | |
Browser.document.body.appendChild(screen); | |
// javascript не переваривает while (true) | |
Browser.window.setInterval(function() { | |
ctx.clearRect(0, 0, w, h); // очистка экрана работает на заходе в функцию | |
for (x in 0 ... w) | |
{ | |
// calculate ray position and direction | |
var cameraX : Float = 2 * x / w - 1; | |
var rayPosX : Float = posX; | |
var rayPosY : Float = posY; | |
var rayDirX : Float = dirX + planeX * cameraX; | |
var rayDirY : Float = dirY + planeY * cameraX; | |
// which box of the map we're in | |
var mapX : Int = Std.int(rayPosX); | |
var mapY : Int = Std.int(rayPosY); | |
// length of ray from current position to next x or y-side | |
var sideDistX : Float; | |
var sideDistY : Float; | |
// length of ray from one x or y-side to next x or y-side | |
var deltaDistX : Float = Math.sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX)); | |
var deltaDistY : Float = Math.sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY)); | |
var perpWallDist : Float; | |
// what direction to step in x or y-direction (either +1 or -1) | |
var stepX : Int; | |
var stepY : Int; | |
var hit : Int = 0; // was there a wall hit? | |
var side : Int = 0; // was a NS or a EW wall hit? | |
// calculate step and initial sideDist | |
if (rayDirX < 0) | |
{ | |
stepX = -1; | |
sideDistX = (rayPosX - mapX) * deltaDistX; | |
} | |
else | |
{ | |
stepX = 1; | |
sideDistX = (mapX + 1 - rayPosX) * deltaDistX; | |
} | |
if (rayDirY < 0) | |
{ | |
stepY = -1; | |
sideDistY = (rayPosY - mapY) * deltaDistY; | |
} | |
else | |
{ | |
stepY = 1; | |
sideDistY = (mapY + 1 - rayPosY) * deltaDistY; | |
} | |
// perform DDA | |
while (hit == 0) | |
{ | |
// jump to next map square, OR in x-direction, OR in y-direction | |
if (sideDistX < sideDistY) | |
{ | |
sideDistX += deltaDistX; | |
mapX += stepX; | |
side = 0; | |
} | |
else | |
{ | |
sideDistY += deltaDistY; | |
mapY += stepY; | |
side = 1; | |
} | |
// Check if ray has hit a wall | |
if (worldMap[mapX][mapY] > 0) hit = 1; | |
} | |
// Calculate distance projected on camera direction (Euclidean distance will give fisheye effect!) | |
if (side == 0) perpWallDist = (mapX - rayPosX + (1 - stepX) / 2) / rayDirX; | |
else perpWallDist = (mapY - rayPosY + (1 - stepY) / 2) / rayDirY; | |
// Calculate height of line to draw on screen | |
var lineHeight : Int = Std.int(h / perpWallDist); | |
// calculate lowest and highest pixel to fill in current stripe | |
var drawStart : Int = Std.int(-lineHeight / 2 + h / 2); | |
if (drawStart < 0) drawStart = 0; | |
var drawEnd : Int = Std.int(lineHeight / 2 + h / 2); | |
if (drawEnd >= h) drawEnd = h - 1; | |
// choose wall color (сделал говнокодом) | |
var color : String; | |
switch(worldMap[mapX][mapY]) | |
{ | |
case 1: | |
if (side == 1) color = "#7f0000"; // red | |
else color = "#f00"; | |
case 2: | |
if (side == 1) color = "#007f00"; // green | |
else color = "#00ff00"; | |
case 3: | |
if (side == 1) color = "#00007f"; // blue | |
else color = "#0000ff"; | |
case 4: | |
if (side == 1) color = "#7f7f7f"; // white | |
else color = "#fff"; | |
default: | |
if (side == 1) color = "#7f7f00"; // yellow | |
else color = "#ffff00"; | |
} | |
ctx.strokeStyle = color; | |
// draw the pixels of the stripe as vertical line | |
ctx.beginPath(); | |
ctx.lineTo(x, drawStart); | |
ctx.lineTo(x, drawEnd); | |
ctx.stroke(); | |
} | |
// timing for input and FPS counter | |
oldTime = time; | |
time = untyped __js__ ("Date.now()"); | |
frameTime = (time - oldTime) / 1000; // frameTime is the time this frame has taken, in seconds | |
//ctx.fillText(Std.string(1 / frameTime), 5, 20); // FPS counter | |
// Тут была очистка | |
}, 0); | |
// Обработка клавиатуры | |
Browser.document.addEventListener("keydown", function(e : KeyboardEvent) { | |
/* LEFT = 37; | |
UP = 38; | |
RIGHT = 39; | |
DOWN = 40; */ | |
if (e.keyCode == 37) | |
{ | |
// LEFT | |
var oldDirX : Float = dirX; | |
dirX = dirX * Math.cos(frameTime * 3) - dirY * Math.sin(frameTime * 3); | |
dirY = oldDirX * Math.sin(frameTime * 3) + dirY * Math.cos(frameTime * 3); | |
var oldPlaneX : Float = planeX; | |
planeX = planeX * Math.cos(frameTime * 3) - planeY * Math.sin(frameTime * 3); | |
planeY = oldPlaneX * Math.sin(frameTime * 3) + planeY * Math.cos(frameTime * 3); | |
} | |
if (e.keyCode == 38) | |
{ | |
// UP | |
if (worldMap[Std.int(posX + dirX * frameTime * 5)][Std.int(posY)] == 0) posX += dirX * frameTime * 5; | |
if (worldMap[Std.int(posX)][Std.int(posY + dirY * frameTime * 5)] == 0) posY += dirY * frameTime * 5; | |
} | |
if (e.keyCode == 39) | |
{ | |
// RIGHT | |
var oldDirX : Float = dirX; | |
dirX = dirX * Math.cos(-frameTime * 3) - dirY * Math.sin(-frameTime * 3); | |
dirY = oldDirX * Math.sin(-frameTime * 3) + dirY * Math.cos(-frameTime * 3); | |
var oldPlaneX : Float = planeX; | |
planeX = planeX * Math.cos(-frameTime * 3) - planeY * Math.sin(-frameTime * 3); | |
planeY = oldPlaneX * Math.sin(-frameTime * 3) + planeY * Math.cos(-frameTime * 3); | |
} | |
if (e.keyCode == 40) | |
{ | |
// DOWN | |
if (worldMap[Std.int(posX - dirX * frameTime * 5)][Std.int(posY)] == 0) posX -= dirX * frameTime * 5; | |
if (worldMap[Std.int(posX)][Std.int(posY - dirY * frameTime * 5)] == 0) posY -= dirY * frameTime * 5; | |
} | |
if (e.keyCode >= 49 && e.keyCode <= 57) | |
screen.style.width = w * 0.25 * (e.keyCode - 48) + "px"; | |
}, false); | |
} | |
static function main() | |
{ | |
new Main(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment