When all tests pass, life is great. And that should be the default case. We are working towards all tests passing, we are not trying to make mistakes.
But when we make mistakes we want to get rid of them asap. That means we need to understand the cause in order to fix it. If the test talks to me like that
"Expected false to be truthy." I get angry. But if the test says
"Expected [object DisplayObject] to have properties 'blendMode'." I get the feeling I know what’s going on and even better, it sounds like I know what I have to fix. That is where custom jasmine matchers come into play.
read more…
We want to wish you all a very happy christmas and a good start into 2013. This year has been very special for us with the launch of http://pixelplant.com, the Flash to HTML5 conversion service including human support ;) and with open sourcing BonsaiJS, after spending almost one year on building something we think would also be useful for others.
We are really looking forward to the next year as we continue improving the Flash conversion and have some very exciting releases coming up – but we won’t mention too much yet, so stay tuned ;)
David, Fabio, Tobias, Tobi, Peter, Wolfram and Nikolai
So you’ve met Orbit, our BonsaiJS editor. Here’s a screencast teaser of what’s nearly ready to be released. It’ll show you that you’ll be able to type code which is then updated in a live running program, without restarting the app. It will also display some of the magic links between source code and output.
Orbit: Visual Code Editor for BonsaiJS
Just to be clear; these changes aren’t part of Orbit yet.
You can find out more about BonsaiJS / Orbit here:
If you want to reuse existing Flash content and convert it to HTML5 / BonsaiJS code, you can visit Pixelplant, which is using BonsaiJS as its graphics engine to display converted Flash content in the browser.
Bonsai is open source and released under the MIT license.
In Bonsai’s latest release (0.4.1) we added support for a new ‘getBoundingBox’ method on all DisplayObjects. We can now accurately calculate the bounding box of paths, and groups containing paths.
To demonstrate we’ve created a demo with a constantly morphing star and a constantly re-calculated bounding-box:
We calculate the bounding box of any given path by converting all of its segments to cubic bezier curves and then calculating the extrema of each curve individually. It’s then a simple case of finding the smallest and biggest values on each axis to determine the bounding box.
Bonsai has always had a split architecture. The renderer has always been seperate to the runner. There are very good reasons for this but unfortunately it meant we could never query the renderer-side for information about drawn objects. So SVG’s getBBox was off the table. This is a good thing though. It’s very slow. Without our runner-side implementation something like the morphing-star demo above would not be possible. There are also many other applications.
All DisplayObject’s now have a ‘getBoundingBox’ method. It returns an object like this:
|
1
2 3 4 5 6 7 8 |
{
left: 22, top: 44, width: 100, height: 100, bottom: 144, right: 122 } |
Calling ‘getBoundingBox’ with no arguments will give you the bounding box of the object in local coordinate space. For example:
|
1
2 |
var rect = new Rect(50, 50, 100, 100);
rect.getBoundingBox(); // 0,0,100,100 |
To get the real position of the object in its parent coordinate space, you would simply pass a matrix transform so that the calculated extrema are transformed:
|
1
2 |
var rect = new Rect(50, 50, 100, 100);
rect.getBoundingBox( rect.attr(‘matrix’) ); // 50,50,100,100 |
In Bonsai, and in most other drawing frameworks, local coordinate space is differentiated from the parent or global coordinate space. Take this simple example:
|
1
|
new Path().moveTo(0,0).lineTo(20,20);
|
That path would have a local bounding box of ’0,0,20,20′. Compare that with:
|
1
|
new Path().moveTo(10,10).lineTo(20,20);
|
That path would have a local bounding box of ’10,10,20,20′.
When we place a DisplayObject, such as one of these paths, onto the stage it is positioned according to:
We can get the bounding box relative to the path’s position within its own parent by grabbing the path’s transform (a 2D matrix in the form ‘scaleX, skewX, skewY, scaleY, translateX, translateY’) and passing it to the ‘getBoundingBox’ method:
|
1
|
var bbox = myPath.getBoundingBox( myPath.attr(‘matrix’) );
|
It follows that we can get the global bounding box of ‘myPath’ by collecting an concat’ing all transform matrices between and including the path and the global stage:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 |
DisplayObject.prototype.getAbsoluteBoundingBox = function() {
var matrix = this.attr(‘matrix’).clone(); var p = this; while ((p = p.parent) && p.id !== 0) { // Get parent’s transform and concat // it with what we have so far: matrix.concat(p.attr(‘matrix’)); } return this.getBoundingBox( matrix ); }; |
And now we can directly call:
|
1
|
var bbox = myPath.getAbsoluteBoundingBox(); // gives global bounding box
|
Note: We are hoping to add something like this to the API very soon. Please follow progress here.
While we wait for some resources to clear before releasing our demo game, King of War, let me give you a sneak preview by releasing the physics engine that’s at the core of it.
The physics of the game basically require a plane (2d area) with circles that can collide. I’ve considered using box2d or related libraries, but as usual decided to do it myself. In hindsight, I’m not sure whether that decision was the best. It might be, because I’m sure box2d would have given me implementation headaches as well. Regardless, I did the engine myself. Which meant diving into some hardcore math. Let me take you through it :)
Let’s start with the basics. We will have only moving circles and we’ll need to properly handle collisions. First we want to be able to detect a collision between two circles. You can do that by checking the distance between the two circles and comparing that to the sum of their radii. If the distance between their center is smaller than the sum of their radii, it must mean that they are overlapping somehow. The formula for the distance between two points is called the Pythagoras theorem and goes like this (where A and B are your points and C is your distance):
1 | A^2+B^2=C^2 |
We could check for this after every frame and then try to correct for it, but why would we want to do that when we can detect collisions before they happen and act accordingly? Let’s try that route.
First we take a look at collision detection between two circles where one circle is idle and the other is moving on a straight path, this resembles our basic most case.
We have two circles, A and B. A has a speed and a course (in radians, not that it really matters). The speed is the number of pixels that A moves for each step (one game frame). Each step A moves on the line A-AA (or A-A’, but I think primes are a bit harder to detect and write in code so I’ll use AA for the end point). We want to know whether A collided with B anywhere while moving on the line A-AA.
To compute this we create a new circle, C. C has a radius of A.radius+B.radius and the same center as B. We can now say that A collides with B while moving on the line A-AA if and only if A-AA intersects with C anywhere (within this step, of course). Turns out there’s a pretty simple algorithm to detect this exact thing.
All we have to do now is to check t1 and t2. If either of them is 0<=t<=1, then the collision will happen this step. t1 and t2 indicate where on the line the collision occurs and where exactly, relative to the line drawn. In our case that means it starts at A and ends at AA. If the number is negative, A might collide with B if it could go exactly backwards. If either t is bigger than 1 than A might collide with B in the future, but not this step.
Now that we have the computation when B is idle, let’s take a look how to do it when B is also moving. Since that’s how it will be a lot of the times in the game. And I tried getting away with it but that won’t work. The problem is too obvious. So how do we do the trick above on two moving bodies instead of one?
I’ve thought a bit about this but couldn’t hack it. I could only come up with extremely complex computations and formula’s. None of them were worth the trouble of even trying to implement them. The horror…
Then I found a nice little trick online that worked brilliantly; You simply deduct one vector from the other and apply the above algorithm on the result. Wow! Ok, so we’ve got that to work. Now what?
When we know where exactly a collision occurs, we must move the stone to that position. If you do this, the stones will be touching exactly. You must then determine what they do next. What happens to the speed and course when two stones collide? After giving that some thought, I’ve concluded (and observed) that it’s actually fine and easy to simply let one stone (the slower stone) move in the original course of the faster stone (this also helped). The faster stone will start moving in a course that makes a line that’s tangent to the exact point of collision. Whether it moves left or right on that line depends on the original angle of approach. This actually works out quite well.
In the demo below both circles have a speed (they’ll follow their blue line at the same fixed speed). The orange line is the delta vector and we can see that a collision will occur if that orange line crosses the outer (grey) circle, just like the example above.
To determine the new speed of the two stones I cheated a little and add a fraction of the original speed of the faster stone to the slower stone and return the remainder to the other stone. This division also depends on the angle of approach, meaning that a stone that barely touches another stone will keep most of its velocity and only changes course slightly. A perfectly head-on collision causes the faster stone to transfer all its velocity to the other stone and become idle. The other stone will continue its path in the original course of the first stone at the same speed of the first stone. You could also play with decreasing the velocity to account for the collision itself, but I didn’t and it still looked fine to me.
Oh and there’s more, much more. If we take a look at an imminent high-speed collision where one of the stones will almost immediately hit another stone after the collision, we’ll see that we must take chaining collisions into account. This means that in the same step, one stone can hit multiple other stones. The thing we must prevent is that we don’t warp the stone by limitlessly moving an attacking stone adjacent to its target (as described above). In some cases this would otherwise cause the stone to warp across the screen and this feels very wrong.
Instead each stone will get a variable that tracks how much time it has used moving while inside a single step. For instance, if a stone would move 50 pixels this step, but it collides after moving 35 pixels, it still has 30% time left in this step. This time is then applied to the new speed and the stone is moved accordingly. At the end of the collision detection cycle, a stone will move the remaining time percentage of the speed it currently has to finish it’s move.
The side effect of this approach is on the one hand that the collisions look much smoother now. But it also means that collision chaining just became a heckuvalot more complex. Because now you have to keep checking for collisions and scan all the stones again after every collision. I’ve had cases where this meant considerate pauses. So it’s a good idea to arbitrarily cut this short. There’s no point in simulating 50 collisions this way. Remember that it’s all about the user. It only has to perceive to be correct.
Here’s a final demo with the entire physics engine at work.
I’ve turned this engine into a plugin. You can find it on https://github.com/bonsai-plugins/circle-physics and include it in your own projects. The Item class is exposed through the Phsyics constructor (so Physics.Item). I suggest subclassing that class.
Hope you enjoyed this article :)
We’re really excited to announce the first public release of our editor “Orbit” which allows you to play with Bonsai and create content without having to do any setup.
Before I dive a little more into the details, go ahead and take it for a testdrive at http://orbit.bonsaijs.org
read more…Bonsai grows with the demand of its users and our flagship project pixelplant.com. The next big thing on our ever growing list of upcoming features was for Audio support. It’s taken us a little over a week to implement the first version and we’re pleased with the results. This version includes an API, a new AssetHandler, tests and a lot of example movies of course. It’s been great fun to replace the normal use of `console.log` with a sound-snippet. Suddenly we’re able to *hear* ticks, events, collisions and even bugs. Of course at some point we hit the boundaries of what is possible in the current web, especially on mobile devices but all in all we’re happy with what we’ve developed. The new Audio API enables a whole new media format and is a great way to express your creativity.
This is how the new API looks:
1 | new Audio('myfile.mp3').addTo(stage).play(); |
So what happens here. We pass a URL to the Audio constructor and thereby create a new instance which also triggers the partial loading of the file. We add the instance to the stage and finally call `play()` what plays the audio as soon as enough data is available.
Press the play button and start the music.
Audio is our fifth supported asset type. We’re already able to handle Bitmaps, Fonts, Submovies and Videos. As with the other asset types, you’ll need to ensure that the file is loaded before it can be used. To do this you should listen for the “load” event and only then start to play.
1 2 3 | new Audio('myfile.mp3').on('load', function() { this.addTo(stage).play(); }); |
We know you’re a good web citizen and want to use more file-formats than just `audio/mp3` but also `audio/ogg` and probably more. The way to do that is to pass an Array of Objects (we call them AssetResourceObjects) to the Audio Constructor.
1 2 3 4 5 6 7 8 | var assetRequest = [ { src: 'myfile.mp3' }, { src: 'myfile.ogg' }, { src: 'myfile.eff', type: 'audio/exoticFileFormat' } ]; new Audio(assetRequest).on('load', function() { this.addTo(stage).play(); }); |
To see the new Audio API in action we extended the existing Pong Game and equiped some collisions with sound. We hope you’ll experience the same difference as we did. Have fun!
We are looking forward to your feedback and seeing some amazing new Bonsai Movies from you.
Your Bonsai-Team
Last Tuesday we released bonsai the light-weight JavaScript library, that makes creating visually rich content on the web easier than ever before, and yes it is inspired by Flash. It was a pretty big day for us, we had been working towards this for months now. Just a couple of weeks ago it was still named Bikeshed, it had almost no documentation and the demos were really just for internal use, but it was always driven by test driven development and we are pretty proud of that.
Bonsai is nothing less than the heart of our Flash to HTML5 conversion service pixelplant. Bonsai is open source and released under the MIT license. Without bonsai there would be nothing ticking. Bonsai is the JavaScript library that does all the hard work and allows you to write really simple code to accomplish even complex things, such as (click the run-button at the upper right corner below):
We had been reshaping the API multiple times, from early on we had input from real users and now we are very confident that it has become consise and easy to use. As you can see there has been a lot of working going into little details such as manipulating the colors.
Bonsai can roughly be separated into three big areas:
When we started out we wanted to see results quickly and not prototype for an eterninty until we could try it out. Pure development had started in October and actually all the optical illusions for our christmas bikeshed episodes had been made with a very early version of bonsai (which still used to be bikeshed).
In order to get the API into our hands quickly we used Raphaël initially as the renderer below, so we didn’t have to worry about this part anymore and built purely the API. When the architecture and API reached a very useable state we replaced Raphaël with our own renderer, a SVG renderer. Besides the SVG renderer we decided for one very important detail early on too: our separation of the renderer and the runner.
The runner is the piece that does the heavy load, it executes the bonsai script you write, does all the calculations and generates a set of rendering messages, for each frame. The messages are requested by the renderer when it is done with the last set of messages, it then has no more to do than translating those messages into visible elements. The two are communicating over a simple protocol. Those two layers allow us to move the execution of all heavy calculations into the WebWorker and give the renderer all the execution time of the web page for rendering, since that is the thing that takes longest, especially on the current mobile devices. And no heavy calculation would hinder the rendering. On top we got for free to execute the runner on the server (in a nodejs process) and send only the rendering messages to the browser, which allows even multi player games served by one server process. The renderer itself has no more than 2000 lines of code that just uses SVG and soon Canvas, WebGL or any other technology for rendering any kind of visuals.
Oh yes, you bet.
We are shipping bonsai already as part of our products and services. Of which pixelplant is the most prominent one. It is running already for months.
Of course we are optimizing speed every day and trying to squeeze every last bit out of it, especially when we jump from our desktop development environment onto a mobile device, such as the iPad to test it out we see that there is lots that can be done.
Thanks go out to all those that have been working hard to get bonsai out of the door, the entire uxebu crew and everyone who has helped us get it to where it is.
We are looking forward to all the input that we can get from the community and hope that everyone out there who is interested becomes productive quickly and has a fun time using what we built.
Some might have heard of the decision we took last year in October, for others it might be new: We jumped into the deep end of the pool by deciding to spend all of our time on what we love doing most – building tools for the web, using technology of the web. It is an incredibly exciting time in the life of uxebu, so let me sum up a little bit why and how we took this somewhat crazy step.
The uxebu incubator
We always tried to make time available for other projects, open-source work and R&D type of work. We pushed out a lot of cool stuff, such as TouchScroll, EmbedJS, HumanAPI, StorageJS and apparat.io. We even were spinning around ideas of giving everybody at uxebu the option to seed-fund their own idea/startup from uxebu funds by creating an incubator. We never were really able though to launch something into its own life – customer projects did a great job sneaking themselfs into our other projects with sometimes too high priority – you probably know exactly how this feels :)
read more…
I am just hacking along, all TDD style of course, and the one problem I always come across again is to realize when I should mock and when not. My current idea is to have two blocks of tests, one with mocked data, the other non-mocking. Let me lead you to why I came up with that. Input and discussion welcome, I am curious about ideas and possible improvements.
read more…