<div class="scene"></div>
<script src="https://code.jquery.com/jquery-3.1.0.slim.min.js"></script>
<script src="https://ricostacruz.com/jquery.transit/jquery.transit.min.js"></script>
html, body {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
body::after {
font-family: "operator mono", "sans-serif";
content: "Hover over a block...";
position: absolute;
top: 25px;
left: 25px;
}
.scene {
position: absolute;
left: 50%;
top: 50%;
margin: -192px 0 0 -192px;
width: 384px;
height: 384px;
background: rgba(100, 100, 255, 0.2);
transform: rotateX(60deg) rotateZ(60deg);
transform-style: preserve-3d;
transform-origin: center;
}
.block {
position: absolute;
left: 0;
top: 0;
width: 64px;
height: 64px;
transform-style: preserve-3d;
transform-origin: 50% 50% 50%;
}
.x-axis,
.y-axis,
.z-axis {
position: absolute;
left: 0;
top: 0;
width: 66px;
height: 66px;
transform-origin: 50% 50% 50%;
pointer-events: none;
}
.x-axis {
/* border: solid 2px rgba(255, 0, 0, 0.3); */
}
.y-axis {
/* border: solid 2px rgba(0, 255, 0, 0.3); */
}
.z-axis {
/* border: solid 2px rgba(0, 0, 255, 0.3); */
}
.side {
position: absolute;
left: 0;
top: 0;
width: 64px;
height: 64px;
backface-visibility: hidden;
outline: 1px solid rgba(0, 0, 0, 0.3);
}
.block:hover .side {
outline: 1px solid rgba(0, 255, 0, 0.5);
}
.ghost {
pointer-events: none;
}
.ghost .side {
opacity: 0.6;
pointer-events: none;
-webkit-filter: brightness(1.5);
}
"use strict"
class Block {
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
this.build();
}
build() {
const size = 64;
const x = this.x * 64;
const y = this.y * 64;
const z = this.z * 64;
const block = this.block = $(`<div class="block" />`)
.css({
transform: `
translateX(${x}px)
translateY(${y}px)
translateZ(${z}px)
scale(0.99)
`
});
$(`<div class="x-axis" />`)
.appendTo(block)
.css({
transform: `
rotateX(90deg)
rotateY(0deg)
rotateZ(0deg)
`
});
$(`<div class="y-axis" />`)
.appendTo(block)
.css({
transform: `
rotateX(0deg)
rotateY(90deg)
rotateZ(0deg)
`
});
$(`<div class="z-axis" />`)
.appendTo(block);
this
.createFace("top", 0, 0, size / 2, 0, 0, 0)
.appendTo(block);
this
.createFace("side-1", 0, size / 2, 0, 270, 0, 0)
.appendTo(block);
this
.createFace("side-2", size / 2, 0, 0, 0, 90, 0)
.appendTo(block);
this
.createFace("side-3", 0, size / -2, 0, -270, 0, 0)
.appendTo(block);
this
.createFace("side-4", size / -2, 0, 0, 0, -90, 0)
.appendTo(block);
this
.createFace("bottom", 0, 0, size / -2, 0, 180, 0)
.appendTo(block);
}
createFace(type, x, y, z, rx, ry, rz) {
return $(`<div class="side side-${type}" />`)
.css({
transform: `
translateX(${x}px)
translateY(${y}px)
translateZ(${z}px)
rotateX(${rx}deg)
rotateY(${ry}deg)
rotateZ(${rz}deg)
`,
background: this.createTexture(type)
})
.data("block", this)
.data("type", type);
}
createTexture(type) {
return `rgba(100, 100, 255, 0.2)`;
}
}
const DIRT_TEXTURES = {
"top": [
"https://github.com/assertchris-tutorials/tutorial-javascript-minecraft-editor/raw/master/textures/dirt-top-1.png",
"https://github.com/assertchris-tutorials/tutorial-javascript-minecraft-editor/raw/master/textures/dirt-top-2.png",
"https://github.com/assertchris-tutorials/tutorial-javascript-minecraft-editor/raw/master/textures/dirt-top-3.png"
],
"side": [
"https://github.com/assertchris-tutorials/tutorial-javascript-minecraft-editor/raw/master/textures/dirt-side-1.png",
"https://github.com/assertchris-tutorials/tutorial-javascript-minecraft-editor/raw/master/textures/dirt-side-2.png",
"https://github.com/assertchris-tutorials/tutorial-javascript-minecraft-editor/raw/master/textures/dirt-side-3.png",
"https://github.com/assertchris-tutorials/tutorial-javascript-minecraft-editor/raw/master/textures/dirt-side-4.png",
"https://github.com/assertchris-tutorials/tutorial-javascript-minecraft-editor/raw/master/textures/dirt-side-5.png"
]
};
class Dirt extends Block {
createTexture(type) {
if (type === "top" || type === "bottom") {
const texture = DIRT_TEXTURES.top.random();
return `url(${texture})`;
}
const texture = DIRT_TEXTURES.side.random();
return `url(${texture})`;
}
}
Block.Dirt = Dirt;
Array.prototype.random = function() {
return this[Math.floor(Math.random() * this.length)];
};
const $scene = $(".scene");
const $body = $("body");
for (let x = 0; x < 6; x++) {
for (let y = 0; y < 6; y++) {
let next = new Block.Dirt(x, y, 0);
next.block.appendTo($scene);
}
}
function createCoordinatesFrom(side, x, y, z) {
if (side == "top") {
z += 1;
}
if (side == "side-1") {
y += 1;
}
if (side == "side-2") {
x += 1;
}
if (side == "side-3") {
y -= 1;
}
if (side == "side-4") {
x -= 1;
}
if (side == "bottom") {
z -= 1;
}
return [x, y, z];
}
$body.on("click", ".side", function(e) {
const $this = $(this);
const previous = $this.data("block");
const coordinates = createCoordinatesFrom(
$this.data("type"),
previous.x,
previous.y,
previous.z
);
const next = new Block.Dirt(...coordinates);
next.block.appendTo($scene);
});
let ghost = null;
function removeGhost() {
if (ghost) {
ghost.block.remove();
ghost = null;
}
}
function createGhostAt(x, y, z) {
const next = new Block.Dirt(x, y, z);
next.block
.addClass("ghost")
.appendTo($scene);
ghost = next;
}
$body.on("mouseenter", ".side", function(e) {
removeGhost();
const $this = jQuery(this);
const previous = $this.data("block");
const coordinates = createCoordinatesFrom(
$this.data("type"),
previous.x,
previous.y,
previous.z
);
createGhostAt(...coordinates);
});
$body.on("mouseleave", ".side", function(e) {
removeGhost()
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.