Can you go from art to program in one or two steps? Well, that’s what today’s post is about.
One of the cool things I remember about web development from years ago was Adobe Flash.
Before you boo me, hear me out!
I’m not saying Flash is a better technologically than HTML5, The Name of Your Favorite JavaScript Framework, CSS, Web Assembly etc… However one place Flash excelled was visual design & layout… an important part of the web!
The problem with many modern tools isn’t that they can’t convey design, it’s that they decouple the design and the development processes!
In practice this means writing code to describe the elements of your software like HTML and later writing more code to style the elements (like CSS, SASS or LESS), none of which is actually visual, though you definitely can get some great results!
Flash Builder (or whatever it was called) was half art studio and half IDE (Integrated Development Environment) where you could draw anything and it was an “object” and you could write code (ActionScript) to control it’s behavior. It wasn’t a mockup or illustration, it was the actual program!
As I recall, once the switch to ActionScript 3 was made the ability to store your code on the objects themselves was depreciated in favor of using references and listeners stored in the main keyframe timeline… I preferred keeping my code on the objects themselves but I digress.
Even with the change to where you stored your code you could still accomplish anything you wanted with the centralized keyframe code and some developers even found this easier to maintain than storing the code on the components.
You would setup your scripts on layered keyframe’s that extended to the last keyframe used in the project, or the last frame that needed that code and by using a sort of “goto keyframe name or id” method you could actually build complex applications quite easily, and more importantly… visually!
That’s why all the games used to be made with Flash, you could basically draw a picture and then turn it into an animation or even a full program in a couple of hours. This meant you were free to experiment & push boundaries.
Now, yes of course there are visual workflows you can use today.There are WYSIWYG editors and CMS App Platforms like WordPress, Drupal & Joomla not to mention the full featured layout capabilities of site builder tools like Wix.
Fundamentally though these tools facilitate laying out HTML elements and applying CSS and maybe some JavaScript via a drag and drop interface. Which is significantly faster than doing visual development via code in my opinion, though I am not arguing it is inherently “better”.
Unlike the aforementioned tools which specialize in “page based” HTML applications, Flash was an element or object that you embed into your page that used Vector Graphics to create lossless re-sizable images, animations and applications.
Inside the Flash movie/app you could draw anything and you were not constrained to HTML elements but you were also not required to code the visual elements.
This made for a wonderfully rapid prototyping experience that I was unable to reproduce until I tried working with Unity 3D which describes itself as “the ultimate game development platform” though I’d go so far as to describe it as “the ultimate app development platform”.
Think about it, at the time of writing this Unity supports 25 Platforms including Desktops (Win/Mac/Linux), the mobile OS’s, and all the major gaming consoles, not to mention the Smart TV’s, Watches etc…. Any platform you want your app on, including the web, well… Unity pretty much supports it right out of the box. Oh, and it’s free until you make $100K a year with it, not too shabby!
The catch? Well, its highly optimized but leans in the 3D gaming direction (though I’ve built 2D apps with Unity) so the applications it produces tend to have a larger size (as far as my tests go) than if you used PhoneGap/Cordova or went native. My guess is this is due to the embedded physics engine and graphics rendering code that gets packaged with the app but i’m only guessing, and there are a few options that let you exclude unnecessary things from the compiled app.
Then again, you may be able to make use of those features in your app so it need not be a negative either.
In any case, the problem as I see it with Unity is that the builder isn’t readily available on Linux, but it will build for Linux ❓ Maybe they should build Unity with Unity so that it can Unity being Unity… 😛
I am aware they kinda released a limited version for Linux… but I could never seem to make it work right and the truth is that it takes some decent (but not outrageous) resources to run the Unity builder application so most micro computers are out and sadly it won’t run on the ARMf architecture so using a Raspberry Pi to do Unity development is just not happening.
Is there another way?
Well, there is a modern Vector Graphic format available for the web called SVG that is basically XML code that can be written in a text editor or it can be drawn using a program like Inkscape (free and what I use) or Adobe Illustrator if you prefer a commercial paid tool.
Since SVG is code, if you place the code inside your HTML (sadly not link to or embed) you don’t just get a static vector image but instead you get elements that are accessible via the DOM (Document Object Model) that you can manipulate using CSS and JavaScript.
That last part should really interest you if you enjoy rapid application prototyping!
Which is the origin of this project, I wanted to know… could I rapid prototype an application by just drawing a picture and writing some code?
Understand that I am not talking about drawing a picture, slicing it then building an app from sliced components or using the sliced images as placeholders or writing code to draw the slices onto a canvas context.
I challenged myself to see if I could only write code that was part of the core functionality and not basic graphic asset creation and certainly not the code to display it, just manipulate it.
I set about creating a very simple “proof of concept” a while back that is basically a “Die Rolling App” that you can view a live example of here: SVG Roller though I never wrote about it. Roller is half image and half app but very basic.
Roller consists mainly of showing and hiding elements in the SVG based on a button click and a random number… good but not all that flashy!
Recently I have been wanting a better SVG application that would be more visual and expand on what I have already done but retain the simplicity of “Draw It then Code it”.
So, I opened up Inkscape and drew this image:

I grouped all the associated assets and gave them id’s like “cloud1”, “player”, “coin2” etc… then saved the image as demo.svg and closed Inkscape.
Why a game? Well, it’s more visual than my SVG Roller and I think it illustrates more of what is possible with an SVG app.
After that I opened demo.svg with a text editor and copied the SVG code into the body tag of my HTML file (remember you can’t link to it you have to include the code in the HTML).
I then wrote a little CSS that helps position the SVG on the page, applied a background color, disabled text highlighting and changed the cursor to the hand icon when the mouse is over a button, minimal CSS.
After that I wrote the JavaScript that turns the image into a playable application.
Game.js
Here is all the code that makes the SVG Platformer game demo work:
var keyEvents = {}; // keyboard state object
// Listen to keyboard outside of game loop to be less "blocky"
var onkeydown = onkeyup = function(key){
key = key || event; // IE Fix 😦
if(key.type == 'keydown'){
keyEvents[key.keyCode] = true;
}
else{
keyEvents[key.keyCode] = false;
}
//console.log(keyEvents);
}
var game = document.getElementById('game'); // A reference to the SVG
if(game){
game.addEventListener("load",function(){
///////////
// Functions
// Clear Instructions
// removes the instructions element
function ClearInstructions() {
instructions.remove();
}
// Get Position
// This function gets the current (x,y) cordinates of GetPosition(object)
function GetPosition(object){
var transformlist = object.transform.baseVal;
var group = transformlist.getItem(0);
var X = 0;
var Y = 0;
if (group.type == SVGTransform.SVG_TRANSFORM_TRANSLATE){
X = group.matrix.e;
Y = group.matrix.f;
}
return [X, Y];
}
// Collide
// A basic box collision detector
function Collide(element1, element2) {
var collisionBox1 = element1.getBoundingClientRect();
var collisionBox2 = element2.getBoundingClientRect();
return !(collisionBox1.top > collisionBox2.bottom ||
collisionBox1.right < collisionBox2.left ||
collisionBox1.bottom < collisionBox2.top ||
collisionBox1.left > collisionBox2.right);
}
// Inside
// A basic inside box collision detector
function Inside(element1, element2) {
var collisionBox1 = element1.getBoundingClientRect();
var collisionBox2 = element2.getBoundingClientRect();
return (collisionBox1.top <= collisionBox2.bottom &&
collisionBox1.bottom >= collisionBox2.top &&
collisionBox1.left <= collisionBox2.right &&
collisionBox1.right >= collisionBox2.left);
}
// Get Bank Total
// Get the number of diamond or coins the player has
function GetBankTotal(element){
var currentValue = element.textContent;
return parseInt(currentValue);
}
// Collect
// Increment the Coin or a Diamond "player bank"
function Collect(element){
element.textContent = GetBankTotal(element) + 1;
}
///////////
// Game play
// Set the "constants"
var step = 1;
var jump = 20;
var gravity = 1.5;
// Setup references to the "named" SVG XML elements
var gameOver = game.getElementById("gameover"); // A hidden "eater/detector" element below the play area to detect player death
var instructions = game.getElementById('instructions'); // Instructions element
var gameOverMenu = game.getElementById("gameovermenu"); // Game over screen element
var player = game.getElementById("player"); // The player element
var playerCoins = game.getElementById("playercoins"); // The "bank" element showing how many coins the player has collected
var playerDiamonds = game.getElementById("playerdiamonds");// The "bank" element showing how many diamond the player has collected
// Setup references to the "named" SVG XML coin elements
var coinPieces = ['coin1', 'coin2'];
var coins = [];
coinPieces.forEach(element => {
coins.push(document.getElementById(element));
});
// Setup references to the "named" SVG XML diamond elements
var diamondPieces = ['diamond1'];
var diamond = [];
diamondPieces.forEach(element => {
diamond.push(document.getElementById(element));
});
// Setup references to the "named" SVG XML ground elements
var terrainPieces = ['ground1', 'ground2', 'ground3', 'ground4'];
var terrain = [];
terrainPieces.forEach(element => {
terrain.push(document.getElementById(element));
});
var winningBankTotal = diamondPieces.length + coinPieces.length;
// Clear the instructions after 3 seconds
setTimeout(ClearInstructions, 3000);
// Redraw Game Loop
var redrawRate = 30; // microseconds
var gameLoop = setInterval(function(){
fall = true; // always try to fall
allowedToJump = false;// disallow jumping because player might be falling
allowedToMove = true; // allow moving until the player is dead
// Check for collisions with ground elements
terrain.forEach(ground => {
// If there is a collision with the ground
if(Collide(player, ground)){
fall = false; // Stop falling
allowedToJump = true; // Allow jumping
}
});
// if player fell below the ground
if(Inside(player, gameOver)){
fall = false; // stop falling
allowedToJump = false; // dont allow jumping
allowedToMove = false; // player is dead stop player movment
ClearInstructions(); // just in case
gameOverMenu.style.display = "inline"; // show game over menu
}
// if there was no collision between a ground element and
// the player
if(fall === true){
position = GetPosition(player); // get updated player position
allowedToJump = false; // dont allow jumping
player.transform.baseVal.getItem(0).setTranslate(position[0], position[1] + gravity); // player falls
}
if(allowedToMove === true){
position = GetPosition(player); // get updated player position
// keyboard movment
// left || a
if (keyEvents[37] === true || keyEvents[65] === true) {
if(position[0] > -10){
player.transform.baseVal.getItem(0).setTranslate(position[0] - step, position[1]);
}
}
// right || d
if (keyEvents[39] === true || keyEvents[68] === true) {
if(position[0] < 140){
player.transform.baseVal.getItem(0).setTranslate(position[0] + step, position[1]);
}
}
// up || w || space
if ((keyEvents[38] === true || keyEvents[87] === true || keyEvents[32] === true) && allowedToJump === true) {
player.transform.baseVal.getItem(0).setTranslate(position[0], position[1] - jump);
}
// down || s
if (keyEvents[40] === true || keyEvents[83] === true) {
//console.log("Down");
}
}
// Item Collection
// Collect coins
coins.forEach(coin => {
if(Inside(player, coin)){
coin.remove();
Collect(playerCoins);
}
});
// Collect diamond
diamond.forEach(diamond => {
if(Inside(player, diamond)){
diamond.remove();
Collect(playerDiamonds);
}
});
// Check for Win
if((GetBankTotal(playerDiamonds) + GetBankTotal(playerCoins)) == winningBankTotal){
clearInterval(gameLoop); // stop the game
fall = false; // stop falling
allowedToJump = false; // dont allow jumping
allowedToMove = false; // player won stop player movment
gameOverMenu.style.display = "inline"; // show game over menu
// Change Game Over text to You Win
game.getElementById("gameovermessage").textContent = ' You Win!';
}
}, redrawRate); // Game Loop - redraw every 30 microseconds
}); // game load event listener
} // if game
As you can see from the code it supports WASD as well as the arrow keys and spacebar for movment. There is a win condition if you collect the two coins and the single diamond. You lose if you fall into one of the two spike pits.
Overall I am pleased with what I accomplished however the collision detection could be improved and there is quite a bit of room for improving how items are collected and enemies would be nice in addition to a larger/longer level, and maybe even a parallax scrolling effect on some background elements as the player moves would also be nice, though again, I am happy with how it turned out.
You can Play a Live Demo: Here
You can Get the Code: Here
You can find a list of all my other posts on my Topics and Posts page.
I hope you enjoyed reading about and playing this SVG game prototype.
Your financial support allows me to dedicate time to developing projects like this and while I am publishing them without cost, that isn’t to say they are free. It takes me a lot of time and effort to build and publish projects like this for your enjoyment.
So I ask that if you like my content, please support me on Patreon for as little as $1 or more a month.
Feel free to suggest a project you would like to see built in the comments and if it sounds interesting it might just get built and featured here on my blog for you to enjoy.

Much Love,
~Joy
Like this:
Like Loading...