I just made a really simple version of Red Light Green Light game from Squid Game with JavaScript and THREE.JS.
You can play it here.
If you want a step by step tutorial on how to create this game I have create a YouTube tutorial that you can check.
But if you want just a brief keep reading this article.
So here are the steps I took to create the game:
i. Basic project setup with three js.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.setClearColor( 0xb7c3f3, 1 );
const light = new THREE.AmbientLight( 0xffffff );
scene.add( light )
camera.position.z = 5;
function animate() {
if(gameStat == "over") return
renderer.render( scene, camera );
requestAnimationFrame( animate );
player.update()
}
animate();
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
ii. Use 3d model of doll from squid game.
const loader = new THREE.GLTFLoader()
loader.load("../models/scene.gltf", (gltf) => {
scene.add( gltf.scene );
gltf.scene.scale.set(.4, .4, .4);
gltf.scene.position.set(0, -1, 0);
this.doll = gltf.scene;
})
iii. I also made a Doll class
for convenience.
function delay(ms){
return new Promise(resolve => setTimeout(resolve, ms));
}
class Doll{
constructor(){
loader.load("../models/scene.gltf", (gltf) => {
scene.add( gltf.scene );
gltf.scene.scale.set(.4, .4, .4);
gltf.scene.position.set(0, -1, 0);
this.doll = gltf.scene;
})
}
lookBackward(){
gsap.to(this.doll.rotation, {y: -3.15, duration: .45})
setTimeout(() => isLookingBackward = true, 150)
}
lookForward(){
gsap.to(this.doll.rotation, {y: 0, duration: .45})
setTimeout(() => isLookingBackward = false, 450)
}
//Makes the doll look back for 1.5 - 3 seconds then look forward for .75 - 1.5 seconds and keep repeating these.
async start(){
this.lookBackward()
await delay((Math.random() * 1000) + 1000)
this.lookForward()
await delay((Math.random() * 750) + 750)
this.start()
}
}
iv. Then I made the track the players have to cross using some cubes.
function createCube(size, positionX, rotY = 0, color = 0xfbc851){
const geometry = new THREE.BoxGeometry(size.w, size.h, size.d);
const material = new THREE.MeshBasicMaterial( { color: color } );
const cube = new THREE.Mesh( geometry, material );
cube.position.x = positionX;
cube.rotation.y = rotY;
scene.add( cube );
return cube
}
function createTrack(){
createCube({w: start_position * 2 + .2, h: 1.5, d: 1}, 0, 0, 0xe5a716).position.z = -1;
createCube({w: .2, h: 1.5, d: 1}, start_position, -.35);
createCube({w: .2, h: 1.5, d: 1}, end_position, .35);
}
createTrack()
v. then I also made a Player class
(player is just a sphere)
class Player{
constructor(){
const geometry = new THREE.SphereGeometry( .3, 32, 16 );
const material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
const sphere = new THREE.Mesh( geometry, material );
sphere.position.z = 1
sphere.position.x = start_position
scene.add( sphere )
this.player = sphere
this.playerInfo = {
positionX: start_position,
velocity: 0
}
}
run(){
this.playerInfo.velocity = .03
}
stop(){
gsap.to(this.playerInfo, {velocity: 0, duration: .1})
}
update(){ //Update function is called in animation loop
this.check()
this.playerInfo.positionX -= this.playerInfo.velocity
this.player.position.x = this.playerInfo.positionX
}
}
vi. Then I added key press events to the Player.
window.addEventListener('keydown', (e) => {
if(e.key == "ArrowUp"){
player.run()
}
})
window.addEventListener('keyup', (e) => {
if(e.key == "ArrowUp"){
player.stop()
}
})
vii. Finally I just put everything together and implementing game logics to make it functional.
You can get complete codes here
You may find my articles and YouTube videos interesting to check them out.