29a.ch

Fast html5 canvas on iPhone/mobile safari

I finally found a way to optimize 2d canvas drawing on the iPhone 4. Because of the retina display the canvas seems to be rescaled in a slow way (in software?). So even though the rendering itself is relatively fast, the end result is slow.

Setting the Viewport

The first step is to set the viewport scale to 0.5 which will result in having one pixel per css pixel.

<meta name="viewport" content="width=device-width, initial-scale=0.5, user-scalable=no"/>

So now the rendering is fast, but the picture is tiny.

3D transforms to the rescue

To scale the picture up we can use css 3d transforms which are fast.

canvas { -webkit-transform: scale3d(2, 2, 0) translate3d(200px, 110px, 0); }

Also note the translation to move the image back into place as it is being scaled from the origin.

That's it you got yourself a massive performance boost in about two lines of code. :)

WebGL Terrain and Water Reflections

I'm doing my first steps into webgl land. It's definitely a love hate relationship, and I still have a lot to learn and improve. :)

I might post the actual demo at a later stage, right now it's a complete mess.

Controlling a usb rocket launcher with kinect

I got myself a kinect to play around with. I decided to hook it up to a usb rocket launcher that I had lying around. I did it with a little bit of python, libfreenect and pyrocket. And no comments about the video editing - that was WAY more difficult for me than the hack itself!

The source code is on github:
https://github.com/jwagner/kinect-experiments

Oh, and thanks to my little brother Nils for filming. ;)

A new html5 game space break



Play it now

Space Break

Space Break is a html5 acrade 'ball and paddle' game written in coffee-script. It features levels full of explosives, extra balls and even nukes. I hope you will enjoy it.

History

Space Break started out as coffee-break - a little project I did to get into coffee script. Because it turned out to be a lot of fun I decided to turn it into a complete game.

Technology

Space Break uses the canvas tag for rendering. The sound effects were created using csound and played using the audio tag. The graphics were made using the gimp and blender. Rake is used for controlling the asset pipeline. All the assets of the game (music, sounds, graphics) are self made - programmer art.

Browsers

Firefox 4 (3.6 kind of works), Chrome 9 and Safari (no ogg - no audio) work. Opera is crashy. Mobile safari on the iPad also works but the frame rate is low. Could be fixed with a bit of optimization.

Source and License

The code and assets are of course on github.

The Sourcecode (break.coffee, Rakefile) is licensed under the GPL V3.

The assets are licensed as Creative Commons BY NC SA

PLEASE LET ME KNOW IF YOU DO SOMETHING COOL WITH IT.

If the licensing doesn't work for you, please let me know.

Feedback

Feedback, both positive and negative is of course appreciated. Just leave me a comment, tweet or send me a email.

Loading twitter widgets asynchronously using yepnope

Twitter widgets block the loading of your page by default. So if twitter goes down it will take half of the internet with it. That of course is fail! So let's use yepnope.js to decouple them from your page.

Starting position

<body>
<a href="http://twitter.com/share" class="twitter-share-button" data-count="vertical" data-via="29a_ch">Tweet</a>
<script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
<script src="http://widgets.twimg.com/j/2/widget.js"></script>
<script>
new TWTR.Widget({
  version: 2,
  type: 'search',
  search: 'rainbow'
  // ...
}).render().start();
</script>
</body>

Twitter button

The twitter button is actually implemented nicely using data attributes and progressive enhancement. This makes life easy for us.

<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="29a_ch">Tweet</a>
<script src="yepnope.js"></script>
<script>yepnope('http://platform.twitter.com/widgets.js');</script>

As you can see loading the twitter button with yepnope is trivial but you get some flickering. Let's improve that with a stylesheet

a.twitter-share-button { display: block; width: 110px; height: 20px; visibility: hidden; }

This will preallocate the space needed for the twitter button. You might need to tweak it depending on the button you have chosen. Making the button fade in with css3 transitions would be another option.

Twitter Search Widget

The twitter search widget is a bit more problematic as it is using document.write(). I really wonder why they got the button so right and the other widgets so wrong. BOOOOH! If you look at the source you will find something interesting though:

if(!o.id){document.write(

It looks like somebody at twitter was aware of the fact that using document.write isn't a good idea and provided a way around it. He just didn't clearly document it. So let's use the id option to fix our problem.

<div id="twat"></div>
<script src="yepnope.js"></script>
<script>
function twatr(){
    new TWTR.Widget({
      id: 'twat',
      version: 2,
      type: 'search',
      search: 'rainbow'
      // ...
    }).render().start();
}
yepnope({load: 'http://widgets.twimg.com/j/2/widget.js', callback: twatr});
</script>

I hope you can now sleep well at night - without nightmares of fail whales (just ignore the fact that you are using an undocumented feature).

Chaotic Particles HTML5 Canvas Demo

I created this demo more or less by accident when prototyping some particle mechanics for a game. It is based on a particle system, and an acceleration map but more on that later. It reminds me quite a bit of simulations of galaxy formation or a lava lamp, it's really nice to watch.

Demo

screenshot

Click the image to open the demo. In the demo, set the particles in motion by dragging with your mouse.

Mobile devices

This demo also works on Android including fullscreen (tested on a nexus one with 2.2), iPhone and iPad! Give it a try ;)

How it works

Each particle has a position and a velocity stored in a typed Float32Array (yes, they work on iOS). In addition to that there is an acceleration 'map' in the background. When you drag over the particle system, you initialize the acceleration map which sets the whole system in motion.

accelerationMap[particle.position] += particle.velocity*someFactor
particle.velocity += accelerationMap[particle.position];
particle.position += particle.velocity;
...
The magic sauce to it is the feedback from the particle velocity to the acceleration map. Together with some damping this results in the system you are seeing. For more details, feel free to have a look at the source.

JS WARS as mobile html5 game

It's been well over a year since I first released JS WARS. I was playing with the idea of having a version that runs on mobile devices for quite a while now, but until recently the technology was not advanced enough to easily do it. With the release of iOS 4.2 there is a platform that is fast enough and has all the features that are needed to run JS WARS - So I did it.

Getting it

You can try JS WARS mobile under the following URL: http://29a.ch/jswarsmobile/.

Tested devices

  • iPhone 4g with iOS 4.2
  • iPad with iOS 4.2

Please report your success with other devices in the comments. If you don't have a device that can run it, you can still play the normal version.

Controls

You can control your ship with the joystick on the top left. Push and hold the laser button on the top right to fire your laser canon (infinite ammo). The second button allows you to fire missiles/nukes when you have any (ammo is limited).

Technology used

and now for some buzzwords...

I'm actually quite impressed by the canvas performance of the tested devices, is this now hardware accelerated?

What's currently (2.2) wrong with Android

Until recently the canvas implementation of the android browser was pretty much unusable due to problems with the pixel density (1 css pixel -> 4 physical pixels). Those problems are solved now, and thanks to the jit the browser is fast enough to support JS WARS as well (faster than mobile safari it seems). The two things that are still missing hovever are multitouch and a way to treat a website like an app. I find it a bit confusing that iOS seems to be more friendly to webapps than android and I really hope the great engineers at google will catch up. Maybe 2.3 will do the trick already. I'll try it out as soon as there is an official release for the Nexus one (or I can get my hands on a Nexus S...).

Graphics

All the graphics in JS WARS were made by myself using open source software (gimp and blender). I have released a part of them under a creative commons license for you to reuse.

Source code

I will not publish the JS WARS mobile source code because it's a mess and I don't intend to clean it up nor do I want to be responsible if you permanently loose your sight because of it. I do however plan to write an article about the associated challenges that will include relevant code.
So if you haven't done so already subscribe to my news feed or follow me on twitter.

Play it slowly 1.3.1

I was close to complaining that there was virtually nothing new in ubuntu 10.10. Well there was something new, it broke play it slowly. This should be fixed in 1.3.1. In addition to this I have fixed a bug that caused an exception when the mimetype of a file could not be detected.

I hope you like it. Feedback is appreciated!

screenshot

Get it Now

HTML5 Water Ripples Demo

Finally after a long time I can present you a new demo. It is inspired by the wave propagation formula mr.doob demoed a while ago. I was quite amazed by how simple it was and so I decided to build myself a little pond.

Demo

screenshot

Click the screenshot to start the demo. Move your mouse over the pool to disturb the water.

How it works

I think the really interesting part here is the wave propagation formula:

waveHeight = (buffer0[i-1] + buffer0[i+1] + buffer0[i+width] + buffer0[i-width])/2-buffer1[i];
buffer1[i] = waveHeight;
aux = buffer0;
buffer0 = buffer1;
buffer1 = aux;
Given are two height maps (buffer0 and buffer1). The buffers get rotated every frame so buffer0 points to heights of the wave in the last frame and buffer1 to the one before it. The height of the wave in the current frame at a certain point is calculated by simply averaging the height of the neighboring points in buffer0 and subtracting the height in buffer1. You can think of it like this, every point wants to be at the same height it's neighbors are and it wants to go towards zero. That is basically all there is to the wave propagation (I also added some simple filtering to make it a bit smoother).

The rest is pretty simple, and made up on the spot. The refraction is done by offsetting the texture coordinates by the height difference between the current point and it's neighbors. The lightning and caustics are faked similarly based on the height differences and the height of the current point.

In short it's all fake.

Performance

Chrome is fast, firefox is slow, at least thats the way it usually is. To my pleasant surprise the jaeger monkey builds of firefox seem to finally catch up. Another interesting thing is that safari seems to be the fastest (for this demo).

Credits

The photo was shot by Travholt licensed CC-BY-SA. As mentioned in the intro, I got the wave propagation function from mr.doob.

Other Experiments

Be sure to check out my other experiments. If you like what you saw you should subscribe to my blog or follow me on twitter.

Deploy ssh public key to multiple servers using python and paramiko

This is a little snippet I wrote to install my publickey onto multiple servers at once. The actual script I use automatically detects all the servers. It is using paramiko to do the actual ssh work.

#!/usr/bin/python
import os
from getpass import getpass

import paramiko

def deploy_key(key, server, username, password):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(server, username=username, password=password)
    client.exec_command('mkdir -p ~/.ssh/')
    client.exec_command('echo "%s" > ~/.ssh/authorized_keys' % key)
    client.exec_command('chmod 644 ~/.ssh/authorized_keys')
    client.exec_command('chmod 700 ~/.ssh/')

key = open(os.path.expanduser('~/.ssh/id_rsa.pub')).read()
username = os.getlogin()
password = getpass()
hosts = ["hostname1", "hostname2", "hostname3"]
for host in hosts:
    deploy_key(key, host, username, password)
Author

Jonas Wagner Jonas Wagner
Software Engineer
Zürich, Switzerland

More about me

Follow 29a_ch on Twitter

Experiments

screenshot screenshot screenshot screenshot

More Experiments

Latest Posts Tags Archive Links

guitarmasterclass.net (guitar lessons)