Showing posts with label js. Show all posts
Showing posts with label js. Show all posts

Monday, May 14, 2012

onGameStart 2012

The most important thing in the life adventure is to remember when and how did it start. First impressions, inspirations and simple steps shape the future.
My gaming experience started in mid '90 on my XT with Hercules graphic card and amber screen. I was too young (and I lived on the other side of the iron curtain) to remember Apple II or Commodore computers before. One of the first games I remember from my early childhood was 'Prince of Persia' made by Jordan Mechner. I played it for almost 12 years before I was able to finish it without cheating (I can still remember 'prince megahit' password that enables cheat mode). I'm sure that a lot of you had similar experience.

What does this have to do with onGameStart?

Earlier this year I tweeted that HTML5 gamedevs are the new generation of game makers, and like every other 'new generation' we reinvent the same patterns or techniques our older friends implemented 30 years ago. There is no better way to learn, than listen to the real experts. That's why Jordan Mechner, creator of Prince of Persia, will share his experience during this year's Main onGameStart Keynote.

During two days of the conference it will be also possible to listen to presentations of the biggest, most talented and most respected HTML5 game developers from all over the world. And differently from last year, we will focus on real HTML5 games, tools that could help you write your own game, and wide variety of services for distribution, payments, statistics, and everything you will need to create great game. No more tech demos or examples - we all know that HTML5 has become mature enough, and players don't care about the technology - they want games. And we need those players and those games to prove that Open Web Technologies can compete with any other technology used in game development.

First part of confirmed speakers list for this year's edition of the first HTML5 game conference:
Seb Lee-Delisle, trainer on CreativeJS workshops
Jerome Etienne, creator of learningthreejs.com and tQuery
Jon Howard, responsible for games for kids in BBC
Andres Pagella, creator of Tracy and author of "Making Isometric Social Real-Time Games with HTML5, CSS3, and JavaScript"
Szymon Pilkowski, former senior JS developer in Crytek & Bigpoint
Robert Podgorski, boss of Black Moon Dev, one of the best pixel artists ever
Jonas Wagner, author of great WebGL demos
And of course last but not least,
Jordan Mechner, creator of Prince of Persia

So about 30 seconds ago we have launched our site, onGameStart.com. And because it's all about gaming, we've simply created a game with outstanding graphics by Robert. Control little astronaut with arrow keys, use space to talk to the speakers (close the window with 'z'), avoid lasers and spikes, and use keycards to open the door. If you don't want to explore our oGS spaceship, you can simply click on the head of the speaker in the top menu, and you will be teleported to the given speaker - you can still talk with him using space. game was created using Dominic's ImpactJS so it should work in most of the browsers. If you happen to find a bug, typo etc, feel free to tweet me about that (@michalbe). Enjoy, and stay tuned (Lanyrd, Facebook & Twitter)! We will announce more speakers and surprises soon.

Friday, October 15, 2010

Four methods of Javascript animation

Quoting Wikipedia:
Animation is the rapid display of a sequence of images in order to create an illusion of movement.

There are few methods to achieve that effect in JS, and I will discuss four of them in here.

1. Canvas animation
I used canvas animation in my Javascript game tutorial, but let's describe it once again. As an example, I will animate jump frames from my very favorite game days ago, Prince of Persia, you can find it on the right side of the post.
Before stating any animation related stuff it's necessarily to define few variables common for all four methods. Let's do this:
var width = 100,
    height = 86,
    frames = 10, 
//our PoP jumping animation has 11 frames, but we count from 0
    
    actualFrame = 0,
       
    posX = 100,
    posY = 100,
//X & Y position of the element

    canvas = document.createElement('canvas'),
//'canvas' variable will be always main element of an animation, not always  type
    canvasStyle = canvas.style,
    ctx = canvas.getContext("2d"),
    image = document.createElement('img');
 
    image.src = 'sprite.jpg';
 
    canvasStyle.position = "absolute";
    canvasStyle.top = posX;
    canvasStyle.left = posY;

    canvas.width = width;
    canvas.height = height;
//width & height are assigned directly to th canvas, not to the canvasStyle because in the other case it would scale the element, not change its size.
    document.body.appendChild(canvas);
 
var draw = function(){
//main function for rendering each frame, here will all the animation logic goes.
} 

setInterval(draw, 80);
//main loop        
To animate our character we need just to display next frames of the jump on the canvas. It's not necessarily to clear whole surface each time in this particular case, because it has the same size as single frame. The draw function will looks like that:
var draw = function(){
    ctx.drawImage(image, 0, height * actualFrame, width, height, 0, 0, width, height);
//the attributes are: image to draw, X coord of the source image, Y coord of the source image, width & height of the cut piece (frame size), X & Y destination coords (our canvas) and destination frame size (not always the same as the source one, eg in case of scaling the frame)

    if (actualFrame == frames) {
        actualFrame = 0;
    } else {
        actualFrame++;
    }
//looping the frames, it is also the common part of all draw() function in this post
} 
So that is the first method of JavaScript animation.
Pros:
- it uses canvas (the future of HTML5 games)
- it's possible to scale, rotate, flip, etc. the frames in browsers that support canvas but no CSS3
- probably much more

Cons:
- need to clear whole canvas to draw another frame
- not supported in old browsers
- quite complex math for display single frame

Life example: [1. Canvas Animation]

2. Background looping
I think it was one of the firstmethods of sprite's animation in web browsers. It is the simplest way ever. Just create div element with background, and change backgroundPosition on each frame. Piece of cake. Try:
var canvas = document.createElement('div'),
//div element is now our 'canvas'
    canvasStyle = canvas.style;
    
    canvasStyle.backgroundImage = "url(sprite.jpg)";
//and our image is just it's background
    canvasStyle.position = "absolute";
    canvasStyle.top = posX;
    canvasStyle.left = posY;

    canvasStyle.width = width;
    canvasStyle.height = height;
//width & height are now assigned to the 'style', not directly to the element
    document.body.appendChild(canvas);
    
var draw = function(){
    canvasStyle.backgroundPosition = "0 -"+height * actualFrame;
//each frame background image moves up, that's why there is minus sign before the value, you can multiply (height * actualFrame) by negative one, it gives the same effect
(...) //here goes frame changing logic from the 1st example
}
Pros:
- simplicity
- works everywhere

Cons:
- not possible to scale, rotate, etc. without CSS3

Example: [2. Background looping animation]

3. Clip-rect method
Hmm, but what when we wan't our game to run on full screen, or on different devices with various resolutions? Changing size of the div from second example gives nothing, just looks ugly. So this is where I introduce clip:rec(), Css attribute of img element. Quoting W3schools:

The clip property lets you specify the dimensions of an absolutely positioned element that should be visible, and the element is clipped into this shape.

Let's try:
var canvas = document.createElement('img'),
//image is not the canvas
    canvasStyle = canvas.style;
    
    canvas.src = 'sprite.jpg';
(...)//rest of the attributes
var draw = function(){
    var frameTop = height * actualFrame, 
        frameLeft = 0, 
        frameRight = width, 
        frameBottom = frameTop + height;
//a little math here for each frame
                                 
    canvasStyle.clip = "rect("
        +frameTop +"px " //top
        +frameRight +"px " //right
        +frameBottom +"px " //bottom
        +frameLeft +"px )"; //left
                                      
    canvasStyle.top = posY - height * actualFrame;
//IMPORTANT: even if we crop piece of source image, it's top & left attrs dont change - it's necessarily to move it to the fixed position. That's what I made above.
Pros:
- only one element needed (just img)
- possibility of scaling without CSS3
- crossbrowser

Cons:
- not possible to rotate, flip, etc
- very lot of math needed on each move/frame changing.

Example: [3. Clip-rect method]

4. Div with overflow:hidden
The last way of animation I want to present is simplest than 3rd one, better than 2nd, and doesn't use canvas. The whole philosophy is to create one div element with image inside, display only part visible in div, and move the image in proper way. Like this:
var canvas = document.createElement('div'),
    canvasStyle = canvas.style,
    image = document.createElement('img'),
    imageStyle = image.style;
    
    image.src = 'sprite.jpg';
//div is the 'canvas' now, but it has an image inside
    
    canvasStyle.position = imageStyle.position = "absolute";
    canvasStyle.top = posX;
    canvasStyle.left = posY;
    canvasStyle.overflow = "hidden";
//that is very important
    canvasStyle.width = width;
    canvasStyle.height = height;
    
    imageStyle.top = 0;
    imageStyle.left = 0;
    canvas.appendChild(image);
    document.body.appendChild(canvas);
//put image in the canvas/div and add it all to the body of the document.    
var draw = function(){
                                 
    imageStyle.top = -1*height * actualFrame;
//as in the 3rd example - direction of the move must be negative. Otherwise animation will be played backwards   
    if (actualFrame == frames) {
        actualFrame = 0;
    }
    else {
        actualFrame++;
    }
    
} 
Pros:
- possibility of scaling without CSS3
- crossbrowser
- much simpler than clip:rect()

Cons:
- not possible to rotate, flip, etc
- two elements needed (img & div)

Example: [4. Div with overflow:hidden]

Changing size of animated elements is very important in gamedev. So as simplicity. That's why in my new JS game engine I will implement both, canvas and overflow:hidden methods. You can find all the sources on my GitHub account: [Javascript animation]

Friday, August 27, 2010

NodeKnockout

It is about 7 hours to the Node Knockout, last time for final preparations. Because I don't plan to sleep during that 48h, I prepare a lot of coffee and energy drinks as well as easy-to-eat stuff like frozen pizzas or fries. If it will be possible I will describe everything I will be working on here in near real time. Wish me luck!

Saturday, August 21, 2010

Random array sort in Javascript

There is such an array method called sort, which puts up the elements of an array in alphabetical order, changing it (without copying the whole array). Additionally, it takes also one function parameter for defining the order of elements. If it returns negative number, given elements will be switched, and when positive one, nothing will happen. So to sort an array in random order, it just need to return random numbers in -1 to 1 range.
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
a.sort(function(){ return Math.random()-0.5; });
//'a' is now something like
//[9, 0, 2, 3, 4, 1, 8, 5, 6, 7]
From the other hand, it is only one week to the NodeKnockout. I'm really looking forward for this!

Wednesday, August 18, 2010

Recursion of anonymous functions

When I declare anonymous function, like

(function(){
//do something...
})();
name of the function is not added to any scope, either local or global, because there is no name at all. When I want to call the function again, for example in timer functions like setTimeout(), I simply call arguments.callee inside it

(function(){
//do something...
setTimeout(arguments.callee, 1000);
})();
According to Mozilla Developers Center:
arguments.callee allows anonymous functions to refer to themselves, which is necessary for recursive anonymous functions.

Monday, April 19, 2010

Isometric Snake game for Facebook

During the weekend I went with my girlfriend to my countryside house. Anyway, I didn't want to waste my daily gamedeveloping time.
I created there simple snake game (days ago one of the most popular mobile game for Nokia cells) with isometric graphic. I modify sprites from one wikipedia graphic and use logic from my old Snake game.

Find VD SNAKE 3d on Facebook or simply try this link: http://apps.facebook.com/vd_snakeiso/. (My average result is 700points, what's yours:)?)
You can also become a fan of the game.

Monday, April 5, 2010

Eastern Compo 2010

It's almost tradition that during Eastern Holidays Warsztat members organize special edition of Compo (game developing competition, check). Randomly chosen topic of competition was "A game with particles-effect, Zombies, arrows and deadly spikes". Quite creative.

I tried to create Tower Defense Game with Zombies as creatures, particle-flame throwers and spike-guns as towers and arrows as obstacles. I use some old javascript particle effects and try even to build few fire-towers. Unfortunately JS and web browsers are not adapted to generate thousand of tiny objects. It worked fine with one tower, very bad with two of them, and with three haven't work at all. Because of that I decided that required 'particle effect' will be "Hell fire", shown on spawn place of Zombie creatures. The same situation was with spike/nail guns. So i change my mind and simply put spikes like arrows - on the ground as obstacles. It took me about 8 hours to design, code, prepare the graphics and test the game, so it is not finished at all.

Finally, except me, there was only one participant took part in Compo, so there was no results. If you are interested in my game, download it here: EasternCompo [290KB]
(Readme and gui are in polish, sorry).

Thursday, March 4, 2010

Removing item with given value from an Array in Javascript

'Delete' operator is the easiest way to remove from Javascript's array elements with given index. It works fine with objects like literals but using it on arrays is worst thing you can ever do. What happens if you try?

var tab = [1,2,3];
delete tab[1];
//result: [1, undefined, 3]

It just removes particular element, not even try to fix undefined space left after the operation. So its better to use splice() instead.

var tab = [1,2,3];
tab.splice(1, 1);
// result: [1, 3]

Okey, but what to do if we have to remove item with some given value? We can google a little and find how to expand prototype of an Array object with remove() method, like that:

Array.prototype.remove = function(value) {
this.splice(this.indexOf(value), 1);
return true;
};
a=[112, 234, 32545];
a.remove(234);
// a is [112, 32545];

It works for that case, for sure, but what when item we try to find is not in our array? indexOf() will return -1, and splice() will start to removing elements from end of an array.

a=[112, 234, 32545];
a.remove(22);
//a is [112, 234]

Not funny. So to avoid situations like that we have to put one additional condition to our method.

Array.prototype.remove = function(value) {
if (this.indexOf(value)!==-1) {
this.splice(this.indexOf(value), 1);
return true;
} else {
return false;
};
}

a=[112, 234, 32545];
a.remove(234);
// [112, 32545];
a.remove(22);
// still [112, 32545];

Everything's fine. But in IE (there is always some 'but' in there, thanks Bill), for sure in 6.0, i don't know about new versions, Array type Objects have no indexOf() method, so we have to build it on our own:

if(!Array.indexOf){
Array.prototype.indexOf = function(obj){
for(var i=0; i < this.length; i++){
if(this[i]==obj){
return i;
}
}
return -1;
};
}


Now it works fine. Thanks.