Hexamem

HexaMem Game

Version: 0.5.0a Last Edit: 2014-04-18
Languages used: Javascript, CSS3
Supported platforms: Firefox 16, Chrome 26, iPad (iOS 7)
Partial (untested) Support: Safari, Opera. Other Modern browsers
GitHub Repo

The purpose of this project was to provide a coding challenge by setting out a set of somewhat, stringent rules, abiding by them, and still create a functional game.

Click to continue to "Hexamem" demo (Github)
Click to continue to “Hexamem” demo (Github)

The Challenge:

The primary goal of this game is to create a “Simon Says” style of game using only CSS3 & HTML for the visuals. No images, either vector or bitmap (png/SVGs), are allowed for the primary visuals. Despite this, the game has to retain a degree of visual appeal (not composed purely of squares).

Additionally the game must provide cross-browser support, not only for Firefox, Chrome & iOS 7 (Safari iPad), but include limited support for IE8 by means of progressive enhancement/graceful degradation.

Lastly, it must be done without the use of external libraries.

Points of Interest

Support

Currently the support for IE8 is very incomplete. This is due to its lack of support for css transformations but can be resolved by the use of [css]ms-filters[/css]. However, these rotations function differently to the modern transformations in their clipping and rotations. Primary browser support was prioritized instead.

Support for varying screen resolutions is also incomplete. This is due to implementation limitations and will be addressed in the near future.

Methods Used

Shapes

To create an interesting layout, I decided on using a mix of hexagons and trapeziums(/trapazoids) as the theme of the UI. In order to do this without the use of images, I decided to use an old trick using borders and block elements.

In this, an extra [html]div[/html] (ideally a pseudo-element) is absolutely positioned with 0 height and width. Then, by employing a combination of transparent and coloured borders, triangles are produced.

Left showing a div set to 0px x 0px & the borders as 50px.  Right showing a div with the left & right borders as transparent.
Left showing a div set to 0px x 0px & the borders as 50px. Right showing a div with the left & right borders as transparent. [jsfiddle]
Using this trick, there are two methods to create a hexagon or similar shape:

  1. Add triangles to the relevant side of a [html]div[/html] in the same colour
  2. Add overlays or masks to block out the underlying ;html]div[/html] using the same background colour

Method 1 shown to the left.   Method 2 shown to the right.
Method 1 shown to the left. Method 2 shown to the right. [jsfiddle]
Method 1 has the advantage of producing shapes that can be rotated closely together, without any risk of overlaps but the resulting shape cannot have any gradients, due to the border limitations. Method 2 is its complement, by allowing gradients while limiting proximity. As such, both methods are used depending on the location and application.

A common limitation to both methods is that borders cannot be defined as percentages and, as such, the UI must be statically sized. This means that in order to support multiple screen resolutions, multiple resolution layouts must be prepared.

Textures

To create the alternating patterns repeating linear-gradients were used. However, doing this alone would not cover the entire area due to its unusual shape.

The solution to this was to apply a skew on the [css]:before[/css] and [css]:after[/css] pseudo-elements and position them carefully to form a trapezium.

An image demonstrating the layout of the pseudo-elements and gradients.
Image demonstrating the layout of the pseudo-elements and gradients.

Animations

To create the “flashes”, a combination of 3 layers were used:

  1. The full colour layer: Set with an ~65% opacity.
  2. The “bulb” layer: A circular gradient going from white to *white transparent. Initially set to a 0% opacity.
  3. The “back-light” layer: A bright, near-white colour (e.g. bright pink for red) set to ~10% opacity.

Flashes are then generated by setting the opacity for the bulb and back-light to 100%, then bringing it back down to their initial values.CSS3 support for animations has been a supported feature in modern browsers for quite some time, albeit many of them require prefixing. Ordinarily, prefixing could handled by libraries such as Autoprefixer. However, due to my “no external libraries” caveat, this became somewhat cumbersome with much repetition.

*It should be noted that the css keyword “transparent” is [css]rgba(0,0,0,0)[/css] which, when used in a gradient, results in unexpected gray hues.

Attaching Actions

If we were using an SVG, attaching actions would be simple, as one could attach to whatever shape is presented. However, when using most other methods, the action area would be a rectangular, regardless of the visuals, leading to either overlaps or dead-zones. The solution to this was to create an image map (using GIMP to help create the coordinates) and to place it at the top z-index of the UI. This allows for better freedom regarding the shapes of action areas.

Yes, I did say no images for the visuals of this project; this still abides to that rule! The image in question is a base64, transparent image used solely for the purposes of creating the image map. There are no additional resources and no visual impact.

Another consideration to take into mind is event types: When on a touch screen device, events such as [js]onclick[/js] or [js]onmousedown[/js] result in a ~300ms delay. This feature is used to prevent accidental clicks and allow zooming but can make game play cumbersome. To avoid this, one used the [js]ontouchstart[/js] event, which has no such delay, while using [js]onclick[/js] as a fall-back.

Known Issues

  • Animations of the border and end game animations may overlap animations of new rounds. This can be somewhat confusing and should be corrected.
  • As previously mentioned, multiple resolutions are not well handled at the moment. This is a high priority item.
  • Audio does not pre-load properly on iOS if viewed from the browser. This is caused by a “feature” of mobile safari (and Android browsers) where audio will only load/play for the first time in direct response to a user action.

Change Log

Version 0.5.0a:

  • Added basic audio support
  • Added local storage for modern browsers
  • Tweaked timing & difficulty
  • Used gradients to enhance the visuals in modern browsers

TODO

  • Enhance visuals for modern browsers
  • Add local storage for modern browsers
  • Tweak timing and difficulty
  • Finish IE8 support
  • Add support for various screen sizes.
  • Add audio support for modern browsers (Partially complete)
  • Enhance randomness of moves
  • Add a settings menu and ability to clear scores