donderdag 29 oktober 2015

AABB collission

Ok, this may be me being stupid, but I was looking for the fastest way to check if two bounding-boxes overlap.
Given a rectangle taking the shape of {x,y,w,h}
If read somewhere on the internet the fastest way to do it was:
function BoxesIntersect(a,b)
{
   return (Math.abs(a.x - b.x) * 2 < (a.w + b.w)) &&
         (Math.abs(a.y - b.y) * 2 < (a.h + b.h));
}

Looks amazingly compact. But the result isn't very accurate. Especially if the bounding boxes differ in size much.


So I thought a bit and I came to this. Which is ALWAYS accurate. Maybe not as fast and certainly not consistently fast, because it bails out at the first sign of failure, but pretty fast anyway.

And here is the algorithm, but it would seem it would be faster, if instead of rectangles, you'd keep a minx-maxx and a miny-maxy.

function _hybridGameBoxIntersect(a,b)
{
  if((a.x+a.w)<b.x) return false;
  if((a.y+a.h)<b.y) return false;
  if((b.x+b.w)<a.x) return false;
  if((b.y+b.h)<a.y) return false;
  return true;
}

donderdag 22 oktober 2015

8-bit graphics on a canvas

This is just to show you how old I am.
When I started programming on a C-64, you could make your own fonts if you did the math.

You just drew a grid like this:
 128   64   32    16     8     4       2     1
[     ][     ][  x ][  x ][  x ][     ][     ][     ] =  32=16+8= 56
[     ][  x ][  x ][     ][  x ][  x ][     ][     ] = 64+ 32+ 8+4=108
[  x ][  x ][     ][     ][     ][  x ][  x ][     ] =128+64+4+2=198
[  x ][  x ][     ][     ][     ][  x ][  x ][     ] =128+64+4+2=198
[  x ][  x ][  x ][  x ][  x ][  x ][  x ][     ] =128+64+32+16+8+4+2+1=255
[  x ][  x ][     ][     ][     ][  x ][  x ][     ] =128+64+4+2=198
[  x ][  x ][     ][     ][     ][  x ][  x ][     ] =128+64+4+2=198


[     ][     ][     ][     ][     ][     ][     ][     ] =0
And you would get the letter A from just 56,108,198,198,255,198,198,0. Just 8 numbers;
We called this a BITMAP and it was actually the only way, to create monochrome graphics on the screen of my C-64. Even if you used the whole screen, it would just mean more adding up.

Now as you may know, those days are LONG gone.
These days we still use basically the same techniques, only no more counting the pixels and adding up powers of 2. Bitmaps are now also RGB bitmaps with millions of colours and billions of pixels.
But it was a great way, to get a lot of graphic in a very small amount of number.

Great for games. It was why these 8-bit games looked like that.
Now if you use 8-bit graphics on a HTML5-canvas, it will automatically blur your image.
That actualy looks very bad with small graphics blown up big.

This fact has been making it very hard to do 8-bit HTML5-games, but never fear.
(Mis)using SVG, which is now supported in all major browsers to create little blocks on the places where we put the numbers in the grid (and doing some number crunching in javascript)
we can now reuse all byte-coded fonts we had on the C-64.

With one added bonus, we can actually rotate the images and they will remain crystal clear.
Ain't that a nice bonus for a otherwise completely useless excercise.

Well.. I say useless, but animations are still quite big and this might be a very nice way to let kids create small animations to use in their own games on MakingGames.org.
I will give them a paint-like program to do the actual animation, I'm not a monster..

HTML5 Canvas, context setTransform explained from skew, rotate, scale and translate

Things are sometimes a little skewed in the world of Adobe. And if you use Adobe products to produce game graphics (like animations) that you'll use on a canvas, (and you don't want the BULK of createJS) you run into trouble quite easily.

So I needed to understand how to get THIS in terms of the canvas context.setTransform() function.



If you want to skip the explanation, my working example is at the bottom of the page.

What are matrices again?

The canvas setTransform function takes a transformation matrix: [[ace],[bdf],[001]]
Now I've had matrices in school for a semester and later dabbled in OpenGL matrices, which are a bit more complicated than 2D matrices, but I always had trouble explaining to myself what happened in either 2D or 3D. So time for some experimentation.

void ctx.setTransform(a, b, c, d, e, f);

They say, it helps to think about these parameters as:
a Horizontal scaling.
b Horizontal skewing.
c Vertical skewing.
d Vertical scaling.
e Horizontal moving.
f Vertical moving.

It helps. If only it wasn't a gross over-simplification.
Because when you start to experiment for real, you'll see the truth is a bit different.
The above is only true, AS LONG AS you do not ROTATE.
But you should be able to set skewing even when rotated, just like that.. That's the beauty of using matrices, I remember that much from school.

So I wrote this little bit of code to experiment and show you (and myself) how simple or difficult it REALLY is to get the results you expect..

If you want to rotate, make sure the angle for x and y are the same. If you want to skew, make the angles for x and y NOT the same. The amount by which they differ is the skewing.

You can visualise this as setting the rotation for the x axis and the rotation for the y axis seperately. Just like you would when you do a non proportional scale and set the length of the X axis and Y axis seperately.
Anyway, it helps me to understand those pesky matrices better and I wanted to clarify what I found to you. So here is the code-breakdown:
It basically sets up a interval and a canvas. Then in the move function draws a stroked rectangle repeatedly from -50 to +50 in x and y.
But before it does that it sets the context transform according to the frame-counter.
The first 45 frames it just rotates and moves a scaled version of the rectangle.
After the first 45 frames it skewes it in the y-direction as well..

The first 45 frames you might achieve the same by doing ctx.translate, ctx.scale and ctx.rotate.
But after 45 frames, you really see the power of setTransform.
Also note, that ctx.translate etc are cumulative and you need to save and restore your context.
With setTransform, you don't. Just set it back to the zero-matrix when you are done and want to draw normally again: ctx.setTransform(1,0,0,1,0,0);

Anyway, here is my code and it's execution:

var counter=0;
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
setInterval(move,25);

function move()
{
    counter++;
    var anglex=45+counter;
    var angley=45+counter;
    if(counter>45) angley=80+counter;
    var scalex=0.5;
    var scaley=0.7;
    var origx=0+counter*2;
    var origy=100;
    var rx=Math.PI*anglex/180;
    var ry=Math.PI*angley/180;
    ctx.setTransform(scalex*Math.cos(rx),scalex*Math.sin(rx),-scaley*Math.sin(ry),scaley*Math.cos(ry),origx,origy);
    ctx.strokeRect(-50,-50,100,100);
}





About skewing

Now skew or slant is a bit of a wrongly used term normally. Speaking Mathematically we mean something else, than what most people know from Adobe's programs.

So I made another example, to mean more what most people THINK skewX and skewY mean: namely skewx and skewy are inverted: If you want the code for that one, just press the edit in fiddle button in the top right hand.
I'm not going to explain that code here, I've kept it very simple.

It's still not exactly how skew works with Adobe, because at low skews in the X the height of the object stays the same with for instance Flash. If you go skew things a lot, it will just give you very unexpected results. This is why: Adobe compensates the length of the axis that is not skewed to make it keep approximately the same height:
I fiddled around a little bit more and ended up with this:

If you are used to adobe products, this will give you something quite a kin to the skewing that you know and love. It's not an exact -pixel perfect- match, mind you, but quite good at low settings (-45/45 degrees) and that's good enough for me right now.


Original article I found (and I found was wrong:)
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setTransform


zaterdag 3 oktober 2015

GameSounds with WebAudio

For MakingGames.org I needed a way to create gamesounds with very little training and effort.

This is my first fiddle, that comes close:
http://jsfiddle.net/FVaWL/24/


The sound is one oscillator and 4 modulators, so with about less than 40 numbers we can describe any sound.
From this very simple recipe a enormous variety of sounds can be created.

By exagerating the gain, you get this clipped 8-bit quality, but you can make beautifull round tones as well. It's nice you can actually get those old school gamesounds and some nice warm sounds quite cheaply from webaudio.

In the later fiddle I added some controls. I guess, if I add a variant button and a volume envelop you can control with a few points, we are there.

Most of them are crap, offcourse, but that's not a problem with the making-games system, as every sound will be rated and possibly labeled by users, before it lands in a library.

Next phase might be to save the generated sound as a wav:
https://gist.github.com/pramodtech/9760681

Then use php to convert to ogg and mp3, as alas IE does not support WebAudio.