Creating a 3D Tetris Game for Dummies Like Me — IX

Oleksii Koshkin
5 min readJun 25, 2023

--

TL;DR: live demo or the advanced game + some shameless advertising wrapper.

Level: for beginners.
See detailed links and table of contents at the bottom of the article.

Post-production time. Today I’m going to add sound effects and polish the styles.

The final fantasy

The sound effects in HTML5 are very simple. However, I will do it even simpler and use 3r-party: HowlerJS. Let’s install:

npm i -S howler

and import to use:

// App.svelte
import {Howl} from 'howler';

And I’m going to try adding the very first effect, the startup call. First, I need to have the sound… Pixabay! A lot of them. I selected a few and saved them to a public folder.

Then, use:

// App.svelte
...
let isDropDown = false;

// sound effects
const startSound = new Howl({
src: ["./start.mp3"],
});
const tickSound = new Howl({
src: ["./tick.mp3"],
});
const newSound = new Howl({
src: ["./new.mp3"],
});
const clickSound = new Howl({
src: ["./click.mp3"],
});
const thudSound = new Howl({
src: ["./thud.mp3"],
});
const tadaSound = new Howl({
src: ["./tada.mp3"],
});

...
function startGame() {
if (started || gameOver) {
return;
}

if (sound) {
startSound.play();
}
...
}

And repeat such piece–

sound && startSound.play();
...
sound && thudSound.play();
...

everywhere. On move, on drop, on remove lines, on start new level…

Next step: I wand to improve the Banners.

Firstly, it turned out that it is more convenient to switch steps using the spacebar, and not any key. So, I replace the texts…

<p>press Space to start</p>

and code in keyboard processing.

// App.svelte
function processKeysDown(ev) {
let e = ev.key;

if (!started) {
// "space" on not started -> to start game
if (e === "Space" || e === " ") {
startGame();
}
return;
}

if (gameOver) {
// "space" on game over -> to not started
if (e === "Space" || e === " ") {
waitGame();
}
return;
}
...
}

Then I tune overall game backgrounds, paddings for banners and styles:

<style>
#pause-banner {
position: absolute;
top: 60px;
left: 60px;
right: 60px;
bottom: 60px;
border-radius: 20px;
box-shadow: 0 10px 60px rgba(0, 0, 0, 0.8);
opacity: .97;
border: 1px solid rgba(255, 255,255, .2);

display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
background: linear-gradient(to bottom right, #00b912, #1d8e01);
}
</style>

Now it looks like:

Next steps: proportions to make the main box a bit bigger, colors, background… and this is the final design:

Last minute bonus level progress bar:

Level progress
  <div id="level-progress">
<span style="width:{linesRemovedOnLevel * 10}%" />
</div>

#level-progress {
width: 100px;
height: 4px;
display: flex;
background-color: rgba(0, 0, 0, 0.2);
margin-top: 30px;
}

#level-progress span {
background-color: #ffa600;
height: 100%;
transition: all 1s ease;
}

Last but not least. To publish the result somewhere, this time on GitHub Pages, I need to make a couple of changes. Otherwise, it will show a white screen and swear that resources are not available.

First, index.html: add <base href=”./”/> to head:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<base href="./"/> <!-- this one -->
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tetris 3D</title>
</head>
<body>
...

The second, add the same to vite.config.ts:

import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [svelte()],
base: './' // <-- add this one
})

What result?

  1. Introduction to ThreeJS. Basic 3D objects, materials, scenes. Compositions and hand-made animations.
  2. An introduction to game design, even something as simple as this: main loop, states, controls…
  3. Basic sound effects.

It ain’t much, but it’s honest work.jpg.

A breath of fresh air after CRUD, REST, Scrum… at least I am satisfied with all this drive and inspiration. And maybe someone will come in handy — this will be the best result.

Of course, there are a lot of things that need to be improved, ranging from the style of the code (I hardly cared about proper code splitting for simplicity) to the game design. Like adding some animations you can see here.

It’s up to you.

And now you have everything to start creating, I’m not afraid to say, Arkanoid! Or Sokoban! Or Halo… well, not this one, yet.

Wow, it’s been a long journey. It’s funny, but the articles took longer than the game itself.

Enjoy!

Here is the GitHub repository with a snapshot of the stage. And here is a live demo.

--

--

Oleksii Koshkin

AWS certified Solution Architect at GlobalLogic/Hitachi