JSFiddle - React, Tailwind, and code Playground
CSS
body {
margin: 0;
background-color: #000;
}
body, div, p, a {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
cursor: default;
}
#container {
width: 100vh;
height: 100vw;
max-width: 100vw;
max-height: 100vh;
background-color: #000;
perspective: 750px;
overflow: hidden;
}
#plane {
width: 60%;
height: 80%;
transform-style: preserve-3d;
transform: rotateX(5deg);
transition: left 0.2s ease-in-out, top 0.2s ease-in-out;
}
.wall {
color: olive;
}
.floor {
color: gray;
transition: color 0.2s ease-in-out;
}
.player {
color: white;
}
.element {
transition: left 0.2s ease-in-out, top 0.2s ease-in-out;
}
.tile {
transition: color 0.2s ease-in-out, opacity 0.2s ease-in-out;
}
.tile, .element {
position: absolute;
width: calc(100% / 25);
height: calc(100% / 25);
background-color: transparent;
font-family: 'Droid Sans Mono', 'Lucida Console', 'Consolas', monospace;
}
.inner-text {
margin: 0;
padding: 0;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
#plane-container {
}
.plane-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
transition: left 0.2s ease-in-out, top 0.2s ease-in-out;
}
.absolute-center {
position: absolute;
margin: auto;
left: 0; right: 0; top: 0; bottom: 0;
}
/* latin */
@font-face {
font-family: 'Droid Sans Mono';
font-style: normal;
font-weight: 400;
src: local('Droid Sans Mono'), local('DroidSansMono'), url(http://fonts.gstatic.com/s/droidsansmono/v7/ns-m2xQYezAtqh7ai59hJYdJ2JT0J65PSe7wdxAnx_I.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
JavaScript
// Changing this variable makes the calculation of the player's position go slightly off.
// Set it to 25 for the floor tiles (dots) to be perfectly lined up.
// Give it a go!
var tileScale = 9;
// Game object to supposedly reduce scope chains
function Game(){
// Game reference for when the this keyword is out of scope
var game = this;
// Out of bounds function
Array.prototype.outOfBounds = function(x, y){
return x < 0 || y < 0 || x >= this[0].length || y >= this.length;
}
// Variable declarations
this.map = [];
this.mapSize = 25;
this.tileScale = tileScale;
// Player circle of vision.
this.playerVision = 8;
this.elements = [];
// Function that executes when the browser resizes.
window.onresize = this.resizeViewport = function(initial){
game.viewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
game.viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
game.windowSize = Math.min(game.viewportWidth, game.viewportHeight);
// Droid Sans Mono has a ratio of 3:4 (width:height), conveniently.
game.tileWidth = game.windowSize*.6 / game.tileScale;
game.tileHeight = game.windowSize*.8 / game.tileScale;
// The first call to this function is at a point where these functions are not defined.
if(initial !== true){
game.updateList(game.tiles);
game.updateList(game.elements);
game.updateCamera();
}
}
this.resizeViewport(true);
// Function for attaching elements to the screen
this.createElement = function(type, parent, properties){
var element = document.createElement(type);
for(var i in properties)element[i] = properties[i];
parent.appendChild(element);
return element;
}
// Find pythagorean distance, with distance x and y values found
this.pythagorean = function(dx, dy){
return Math.sqrt(dx*dx+dy*dy);
}
// Change hex value to RGB (in format of e.g. FFFFFF, without #)
this.toRGB = function(triplet){
var color = {};
var sequence = ["red",...