HTML5 Canvas Bindings for Nim's JavaScript Target

It seems like every one to two weeks I've been writing a new package for Nim.  I've been playing around with the JavaScript target.  There is some basic stuff there in the dom module for HTML manipulation but I noticed something very important was missing; the canvas tag.  So well, I added a thin wrapper for it (GitHub mirror).  It's available under the html5_canvas package in nimble.

When I first heard about HTML5 and read the spec a little, I think one of the most important things that was added was the canvas tag, and along with it a JavaScript API for all sorts of drawing operations.  Interactive content for the web that was being made with technologies like Flash and Java (applets) could now closer to the browser level (and have better performance to boot)!

The only thing is that I don't really like writing JS code; it's my least favorite language out there.  But you know we live in a time where you don't have to write JavaScript to write JavaScript anymore!  While Nim's JS backend is still marked as experimental I think that its nice enough where we can still make some cool stuff with it.

I tried to keep the API as close as possible to the one listed in the Mozilla docs.  Though I did have to make a few changes.  One of those in particular are the fillStyle and strokeStyle getters and setters.  The problem with these two fields of CanvasRenderingContext2D is that they can be one of any three different types (see here).  Nim being a strongly typed language wouldn't let me put those properties right under the type ... object definition.  Luckily though there is still a way to keep the API so it looks like we're setting a field instead of having to add a setFillStyle() proc.  Taken from the source, look a this:

proc `fillStyle=`*(
  ctx: CanvasRenderingContext2D;
  color: cstring
) {.inline.} =
  {.emit: [ctx, ".fillStyle=", color, ";"].}

# Can do this now!
ctx.fillStyle = rgb(255, 0, 255)

But as for the getters I had to do this:

proc fillStyleColor*(ctx: CanvasRenderingContext2D): cstring {.inline.} =
  {.emit: [result, "=", ctx, ".fillStyle;"].}

There's one for Gradient and one for Pattern as well.

For some extra fun, I ported over my 3D Canvas Cube from Dart (another language that compiles to JS).  I've put the source up in my toybox repo.  What's also pretty cool is that the compressed JS output from dart2js was about 90 kilobytes, where as Nim's compressed JS is around 20 kilobytes!  Originally when when did full imports (i.e. import math) I was getting 124 KB compressed, but when I changed to selective imports (from math import Pi, sin, cos, floor) I was able to drastically reduce the size.

 

 

I was able to get the animation to work by adding a mini proc to wrap JS's setTimeout() function:

proc setTimeout(function: proc(); ms: float) =
  {.emit: ["setTimeout(", function, ",", ms, ");"].}

If you're bored with 2D graphics and want to do something 3D in Nim (and in the browser), take a look at stisa's nice WebGL wrapper.

Here is the link to the repo for this again (GitHub mirror).  It's also on nimble under html5_canvas.  Have fun!

Masala, A ChaiScript game engine

Over the last semester, I've been working on a game engine.  It was meant to be a personal challenge for myself,  to see if I could make my own game engine with some bare materials.  Those being C++, OpenGL, and Qt.  I wanted it to be more though.  Seeing as most professional game engines these days (developed by community or company) feature some sort of scripting engine, I decided to make my own scriptable game engine.

After some troubles with trying to embed Python & Lua inside of a C++ dummy projects, I discovered this thing called ChaiScript.  The tl;dr is that it's a scripting language for C++ that's dead simple to use.  I decided to use it for my project since it gave me a no hassle way to add scripting features to my project.  It was dead simple as "include the headers," and "give me a pointer to your C++ function/variable, and tell me what you want to call it."

Of course with simplicity, comes some cost.  One of the first things for example are the long build times.  If you statically include ChaiScript (which is the simplest way of using it), expect to take a small break when compiling.  This can be easily remedied by dynamically linking ChaiScript's standard library and including a .dll/.so file alongside your executable.  I did this when developing Masala.

I also ran into performance issues with ChaiScript.  At the current version (5.8.1), the language is executed using an Abstract Syntax Tree.  While this is necessary for parsing a language, using it to run code is much slower than it could be.

Enough about ChaiScript, let's talk about the engine itself, Masala!

Masala was built using C++ (14), Qt 5.x, ChaiScript, and OpenGL.  I had the goal of trying to create a reusable game engine where you write all of your logic inside of ChaiScript files.  It follows a very lose XNA/MonoGame-like pattern.  Right now it features:

  • 2D
  • Cross platform (Built with Linux)
  • Featureful sprite object (with animations!)
  • Tilemaps (Flare maps)
  • Basic sound effects
  • Keyboard Input
  • Interactive debugging terminal

It's pretty simple.  I mean, very simple.  I don't think it stands up well to other engines that are out there, so I really consider it to be an experiment in using ChaiScript for a game engine.

I implemented two simple games, one being a clone of the classic Atari Pong:

Pong is (c) Atari Inc.

And another more original one I've dubbed "Grab n' Dodge:"

It's more difficult than it looks, but not too fun.

I would say that I accomplished my goal in writing a game engine.  Something that I have never done.  As for the cross-platform part, I was able to get the code to compile on OS X and Windows, but had some trouble upon running it.  One of my friends said that he was able to get it working on OS X, but I haven't seen the proof.

If anyone wants to help me getting this running on Windows or OS X, contact me.  Since it was made using cross platform tools, it should work on all of the OSes Qt & OpenGL support.

And last, you can find the official code repository over here on GitLab.  It's GPLv3 licensed.

Toying Around with HTML5 Canvas & JavaScript

It's finals week right now and though I should be studying, but I decided to play around a bit and see if I could make some sort of pseudo-3D renderer.  Originally I was going to work on it in C/C++ and SDL, but I should try something different and check out this newfangled HTML5 & JavaScript stuff.  I'm not the biggest fan of JavaScript, in fact, every single time I've ever had to do something in the language I've found it to be quite a painful experience.  But I have to admit, with HTML5's Canvas tag, you can do cool things like this:

The "3D plane," wasn't too hard to setup, and it's pretty bad 3D as it is.  Using some of the basic slope mathematics, and rotation matrices I was able to achive this effect. HTML5 canvas gradients also were used to create the illustion of depth.

I'll be taking Computer Graphics next semseter; I'm really looking forward to it.  If you want to check out the code for this, I put it in my toybox repo.

© 16BPP.net – Made using & love.
Back to Top of Page
This site uses cookies.