in this article, we’re going to learn how we can Build Pokémon game using HTML CSS JavaScript, so this is a very simplified Pokémon game and the only thing you do in this game is collect these Pokéballs so every time you collect the balls you get the sound and a new Pokéballs gets generated in place of that ball, so we can again collect another ball we can collect more, so this is a very simple version of a Pokémon game, and we are going to do everything from scratch we won’t be using any library or anything.
Pre-requisites to Build Pokémon Game Using HTML CSS JavaScript
- A good knowledge of HTML.
- Knowledge of CSS and CSS3.
- Good knowledge of JavaScript.
Implementing HTML Markup
in our html let’s create a basic markup and link everything, so we are going to say exclamation mark and hit tab let me close the sidebar by hitting ctrl b and here we can use a link tag to link our CSS, so we are going to use link and the href will be style.css let’s do the same for our JavaScript, so we’re going to say script source will be main.js.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="player"></div>
<script src="main.js"></script>
</body>
</html>
Creating Player & Background
body{
background-image: url("assets/land.png");
}
.player{
width: 80px;
height: 100px;
background-image: url("assets/player_front.png");
background-size: 240px 100px;
background-position: -80px 0;
}
.player.active{
animation: .2s walk linear infinite;
}
@keyframes walk{
0%, 32%{
background-position: 0 0;
}
33%, 65%{
background-position: -80px 0;
}
66%, 100%{
background-position: -160px 0;
}
}
Let’s start by going to our style sheet so here we’re going to start body and our body will have a green background color, so we are going to say background-image equals to assets/land.png.
So after that we want our player, let’s say our player will have a width of 80 pixels and the height can be 100 pixels, we can loop through all the images to create an effect of running, so we have an image for every side. we are going to say background image will be player_front.png.
And we also need to set the size for the x-axis it will be 240 pixels and for the y-axis or the height will be 100 pixels, we will set background-position to -80 pixels and 0. we’re going to set animation and the duration can be let’s say 0.2 second and the name of it can be let’s say work, and it will be linear.
So let’s create that animation now so here we’re going to add keyframes we called it work so from 0% to 32% let’s make the background position will be 0 0, and from 33% to 65% the background position will be -80 pixel 0, and from 66% to 100% the background position will be -160 pixels and 0, we will set animation to infinite, so it won’t stop, we will put this animation to active class, so it can be changed from JavaScript.
Setting Up Bushes
.player{
width: 80px;
height: 100px;
background-image: url("assets/player_front.png");
background-size: 240px 100px;
background-position: -80px 0;
position: fixed;
z-index: 999;
}
.bush{
width: 50px;
height: 40px;
background-image: url("assets/bush.png");
background-size: 100% 100%;
position: fixed;
z-index: -1;
}
Now we also want some bush, the bush will have a width 50 pixels and a height of 40 pixels, and the background image will be our bush.png, then background size will be 100% 100%, our player, bush everything will have a position of fixed, so we are going to say position of fixed, so now the bush is over our player we don’t want that, so we’re also going to say our bush will have a z index of -1 and for our player we can say the z index can be something high like 999 so that way our player will always be above the bush.
const NUM_BUSHES = 50
function createBushes(){
for(let i = 0; i < NUM_BUSHES; i++){
const div = document.createElement('div')
div.classList.add('bush')
div.style.left = Math.random() * 100 + '%'
div.style.top = Math.random() * 100 + '%'
document.body.appendChild(div)
}
}
function init(){
createBushes()
}
init()
Now we don’t want just one bush we want to create a lot of them, so we’re going to create our bushes using JavaScript, so here we’re going to create a function called init() and this init function will initialize our game, now we have to make createBushes() function, let’s also create a constant const num_bushes.
So basically we want to generate like 50 bushes, here we are going to use a for loop, create a const div = document.createElement(’div’), and then we are going to say div.classList.add(’bush’), finally we can say bush.style.left = math.random()*100+’%’, and we’re going to do the same for our style top, and finally we can say document.body.appendChild(div) so we’re adding the div to our document or our body, and we have to call the init function.
Adding Pokéballs To Ground
.pokeball{
width: 30px;
height: 30px;
background-image: url("assets/pokeball.png");
background-size: 100% 100%;
position: fixed;
}
The same way we have to place some Pokéballs randomly, we can just copy bushes so let’s just copy it, for this time the width can be let’s say 30 pixels the height can be let’s say 30 pixels, let’s set background-image Pokéball.png, so again instead of having it in CSS we are going to have it in our JavaScript.
const NUM_BALLS = 5
function createBalls(){
for(let i=0; i<NUM_BALLS; i++:){
const div = document.createElement('div')
div.classList.add('pokeball')
div.style.left = Math.random() * 100 + '%'
div.style.top = Math.random() * 100 + '%'
document.body.appendChild(div)
}
function init(){
createBushes()
createBalls()
}
We’re going to say const NUM_BALLS let’s say we want 5 balls, let’s create the function, we’re going to say function createBalls() and again we’re going to have a for loop inside that we’re going to create a div, so we’re going to say const div = document.createElement(’div’), we’re going to say div.style.left, we’re adding the Pokéball class here, let’s set top and left position, and then we’re adding it to our body by saying document.body.appendChild(’div’).
Adding Movement to Player
const player = document.querySelector('.player')
const player_pos = {
x: parseInt(window.innerWidth / 2),
y: parseInt(window.innerHeight / 2)
}
const player_vel = {
x: 0,
y: 0
}
function run(){
player_pos.x += player_vel.x
player_pos.y += player_vel.y
player.style.left = player_pos.x + 'px'
player.style.bottom = player_pos.y + 'px'
requestAnimationFrame(run)
}
function init(){
createBushes()
createBalls()
run()
}
window.addEventListener('keydown', function(e){
if(e.key == "ArrowUp"){
player_vel.y = 3
player.style.backgroundImage = 'url("assets/player_front.png")'
}
if(e.key == "ArrowDown"){
player_vel.y = -3
player.style.backgroundImage = 'url("assets/player_back.png")'
}
if(e.key == "ArrowLeft"){
player_vel.x = -3
player.style.backgroundImage = 'url("assets/player_left.png")'
}
if(e.key == "ArrowRight"){
player_vel.x = 3
player.style.backgroundImage = 'url("assets/player_right.png")'
}
player.classList.add('active')
})
window.addEventListener('keyup', function(){
player_vel.x = 0
player_vel.y = 0
player.classList.remove('active')
})
Now we want to move our player, for that here we can say const player=document.queryselector, now when to move our player whenever we press our arrow key but before that we’re going to say const player_pause for player position equals to the position can be parseint inside that we can position it in middle somewhere by default.
So we can say window.innerWidth/2 and for the y window.innerHeight/2, we are also going to create a function called run, so function run and this will be our game loop so here we are going to say player.style.left = player pause.x
we want this run function to be called again and again, so we are going to use the request animation frame function, we also want our player to move for that we are going to create another object player velocity, basically x will be 0 y will be 0 initially.
After that we will add an event listener so if player clicks on arrows button player will move for that we will use key down in that we will change the player velocities according to pressed key, we also change default player’s image according to key, after that we will use player.classList.add(’active’) with this line of code we can hold the key, and player will keep moving, then after we want to stop our player if key is not pressing anymore for that we will use another event listener key up, in this case we will reset player’s velocity and remove active.
Setting Up Music & Pokéballs Animation
const balls = []
const sound = new Audio('assets/coin.mp3')
function generateBall(){
const div = document.createElement('div')
div.classList.add('pokeball')
let x = Math.random() * 100 + '%'
let y = Math.random() * 100 + '%'
div.style.left = x
div.style.top = y
balls.push({
ball: div,
pos: {
x,
y
}
})
document.body.appendChild(div)
}
function createBalls(){
for(let i = 0; i < NUM_BALLS; i++){
generateBall()
}
}
function collision($div1, $div2) {
var x1 = $div1.getBoundingClientRect().left;
var y1 = $div1.getBoundingClientRect().top;
var h1 = $div1.clientHeight;
var w1 = $div1.clientWidth;
var b1 = y1 + h1;
var r1 = x1 + w1;
var x2 = $div2.getBoundingClientRect().left;
var y2 = $div2.getBoundingClientRect().top;
var h2 = $div2.clientHeight;
var w2 = $div2.clientWidth;
var b2 = y2 + h2;
var r2 = x2 + w2;
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false;
return true;
}
function checkCollisions(){
balls.forEach(ball => {
if(collision(ball.ball, player)){
sound.play()
ball.ball.remove()
generateBall()
}
})
}
We want to do is when our player is over our Pokéball when to grab this Pokéball, we want to play a sound we want to remove this Pokéball and generate a new Pokéball, so now we need to keep track of our Pokéballs, we are going to add an object here we are going to say ball = div, so ball equals to our div that we created, and we also need to keep track of our position so the x and y position so instead of just saying style. left and style. right, we are going use x and y and after that we are going to say div.style.left equals to x and div.style.right equals to y.
Now when we move our player we also want to know if our player is over on a Pokéball, for that in our run function we are also going to create a function called check collision, we are going to get our ball, and we want to check if our ball is colliding with our div for that we will use get bounding client rate.
This is the functions you have to call it so get bound incline rate will give us the position, we are going to create a variable that stores the position y and height and then position x and width. we can say if collision, if we have a collision between ball, so ball is your objects and ball that ball will give us the div.
If player collides with the ball it should give sound effect for that we will play it using play function, in collision function we will simply return exact position of player and balls. so after determining collision we will remove the colliding ball, and instead of it we will create a new ball at random position for that we have to call create ball function again and again to avoid it we will create a new function called generate ball in that we will move content of create ball function, and we will call it in a loop.
Full Source code of Build Pokémon Game Using HTML CSS JavaScript
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="player"></div>
<script src="main.js"></script>
</body>
</html>
style.css
body{
background-image: url("assets/land.png");
}
.player{
width: 80px;
height: 100px;
background-image: url("assets/player_front.png");
background-size: 240px 100px;
background-position: -80px 0;
position: fixed;
z-index: 999;
}
.player.active{
animation: .2s walk linear infinite;
}
@keyframes walk{
0%, 32%{
background-position: 0 0;
}
33%, 65%{
background-position: -80px 0;
}
66%, 100%{
background-position: -160px 0;
}
}
.bush{
width: 50px;
height: 40px;
background-image: url("assets/bush.png");
background-size: 100% 100%;
position: fixed;
z-index: -1;
}
.pokeball{
width: 30px;
height: 30px;
background-image: url("assets/pokeball.png");
background-size: 100% 100%;
position: fixed;
}
main.js
const NUM_BUSHES = 50
const NUM_BALLS = 5
const player = document.querySelector('.player')
const player_pos = {
x: parseInt(window.innerWidth / 2),
y: parseInt(window.innerHeight / 2)
}
const player_vel = {
x: 0,
y: 0
}
const balls = []
const sound = new Audio('assets/coin.mp3')
function createBushes(){
for(let i = 0; i < NUM_BUSHES; i++){
const div = document.createElement('div')
div.classList.add('bush')
div.style.left = Math.random() * 100 + '%'
div.style.top = Math.random() * 100 + '%'
document.body.appendChild(div)
}
}
function generateBall(){
const div = document.createElement('div')
div.classList.add('pokeball')
let x = Math.random() * 100 + '%'
let y = Math.random() * 100 + '%'
div.style.left = x
div.style.top = y
balls.push({
ball: div,
pos: {
x,
y
}
})
document.body.appendChild(div)
}
function createBalls(){
for(let i = 0; i < NUM_BALLS; i++){
generateBall()
}
}
function collision($div1, $div2) {
var x1 = $div1.getBoundingClientRect().left;
var y1 = $div1.getBoundingClientRect().top;
var h1 = $div1.clientHeight;
var w1 = $div1.clientWidth;
var b1 = y1 + h1;
var r1 = x1 + w1;
var x2 = $div2.getBoundingClientRect().left;
var y2 = $div2.getBoundingClientRect().top;
var h2 = $div2.clientHeight;
var w2 = $div2.clientWidth;
var b2 = y2 + h2;
var r2 = x2 + w2;
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false;
return true;
}
function checkCollisions(){
balls.forEach(ball => {
if(collision(ball.ball, player)){
sound.play()
ball.ball.remove()
generateBall()
}
})
}
function run(){
player_pos.x += player_vel.x
player_pos.y += player_vel.y
player.style.left = player_pos.x + 'px'
player.style.bottom = player_pos.y + 'px'
checkCollisions()
requestAnimationFrame(run)
}
function init(){
createBushes()
createBalls()
run()
}
init()
window.addEventListener('keydown', function(e){
if(e.key == "ArrowUp"){
player_vel.y = 3
player.style.backgroundImage = 'url("assets/player_front.png")'
}
if(e.key == "ArrowDown"){
player_vel.y = -3
player.style.backgroundImage = 'url("assets/player_back.png")'
}
if(e.key == "ArrowLeft"){
player_vel.x = -3
player.style.backgroundImage = 'url("assets/player_left.png")'
}
if(e.key == "ArrowRight"){
player_vel.x = 3
player.style.backgroundImage = 'url("assets/player_right.png")'
}
player.classList.add('active')
})
window.addEventListener('keyup', function(){
player_vel.x = 0
player_vel.y = 0
player.classList.remove('active')
})