Tower Blocks Game Using HTML CSS And JavaScript

Introduction
Hello coders, welcome to another new blog. Today in this blog we’ll learn to create a Tower Block game. We’ve used HTML CSS and JavaScript to create our Tower Block game. In this game we’ve have set blocks on one another and with each set block our score increases.
We’ve used HTML CSS and JavaScript to create this game. In our Tower Block game, HTML sets up the basic structure of our game and set elements for our game. CSS designs our Tower block game. At last, the main part comes JavaScript. JavaScript and its libraries adds interactive functionality to our game.
If you also want to create this type of game then you should have knowledge of HTML CSS and JavaScript. If you’ve have good amount of knowledge and skills in these technologies then you’re good to go. These type of project always enhance our coding skills and gives a satisfaction. Let’s understand our code.
HTML (index.html)
Get Discount on Top Educational Courses
This is our HTML code which sets up the basic structure for our Tower Block game. Using this HTML code build basic elements of our game. Let’s breakdown our code.
- <!DOCTYPE html> : It defines the type of our document and ensures that our document is a HTML file document.
- <title> : This sets title for our webpage as Tower Blocks.
- <script> : It adds external JavaScript libraries cdn which we can use in our JavaScript file.
- <link> : This tag links external CSS file in our code.
- <script src=”script.js”> : This adds external JavaScript file in our code and ensures to load asynchronously.
- <div id=”container”> : This contains all the game content in main container div.
- <div id=”game”> : This represent the main game area content which we’ll design using JS.
- <div id=”score”> : This displays the in game score of the player.
- <div id=”instruction”> : This displays instruction to play the game .
- <div class =” game-over”> : A h2 and 2 paragraph tags are in this div which will represent the game over condition.
- <div class=”game-ready”> : This will represent the start of the game condition where user can start the game.
Tower Blocks
0
Click (or press the spacebar) to place the block
Game Over
You did great, you're the best.
Click or spacebar to start again
Start
CSS (Style.css)
This is our CSS code which designs our Tower blocks game. CSS is used to design web pages. CSS makes our webpage visually appealing. Let’s breakdown our CSS code.
- Our code starts by importing the google font “Comfortaa”.
- The html and body sets full height and width and removes margin. It sets overflow hidden and position relative.
- The #conatainer sets 100% height and width.
- The #score sets 100% width, displays the score in the center, and applies animation using transition and transform properties. Position set as absolute.
- The #game takes full area by applying all sides as 0 and sets position as absolute.
- The .game-over sets position absolute with top left of 0 and width of 100%. It sets height 85% and center the elements using flexbox.
- A transition is applied to the .game-over class.
- .game-ready takes full height and width and center the elements using flexbox. It also sets position absolute with top and left of 0.
- The #start-button styled with animation and fade movement. It sets transition properties and displays the big font size with transparent background.
- #instruction sets position absolute, 100% width, top 16vh and left 0. It centers the text and adds some animation.
- All the .playing .resetting .ready .ended classes handles the animation for various states of the game.
@import url("https://fonts.googleapis.com/css?family=Comfortaa");
html,
body {
margin: 0;
overflow: hidden;
height: 100%;
width: 100%;
position: relative;
font-family: "Comfortaa", cursive;
}
#container {
width: 100%;
height: 100%;
}
#container #score {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
font-size: 10vh;
transition: transform 0.5s ease;
color: #334;
transform: translatey(-200px) scale(1);
}
#container #game {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
#container .game-over {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 85%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#container .game-over * {
transition: opacity 0.5s ease, transform 0.5s ease;
opacity: 0;
transform: translatey(-50px);
color: #334;
}
#container .game-over h2 {
margin: 0;
padding: 0;
font-size: 40px;
}
#container .game-ready {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
#container .game-ready #start-button {
transition: opacity 0.5s ease, transform 0.5s ease;
opacity: 0;
transform: translatey(-50px);
border: 3px solid #334;
padding: 10px 20px;
background-color: transparent;
color: #334;
font-size: 30px;
}
#container #instructions {
position: absolute;
width: 100%;
top: 16vh;
left: 0;
text-align: center;
transition: opacity 0.5s ease, transform 0.5s ease;
opacity: 0;
}
#container #instructions.hide {
opacity: 0 !important;
}
#container.playing #score,
#container.resetting #score {
transform: translatey(0px) scale(1);
}
#container.playing #instructions {
opacity: 1;
}
#container.ready .game-ready #start-button {
opacity: 1;
transform: translatey(0);
}
#container.ended #score {
transform: translatey(6vh) scale(1.5);
}
#container.ended .game-over * {
opacity: 1;
transform: translatey(0);
}
#container.ended .game-over p {
transition-delay: 0.3s;
}
Javascript (Script.js)
This is our JavaScript code which is the most important code for our Towe Block game. This code adds interactive functionality in our game. In our code we’ve used Three.js , TweenMax.js and JavaScript to make our game animated and visually appealing with proper functionality.
Three.js is generally used to make 3D websites. This is a JavaScript library which is widely used in market to make 3D and animated stuff. We’ve used TweenMax.js in our code as well. TweenMax.js animates any property of any object which JavaScript can touch. This library of JavaScript is mainly used to add animations.
In our JavaScript code we’ve used all these libraries to make our Tower block game user interactive. This game is well designed and works good too. Let’s understand our code in short and easy way.
- Stage class: It handles the 3D visuals set up using Three.js library.
- This class initialize the game container, renderer, scene and lights.
- This class controls the camera movement as well using Tweenlight.
- Block class : In the state management section it handles the active, stopped and missed state of blocks.
- This class controls the size, position and color of the block.
- Movement and direction controls are setup by this class.
- Game class: This class handles all the game logic.
- This class controls the different stages of the game like playing, ready , ending etc.
- It adds blocks and handles their placing in game and updates the score as well.
- It also handles reset and restart game state.
- Game mechanics : This section controls the adding of new block, camera position and all the block placements.
- At last rendering section uses the tick method to update the game and render each frame continuously.
console.clear();
var Stage = /** @class */ (function () {
function Stage() {
// container
var _this = this;
this.render = function () {
this.renderer.render(this.scene, this.camera);
};
this.add = function (elem) {
this.scene.add(elem);
};
this.remove = function (elem) {
this.scene.remove(elem);
};
this.container = document.getElementById("game");
// renderer
this.renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: false,
});
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.setClearColor("#D0CBC7", 1);
this.container.appendChild(this.renderer.domElement);
// scene
this.scene = new THREE.Scene();
// camera
var aspect = window.innerWidth / window.innerHeight;
var d = 20;
this.camera = new THREE.OrthographicCamera(
-d * aspect,
d * aspect,
d,
-d,
-100,
1000
);
this.camera.position.x = 2;
this.camera.position.y = 2;
this.camera.position.z = 2;
this.camera.lookAt(new THREE.Vector3(0, 0, 0));
//light
this.light = new THREE.DirectionalLight(0xffffff, 0.5);
this.light.position.set(0, 499, 0);
this.scene.add(this.light);
this.softLight = new THREE.AmbientLight(0xffffff, 0.4);
this.scene.add(this.softLight);
window.addEventListener("resize", function () {
return _this.onResize();
});
this.onResize();
}
Stage.prototype.setCamera = function (y, speed) {
if (speed === void 0) {
speed = 0.3;
}
TweenLite.to(this.camera.position, speed, {
y: y + 4,
ease: Power1.easeInOut,
});
TweenLite.to(this.camera.lookAt, speed, { y: y, ease: Power1.easeInOut });
};
Stage.prototype.onResize = function () {
var viewSize = 30;
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.camera.left = window.innerWidth / -viewSize;
this.camera.right = window.innerWidth / viewSize;
this.camera.top = window.innerHeight / viewSize;
this.camera.bottom = window.innerHeight / -viewSize;
this.camera.updateProjectionMatrix();
};
return Stage;
})();
var Block = /** @class */ (function () {
function Block(block) {
// set size and position
this.STATES = { ACTIVE: "active", STOPPED: "stopped", MISSED: "missed" };
this.MOVE_AMOUNT = 12;
this.dimension = { width: 0, height: 0, depth: 0 };
this.position = { x: 0, y: 0, z: 0 };
this.targetBlock = block;
this.index = (this.targetBlock ? this.targetBlock.index : 0) + 1;
this.workingPlane = this.index % 2 ? "x" : "z";
this.workingDimension = this.index % 2 ? "width" : "depth";
// set the dimensions from the target block, or defaults.
this.dimension.width = this.targetBlock
? this.targetBlock.dimension.width
: 10;
this.dimension.height = this.targetBlock
? this.targetBlock.dimension.height
: 2;
this.dimension.depth = this.targetBlock
? this.targetBlock.dimension.depth
: 10;
this.position.x = this.targetBlock ? this.targetBlock.position.x : 0;
this.position.y = this.dimension.height * this.index;
this.position.z = this.targetBlock ? this.targetBlock.position.z : 0;
this.colorOffset = this.targetBlock
? this.targetBlock.colorOffset
: Math.round(Math.random() * 100);
// set color
if (!this.targetBlock) {
this.color = 0x333344;
} else {
var offset = this.index + this.colorOffset;
var r = Math.sin(0.3 * offset) * 55 + 200;
var g = Math.sin(0.3 * offset + 2) * 55 + 200;
var b = Math.sin(0.3 * offset + 4) * 55 + 200;
this.color = new THREE.Color(r / 255, g / 255, b / 255);
}
// state
this.state = this.index > 1 ? this.STATES.ACTIVE : this.STATES.STOPPED;
// set direction
this.speed = -0.1 - this.index * 0.005;
if (this.speed 0.5 ? -this.MOVE_AMOUNT : this.MOVE_AMOUNT;
}
}
Block.prototype.reverseDirection = function () {
this.direction = this.direction > 0 ? this.speed : Math.abs(this.speed);
};
Block.prototype.place = function () {
this.state = this.STATES.STOPPED;
var overlap =
this.targetBlock.dimension[this.workingDimension] -
Math.abs(
this.position[this.workingPlane] -
this.targetBlock.position[this.workingPlane]
);
var blocksToReturn = {
plane: this.workingPlane,
direction: this.direction,
};
if (this.dimension[this.workingDimension] - overlap 0) {
var choppedDimensions = {
width: this.dimension.width,
height: this.dimension.height,
depth: this.dimension.depth,
};
choppedDimensions[this.workingDimension] -= overlap;
this.dimension[this.workingDimension] = overlap;
var placedGeometry = new THREE.BoxGeometry(
this.dimension.width,
this.dimension.height,
this.dimension.depth
);
placedGeometry.applyMatrix(
new THREE.Matrix4().makeTranslation(
this.dimension.width / 2,
this.dimension.height / 2,
this.dimension.depth / 2
)
);
var placedMesh = new THREE.Mesh(placedGeometry, this.material);
var choppedGeometry = new THREE.BoxGeometry(
choppedDimensions.width,
choppedDimensions.height,
choppedDimensions.depth
);
choppedGeometry.applyMatrix(
new THREE.Matrix4().makeTranslation(
choppedDimensions.width / 2,
choppedDimensions.height / 2,
choppedDimensions.depth / 2
)
);
var choppedMesh = new THREE.Mesh(choppedGeometry, this.material);
var choppedPosition = {
x: this.position.x,
y: this.position.y,
z: this.position.z,
};
if (
this.position[this.workingPlane] this.MOVE_AMOUNT || value < -this.MOVE_AMOUNT)
this.reverseDirection();
this.position[this.workingPlane] += this.direction;
this.mesh.position[this.workingPlane] = this.position[this.workingPlane];
}
};
return Block;
})();
var Game = /** @class */ (function () {
function Game() {
var _this = this;
this.STATES = {
LOADING: "loading",
PLAYING: "playing",
READY: "ready",
ENDED: "ended",
RESETTING: "resetting",
};
this.blocks = [];
this.state = this.STATES.LOADING;
this.stage = new Stage();
this.mainContainer = document.getElementById("container");
this.scoreContainer = document.getElementById("score");
this.startButton = document.getElementById("start-button");
this.instructions = document.getElementById("instructions");
this.scoreContainer.innerHTML = "0";
this.newBlocks = new THREE.Group();
this.placedBlocks = new THREE.Group();
this.choppedBlocks = new THREE.Group();
this.stage.add(this.newBlocks);
this.stage.add(this.placedBlocks);
this.stage.add(this.choppedBlocks);
this.addBlock();
this.tick();
this.updateState(this.STATES.READY);
document.addEventListener("keydown", function (e) {
if (e.keyCode == 32) _this.onAction();
});
document.addEventListener("click", function (e) {
_this.onAction();
});
document.addEventListener("touchstart", function (e) {
e.preventDefault();
// this.onAction();
// ☝️ this triggers after click on android so you
// insta-lose, will figure it out later.
});
}
Game.prototype.updateState = function (newState) {
for (var key in this.STATES)
this.mainContainer.classList.remove(this.STATES[key]);
this.mainContainer.classList.add(newState);
this.state = newState;
};
Game.prototype.onAction = function () {
switch (this.state) {
case this.STATES.READY:
this.startGame();
break;
case this.STATES.PLAYING:
this.placeBlock();
break;
case this.STATES.ENDED:
this.restartGame();
break;
}
};
Game.prototype.startGame = function () {
if (this.state != this.STATES.PLAYING) {
this.scoreContainer.innerHTML = "0";
this.updateState(this.STATES.PLAYING);
this.addBlock();
}
};
Game.prototype.restartGame = function () {
var _this = this;
this.updateState(this.STATES.RESETTING);
var oldBlocks = this.placedBlocks.children;
var removeSpeed = 0.2;
var delayAmount = 0.02;
var _loop_1 = function (i) {
TweenLite.to(oldBlocks[i].scale, removeSpeed, {
x: 0,
y: 0,
z: 0,
delay: (oldBlocks.length - i) * delayAmount,
ease: Power1.easeIn,
onComplete: function () {
return _this.placedBlocks.remove(oldBlocks[i]);
},
});
TweenLite.to(oldBlocks[i].rotation, removeSpeed, {
y: 0.5,
delay: (oldBlocks.length - i) * delayAmount,
ease: Power1.easeIn,
});
};
for (var i = 0; i
newBlocks.placed.position[newBlocks.plane]
) {
positionParams[newBlocks.plane] =
"+=" + 40 * Math.abs(newBlocks.direction);
} else {
positionParams[newBlocks.plane] =
"-=" + 40 * Math.abs(newBlocks.direction);
}
TweenLite.to(newBlocks.chopped.position, 1, positionParams);
TweenLite.to(newBlocks.chopped.rotation, 1, rotationParams);
}
this.addBlock();
};
Game.prototype.addBlock = function () {
var lastBlock = this.blocks[this.blocks.length - 1];
if (lastBlock && lastBlock.state == lastBlock.STATES.MISSED) {
return this.endGame();
}
this.scoreContainer.innerHTML = String(this.blocks.length - 1);
var newKidOnTheBlock = new Block(lastBlock);
this.newBlocks.add(newKidOnTheBlock.mesh);
this.blocks.push(newKidOnTheBlock);
this.stage.setCamera(this.blocks.length * 2);
if (this.blocks.length >= 5) this.instructions.classList.add("hide");
};
Game.prototype.endGame = function () {
this.updateState(this.STATES.ENDED);
};
Game.prototype.tick = function () {
var _this = this;
this.blocks[this.blocks.length - 1].tick();
this.stage.render();
requestAnimationFrame(function () {
_this.tick();
});
};
return Game;
})();
var game = new Game();
Output:

Disclaimer: The code provided in this post is sourced from GitHub and is distributed under the MIT License. All credits for the original code go to the respective owner. We have shared this code for educational purposes only. Please refer to the original repository for detailed information and any additional usage rights or restrictions.
Windows 12 Notepad Using Python Introduction: In this article, we will create a Windows 12 Notepad using Python. If you are a …
Animated Search Bar using Html CSS And JavaScript Introduction Hello friends, all of you developers are welcome to today’s beautiful blog post. …
Best Quiz Game Using HTML CSS And JavaScript Introduction Hello coders, welcome to another new blog. Today in this article we’ll learn …
Tower Blocks Game Using HTML CSS And JavaScript Introduction Hello coders, welcome to another new blog. Today in this blog we’ll learn …