DZone
Web Dev Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Web Dev Zone > 3D Tetris with Three.js Tutorial – Part 5

3D Tetris with Three.js Tutorial – Part 5

Sebastian Poręba user avatar by
Sebastian Poręba
·
May. 04, 12 · Web Dev Zone · Interview
Like (0)
Save
Tweet
4.81K Views

Join the DZone community and get the full member experience.

Join For Free

In the fifth part of tutorial we add some final polish to the game.

  • Part 1: Introduction and game loop
  • Part 2: Static blocks and keeping score
  • Part 3: Adding and moving a block
  • Part 4: Collision detection
  • Part 5: Audio and scoring

Completed slices and score counting

This function will be quite long but simple. To check if a slice is completed I calculate the maximum number of occupied fields and check every slice (moving on z-axis) if it’s full. This way I can change size of the board and this function should be still working. Try to think about all your functions in such way – if something may ever change, make your code flexible.

Tetris.Board.checkCompleted = function() {
  var x,y,z,x2,y2,z2, fields = Tetris.Board.fields;
  var rebuild = false;
 
  var sum, expected = fields[0].length*fields.length, bonus = 0;
 
  for(z = 0; z < fields[0][0].length; z++) {
    sum = 0;
    for(y = 0; y < fields[0].length; y++) {
      for(x = 0; x < fields.length; x++) {
        if(fields[x][y][z] === Tetris.Board.FIELD.PETRIFIED) sum++;
      }
    }
    // to be continued

When the slice is full, we should remove it and shift all the following slices. To make sure that we don’t skip a shifted slice we decrease z once. To make the game more interesting, bonus points are granted if there are multiple slices completed at once.

  if(sum == expected) {
    bonus += 1 + bonus; // 1, 3, 7, 15...
 
    for(y2 = 0; y2 < fields[0].length; y2++) {
      for(x2 = 0; x2 < fields.length; x2++) {
        for(z2 = z; z2 < fields[0][0].length-1; z2++) {
          Tetris.Board.fields[x2][y2][z2] = fields[x2][y2][z2+1]; // shift
        }
        Tetris.Board.fields[x2][y2][fields[0][0].length-1] = Tetris.Board.FIELD.EMPTY;
      }
    }
    rebuild = true;
    z--;
  }
}
if(bonus) {
  Tetris.addPoints(1000 * bonus);
}

Now, even though we dealt with board information, we still have to make changes to Three.js geometries. We couldn’t do it in previous loop as it could rebuild the geometries twice or even more if multiple slices were completed at once. This loop checks every Tetris.Board.fields with corresponding Tetris.staticBlocks adding and removing geometries where needed.

  if(rebuild) {
    for(var z = 0; z < fields[0][0].length-1; z++) {
      for(var y = 0; y < fields[0].length; y++) {
        for(var x = 0; x < fields.length; x++) {
          if(fields[x][y][z] === Tetris.Board.FIELD.PETRIFIED && !Tetris.staticBlocks[x][y][z]) {
            Tetris.addStaticBlock(x,y,z);
          }
          if(fields[x][y][z] == Tetris.Board.FIELD.EMPTY && Tetris.staticBlocks[x][y][z]) {
            Tetris.scene.removeObject(Tetris.staticBlocks[x][y][z]);
            Tetris.staticBlocks[x][y][z] = undefined;
          }
        }
      }
    }
  }
};

Audio API

Adding audio is very simple with HTML5. Let’s start with adding <audio> elements to index.html.

<audio id="audio_theme" src="music/tetris.mp3" preload="auto"></audio>
<audio id="audio_move" src="music/move.mp3" preload="auto"></audio>
<audio id="audio_collision" src="music/collision.mp3" preload="auto"></audio>
<audio id="audio_gameover" src="music/gameover.mp3" preload="auto"></audio>
<audio id="audio_score" src="music/cash.mp3" preload="auto"></audio>

Using these files in JS is also easy. First create an object to store your sounds:

// before Tetris.init()
Tetris.sounds = {};

To call Audio API we have to retrieve these DOM elements.

// in Tetris.init()
Tetris.sounds["theme"] = document.getElementById("audio_theme");
Tetris.sounds["collision"] = document.getElementById("audio_collision");
Tetris.sounds["move"] = document.getElementById("audio_move");
Tetris.sounds["gameover"] = document.getElementById("audio_gameover");
Tetris.sounds["score"] = document.getElementById("audio_score");

There are numerous methods and you can create you own audio player but for our purposes play() and pause() is enough. You can probably guess where you should add the music :)

  • Tetris.sounds["theme"].play() – in Tetris.init(), right after initialization of sound object.
  • Tetris.sounds["theme"].pause() – in Tetris.start().
  • else {Tetris.sounds["move"].play();} – in Tetris.Block.move(), if there is no ground collision.
  • Tetris.sounds["collision"].play(); – in Tetris.Block.move(), if there is a ground collision.
  • Tetris.sounds["score"].play(); – in Tetris.addPoints().
  • Tetris.sounds["gameover"].play(); – in Tetris.Block.generate(), where we test for the lost game.

The end

That’s all folks! Our Tetris is fully functional now. I hope it was a fun way to learn Three.js. There are many topics like advanced geometries, shaders, lights, skeletal animation, etc., that were not covered here. I just wanted to show that to create a game they’re not always needed. Actually, the best fun I’ve ever had was with games like Tetris, where gameplay was not directly related to the graphics quality. Obviously, great games often comes with great looks, but if you are not having fun from the first to the last minute, not even the best graphics can help.

If you liked the series, please share and comment. If you want to learn more, you should probably use pure WebGL from now on. You may start with this tutorial. Check also "Building the game" by Brandon Jones.

After this tutorial you should:

  • Know how to detect and manage completed slices.
  • Know basics of Audio API.
  • Know how to have fun.
  • Start writing your own game.

Grab source from github

If you have trouble with any of these, check tutorial again or ask a question in the comments below.

code style Collision detection Collision (computer science) API Blocks Element Object (computer science) WebGL Testing GitHub

Published at DZone with permission of Sebastian Poręba, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Version Number Anti-Patterns
  • Terraform Controller: Cloud Resource Self-Service
  • Kubernetes Service Types Explained In-Detail
  • SSH Tutorial: Nice and Easy [Video]

Comments

Web Dev Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo