<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>Smashinglabs</title> <atom:link href="http://www.smashinglabs.pl/feed" rel="self" type="application/rss+xml" /><link>http://www.smashinglabs.pl</link> <description>Sebastian Poręba&#039;s blog</description> <lastBuildDate>Sat, 17 Mar 2012 14:57:48 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>Talks and lectures weekend</title><link>http://www.smashinglabs.pl/talks-and-lectures-weekend</link> <comments>http://www.smashinglabs.pl/talks-and-lectures-weekend#comments</comments> <pubDate>Sat, 17 Mar 2012 14:57:48 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[links]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=795</guid> <description><![CDATA[Every now and then I spend a weekend watching various lectures and talks. I&#8217;d like to share some of my favourites from the last few days: Bret Victor &#8211; Inventing on Principle Very inspiring talk about tools with graphical feedback and finding your principles in life. I love one of the comments on HN: &#8220;It&#8217;s<a
href="http://www.smashinglabs.pl/talks-and-lectures-weekend">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>Every now and then I spend a weekend watching various lectures and talks. I&#8217;d like to share some of my favourites from the last few days:<br
/> <span
id="more-795"></span></p><h2>Bret Victor &#8211; Inventing on Principle</h2><p>Very inspiring talk about tools with graphical feedback and finding your principles in life. I love one of the comments on HN: &#8220;It&#8217;s embarrassing and inspiring how many orders of magnitude higher this guy is playing at. What a presentation.&#8221;</p><p><iframe
src="http://player.vimeo.com/video/36579366?byline=0" width="560" height="315" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></p><h2>GDC 2012: From Console to Chrome</h2><p>I enjoyed this one, it&#8217;s kinda like my <a
href="http://www.smashinglabs.pl/lectures/js-performance" title="lecture on JavaScript performance">lecture on JavaScript performance</a>, but done waaaay better and by someone who actually knows how it works. There is a lot about V8 performance in deep details. My favourite quote: &#8220;JavaScript always thinks that everything is ok&#8221;.</p><p><iframe
width="560" height="315" src="http://www.youtube.com/embed/XAqIpGU8ZZk" frameborder="0" allowfullscreen></iframe></p><h2>GDC 2012: Best practices in developing a web game</h2><p>It should be named &#8220;Cool Google APIs for a web game&#8221;, but it&#8217;s worth watching. It has some good comments on delievering and caching content. There is also a part about localization, monetization and V8 performance. My favourite quote: &#8220;Monetization is a dark art&#8221;.</p><p><iframe
width="560" height="315" src="http://www.youtube.com/embed/huXucPChX3g" frameborder="0" allowfullscreen></iframe></p><h2>Google I/O 2011: WebGL Techniques and Performance</h2><p>It&#8217;s a great intoruction to math and optimizations in WebGL with plenty of do&#8217;s and dont&#8217;s about use of uniforms and structuring your shaders for performance.</p><p><iframe
width="560" height="315" src="http://www.youtube.com/embed/rfQ8rKGTVlg" frameborder="0" allowfullscreen></iframe></p><h2>Dialogue with Richard Dawkins, Rowan Williams and Anthony Kenny</h2><p>Absolutely (well, almost) non-technical video of dialogue between Richard Dawkins and Archbishop Rowan Williams, led by Anthony Kenny. I expected it to be a classic believer-atheist mayhem, but it turned out to be a great discussion. It goes deep into philosophy, concept of mind, conciousness and history of man, proving a great erudicion and articulation skills of both adversaries.</p><p><iframe
width="560" height="315" src="http://www.youtube.com/embed/bow4nnh1Wv0" frameborder="0" allowfullscreen></iframe></p><h2>A Walk on the Dart Side: A Quick Tour of Dart</h2><p>In contrary to the previous video, this lecture turned (at the end) into a flamewar about static/dynamic typing. In fact, most of the presentation is about types and I genuinely hope that Dart introduces a little more than that. Gilad Bracha is obviously a wise and experienced guy, but he is a little too religious about his language choices for me. I consider myself a technology agnostic.</p><p><iframe
width="560" height="410" src="http://www.youtube.com/embed/-IavVtOE_Fg" frameborder="0" allowfullscreen></iframe></p><h2>Using Google Closure for Lean and Mean Javascript Projects &#8211; New Game 2011</h2><p>Google Closure compiler suffers from lack of tutorials and documentation (especially on Closure Tools). This presentation is a nice introduction to concepts behind Closure toolset.</p><p><iframe
width="560" height="315" src="http://www.youtube.com/embed/OJ-vTq4lp10" frameborder="0" allowfullscreen></iframe></p><p>I also watched enormous amount of Mythbusters episodes, a great combination of fun and engineering <img
src='http://www.smashinglabs.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> After watching all of the above during one weekend I&#8217;m completely brainwashed. I&#8217;ll probably wait few months before next lectures weekend, but I&#8217;ll be happy to hear about any new videos out there.</p> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/talks-and-lectures-weekend/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>3D Tetris with Three.js tutorial &#8211; part 5</title><link>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-5</link> <comments>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-5#comments</comments> <pubDate>Mon, 12 Mar 2012 11:09:10 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[Tetris tutorial]]></category> <category><![CDATA[WebGL]]></category> <category><![CDATA[JavaScript]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=782</guid> <description><![CDATA[In the fifth part of tutorial we add some final polish to the game. 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&#8217;s full. This way I<a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-5">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>In the fifth part of tutorial we add some final polish to the game.</p><p><span
id="more-782"></span></p><ul><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-1">Part 1: Introduction and game loop</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-2">Part 2: Static blocks and keeping score</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-3">Part 3: Adding and moving a block</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 4: Collision detection</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 5: Audio and scoring</a></li></ul><h2>Completed slices and score counting</h2><p>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&#8217;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 &#8211; if something may ever change, make your code flexible.</p><pre class="brush: jscript; title: ; notranslate">
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 &lt; fields[0][0].length; z++) {
    sum = 0;
    for(y = 0; y &lt; fields[0].length; y++) {
      for(x = 0; x &lt; fields.length; x++) {
        if(fields[x][y][z] === Tetris.Board.FIELD.PETRIFIED) sum++;
      }
    }
    // to be continued
</pre><p>When the slice is full, we should remove it and shift all the following slices. To make sure that we don&#8217;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.</p><pre class="brush: jscript; title: ; notranslate">
    if(sum == expected) {
      bonus += 1 + bonus; // 1, 3, 7, 15...

      for(y2 = 0; y2 &lt; fields[0].length; y2++) {
        for(x2 = 0; x2 &lt; fields.length; x2++) {
          for(z2 = z; z2 &lt; 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);
  }
</pre><p>Now, even though we dealt with board information, we still have to make changes to Three.js geometries. We couldn&#8217;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.</p><pre class="brush: jscript; title: ; notranslate">
  if(rebuild) {
    for(var z = 0; z &lt; fields[0][0].length-1; z++) {
      for(var y = 0; y &lt; fields[0].length; y++) {
        for(var x = 0; x &lt; fields.length; x++) {
          if(fields[x][y][z] === Tetris.Board.FIELD.PETRIFIED &amp;&amp; !Tetris.staticBlocks[x][y][z]) {
            Tetris.addStaticBlock(x,y,z);
          }
          if(fields[x][y][z] == Tetris.Board.FIELD.EMPTY &amp;&amp; Tetris.staticBlocks[x][y][z]) {
            Tetris.scene.removeObject(Tetris.staticBlocks[x][y][z]);
            Tetris.staticBlocks[x][y][z] = undefined;
          }
        }
      }
    }
  }
};
</pre><h2>Audio API</h2><p>Adding audio is very simple with HTML5. Let&#8217;s start with adding &lt;audio&gt; elements to index.html.</p><pre class="brush: xml; title: ; notranslate">
&lt;audio id=&quot;audio_theme&quot; src=&quot;music/tetris.mp3&quot; preload=&quot;auto&quot;&gt;&lt;/audio&gt;
&lt;audio id=&quot;audio_move&quot; src=&quot;music/move.mp3&quot; preload=&quot;auto&quot;&gt;&lt;/audio&gt;
&lt;audio id=&quot;audio_collision&quot; src=&quot;music/collision.mp3&quot; preload=&quot;auto&quot;&gt;&lt;/audio&gt;
&lt;audio id=&quot;audio_gameover&quot; src=&quot;music/gameover.mp3&quot; preload=&quot;auto&quot;&gt;&lt;/audio&gt;
&lt;audio id=&quot;audio_score&quot; src=&quot;music/cash.mp3&quot; preload=&quot;auto&quot;&gt;&lt;/audio&gt;
</pre><p>Using these files in JS is also easy. First create an object to store your sounds:</p><pre class="brush: jscript; title: ; notranslate">
// before Tetris.init()
Tetris.sounds = {};
</pre><p>To call Audio API we have to retrieve these DOM elements.</p><pre class="brush: jscript; title: ; notranslate">
// in Tetris.init()
Tetris.sounds[&quot;theme&quot;] = document.getElementById(&quot;audio_theme&quot;);
Tetris.sounds[&quot;collision&quot;] = document.getElementById(&quot;audio_collision&quot;);
Tetris.sounds[&quot;move&quot;] = document.getElementById(&quot;audio_move&quot;);
Tetris.sounds[&quot;gameover&quot;] = document.getElementById(&quot;audio_gameover&quot;);
Tetris.sounds[&quot;score&quot;] = document.getElementById(&quot;audio_score&quot;);
</pre><p>There are <a
href="https://developer.mozilla.org/en/Using_HTML5_audio_and_video">numerous methods</a> 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 <img
src='http://www.smashinglabs.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><ul><li>Tetris.sounds["theme"].play() &#8211; in Tetris.init(), right after initialization of sound object.</li><li>Tetris.sounds["theme"].pause() &#8211; in Tetris.start().</li><li>else {Tetris.sounds["move"].play();} &#8211; in Tetris.Block.move(), if there is no ground collision.</li><li>Tetris.sounds["collision"].play();  &#8211; in Tetris.Block.move(), if there is a ground collision.</li><li>Tetris.sounds["score"].play(); &#8211; in Tetris.addPoints().</li><li>Tetris.sounds["gameover"].play(); &#8211; in Tetris.Block.generate(), where we test for the lost game.</li></ul><h2>The end</h2><p>That&#8217;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&#8217;re not always needed. Actually, the best fun I&#8217;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.</p><p>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 <a
href="http://blogoben.wordpress.com/webgl-basics/">this tutorial</a>. Check also <a
href="http://blog.tojicode.com/2011/10/building-game-part-0-foreword.html">&quot;Building the game&quot; by Brandon Jones</a>.</p><div
class="summarybox"><h2>After this tutorial you should:</h2><ul><li>Know how to detect and manage completed slices.</li><li>Know basics of Audio API.</li><li>Know how to have fun.</li><li>Start writing your own game.</li></ul><p> <a
href="https://github.com/fridek/Threejs-Tetris-Tutorial/tree/Tutorial_part_5"><img
src="http://www.smashinglabs.pl/wp-content/themes/Horcrux/images/github.png"> Grab source from github</a></p><p> If you have trouble with any of these, check tutorial again or ask a question in the comments below.</p></div> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-5/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>3D Tetris with Three.js tutorial &#8211; part 4</title><link>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4</link> <comments>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4#comments</comments> <pubDate>Mon, 05 Mar 2012 09:22:54 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[Tetris tutorial]]></category> <category><![CDATA[WebGL]]></category> <category><![CDATA[JavaScript]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=741</guid> <description><![CDATA[Fourth part may be the most difficult so far. We will talk about collision detection. Board object We will start with a new class to store our 3D space information. We need few &#8220;const&#8221;, &#8220;enum&#8221; values. They are really neither const nor enum, as there are no such things in JS, but there is a<a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>Fourth part may be the most difficult so far. We will talk about collision detection.</p><p><span
id="more-741"></span></p><ul><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-1">Part 1: Introduction and game loop</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-2">Part 2: Static blocks and keeping score</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-3">Part 3: Adding and moving a block</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 4: Collision detection</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 5: Audio and scoring</a></li></ul><h2>Board object</h2><p>We will start with a new class to store our 3D space information. We need few &#8220;const&#8221;, &#8220;enum&#8221; values. They are really neither const nor enum, as there are no such things in JS, but there is a <a
href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze">new function in JS 1.8.5 &#8211; freeze</a>. You can create an object and protect it from any further modification. It is widely supported in all browsers that may run WebGL and will give us enum-like objects.</p><pre class="brush: jscript; title: ; notranslate">
window.Tetris = window.Tetris  || {};
Tetris.Board = {};

Tetris.Board.COLLISION = {NONE:0, WALL:1, GROUND:2};
Object.freeze(Tetris.Board.COLLISION);

Tetris.Board.FIELD = {EMPTY:0, ACTIVE:1, PETRIFIED:2};
Object.freeze(Tetris.Board.FIELD);
</pre><p>We will use field enum to store state of our board in fields array. On game start we need to initialize it as empty.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Board.fields = [];

Tetris.Board.init = function(_x,_y,_z) {
	for(var x = 0; x &lt; _x; x++) {
		Tetris.Board.fields[x] = [];
		for(var y = 0; y &lt; _y; y++) {
			Tetris.Board.fields[x][y] = [];
			for(var z = 0; z &lt; _z; z++) {
				Tetris.Board.fields[x][y][z] = Tetris.Board.FIELD.EMPTY;
			}
		}
	}
};
</pre><p>Tetris.Board.init() should be called before any block appears in game. I call it from Tetris.init, because we can easily provide board dimensions as parameters:</p><pre class="brush: jscript; title: ; notranslate">
// add anywhere in Tetris.init
Tetris.Board.init(boundingBoxConfig.splitX, boundingBoxConfig.splitY, boundingBoxConfig.splitZ);
</pre><p>We should also modify Tetris.Block.petrify function, so that it stores information in our new array.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Block.petrify = function () {
    var shape = Tetris.Block.shape;
    for (var i = 0; i &lt; shape.length; i++) {
        Tetris.addStaticBlock(Tetris.Block.position.x + shape[i].x, Tetris.Block.position.y + shape[i].y, Tetris.Block.position.z + shape[i].z);
        Tetris.Board.fields[Tetris.Block.position.x + shape[i].x][Tetris.Block.position.y + shape[i].y][Tetris.Block.position.z + shape[i].z] = Tetris.Board.FIELD.PETRIFIED;
    }
};
</pre><h2>Collision detection</h2><p>There are two main types of collisions in Tetris. First one is wall collision, when active block hits a wall or another block while being moved or rotated on x/y axes (e.g. on one level). Second one is ground collision which happens when block is moved on z-axis and hits floor or another block and it&#8217;s life cycle is finished.</p><p>We will start with board walls collision, which is quite easy. To make code nicer (and faster) I used shorthands again.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Board.testCollision = function (ground_check) {
    var x, y, z, i;

    // shorthands
    var fields = Tetris.Board.fields;
    var posx = Tetris.Block.position.x, posy = Tetris.Block.position.y,
        posz = Tetris.Block.position.z, shape = Tetris.Block.shape;

    for (i = 0; i &lt; shape.length; i++) {
        // 4 walls detection for every part of the shape
        if ((shape[i].x + posx) &lt; 0 ||
            (shape[i].y + posy) &lt; 0 ||
            (shape[i].x + posx) &gt;= fields.length ||
            (shape[i].y + posy) &gt;= fields[0].length) {
            return Tetris.Board.COLLISION.WALL;
        }
        // to be continued
</pre><p>Now how to deal with block-block collision? We already store petrified blocks in our array, so we can check if block is intersecting with any of existing cubes. You may wonder why testCollision has ground_check as an argument. It&#8217;s a result of a simple observation, that block-block collision is detected in almost the same way for ground and wall collision. The only distinction is movement on z-axis which should cause ground hit.</p><pre class="brush: jscript; title: ; notranslate">
        if (fields[shape[i].x + posx][shape[i].y + posy][shape[i].z + posz - 1] === Tetris.Board.FIELD.PETRIFIED) {
            return ground_check ? Tetris.Board.COLLISION.GROUND : Tetris.Board.COLLISION.WALL;
        }
        // to be continued
</pre><p>We will also test if position on z-axis in not equal to zero. That means that there are no cubes below our moving block, but it reached the ground level and should be petrified anyway.</p><pre class="brush: jscript; title: ; notranslate">
        if((shape[i].z + posz) &lt;= 0) {
            return Tetris.Board.COLLISION.GROUND;
        }
    }
};
</pre><h2>Collision reaction</h2><p>It wasn&#8217;t so bad, was it? Now lets do something with information we have. We will start in the easiest place, detection of the lost game. We can do it by testing if there is a collision immediately after creating a new block. If it hits the ground, there is no point in playing further.</p><p>Add to Tetris.Block.generate after block position is calculated:</p><pre class="brush: jscript; title: ; notranslate">
    if (Tetris.Board.testCollision(true) === Tetris.Board.COLLISION.GROUND) {
        Tetris.gameOver = true;
        Tetris.pointsDOM.innerHTML = &quot;GAME OVER&quot;;
        Cufon.replace('#points');
    }
</pre><p>Movement is also simple. After we change a position we call collision detection, passing the information about z-axis movement as an argument.</p><p>If there is a wall collision the move was impossible and we should undo it. We could add few lines to subtract position but I&#8217;m lazy and I prefer to call the move function again, but with inverted arguments. It will be never used with z-axis movement so we can pass a zero as z.</p><p>If the shape hits the ground, we already have a function hitBottom() that should be called. It will remove active shape from the game, modify board state and create a new shape.</p><pre class="brush: jscript; title: ; notranslate">
    // add instead of ground level detection from part 3
    var collision = Tetris.Board.testCollision((z != 0));
    if (collision === Tetris.Board.COLLISION.WALL) {
        Tetris.Block.move(-x, -y, 0); // laziness FTW
    }
    if (collision === Tetris.Board.COLLISION.GROUND) {
        Tetris.Block.hitBottom();
    }
</pre><p>And now comes the crazy part. If you run game at this point, you will notice that rotating shape is not permanent. When it hits the ground, it returns to the initial rotation. That&#8217;s because we apply rotation to the Three.js mesh (as Tetris.Block.mesh.rotation) but we don&#8217;t use it to get coordinates of our cube-based shape representation. To deal with it we need to go through a quick math lesson.</p><h2>3D math</h2><p><em>DISCLAIMER: If you are afraid of math or have little time, you can actually skip this part. It&#8217;s important to know what happens inside your engine, but later we will use a Three.js functions for that.</em></p><p>Consider a 3-element vector (which represents position in 3D space).  To transform such vector in euclidean space we have to add another vector. It can be represented as:</p><p>\[\begin{matrix}x\\y\\z\\\end{matrix}\ + \begin{matrix}\delta x\\\delta y\\\delta z\\\end{matrix} = \begin{matrix}x'\\ y'\\ z'\\\end{matrix} \]</p><p>It&#8217;s fairly simple. The problem appears when we would like to rotate a vector. Rotation around a single axis affects two of the three coordinates (check if you don&#8217;t believe) and equations aren&#8217;t that simple. Luckily, there is one method used in almost all computer generated graphics, including Three.js, WebGL, OpenGL and GPU itself. If you remember from high school, multiplying a vector by matrix will result in another vector. There is a number of transformations based on that. The easiest one is neutral transformation (using identity matrix) that does nothing but shows general idea and is used as a base for other transformations.</p><p>\[\begin{matrix}x\\y\\z\\w\\\end{matrix}\ * \begin{matrix} 1 &#038; 0 &#038; 0 &#038; 0\\0 &#038; 1 &#038; 0 &#038; 0\\0 &#038; 0 &#038; 1 &#038; 0\\0 &#038; 0 &#038; 0 &#038; 1\end{matrix}\ = \begin{matrix}x\\y\\z\\w\\\end{matrix}\]</p><p>Why do we use 4&#215;4 matrices and 4-element vectors instead of 3&#215;3 and 3-elements? It&#8217;s used to enable translation by a vector:</p><p>\[\begin{matrix}x\\y\\z\\w\\\end{matrix}\ * \begin{matrix} 1 &#038; 0 &#038; 0 &#038; \delta x\\0 &#038; 1 &#038; 0 &#038; \delta y\\0 &#038; 0 &#038; 1 &#038; \delta z\\0 &#038; 0 &#038; 0 &#038; 1\end{matrix}\ = \begin{matrix}x'\\y'\\z'\\w'\\\end{matrix}\]</p><p>It&#8217;s a nice math trick that makes all equations easier. It also helps with numerical errors and enables us to use even more advanced concepts like <a
href="http://www.cprogramming.com/tutorial/3d/quaternions.html">quaternions</a>.</p><p>Scaling is also simple:</p><p>\[\begin{matrix}x\\y\\z\\w\\\end{matrix}\ * \begin{matrix} sx &#038; 0 &#038; 0 &#038; 0\\ 0 &#038; sy &#038; 0 &#038; 0\\ 0 &#038; 0 &#038; sz &#038; 0\\ 0 &#038; 0 &#038; 0 &#038; 1 \end{matrix}= \begin{matrix}x * sx\\y * sy\\z * sz\\w'\\\end{matrix}\]</p><p>There are three matrices for rotations, one for every axis.</p><p>For x-axis</p><p>\[ \begin{matrix}  1 &#038; 0 &#038; 0 &#038; 0\\  0 &#038; cos \alpha &#038; -sin \alpha &#038; 0\\  0 &#038; sin \alpha &#038; cos \alpha &#038; 0\\  0 &#038; 0 &#038; 0 &#038; 1 \end{matrix}\]</p><p>For y-axis</p><p>\[ \begin{matrix}  cos \alpha &#038; 0 &#038; sin \alpha &#038; 0\\  0 &#038; 1 &#038; 0 &#038; 0\\  -sin \alpha &#038; 0 &#038; cos \alpha &#038; 0\\  0 &#038; 0 &#038; 0 &#038; 1 \end{matrix}\]</p><p>For z-axis</p><p>\[ \begin{matrix}  cos \alpha &#038; -sin \alpha &#038; 0 &#038; 0\\  sin \alpha &#038; cos \alpha &#038; 0 &#038; 0\\  0 &#038; 0 &#038; 1 &#038; 0\\  0 &#038; 0 &#038; 0 &#038; 1 \end{matrix}\]</p><p>Another great thing about matrix transformations is that we can easily combine two transformations by multiplying its matrices. If you want to rotate around all three axes, you can multiply three matrices and get something called transformation matrix. It will easily transform a vector that represents a position.</p><p>If you are interested in writing your own math library, you can <a
href="http://blogoben.wordpress.com/2011/06/05/webgl-basics-5-full-transformation-matrix/">read this tutorial on blog-o-ben</a>. Very good introduction to math and pure WebGL. You may also need to read some good book about physics or graphics. <a
href="http://www.amazon.com/Game-Physics-Engine-Development-Second/dp/0123819768/">I recommend Ian Millington&#8217;s Game Physics Engine Development</a>.</p><p>Luckily most of the times you don&#8217;t have to work on that. Three.js already has a built in math library and we are going to use it.</p><h2>Back to rotation</h2><p>To rotate a shape in Three.js we need to create a rotation matrix and multiply it with shape&#8217;s every vector. We will use cloneVector again to make sure that created shape is independent from the one stored as a pattern.</p><pre class="brush: jscript; title: ; notranslate">
    // append to Tetris.Block.rotate()
    var rotationMatrix = new THREE.Matrix4();
    rotationMatrix.setRotationFromEuler(Tetris.Block.mesh.rotation);

    for (var i = 0; i &lt; Tetris.Block.shape.length; i++) {
        Tetris.Block.shape[i] = rotationMatrix.multiplyVector3(
            Tetris.Utils.cloneVector(Tetris.Block.shapes[this.blockType][i])
        );
        Tetris.Utils.roundVector(Tetris.Block.shape[i]);
    }
    // to be continued
</pre><p>There is one problem with rotation matrix and our representation of the board. Fields are represented as an array which is indexed by integers, while a result of matrix-vector multiplication may be a float. JavaScript is not very good with floating point numbers and it&#8217;s almost sure that it will produce positions like 1.000001 or 2.999998. This is why we need a rounding function.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Utils.roundVector = function(v) {
    v.x = Math.round(v.x);
    v.y = Math.round(v.y);
    v.z = Math.round(v.z);
};
</pre><p>When we have our shape rotated, it&#8217;s very simple to check if collision occurs. I used the same trick with undoing rotation by calling function again, but with inverted parameters. Please note, that collision will never occur when undoing a move. If you want, you can add additional parameter so it won&#8217;t be checked again when not needed.</p><pre class="brush: jscript; title: ; notranslate">
    // append to Tetris.Block.rotate()
    if (Tetris.Board.testCollision(false) === Tetris.Board.COLLISION.WALL) {
        Tetris.Block.rotate(-x, -y, -z); // laziness FTW
    }
</pre><h2>Summary</h2><p>Our Tetris is almost completed. Playing it is already some fun. In following parts of tutorial we will focus on adding more juice to the game &#8211; there will be scoring system, some HTML5 audio and eye candies.</p><div
class="summarybox"><h2>After this tutorial you should:</h2><ul><li>Know what enum is and how to emulate it in JavaScript.</li><li>Know how to detect different types of collision in Tetris.</li><li>Be familiar with shorthands for<ul><li>if conditional: test ? if_true : if_false</li><li>long scope resolution: var tmpVal = some.long.obj.val</li><li>boolean as a parameter: myFunc((foo === 42))</li></ul></li><li>Understand 3D math &#8211; transforming vectors (positions) with matrices.</li></ul><p> <a
href="https://github.com/fridek/Threejs-Tetris-Tutorial/tree/Tutorial_part_4"><img
src="http://www.smashinglabs.pl/wp-content/themes/Horcrux/images/github.png"> Grab source from github</a></p><p> If you have trouble with any of these, check tutorial again or ask a question in the comments below.</p></div> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>3D Tetris with Three.js tutorial &#8211; part 3</title><link>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-3</link> <comments>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-3#comments</comments> <pubDate>Mon, 27 Feb 2012 09:31:28 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[Tetris tutorial]]></category> <category><![CDATA[WebGL]]></category> <category><![CDATA[JavaScript]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=669</guid> <description><![CDATA[Third part of the tutorial is about moving blocks. We will create a block, introduce some movement and steering. For now we won&#8217;t care about collision detection. Lets start with a summary. What is a lifecycle of a Tetris block? It&#8217;s created at some fixed point, moved and rotated by the player, as time passes<a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-3">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>Third part of the tutorial is about moving blocks. We will create a block, introduce some movement and steering. For now we won&#8217;t care about collision detection.</p><p><span
id="more-669"></span></p><ul><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-1">Part 1: Introduction and game loop</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-2">Part 2: Static blocks and keeping score</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-3">Part 3: Adding and moving a block</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 4: Collision detection</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 5: Audio and scoring</a></li></ul><p>Lets start with a summary. What is a lifecycle of a Tetris block? It&#8217;s created at some fixed point, moved and rotated by the player, as time passes it also falls down by itself and at the very end it hits the ground and is turned into a static element. Then a next block is created and the cycle repeats. This description is more or less a plan of methods we should have in our block object.</p><h2>Preparation</h2><p>At first create a new file to hold our block object and include it in index.html. The file should start with:</p><pre class="brush: jscript; title: ; notranslate">
window.Tetris = window.Tetris  || {}; // equivalent to if(!window.Tetris) window.Tetris = {};
</pre><p>This way, even if file parse order is somehow disturbed (which is very unlikely, BTW) you will never overwrite existing objects or use undefined variables. At this point you may want to replace &#8220;var Tetris = {};&#8221; declaration in our main file as well.</p><p>We need one utility function before we continue.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Utils = {};

Tetris.Utils.cloneVector = function (v) {
  return {x: v.x, y: v.y, z: v.z};
};
</pre><p>To understand why on Earth would we need it, we have to talk about variables in JS. If we use a number, it&#8217;s always passed by value. It means that writing:</p><pre class="brush: jscript; title: ; notranslate">
var a = 5;
var b = a;
</pre><p>will put number 5 in <em>b</em>, but it won&#8217;t be related anyhow to <em>a</em>. However, when using objects:</p><pre class="brush: jscript; title: ; notranslate">
var a = (x: 5};
var b = a;
</pre><p><em>b</em> is a reference to the object. Using <em>b.x = 6;</em> will write to the very same object that is referenced by <em>a</em>.</p><p>That&#8217;s why we need a method to create a copy of a vector. Simple v1 = v2 will mean that there is only one vector in our memory. However, if we access directly numeric parts of vector and make a clone, we would have two vectors and manipulating them will be independent.</p><p>The last preparation is definition of shapes.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Block = {};

Tetris.Block.shapes = [
	[
		{x: 0, y: 0, z: 0},
		{x: 1, y: 0, z: 0},
		{x: 1, y: 1, z: 0},
		{x: 1, y: 2, z: 0}
	],
	[
		{x: 0, y: 0, z: 0},
		{x: 0, y: 1, z: 0},
		{x: 0, y: 2, z: 0},
	],
	[
		{x: 0, y: 0, z: 0},
		{x: 0, y: 1, z: 0},
		{x: 1, y: 0, z: 0},
		{x: 1, y: 1, z: 0}
	],
	[
		{x: 0, y: 0, z: 0},
		{x: 0, y: 1, z: 0},
		{x: 0, y: 2, z: 0},
		{x: 1, y: 1, z: 0}
	],
	[
		{x: 0, y: 0, z: 0},
		{x: 0, y: 1, z: 0},
		{x: 1, y: 1, z: 0},
		{x: 1, y: 2, z: 0}
	]
];
</pre><p>Note that every shape&#8217;s first cube is (0,0,0). It&#8217;s very important and will be explained in the next section.</p><h2>Shape generation</h2><p>There are three values that describe a block: base shape, position and rotation. At this point we should think ahead about how we want to detect collision.</p><p>From my experience I can tell that <strong>collision detection in games is always more or less fake</strong>. And I&#8217;m not talking only about silly JS games. It&#8217;s all about performance &#8211; geometries are simplified, collisions for specific situations are ruled out first, some collisions are not considered at all and collision response is almost always not accurate. It doesn&#8217;t matter &#8211; if it looks natural, nobody will ever notice and we save a lot of precious CPU cycles.</p><p>So, what is the simplest collision detection for Tetris? All shapes are axis aligned cubes with centers in one of specified group of points. I&#8217;m 99% sure that keeping an array of values [FREE, MOVING, STATIC] for every position on the board is the best way to deal with it. This way, if we want to move a shape and space it would need is already occupied &#8211; we have a collision. Complexity: O(number of cubes in a shape) <=> O(1). Boo-yah!</p><p>Now, I&#8217;m a little pedantic and I know, that rotation is quite complex and we should avoid it if possible. That&#8217;s why we will keep the basic shape of block in a rotated form. This way we can apply only position (which is simple) and quickly check if we have a collision. It actually doesn&#8217;t matter that much in our case, but it would in a game that would be more complex. There is no game small enough to be programmed in a lazy way.</p><p>About position and rotation &#8211; both of these are used in Three.js. The problem is, however, that we use different units in Three.js and on our board. To keep our code simple, we will store position separately. Rotation is the same everywhere so we will use the built-in one.</p><p>First, we take a shape at random and create a copy. This is why we needed cloneVector function.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Block.position = {};

Tetris.Block.generate = function() {
  var geometry, tmpGeometry;

  var type = Math.floor(Math.random()*(Tetris.Block.shapes.length));
  this.blockType = type;

  Tetris.Block.shape = [];
  for(var i = 0; i &lt; Tetris.Block.shapes[type].length; i++) {
    Tetris.Block.shape[i] = Tetris.Utils.cloneVector(Tetris.Block.shapes[type][i]);
  }
  // to be continued...
</pre><p>Now we need to connect all the cubes to act as one shape.</p><p>There is a Three.js function for that &#8211; it takes a geometry and a mesh and merges them. What actually happens here is a merge of internal vertices array. It takes into account position of merged geometry. It is a reason why we needed the first cube to be (0,0,0). Mesh has a position, but geometry hasn&#8217;t &#8211; it&#8217;s always considered to be (0,0,0). It would be possible to write a merge function for two meshes, but it&#8217;s more complicated than keeping shapes like we did, isn&#8217;t it?</p><pre class="brush: jscript; title: ; notranslate">
geometry = new THREE.CubeGeometry(Tetris.blockSize, Tetris.blockSize, Tetris.blockSize);
for(var i = 1 ; i &lt; Tetris.Block.shape.length; i++) {
  tmpGeometry = new THREE.Mesh(new THREE.CubeGeometry(Tetris.blockSize, Tetris.blockSize, Tetris.blockSize));
  tmpGeometry.position.x = Tetris.blockSize * Tetris.Block.shape[i].x;
  tmpGeometry.position.y = Tetris.blockSize * Tetris.Block.shape[i].y;
  THREE.GeometryUtils.merge(geometry, tmpGeometry);
}
  // to be continued...
</pre><p>With merged geometry we can use a trick with double materials from part 1 of the tutorial.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Block.mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, [
  new THREE.MeshBasicMaterial({color: 0x000000, shading: THREE.FlatShading, wireframe: true, transparent: true}),
  new THREE.MeshBasicMaterial({color: 0xff0000})
]);
  // to be continued...
</pre><p>We have to set initial position and rotation for our block (a center of board for x,y and some arbitrary number for z).</p><pre class="brush: jscript; title: ; notranslate">
  // initial position
  Tetris.Block.position = {x: Math.floor(Tetris.boundingBoxConfig.splitX/2)-1, y: Math.floor(Tetris.boundingBoxConfig.splitY/2)-1, z: 15};

  Tetris.Block.mesh.position.x = (Tetris.Block.position.x - Tetris.boundingBoxConfig.splitX/2)*Tetris.blockSize/2;
  Tetris.Block.mesh.position.y = (Tetris.Block.position.y - Tetris.boundingBoxConfig.splitY/2)*Tetris.blockSize/2;
  Tetris.Block.mesh.position.z = (Tetris.Block.position.z - Tetris.boundingBoxConfig.splitZ/2)*Tetris.blockSize + Tetris.blockSize/2;
  Tetris.Block.mesh.rotation = {x: 0, y: 0, z: 0};
  Tetris.Block.mesh.overdraw = true;

  Tetris.scene.add(Tetris.Block.mesh);
}; // end of Tetris.Block.generate()
</pre><p>If you want, you can call Tetris.Block.generate() from you console.</p><h2>Moving</h2><p>Moving a block is actually very simple. For rotation we use Three.js internals and we have to convert angles to radians.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Block.rotate = function(x,y,z) {
  Tetris.Block.mesh.rotation.x += x * Math.PI / 180;
  Tetris.Block.mesh.rotation.y += y * Math.PI / 180;
  Tetris.Block.mesh.rotation.z += z * Math.PI / 180;
};
</pre><p>Position is also simple &#8211; Three.js needs a position considering block size and our copy doesn&#8217;t. There is a simple floor hit check for our entertainment &#8211; it will be removed later.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Block.move = function(x,y,z) {
  Tetris.Block.mesh.position.x += x*Tetris.blockSize;
  Tetris.Block.position.x += x;

  Tetris.Block.mesh.position.y += y*Tetris.blockSize;
  Tetris.Block.position.y += y;

  Tetris.Block.mesh.position.z += z*Tetris.blockSize;
  Tetris.Block.position.z += z;
  if(Tetris.Block.position.z == 0) Tetris.Block.hitBottom();
};
</pre><h2>hit &#038; create again</h2><p>What is hitBottom for? Remember? If a block life cycle has ended, we should convert it to static cubes, remove it from the scene and generate a new one.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Block.hitBottom = function() {
  Tetris.Block.petrify();
  Tetris.scene.removeObject(Tetris.Block.mesh);
  Tetris.Block.generate();
};
</pre><p>We already have generate() and removeObject() is a Three.js function for removing unused meshes. Luckily, in part 2 of this tutorial we wrote a function for static cubes and we now will use it in petrify().</p><pre class="brush: jscript; title: ; notranslate">
Tetris.Block.petrify = function() {
  var shape = Tetris.Block.shape;
  for(var i = 0 ; i &lt; shape.length; i++) {
    Tetris.addStaticBlock(Tetris.Block.position.x + shape[i].x, Tetris.Block.position.y + shape[i].y, Tetris.Block.position.z + shape[i].z);
  }
};
</pre><p>There is a shorthand for Tetris.Block.shape used &#8211; it improves both code clarity and performance, so use this technique every time it&#8217;s suitable. In this function you can see why keeping a rotated shape and separated position was a good idea. Thanks to that our code will be pleasant to read and with collision detection it will be even more important.</p><h2>Connect the dots</h2><p>Ok, now we have all functions we need for blocks, let&#8217;s hook them where needed. We need to generate one block on start, so change Tetris.start() to</p><pre class="brush: jscript; title: ; notranslate">
Tetris.start = function() {
  document.getElementById(&quot;menu&quot;).style.display = &quot;none&quot;;
  Tetris.pointsDOM = document.getElementById(&quot;points&quot;);
  Tetris.pointsDOM.style.display = &quot;block&quot;;
  Tetris.Block.generate(); // add this line
  Tetris.animate();
};
</pre><p>With every game step we should move the block one step forward, so locate a place in Tetris.animate() where we make a move and change it to:</p><pre class="brush: jscript; title: ; notranslate">
while(Tetris.cumulatedFrameTime &gt; Tetris.gameStepTime) {
   Tetris.cumulatedFrameTime -= Tetris.gameStepTime;
   Tetris.Block.move(0,0,-1); // add this line
}
</pre><h2>Keyboard</h2><p>I have to be honest &#8211; I hate keyboard events. The keycodes are meaningless and they <a
href="http://www.quirksmode.org/js/keys.html">are different for keydown and keypress</a>. There is no good way to poll keyboard state, after second keypress event is repeated 10 times faster than for the first two, etc. If you think about serious game with a lot of keyboard interaction, you will almost certainly build some kind of wrapper for all this bullshit. You may try <a
href="http://robertwhurst.github.com/KeyboardJS/">KeyboardJS</a>, it looks good. I&#8217;ll use vanilla JS to show the general idea. To debug it I&#8217;ve used console.log(keycode) &#8211; it helps a lot to find correct codes <img
src='http://www.smashinglabs.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><pre class="brush: jscript; title: ; notranslate">
window.addEventListener('keydown', function (event) {
  var key = event.which ? event.which : event.keyCode;

  switch(key) {
    case 38: // up (arrow)
      Tetris.Block.move(0, 1, 0);
      break;
    case 40: // down (arrow)
      Tetris.Block.move(0, -1, 0);
      break;
    case 37: // left(arrow)
      Tetris.Block.move(-1, 0, 0);
      break;
    case 39: // right (arrow)
      Tetris.Block.move(1, 0, 0);
      break;
    case 32: // space
      Tetris.Block.move(0, 0, -1);
      break;

    case 87: // up (w)
      Tetris.Block.rotate(90, 0, 0);
      break;
    case 83: // down (s)
      Tetris.Block.rotate(-90, 0, 0);
      break;

    case 65: // left(a)
      Tetris.Block.rotate(0, 0, 90);
      break;
    case 68: // right (d)
      Tetris.Block.rotate(0, 0, -90);
      break;	

    case 81: // (q)
      Tetris.Block.rotate(0, 90, 0);
      break;
    case 69: // (e)
      Tetris.Block.rotate(0, -90, 0);
      break;
  }
}, false);
</pre><p>If you try to play the game now, you should be able to move and rotate a block. There will be no collision detection, but when it hits the ground, it will be removed and new block will appear on board. Because we don&#8217;t apply rotation to the stored shape, static version may be rotated differently.</p><div
class="summarybox"><h2>After this tutorial you should:</h2><ul><li>Know that numerics are passed by value and objects by reference.</li><li>Understand life cycle of a Tetris block.</li><li>Know how to merge geometries and the difference between mesh and geometry.</li><li>Know how to bind keyoboard events.</li></ul><p> <a
href="https://github.com/fridek/Threejs-Tetris-Tutorial/tree/Tutorial_part_3"><img
src="http://www.smashinglabs.pl/wp-content/themes/Horcrux/images/github.png"> Grab source from github</a></p><p> If you have trouble with any of these, check tutorial again or ask a question in the comments below.</p></div> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-3/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>gMap 3.3.1 released</title><link>http://www.smashinglabs.pl/gmap-3-3-1-released</link> <comments>http://www.smashinglabs.pl/gmap-3-3-1-released#comments</comments> <pubDate>Sat, 25 Feb 2012 23:19:20 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[gMap]]></category> <category><![CDATA[javascript]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[QUnit]]></category> <category><![CDATA[release]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=717</guid> <description><![CDATA[Bugfix release of gMap landed on github yesterday. It fixes an issue with zoom and address geocoded markers. There are no changes in the API. You can run all unit tests here. It&#8217;s also a great repository of examples. If you submit a bug report it&#8217;s great to have a unit test that shows an<a
href="http://www.smashinglabs.pl/gmap-3-3-1-released">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>Bugfix release of gMap landed on github yesterday.<br
/> It fixes an issue with zoom and address geocoded markers. There are no changes in the API.<br
/> <span
id="more-717"></span><br
/> You can run all unit tests <a
href="http://fridek.github.com/gmap/tests/index.html">here</a>. It&#8217;s also a great repository of examples.<br
/> If you submit a bug report it&#8217;s great to have a unit test that shows an issue. If you are not familiar with QUnit, please send a stand-alone html file. Include gmap and jquery version you used.</p> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/gmap-3-3-1-released/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>3D Tetris with Three.js tutorial &#8211; part 2</title><link>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-2</link> <comments>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-2#comments</comments> <pubDate>Mon, 20 Feb 2012 08:51:02 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[Tetris tutorial]]></category> <category><![CDATA[WebGL]]></category> <category><![CDATA[JavaScript]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=664</guid> <description><![CDATA[Second part of tutorial is about adding static blocks. It will be short but very important. Joined or separated? Think about the way we play Tetris. When the block is moving, we transform and rotate it freely. Cubes that make block are clearly connected and it&#8217;s intuitive that their representation in code should be as<a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-2">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>Second part of tutorial is about adding static blocks. It will be short but very important.<br
/> <span
id="more-664"></span></p><ul><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-1">Part 1: Introduction and game loop</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-2">Part 2: Static blocks and keeping score</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-3">Part 3: Adding and moving a block</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 4: Collision detection</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 5: Audio and scoring</a></li></ul><h2>Joined or separated?</h2><p>Think about the way we play Tetris. When the block is moving, we transform and rotate it freely. Cubes that make block are clearly connected and it&#8217;s intuitive that their representation in code should be as well. On the other hand, when we try to complete a slice (in 2D &#8211; a row) and we succed, the cubes are removed and the block that was their origin doesn&#8217;t matter at this point. In fact, it shouldn&#8217;t matter &#8211; some boxes from a block may be removed and other not. Tracing an origin of a box would require constant splitting and merging geometries and trust me &#8211; that would be a crazy mess. In original 2D Tetris sometimes the color of a square was the indicator of the origin block. In 3D however we need a quick way to show z-axis and color is perfect for this.</p><p>In our game cubes will be connected when are dynamic and static when they are not. At the end of tutorial we will further optimize static cubes.</p><h2>Adding a static block</h2><p>Lets start with a moment when a moving block touches the floor (or another block). The moving block (with merged geometry of few cubes) is transformed into static, separated cubes that don&#8217;t move anymore. It&#8217;s convenient to keep these cubes in a 3D array.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.staticBlocks = [];
Tetris.zColors = [
  0x6666ff, 0x66ffff, 0xcc68EE, 0x666633, 0x66ff66, 0x9966ff, 0x00ff66, 0x66EE33, 0x003399, 0x330099, 0xFFA500, 0x99ff00, 0xee1289, 0x71C671, 0x00BFFF, 0x666633, 0x669966, 0x9966ff
];
Tetris.addStaticBlock = function(x,y,z) {
  if(Tetris.staticBlocks[x] === undefined) Tetris.staticBlocks[x] = [];
  if(Tetris.staticBlocks[x][y] === undefined) Tetris.staticBlocks[x][y] = [];

  var mesh = THREE.SceneUtils.createMultiMaterialObject(new THREE.CubeGeometry( Tetris.blockSize, Tetris.blockSize, Tetris.blockSize), [
    new THREE.MeshBasicMaterial({color: 0x000000, shading: THREE.FlatShading, wireframe: true, transparent: true}),
    new THREE.MeshBasicMaterial({color: Tetris.zColors[z]})
  ] );

  mesh.position.x = (x - Tetris.boundingBoxConfig.splitX/2)*Tetris.blockSize + Tetris.blockSize/2;
  mesh.position.y = (y - Tetris.boundingBoxConfig.splitY/2)*Tetris.blockSize + Tetris.blockSize/2;
  mesh.position.z = (z - Tetris.boundingBoxConfig.splitZ/2)*Tetris.blockSize + Tetris.blockSize/2;
  mesh.overdraw = true;

  Tetris.scene.add(mesh);
  Tetris.staticBlocks[x][y][z] = mesh;
};
</pre><p>There is a lot to explain here.</p><h3>Colors and materials</h3><p>Tetris.zColors keeps a list of colors that indicate position of a cube on z-axis. I&#8217;d like to have a good looking cube, so it should have a color AND outlined border. I&#8217;m going to use something that is not very popular in Three.js tutorials &#8211; multiMaterials. There is a function in Three.js SceneUtils that takes a geometry and <strong>an array</strong> (notice brackets []) of materials. If you look in Three.js source:</p><pre class="brush: jscript; title: ; notranslate">
  createMultiMaterialObject : function ( geometry, materials ) {
  var i, il = materials.length, group = new THREE.Object3D();
  for ( i = 0; i &lt; il; i ++ ) {
    var object = new THREE.Mesh( geometry, materials[ i ] );
    group.add( object );
  }
  return group;
},
</pre><p>It&#8217;s a very simple hack that creates a mesh for every material. With pure WebGL there are better ways to achieve the same result (f.e. calling draw two times, once with gl.LINES and second with gl.something) but the usual use of this function is to for example to merge textures and materials at the same time &#8211; not different types of drawing.</p><h3>Position in 3D space</h3><p>Now, why the hell does position look like that?</p><pre class="brush: jscript; title: ; notranslate">
mesh.position.x = (x - Tetris.boundingBoxConfig.splitX/2)*Tetris.blockSize + Tetris.blockSize/2;
</pre><p>Our board <strong>center</strong> on init was placed in the (0,0,0) point. It is not a very good spot, as it means that some cubes will have negative position and others positive. It would be better to specify a corner of an object in our case. Moreover, we would like to think of our boxes positions as a discrete values from 1 to 6, or at least 0 to 5. Three.js (and WebGL, OpenGL and everything else) uses its own units that rather relate to meters or pixels. If you remember, in config we put a value</p><pre class="brush: jscript; title: ; notranslate">
Tetris.blockSize = boundingBoxConfig.width/boundingBoxConfig.splitX;
</pre><p>that is responsible for conversion. So as a summary:</p><pre class="brush: jscript; title: ; notranslate">
 // transform 0-5 to -3 - +2
(x - Tetris.boundingBoxConfig.splitX/2)
 // scale to Three.js units
*Tetris.blockSize
 // we specify cube center, not a corner - we have to shift position
 + Tetris.blockSize/2
</pre><h2>Nice test</h2><p>Our game is still very static, but you can open your console and run:</p><pre class="brush: jscript; title: ; notranslate">
var i = 0, j = 0, k = 0, interval = setInterval(function() {if(i==6) {i=0;j++;} if(j==6) {j=0;k++;} if(k==6) {clearInterval(interval); return;} Tetris.addStaticBlock(i,j,k); i++;},30)
</pre><p>It should animate filling the board with cubes.</p><h2>Keeping score</h2><p>A small utility function to keep score:</p><pre class="brush: jscript; title: ; notranslate">
Tetris.currentPoints = 0;
Tetris.addPoints = function(n) {
  Tetris.currentPoints += n;
  Tetris.pointsDOM.innerHTML = Tetris.currentPoints;
  Cufon.replace('#points');
}
</pre><p>You can call it from console as well.</p><div
class="summarybox"><h2>After this tutorial you should:</h2><ul><li>Know the difference between connected and separated geometries.</li><li>Understand basics of materials and how to mix them.</li><li>Understand what exactly does position mean in Three.js.</li></ul><p> <a
href="https://github.com/fridek/Threejs-Tetris-Tutorial/tree/Tutorial_part_2"><img
src="http://www.smashinglabs.pl/wp-content/themes/Horcrux/images/github.png"> Grab source from github</a><br
/> If you have trouble with any of these, check tutorial again or ask a question in the comments below.</div> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-2/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>3D Tetris with Three.js tutorial &#8211; part 1</title><link>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-1</link> <comments>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-1#comments</comments> <pubDate>Mon, 20 Feb 2012 08:50:22 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[Tetris tutorial]]></category> <category><![CDATA[WebGL]]></category> <category><![CDATA[JavaScript]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=652</guid> <description><![CDATA[Learning Three.js is fairly easy. This series may be not the best tutorial ever, but I&#8217;ll share my experiences from writing a game &#8211; 3D Tetris. I hope you find it useful. Preparation First you need to download Three.js: https://github.com/mrdoob/three.js I also use Stats from mrdoob: https://github.com/mrdoob/stats.js In both cases you need only files from build directory.<a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-1">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>Learning Three.js is fairly easy. This series may be not the best tutorial ever, but I&#8217;ll share my experiences from writing a game &#8211; <a
href="https://github.com/fridek/Threejs-Tetris">3D Tetris</a>. I hope you find it useful.</p><p><span
id="more-652"></span></p><ul><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-1">Part 1: Introduction and game loop</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-2">Part 2: Static blocks and keeping score</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-3">Part 3: Adding and moving a block</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 4: Collision detection</a></li><li><a
href="http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-4">Part 5: Audio and scoring</a></li></ul><h2>Preparation</h2><p>First you need to download Three.js: <a
href="https://github.com/mrdoob/three.js">https://github.com/mrdoob/three.js</a></p><p>I also use Stats from mrdoob: <a
href="https://github.com/mrdoob/stats.js">https://github.com/mrdoob/stats.js</a></p><p>In both cases you need only files from build directory.</p><p>Blox is a nice font for menu and points: <a
href="http://www.dafont.com/blox.font">http://www.dafont.com/blox.font</a></p><p>To use it you have to convert it with Cufon: <a
href="http://cufon.shoqolate.com/generate/">http://cufon.shoqolate.com/generate/</a></p><p>In my project all JS files go to js folder, music into music folder and html in root.</p><h2>HTML</h2><p>I&#8217;m lazy so all the CSS goes directly into html header. It&#8217;s not as bad as it sounds &#8211; it&#8217;s very short and there is only one page so caching is unnecessary anyway. There is not much to explain, just some CSS for the intro and score counter. Also you have to include all js and init cufon.</p><pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Three.js Tetris&lt;/title&gt;
	&lt;style&gt;
		body {margin: 0; padding: 0; overflow: hidden;}

		#menu {
			position: absolute;
			width: 200px;
			height: 250px;

			top: 50%; left: 50%;
			margin: -125px 0 0 -100px;

			text-align: center;

			border: 3px solid #fff;
			border-radius: 15px;

			background-color: #E36B23;
			box-shadow: 2px 10px 5px #888;
		}

    #menu p {font-weight: bold; color: #fff;}
    #menu p a {color: #fff;}

		#menu button {
			width: 80px;
			height: 25px;

			background-color: #C44032;

			border: 3px solid #fff;
			border-radius: 5px;	

			font-size: 14px;
			font-weight: bold;
			color: #fff;
		}

		#points {
			position: absolute;
			width: 120px;
			height: 16px;	

			padding: 12px;

			top: 20px;
			right: 80px;

			border: 3px solid #fff;
			border-radius: 15px;

			background-color: #E36B23;
			box-shadow: 2px 10px 5px #888;	

			font-size: 14px;
			font-weight: bold;
			color: #fff;	

			text-align: right;

			display: none;
		}
	&lt;/style&gt;
    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;/&gt;
	&lt;/head&gt;
  &lt;body&gt;
	&lt;div id=&quot;menu&quot;&gt;
		&lt;h1&gt;Three.js Tetris&lt;/h1&gt;
    &lt;p&gt;
      Movement: arrows&lt;br&gt;
      Rotation: AD/SW/QE&lt;br&gt;
      Author: &lt;a href=&quot;http://www.smashinglabs.pl&quot;&gt;smashinglabs.pl&lt;/a&gt;
    &lt;/p&gt;
		&lt;button id=&quot;play_button&quot;&gt;Play&lt;/button&gt;
	&lt;/div&gt;

	&lt;div id=&quot;points&quot;&gt;
		0
	&lt;/div&gt;

	&lt;script type=&quot;text/javascript&quot; src=&quot;js/Three.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;js/Stats.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;js/tetris.js&quot;&gt;&lt;/script&gt;

	&lt;script src=&quot;js/cufon-yui.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
	&lt;script src=&quot;js/Blox_400.font.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;	

	&lt;script type=&quot;text/javascript&quot;&gt;
		Cufon.replace('#menu h1');
		Cufon.replace('#points');
	&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre><h2>Basic Structure and Three.js init</h2><p>There are many ways of organizing your game. If you want to host it on a gaming portal, you may need to use some kind of closure (i.e. not use global variables). If your game is very complex, inheritance becomes useful. But for the simple game working fullscreen all these concepts show as hard to maintain and not without some impact on preformace. The project will use one global namespace</p><pre class="brush: jscript; title: ; notranslate">
var Tetris = {};
</pre><p>All objects, functions and variables will be a member of Tetris. It&#8217;s a very useful way to maintain your code and to avoid usage of &#8220;this&#8221;. To make things even better, every object I use is a singleton. There are some drawbacks &#8211; it&#8217;s <a
href="http://en.wikipedia.org/wiki/God_object">a classic god object</a> and a mixture of everything, but as long as it&#8217;s small I don&#8217;t care and you shouldn’t either.</p><p>We will focus on this structure later, now lets initialize Three.js. I used a tutorial by <a
href="http://www.aerotwist.com/tutorials/getting-started-with-three-js/">Aerotwist</a> which is very simple, but plain and good enough. You should probably read it before you proceed.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.init = function() {
  // set the scene size
  var WIDTH = window.innerWidth,
      HEIGHT = window.innerHeight;

  // set some camera attributes
  var VIEW_ANGLE = 45,
      ASPECT = WIDTH / HEIGHT,
      NEAR = 0.1,
      FAR = 10000;

  // create a WebGL renderer, camera
  // and a scene
  Tetris.renderer = new THREE.WebGLRenderer();
  Tetris.camera = new THREE.PerspectiveCamera(  VIEW_ANGLE,
                                  ASPECT,
                                  NEAR,
                                  FAR  );
  Tetris.scene = new THREE.Scene();

  // the camera starts at 0,0,0 so pull it back
  Tetris.camera.position.z = 600;
  Tetris.scene.add(Tetris.camera);

  // start the renderer
  Tetris.renderer.setSize(WIDTH, HEIGHT);

  // attach the render-supplied DOM element
  document.body.appendChild(Tetris.renderer.domElement);

  // to be continued...
</pre><p>The introduced Tetris.init is creating a Three.js objects and store them in global namespace. There is a renderer, a scene and a camera. I want the game to be fullscreen so I use window.innerWidth and window.innerHeight. You may want to experiment with <a
href="http://learningthreejs.com/blog/2011/11/17/lets-make-a-3d-game-make-it-fullscreen/">fullscreen API</a> there. The camera needs to be pulled back and an exact distance should be determined by the size and position of the game world you use.</p><p>Our game world is a 3D wireframe box with lines showing where boxes can be dropped. When you work on a game it&#8217;s important to realize that the final effect is what matters most. <strong>Don&#8217;t be afraid to cheat!</strong> In this case, there is no good reason to draw lines on bounding box. We may as well use a normal box geometry, place a vertex on every line cross and connect vertices with lines instead of usual triangles. And luckily there is a Three.js syntax just for that!</p><pre class="brush: jscript; title: ; notranslate">
  // configuration object
  var boundingBoxConfig = {
    width: 360,
    height: 360,
    depth: 1200,
    splitX: 6,
    splitY: 6,
    splitZ: 20
  };

  Tetris.boundingBoxConfig = boundingBoxConfig;
  Tetris.blockSize = boundingBoxConfig.width/boundingBoxConfig.splitX;

  var boundingBox = new THREE.Mesh(
    new THREE.CubeGeometry(
      boundingBoxConfig.width, boundingBoxConfig.height, boundingBoxConfig.depth,
      boundingBoxConfig.splitX, boundingBoxConfig.splitY, boundingBoxConfig.splitZ),
    new THREE.MeshBasicMaterial( { color: 0xffaa00, wireframe: true } )
  );
  Tetris.scene.add(boundingBox);

  // first render
  Tetris.renderer.render(Tetris.scene, Tetris.camera);
  // to be continued...
</pre><p>A Three.js API describes <a
href="http://threejs.org/io/s/CubeGeometry">CubeGeometry</a> constructor as:</p><pre class="brush: jscript; title: ; notranslate">
(width &lt;Number&gt;, height &lt;Number&gt;, depth &lt;Number&gt;, segmentsWidth &lt;Number&gt;, segmentsHeight &lt;Number&gt;, segmentsDepth &lt;Number&gt;, materials &lt;Array&gt;, sides &lt;Object&gt;)
</pre><p>and we make use of &#8220;segmentX&#8221; options to define how many boxes can be fitted into our gameboard. We use also MeshBasicMaterial option wireframe to draw lines instead of triangles.</p><p>Last things to do in init function:</p><pre class="brush: jscript; title: ; notranslate">
  Tetris.stats = new Stats();
  Tetris.stats.domElement.style.position = 'absolute';
  Tetris.stats.domElement.style.top = '10px';
  Tetris.stats.domElement.style.left = '10px';
  document.body.appendChild( Tetris.stats.domElement );

  document.getElementById(&quot;play_button&quot;).addEventListener('click', function (event) {
    event.preventDefault();
    Tetris.start();
  });
};
</pre><p>We add FPS stats and bind Tetris.start() to the play button. What should be done in start()?</p><pre class="brush: jscript; title: ; notranslate">
Tetris.start = function() {
   document.getElementById(&quot;menu&quot;).style.display = &quot;none&quot;;
   Tetris.pointsDOM = document.getElementById(&quot;points&quot;);
   Tetris.pointsDOM.style.display = &quot;block&quot;;

   Tetris.animate();
};
</pre><p>Hide instructions, show score box and start first animate() function.</p><h2>Game loop</h2><p>You may wonder why there was no setInterval for animation. There is a much better function for that &#8211; requestAnimationFrame(). It calls specified functions when the browser is not busy, but no more than 60 times per second. It means that you will have exactly the number of FPS that is possible to render. No need to worry about calculating the best time step for setInterval or clots if you try to render more FPS than it&#8217;s possible to calculate. The function is still something new, so on top of our script we will place a compatibility code:</p><pre class="brush: jscript; title: ; notranslate">
if ( !window.requestAnimationFrame ) {
  window.requestAnimationFrame = ( function() {
    return window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {
      window.setTimeout( callback, 1000 / 60 );
    };
  })();
}
</pre><p>Now we need to write animate() function. Tetris is real-time, but a step of game is quite long, like one z-axis move per second. We need to calculate when to move our block forward, so some time-related variables have to be introduced:</p><pre class="brush: jscript; title: ; notranslate">
Tetris.gameStepTime = 1000;

Tetris.frameTime = 0; // ms
Tetris.cumulatedFrameTime = 0; // ms
Tetris._lastFrameTime = Date.now(); // timestamp

Tetris.gameOver = false;
</pre><p>Now, the animate function in simplified version has to call Three.js render method and call itself again using requestAnimationFrame. This would make our game static, so we need to calculate a passage of time and act if it was long enough.</p><pre class="brush: jscript; title: ; notranslate">
Tetris.animate = function() {
  var time = Date.now();
  Tetris.frameTime = time - Tetris._lastFrameTime;
  Tetris._lastFrameTime = time;
  Tetris.cumulatedFrameTime += Tetris.frameTime;

  while(Tetris.cumulatedFrameTime &gt; Tetris.gameStepTime) {
    // block movement will go here
    Tetris.cumulatedFrameTime -= Tetris.gameStepTime;
  }

  Tetris.renderer.render(Tetris.scene, Tetris.camera);

  Tetris.stats.update();

  if(!Tetris.gameOver) window.requestAnimationFrame(Tetris.animate);
}
</pre><p>If you noticed stats update, you may think it&#8217;s a little redundant. Stats are obviously counting FPS and we do the same thing. You may want to dig into stats code and re-use some data, but I&#8217;ve found it simpler to write my own few lines of code. Stats were not intended for such usage and the overhead is close to zero. Besides, if you&#8217;d like to remove FPS counter from your game when it&#8217;s released, it could be a problem. The less dependencies the better.</p><p>And, at last, we should call init() when the page is loaded:</p><pre class="brush: jscript; title: ; notranslate">
window.addEventListener(&quot;load&quot;, Tetris.init);
</pre><div
class="summarybox"><h2>After this tutorial you should:</h2><ul><li>Know how to setup a renderer and scene with Three.js.</li><li>Understand what a game loop is and</li><li>why requestAnimationFrame is great.</li><li>Know that if it looks good, it&#8217;s good.</li></ul><p> <a
href="https://github.com/fridek/Threejs-Tetris-Tutorial/tree/Tutorial_part_1"><img
src="http://www.smashinglabs.pl/wp-content/themes/Horcrux/images/github.png"> Grab source from github</a><br
/> If you have trouble with any of these, check tutorial again or ask a question in the comments below.</div> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/3d-tetris-with-three-js-tutorial-part-1/feed</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>gMap 3.3.0 released</title><link>http://www.smashinglabs.pl/gmap-3-3-0-released</link> <comments>http://www.smashinglabs.pl/gmap-3-3-0-released#comments</comments> <pubDate>Wed, 21 Dec 2011 21:05:36 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[featured]]></category> <category><![CDATA[gMap]]></category> <category><![CDATA[Google Map]]></category> <category><![CDATA[google maps]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[release]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=625</guid> <description><![CDATA[Christmas came early! New version of gMap is ready! As always, you can download it from github. I had a lot of feature requests since last version and I hope I covered them all. Here is what&#8217;s new in 3.3.0: clustering fixAfterResize &#8211; fixing issues with loading gMaps in tabs changeSettings &#8211; works with most<a
href="http://www.smashinglabs.pl/gmap-3-3-0-released">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>Christmas came early! New version of gMap is ready!</p><p><span
id="more-625"></span></p><p><a
href="http://www.smashinglabs.pl/wp-content/uploads/2011/08/gmap_example2.jpg"><img
class="aligncenter size-medium wp-image-282" title="Gmap image" src="http://www.smashinglabs.pl/wp-content/uploads/2011/08/gmap_example2-300x175.jpg" alt="" width="300" height="175" /></a></p><p>As always, you can <a
href="https://github.com/fridek/gmap">download it from github</a>.</p><p>I had a lot of feature requests since last version and I hope I covered them all.<br
/> Here is what&#8217;s new in 3.3.0:</p><ul><li>clustering</li><li>fixAfterResize &#8211; fixing issues with loading gMaps in tabs</li><li>changeSettings &#8211; works with most of initial options</li><li>mapclick(callback) &#8211; bind for map click event</li><li>geocode(address, callback) &#8211; shorthand for geocoding</li><li>draggable markers (thanks to theMarvin)</li></ul><p>I&#8217;m getting close to the point where I&#8217;ll consider gMap completed. Now it&#8217;s just about the time to improve documentation, which is still in 3.1.0 (sorry for that) and to complete test coverage.</p><p>I&#8217;d like to share a link to Magic Gallery WordPress Plugin: <a
href="http://www.magicgalleryplugin.com/">http://www.magicgalleryplugin.com/</a> It uses gMap and has a very nice design.</p><p>If you want to support my work and make my Christmas even better, please consider donating (button on the right sidebar).</p><p>That&#8217;s all the news, merry Christmas everyone!</p> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/gmap-3-3-0-released/feed</wfw:commentRss> <slash:comments>8</slash:comments> </item> <item><title>JavaScript performance lecture followup</title><link>http://www.smashinglabs.pl/javascript-performance-lecture-followup</link> <comments>http://www.smashinglabs.pl/javascript-performance-lecture-followup#comments</comments> <pubDate>Sat, 17 Dec 2011 23:09:47 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[javascript]]></category> <category><![CDATA[GTUG]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[JIT]]></category> <category><![CDATA[optimization]]></category> <category><![CDATA[performance]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=586</guid> <description><![CDATA[After my last lecture I got some comments, found some resources and I updated my slides. Some highlights of things that has changed: Trace JIT is no more I was surprised by the news that trace JIT was removed from Firefox trunk. I hoped that it will grow and replace method JIT completely one day. Post from from<a
href="http://www.smashinglabs.pl/javascript-performance-lecture-followup">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>After <a
title="Lecture for GTUG: JavaScript performance" href="http://www.smashinglabs.pl/lecture-for-gtug-javascript-performance">my last lecture</a> I got some comments, found some resources and I updated my slides.</p><p>Some highlights of things that has changed:</p><p><span
id="more-586"></span></p><h3>Trace JIT is no more</h3><p>I was surprised by the news that trace JIT was removed from Firefox trunk. I hoped that it will grow and replace method JIT completely one day. <a
href="http://blog.mozilla.com/dmandelin/2011/11/29/js-development-newsletter-1123-1129/">Post from from David Mandelin</a> explains details behind this  decision.</p><h3>Method JIT works better than I expected</h3><p>During my talk I stated that using config object (which e.g. jQuery plugins do) may break JIT and that the safest way is to use integer and float arguments only.</p><p>I got a very detailed description from Rob Brackett on how JIT works with objects:</p><blockquote><p>Passing config objects to functions can often cause them to run slower — most engines use a concept of &#8220;shape&#8221; to JIT code related to objects (shape is basically the set of keys on your object, so {a:&#8221;a&#8221;, b:&#8221;b&#8221;} and {a:&#8221;c&#8221;, b:&#8221;d&#8221;} are the same shape but {a:&#8221;a&#8221;, c:&#8221;b&#8221;} is a different shape). The function will generally have to be JITed once for each shape that is passed in. Some engines stop re-JITing after they&#8217;ve seen a certain number of shapes (the threshold is different for different engines) and some do not.</p></blockquote><p>My second statement, about integers and floats was based on NanoJIT capabilities. Since it was removed from Firefox with Trace JIT, I can now safely say that any argument type that fulfill static &#8220;shape&#8221; description above can be JITed.</p><p>Source: <a
href="http://groups.google.com/group/jsmentors/browse_thread/thread/9286c04c908cd722">http://groups.google.com/group/jsmentors/browse_thread/thread/9286c04c908cd722</a></p><h3>Reflow is blocking</h3><p>I got a question, if reflow has been or could be moved to separated thread, so it won&#8217;t be blocking. The short answer is &#8220;no&#8221;. There are plenty of functions that depend on calculated result and it would require synchronizing very often. <a
href="http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html">The list of functions that require reflow to be completed</a>.</p><h3>More</h3><p>It was linked in my slides, but I&#8217;d like to say it again &#8211; read David Madelin&#8217;s slides <a
href="http://blog.mozilla.com/dmandelin/2011/06/16/know-your-engines-at-oreilly-velocity-2011/">Know Your Engines</a> from Velocity Conf 2011. It&#8217;s the most detailed source about engines I&#8217;ve found so far.</p><p><a
href="http://groups.google.com/group/jsmentors/browse_thread/thread/9286c04c908cd722">I&#8217;ve asked some questions on JSMentors group</a>, you may want to check it out.</p><p>Bonus: some <a
href="https://picasaweb.google.com/107595839032738148454/KRKOptymalizacjaJavaScriptuGWTGAE#">photos from the event</a></p> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/javascript-performance-lecture-followup/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Lecture for GTUG: JavaScript performance</title><link>http://www.smashinglabs.pl/lecture-for-gtug-javascript-performance</link> <comments>http://www.smashinglabs.pl/lecture-for-gtug-javascript-performance#comments</comments> <pubDate>Wed, 07 Dec 2011 22:22:15 +0000</pubDate> <dc:creator>Sebastian Poręba</dc:creator> <category><![CDATA[featured]]></category> <category><![CDATA[javascript]]></category> <category><![CDATA[garbage collector]]></category> <category><![CDATA[GC]]></category> <category><![CDATA[GTUG]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[JIT]]></category> <category><![CDATA[optimization]]></category> <category><![CDATA[performance]]></category> <category><![CDATA[reflow]]></category> <category><![CDATA[repaint]]></category><guid
isPermaLink="false">http://www.smashinglabs.pl/?p=579</guid> <description><![CDATA[Today I gave a lecture for GTUG Krakow about optimizations in JS. My main topics were: Optimization in general DOM Reflow/repaint Garbage collector JIT Google Closure (Compiler/Tools/Library) You can check my slides here. I collected plenty of links and wrote a few examples. Feel free to comment and criticize. I&#8217;ll be happy to add anything that<a
href="http://www.smashinglabs.pl/lecture-for-gtug-javascript-performance">&#160;&#160;[ Read More ]</a>]]></description> <content:encoded><![CDATA[<p>Today I gave a lecture for <a
href="http://krakow.gtug.pl/">GTUG Krakow</a> about optimizations in JS.</p><p><span
id="more-579"></span></p><p><img
class="aligncenter size-medium wp-image-581" style="border-style: initial; border-color: initial;" title="gtug cracow 2 sign 1" src="http://www.smashinglabs.pl/wp-content/uploads/2011/12/gtug-cracow-2-sign-1-300x139.png" alt="" width="300" height="139" /></p><p>My main topics were:</p><ul><li>Optimization in general</li><li>DOM</li><li>Reflow/repaint</li><li>Garbage collector</li><li>JIT</li><li>Google Closure (Compiler/Tools/Library)</li></ul><p>You can check my slides <a
href="http://smashinglabs.pl/lectures/js-performance/" target="_blank">here</a>. I collected plenty of links and wrote a few examples.<br
/> <a
href="http://www.smashinglabs.pl/wp-content/uploads/2011/12/gtug-cracow-2-sign-1.png"><br
/> </a>Feel free to comment and criticize. I&#8217;ll be happy to add anything that I&#8217;ve missed or to correct any mistakes. There are few good optimization resources and I had some doubts in few cases.</p> ]]></content:encoded> <wfw:commentRss>http://www.smashinglabs.pl/lecture-for-gtug-javascript-performance/feed</wfw:commentRss> <slash:comments>2</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching using disk: basic
Object Caching 874/990 objects using disk: basic

Served from: www.smashinglabs.pl @ 2012-05-18 22:00:35 -->
