Super Jamicom

§ Introduction▲ top

The Super Jamicom imaginary console is patterned after the way 16 bit consoles used to work back in the late 80s to mid 90s or what was commonly referred to as the “16 bit era” †. This means a relatively low resolution, paletted graphics and constrained sound.

† see this article for more information on those consoles.

In contrast to those old platforms though, Super Jamicom offers a much simpler development experience, with a modern programing language, a suite of built in tools and very low iteration time; The goal is to make starting a collaborative game jam game as easy as clicking a link!

Super Jamicom improves from time to time. To keep up with the latest changes visit the news page.

§ Games▲ top

Clicking on any game in the game list will take you to that game’s player page, for example: http://superjami.com/games/adhq

If you’re interested in exploring how the game works, you can click the edit button to move to the game’s edit page. On this page, you can read and modify the graphics and code that make up the game.

Unless you were the original creator of this game though, you will not be able to save any changes you make. To really get started making your own games, you’ll also need to login so that the system can save your data.

Once you’ve done so, choose a game from the main page that most closely matches what you want to do and then go to its edit page.

Once inside the editor you can “fork” the game, that is to say make a copy of the game where you are the owner instead. You can now edit your forked game without affecting the original.

To modify the information displayed under a game on its player page, find the ‘edit this info’ button in the edit page of a game you own.

Here, you can modify the game’s title, give it a description, and add additional authors to the project who will have the same ability as you do to add new graphics and code to the game.

§ Code▲ top

On CoffeeScript and the Browser▲ top

Super Jamicom games, and Super Jamicom itself, are written in a language called CoffeeScript. CoffeeScript is an extension of the Javascript language that runs in your web browser, and in fact works by compiling itself back into Javascript. When you write CoffeeScript for your games, in the background Super Jamicom does the conversion for you.

To learn more about CoffeeScript, please see The CoffeeScript website.

The CoffeeScript Cookbook is another useful resource, providing an advanced guide and tips for programmers coming from different languages.

Should you make a mistake while coding (and who doesn’t!) then errors will appear in the System Messages panel. These should tell you the file name and the line and character numbers where the error was detected, as well as what it thinks the error might be.

To work out errors in your logic, it’s often useful to observe some crucial value as your game unfolds. The Watched Variables panel will display any named value you pass it from your code using the watch command. For example, if you have the variable playerXPosition and you’d like to call it “player x”, then invoke the watch command as so:

watch 'player x', playerXPosition

Each subsequent call to the watch command using the same name will intentionally overwrite the same line in the Wached Variables panel, letting you call watch repeatedly while only retaining the latest value.

Finally, for the deepest look at how your code is behaving, please see your browser’s developer tools documentation†. Super Jamicom publishes the information necessary for your browser to ’see’ the code files you write, enabling the full range of its developer tools.

† Super Jamicom was largely developed in Google’s Chrome browser, and so has greatly benefited from Google Chrome’s Javacript Tools.

Hooks▲ top

In order to address the game environment, Super Jamicom reserves the global name game. This variable holds crucial state information and is the only variable that is visible to the code across all of your files. That is to say if you have files foo.coffee and bar.coffee, and you’d like to share variable health between them, you’ll need to name the variable game.health.

Advanced note: Accessing the game variable is so common, that it is actually bound as the root context for each of your files. This means that the CoffeeScript shortcut @ can be used to refer to it when you are not in a function; e.g. @health.

There are two critical hooks to get to know when developing a Super Jamicom game:

game.init

This function will be called when your game first starts up or is reset, after every code file has been evaluated. This means that all your classes and assorted globals will be ready to use at this point. You should use this hook to create your game’s initial state, e.g. your player’s starting position and health.

# in the player file
class game.Player
  constructor: (@x, @y, @health) ->

# in your main file
game.init ->
  game.player = new game.Player 100, 120, 100
  # etc
game.update

This function will be called after game.init as often as possible, up to a maximum rate of 60 times per second. Use this function to run your main game logic, moving sprites around, detecting intersections, etc.

game.update ->
  player.x += velocity
  counter += 1
  # etc

Global Functions▲ top

Most of the functions available in a normal Javascript environment are present in Super Jamicom. In addition, due to common usage, the following functions have all been lifted into the global namespace from the Math namespace, allowing you to omit the prefix: sin, cos, tan, abs, floor, ceil, round, random, min, max, pow, PI

For instance, you can type min(x, y) or sin(angle) rather than Math.min(x,y) or Math.sin(angle)

For more information on the Math functions in Javascript, see this handy MDN page

A few more convenience functions have been defined globally.

clamp(min, max, value)
Returns value, or min if value is less than min, or max if value is greater than max.
lerp(min, max, fraction)
Returns an interpolated value between min and max, where a fraction of 0 means min and a fraction of 1 means max. When the value of fraction is less than min or greater than max, linear extrapolation occurs.

§ Graphics▲ top

There are two main components to the graphics system: sprites and backgrounds. Think of sprites as smaller pieces of graphics that move around independently, while a background is a larger, full screen sized graphic.

Both sprites and backgrounds are made of characters. A character is an 8 by 8 pixel square of pixels †. Each pixel can have one of 16 colors. Which 16 colors are applied to a sprite depend on its palette index.

A palette is a list of colors. A full palette has 256 colors, organized into 16 rows of 16 colors each. A palette index refers to one of these rows.

† a pixel, or ‘pixel element’, is the smallest solid colored chunk of a computer graphic. Think of them as the atoms of a modern graphical display. See this wikipedia article for more information.

The Super Jamicom screen is a 256 by 224 pixel surface which can display up to 4 backgrounds and up to 128 sprites. Positions on screen are specified in terms of the pixel distance from the lower left corner of the screen, in whole pixels. For example the position (4,6) means 4 pixels from the left of the screen and 6 pixels from the bottom.

Sprites▲ top

There are a fixed number of 128 sprites. Each sprite can be enabled and positioned independently on the screen.

To setup a sprite, adjust the values in the global sprites array. Here’s an example:

sprites[0].on = true
sprites[0].x = 10
sprites[0].y = 40

This turns on and then positions the 0-th sprite (the first sprite in the system) such that its bottom left corner will be 10 pixels from the left of the screen, and 40 pixels from the bottom.

Here’s the full list of properties that a sprite understands. Because these are so very common in a Super Jamicom codebase, the parameter names have been severely abbreviated.

sprite.on
This controls whether the sprite will (true) or won’t (false) be displayed on the screen.
sprite.x
The x position, that is to say the distance in pixels from the left edge of the screen
sprite.y
The y position, so the distance from the bottom of the screen Note: both sprite.x and sprite.y refer to the position of the bottom left hand corner of the sprite. So an x of 0 and a y of 0 would mean that the sprite’s left and bottom boundaries would be exactly up against the left and bottom boundaries of the screen. Try it out!
sprite.w & sprite.h
The width and height of the sprite in characters, that is to say in multiples of 8 pixels. A sprite with w = 2 would be 16 pixels wide.
sprite.cx & sprite.cy
The offset, in characters, of the sprite source in its character sheet. In contrast to the x and y positions, this offset is from the top left instead. So the top left most character on a sheet is cx 0 and cy 0. The best way to discover these values is to hover over the Sprite Editor panel and read the output in its title bar.
sprite.fx & sprite.fy
These control flipping, horizontally and vertically respectfully. Each should be set the value 1 for a flip, and 0 for no flip. A flipped sprite occupies the same space as an unflipped sprite; that is to say that the sprite is always flipped across its center.
sprite.pi
“Palette Index” This controls which row of the current palette the sprite will draw its colors from. You can change this at any time to quickly recolor the whole sprite.
sprite.po
“Palette Offset” This is a numerical shift offset applied to the palette index, letting you easily setup the most common style of palette based animation. Palette indexes wrap on a single row, so increasing this value will shift colors on the right around to the left side.

Backgrounds▲ top

There are a fixed number of 4 backgrounds.

Like the sprites, backgrounds are composed of characters which can be flipped horizontally and vertically. Entire backgrounds as a whole can also be positioned on the screen, allowing for scrolling effects.

Unlike sprites, the characters used by a background don’t have to be next to each other on the character sheet. To work out which character goes where, you create and assign a map object: a rectangular array of information that encodes for each character on the map, where to get the data from the character sheet and how to flip it. See the Maps topic below for more information about programming with maps, and read about the Map Editor for the easiest way to set one up.

Backgrounds can wrap, meaning that if you move a background to the right, instead of being blank, the area further to the left of the leftmost edge of a background will look like a copy of the far right side of the background instead.

To setup a background, adjust the values in the backgrounds array. Here’s an example:

backgrounds[0].on = true
backgrounds[0].palette = 'daylight'
backgrounds[0].map = 'forest'
backgrounds[0].x = 20
backgrounds[0].wrapX = true

This turns on the first background in the system, and sets it to read from the ‘forest’ map, using the colors in the ‘daylight’ palette. It then sets it to draw 20 pixels from the left of the screen, and to wrap horizontally, meaning that the left most 20 pixel column of the screen will actually show the right most characters in the ‘forest’ map.

background.on
This controls whether the background will (true) or won’t (false) be displayed on the screen.
background.x & background.y
Offset the position of the background on the screen.
background.map
This it he name of the map you want this background to use.
background.palette
This is the name of the palette you want this background to use.
background.paletteRowOffset & background.paletteRowOffset
These values let you offset the palette index for every pixel in the background. Use this to create large palette animation.
background.transparency
Whether the first color of the background should be considered transparent or solid.
background.wrapX & background.wrapY
Whether the background should wrap around horizontally and vertically
background.pr
“Priority”. Determines the order that the background will draw in, compared to the rest of the sprites and backgrounds in the system. See the Priorities and Sorting topic below for more info.

Maps▲ top

A map contains the information a background uses to choose which characters go where on screen.

While the easiest way to create a map is to use the map editor, there are plenty of interesting uses for creating and modifying maps from code.

To begin working with a map, fetch it from the map system with the command ‘mapSystem.getByName(YourMapName)’.

Once you have one, working with maps involves calling functions on the map object.

map.setDimensions: (width, height, options)

This lets you change the size of a map. A map can only be up to 1024 character in width and height, and must be at least 16 characters wide and tall. Specify the width and height in characters. This function gives you some options with regards to what to do with the data that was in the map before the resize.

map.set(x, y, cx, cy, flips)

Sets which character should be used at offset x and y, where x and y are given in whole characters from the top left of the map. The cx and cy values work like the same named properties on sprites, representing offsets in the character sheet. The flip value is a specially encoded set of numbers meaning:

value action
0: do not flip the character
1: flip the character horizontally
2: flip the character vertically
3: flip both horizontally and vertically
map.get(x, y)

This will return the cx, cy and flips values for the character at the given x and y offset in the map. The result is given in the form of an array as so [cx, cy, flips].

Priority and Sorting▲ top

By default, all backgrounds draw before all sprites. There are 8 levels of priority in the rendering system that allow you to influence this ordering.

By default all sprites and backgrounds have a priority of 0. Increasing this number causes the item to be rendered later.

Backgrounds in the background system that have the same priority draw in their index order, i.e. backgrounds[0] draws before backgrounds[1]. Likewise, sprites[0] draws before sprites[1].

So, let’s say you want to draw your level backdrop in backgrounds[0], then your player character sprites[0], then a user interface in background[1] on top of that; you could to set your priorities as follows:

backgrounds[0].pr = 0
sprites[0].pr = 0 # remember: backgrounds still go first
backgrounds[1].pr = 1

Palette Editor▲ top

The Palette editor lets you create and modify named sets of palettes.

Each palette contains 16 rows of 16 colors each. Recall that a sprite or a background can be set to use any color within a single row of a palette.

To create a new palette, click the ‘add palette’ button in the palette list to the left of the editor. All you need to specify at this time is the name for the new palette.

To modify a color in a palette, click on the relevant color swatch and use the sliders on the right side of the editor to modify the amounts of red, green and blue in the color.

Notice that moving your cursor across the palette updates the display in the editor title bar that identifies the row and column of the color you’re hovering over. When writing code to modify palettes dynamically, this is the easiest way to get your bearings.

Character Editor▲ top

The character editor is for… editing character data :)

Recall that each character is 8 pixels wide and 8 pixels tall.

Each pixel in turn is 4 bits of data, or 1 of 16 possible values.

When a pixel value is rendered to the screen later, it will used as an index into a palette, which converts it into a full RGB color.

Each character sheet is 32 characters wide and 32 characters tall.

The editor displays the entire current character sheet using a single palette. Use the row arrows at the bottom of the palette strip to switch to another palette row.

Of the 16 possible values, one is always the selected value, and one is always the alternate. To change the current selected value, click on it in the palette strip. To change the alternate value, hold down the alt key while clicking on a value, or click it with the right mouse button.

To see other parts of the character sheet, use the following controls:

Shift + click & drag or middle click & drag
moves the view around the sheet
Mouse wheel
zooms the view

Use the toolbar to select one of the following tools:

1 pixel brush

fill a single pixel with the currently selected value when you left click on the sheet. Hold down the alt key or use the right mouse button to fill a pixel with the alternate value instead.

2 pixel brush

fill a 2x2 area of pixels with the currently selected value, or with the alt key (or right mouse button) held, the alternate value.

Selector

left click and drag on the sheet to create a selection.

Once you have an active selection, you can use the arrow keys on the keyboard to shift the pixels inside the selection.

Clone brush

you must already have created a selection to use this tool. Once you have set it up, left clicking on the sheet will copy the contents of the selection there.

Map Editor▲ top

Documentation coming soon!

Meanwhile, have fun experimenting ^__^

§ Input▲ top

Super Jamicom supports a fixed set of inputs, normally mapped to the keyboard. You access these inputs using the buttons global variable which contains a set of named booleans that are true when the button is currently pressed.

For example, to move the player when the up button is pressed

if buttons.up
  player.y += 1
buttons.up, buttons.down, buttons.left, buttons.right
These map to the directional arrow keys on the keyboard
buttons.a, buttons.b
The primary two buttons, these map to the keys Z and X.
buttons.x, buttons.y
The secondary buttons, these map to A and S
buttons.l, buttons.r
The extended buttons, these map to Q and W
buttons.select, buttons.start
These are mapped to the keys 1 and 2, usually used for invoking in‑game menus

Gamepad Support▲ top

Super Jamicom has some very rudimentary support for the new Javascript gamepad API. If you’re using the latest Chrome, Firefox or Edge browsers, your gamepad may already work.

Alternatively, any gamepad input can be translated into keyboard input with an appropriate utility.

On the Mac, try the free Enjoyable app by Yukkuri Games.

On the PC, try the shareware JoyToKey by JTKSOFT.

§ Debugging▲ top

Visual Tools▲ top

The global debug object contains a system for plotting visual information on the screen. You could use this, for example, when you’re trying to work out if your collision or movement code is correct.

All draw functions happen after the game render, so will always be on top of every thing else the system draws.

Note: This system is disabled in the game player, so it isn’t available for general game drawing! It is safe however, to leave your debug calls in the code; the player will just ignore them.

debug.color( r, g, b )
This function sets components of the color for all subsequent debug draw functions to the given red, green and blue, r, g, b values. All values are in the range 0 to 255
debug.box( x, y, w, h )
Draws a box with the given x, y position, and the given height h and width w. All values are in pixels from the bottom left of the screen.
debug.boxOutline( x, y, w, h )
The same as debug.box, but instead of filling the area, it draws a single pixel outline instead.
debug.circle( x, y, r )
Draws a circle instead, centered at x, y, with the radius r. Radius also given in pixels.
debug.circleOutline( x, y, r )
The same as debug.circle, but as a single pixel outline instead
debug.line( x1, y1, x2, y2 )
Draws a single pixel line between the coordinates x1, y1 and x2, y2
debug.pixel( x, y )
Draws a single pixel at the given coordinate

So, let’s say you have some logic where you have a position x, y that will chase a target tx, ty. It might be helpful to draw the current point and target points as red dots, and to draw a green line between them.

debug.color 255, 0, 0
debug.circle x, y, 4
debug.circle tx, ty, 4

debug.color 0, 255, 0
debug.line x, y, tx, ty

Additionally, the print command can also be useful. This function draws text to the screen at a given position, or sequentially from top to bottom. Unlike the debug functions, the print function is still available in the player page.

print( text )
draws the given text. The first call of this kind every frame will draw the text at the top left of the screen. Subsequent calls will draw the text beneath the previous line.
print( text, x, y )
when x and y coordinates are specified, then the text is drawn with the bottom left corner of the text explicitly sitting at the given coordinates.

§ Acknowledgements▲ top

Super Jamicom was made possible due to the wonderful work put into the following projects.

Amazon Web Services
Super Jamicom is served from and backed by various services in the Amazon Web Services family, including Elastic Beanstalk, DynamoDB, and Elastic Cache.
Node.js
Node.js is a technology that powers servers using the same Javascript language that works in your browser, and is what runs the Super Jamicom server.
Express
A versatile web server framework written on top of Node.js
Passport
Super easy o-auth based authorization. This library is what lets Super Jamicom users log in using their existing identities on Twitter and Twitch.
CoffeeScript
A pleasant alternative to Javascript, CoffeeScript is both the language Super Jamicom games are written in, and what Super Jamicom itself is written in.
Stylus
Much like CoffeeScript enhances Javascript, so does the Stylus library elevate CSS.
Jade
Like Stylus and CoffeeScript, Jade makes HTML easier to write and maintain.
Ace
Ace is the library that provides Super Jamicom’s awesome code editor.
JQuery
JQuery is a Javascript library that makes handling dom elements in Javascript both easier and more uniform across different browsers.
Google Fonts
Google Fonts is a collection of free beautiful web compatible fonts.