Initial map rendering support
The next major step for the clone is the loading and parsing of LVL files
(maps). This is especially imporant for the purpose of ensuring that users can
continue to use the maps the know and love (and possibly created themselves),
rather than having to recreate them in the clone.
The maps are concatenated into a single fixed-width file and loaded (in the
original sources) into the TLEVEL struct (LTANK.H). The main thing to note about
this data is the manner in which the object data (the playfield) is stored. The
TPLAYFIELD type (defined as a 16x16 multidimensional signed char array) is
formatted as [x][y], meaning that it is an array of *columns*, not rows. While
at first confusing, this does not complicate matters any.
This commit adds initial rendering support for the playfield via MapRender and
is demonstrated in the same demo file as LtgLoader. After loading a tile set,
the user can load an LVL file. The rendering is done using two canvas elements,
the second of which is created by MapRender itself and overlayed atop of the
original canvas. Unmasked tiles are rendered to the bottom canvas and masked
tiles to the upper, allowing us to move game objects without having to redraw
underlying tiles. This is also necessary as the context putImageData() method
overwrites any existing data rather than leaving values corresponding to the
transparent pixels in tact.
This commit also added support for tunnel coloring - each set of tunnels has its
own distinct color. The color values were taken from ColorList in LTANK2.C in
the original sources rather than using CSS color names (e.g. 'red', 'blue',
'magenta') because different environments may assign slightly different colors
to those values (as an example, FireFox does not use #00FF00 for 'green').
Tunnels themselves are identified by a bitmask (0x40), so we can get the tunnel
id by XORing with that mask. The ids are incremented by two in the LVL data
(e.g. 0x40 for index 1, 0x42 for index 2), so we can then divide by two and take
that index in the color array. This color is used to fill the tile with a solid
color in the lower canvas. We can then paint the tile on the upper canvas, which
will allow the color of the lower canvas to peek through the transparent pixels.
Animation support has not yet been added (but animations are still visible in
the demo to the left of the map rendering). This is an exciting start, as we can
clearly see what the game will look like in the browser. This commit also does
not cover any additional level metadata (e.g. author, difficulty, hints); that
will be addressed in future commits and added to the demo.
2012-03-15 23:30:20 -04:00
|
|
|
/**
|
|
|
|
* Renders a given map
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Mike Gerwitz
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders a map to a canvas
|
|
|
|
*/
|
|
|
|
ltjs.MapRender = Class( 'MapRender',
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Tunnel bitmask
|
|
|
|
* @type {number}
|
|
|
|
*/
|
|
|
|
'private const _TMASK': 0x40,
|
|
|
|
|
2012-03-16 19:42:59 -04:00
|
|
|
/**
|
|
|
|
* Property to hold lock bit on canvas element
|
|
|
|
* @type {string}
|
|
|
|
*/
|
|
|
|
'private const _LOCK': '__$$MapRenderLock$$',
|
|
|
|
|
Initial map rendering support
The next major step for the clone is the loading and parsing of LVL files
(maps). This is especially imporant for the purpose of ensuring that users can
continue to use the maps the know and love (and possibly created themselves),
rather than having to recreate them in the clone.
The maps are concatenated into a single fixed-width file and loaded (in the
original sources) into the TLEVEL struct (LTANK.H). The main thing to note about
this data is the manner in which the object data (the playfield) is stored. The
TPLAYFIELD type (defined as a 16x16 multidimensional signed char array) is
formatted as [x][y], meaning that it is an array of *columns*, not rows. While
at first confusing, this does not complicate matters any.
This commit adds initial rendering support for the playfield via MapRender and
is demonstrated in the same demo file as LtgLoader. After loading a tile set,
the user can load an LVL file. The rendering is done using two canvas elements,
the second of which is created by MapRender itself and overlayed atop of the
original canvas. Unmasked tiles are rendered to the bottom canvas and masked
tiles to the upper, allowing us to move game objects without having to redraw
underlying tiles. This is also necessary as the context putImageData() method
overwrites any existing data rather than leaving values corresponding to the
transparent pixels in tact.
This commit also added support for tunnel coloring - each set of tunnels has its
own distinct color. The color values were taken from ColorList in LTANK2.C in
the original sources rather than using CSS color names (e.g. 'red', 'blue',
'magenta') because different environments may assign slightly different colors
to those values (as an example, FireFox does not use #00FF00 for 'green').
Tunnels themselves are identified by a bitmask (0x40), so we can get the tunnel
id by XORing with that mask. The ids are incremented by two in the LVL data
(e.g. 0x40 for index 1, 0x42 for index 2), so we can then divide by two and take
that index in the color array. This color is used to fill the tile with a solid
color in the lower canvas. We can then paint the tile on the upper canvas, which
will allow the color of the lower canvas to peek through the transparent pixels.
Animation support has not yet been added (but animations are still visible in
the demo to the left of the map rendering). This is an exciting start, as we can
clearly see what the game will look like in the browser. This commit also does
not cover any additional level metadata (e.g. author, difficulty, hints); that
will be addressed in future commits and added to the demo.
2012-03-15 23:30:20 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 2d context to which map should be drawn
|
|
|
|
* @type {CanvasRenderingContext2d}
|
|
|
|
*/
|
|
|
|
'private _ctx': null,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 2d context to which masked game objects should be drawn
|
|
|
|
* @type {CanvasRenderingContext2d}
|
|
|
|
*/
|
|
|
|
'private _ctxObj': null,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tile set to be rendered
|
|
|
|
* @type {Object}
|
|
|
|
*/
|
|
|
|
'private _tiles': {},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps each "game object" in the map to a tile id
|
|
|
|
* TODO: abstract
|
|
|
|
* @type {Array.<string>}
|
|
|
|
*/
|
|
|
|
'private _objMap': [
|
|
|
|
'dirt', 'tup', 'base', 'water', 'block', 'mblock', 'brick',
|
|
|
|
'atup', 'atright', 'atdown', 'atleft', 'mirrorul', 'mirrorur',
|
|
|
|
'mirrordr', 'mirrordl', 'owup', 'owright', 'owdown', 'owleft',
|
|
|
|
'cblock', 'rmirrorul', 'rmirrorur', 'rmirrordr', 'rmirrordl',
|
|
|
|
'ice', 'thinice'
|
|
|
|
],
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Colors used to identify tunnels
|
|
|
|
*
|
|
|
|
* These colors will be rendered in the background and will bleed through
|
|
|
|
* the transparent portions of the tile. We use explicit HEX codes rather
|
|
|
|
* than CSS color names because environments may vary the colors used.
|
|
|
|
*
|
|
|
|
* Taken from ColorList in LTANK2.C in the original sources. Note that there
|
|
|
|
* is an endianness difference.
|
|
|
|
*
|
|
|
|
* TODO: abstract
|
|
|
|
*
|
|
|
|
* @type {Array.<string>}
|
|
|
|
*/
|
|
|
|
'private _tunnelColors': [
|
|
|
|
'#ff0000', '#00ff00', '#0000ff', '#00ffff', // r g b c
|
|
|
|
'#ffff00', '#ff00ff', '#ffffff', '#808080' // y m w b
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize renderer with a canvas context and a tile set
|
|
|
|
*
|
|
|
|
* An additional canvas of equal dimensions will be created and laid atop of
|
|
|
|
* the provided canvas to render masked game objects.
|
|
|
|
*
|
|
|
|
* @param {CanvasRenderingContext2d} ctx canvas 2d context
|
|
|
|
* @param {Object} tiles tile set to render
|
|
|
|
*/
|
|
|
|
__construct: function( ctx, tiles )
|
|
|
|
{
|
|
|
|
this._ctx = ctx;
|
|
|
|
this._tiles = tiles;
|
|
|
|
|
2012-03-16 19:42:59 -04:00
|
|
|
// ensure that we are exclusively rendering to this canvas (no other
|
|
|
|
// MapRenders)
|
|
|
|
this._lockCanvas();
|
|
|
|
|
Initial map rendering support
The next major step for the clone is the loading and parsing of LVL files
(maps). This is especially imporant for the purpose of ensuring that users can
continue to use the maps the know and love (and possibly created themselves),
rather than having to recreate them in the clone.
The maps are concatenated into a single fixed-width file and loaded (in the
original sources) into the TLEVEL struct (LTANK.H). The main thing to note about
this data is the manner in which the object data (the playfield) is stored. The
TPLAYFIELD type (defined as a 16x16 multidimensional signed char array) is
formatted as [x][y], meaning that it is an array of *columns*, not rows. While
at first confusing, this does not complicate matters any.
This commit adds initial rendering support for the playfield via MapRender and
is demonstrated in the same demo file as LtgLoader. After loading a tile set,
the user can load an LVL file. The rendering is done using two canvas elements,
the second of which is created by MapRender itself and overlayed atop of the
original canvas. Unmasked tiles are rendered to the bottom canvas and masked
tiles to the upper, allowing us to move game objects without having to redraw
underlying tiles. This is also necessary as the context putImageData() method
overwrites any existing data rather than leaving values corresponding to the
transparent pixels in tact.
This commit also added support for tunnel coloring - each set of tunnels has its
own distinct color. The color values were taken from ColorList in LTANK2.C in
the original sources rather than using CSS color names (e.g. 'red', 'blue',
'magenta') because different environments may assign slightly different colors
to those values (as an example, FireFox does not use #00FF00 for 'green').
Tunnels themselves are identified by a bitmask (0x40), so we can get the tunnel
id by XORing with that mask. The ids are incremented by two in the LVL data
(e.g. 0x40 for index 1, 0x42 for index 2), so we can then divide by two and take
that index in the color array. This color is used to fill the tile with a solid
color in the lower canvas. We can then paint the tile on the upper canvas, which
will allow the color of the lower canvas to peek through the transparent pixels.
Animation support has not yet been added (but animations are still visible in
the demo to the left of the map rendering). This is an exciting start, as we can
clearly see what the game will look like in the browser. This commit also does
not cover any additional level metadata (e.g. author, difficulty, hints); that
will be addressed in future commits and added to the demo.
2012-03-15 23:30:20 -04:00
|
|
|
this._ctxObj = this._getObjCanvas();
|
|
|
|
},
|
|
|
|
|
|
|
|
|
2012-03-16 19:42:59 -04:00
|
|
|
/**
|
|
|
|
* Lock the canvas to prevent other MapRender instances from rendering to it
|
|
|
|
*
|
|
|
|
* The purpose of this is to provide feedback to the user/developer in the
|
|
|
|
* event that multiple MapRender instances are attempting to render to the
|
|
|
|
* same canvas, which would certainly cause display issues and confusion.
|
|
|
|
*
|
|
|
|
* @return {undefined}
|
|
|
|
*/
|
|
|
|
'private _lockCanvas': function()
|
|
|
|
{
|
|
|
|
var o = this._ctx,
|
|
|
|
l = this.__self.$( '_LOCK' );
|
|
|
|
|
|
|
|
// simple one-line check to both set the lock and fail if the lock is
|
|
|
|
// already set (implying that something else is already rendering to the
|
|
|
|
// canvas)
|
|
|
|
if ( ( o[ l ] ^= 1 ) !== 1 )
|
|
|
|
{
|
|
|
|
// reset the lock
|
|
|
|
o[ l ] = 1;
|
|
|
|
|
|
|
|
throw Error(
|
|
|
|
'Could not set exclusive lock on canvas (in use by another ' +
|
|
|
|
'MapRender instance)'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove exclusive lock on canvas to permit other MapRender instances to
|
|
|
|
* render to it
|
|
|
|
*
|
|
|
|
* This will also destroy the overlay canvas that the masked objects were
|
|
|
|
* rendered to. The remaining canvas will not be cleared.
|
|
|
|
*
|
|
|
|
* @return {MapRender} self
|
|
|
|
*/
|
|
|
|
'public freeCanvas': function()
|
|
|
|
{
|
|
|
|
var c = this._ctxObj.canvas;
|
|
|
|
|
|
|
|
// destroy the overlay canvas
|
|
|
|
c.parentNode.removeChild( c );
|
|
|
|
|
|
|
|
// free the lock
|
|
|
|
this._ctx[ this.__self.$( '_LOCK' ) ] = 0;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
|
Initial map rendering support
The next major step for the clone is the loading and parsing of LVL files
(maps). This is especially imporant for the purpose of ensuring that users can
continue to use the maps the know and love (and possibly created themselves),
rather than having to recreate them in the clone.
The maps are concatenated into a single fixed-width file and loaded (in the
original sources) into the TLEVEL struct (LTANK.H). The main thing to note about
this data is the manner in which the object data (the playfield) is stored. The
TPLAYFIELD type (defined as a 16x16 multidimensional signed char array) is
formatted as [x][y], meaning that it is an array of *columns*, not rows. While
at first confusing, this does not complicate matters any.
This commit adds initial rendering support for the playfield via MapRender and
is demonstrated in the same demo file as LtgLoader. After loading a tile set,
the user can load an LVL file. The rendering is done using two canvas elements,
the second of which is created by MapRender itself and overlayed atop of the
original canvas. Unmasked tiles are rendered to the bottom canvas and masked
tiles to the upper, allowing us to move game objects without having to redraw
underlying tiles. This is also necessary as the context putImageData() method
overwrites any existing data rather than leaving values corresponding to the
transparent pixels in tact.
This commit also added support for tunnel coloring - each set of tunnels has its
own distinct color. The color values were taken from ColorList in LTANK2.C in
the original sources rather than using CSS color names (e.g. 'red', 'blue',
'magenta') because different environments may assign slightly different colors
to those values (as an example, FireFox does not use #00FF00 for 'green').
Tunnels themselves are identified by a bitmask (0x40), so we can get the tunnel
id by XORing with that mask. The ids are incremented by two in the LVL data
(e.g. 0x40 for index 1, 0x42 for index 2), so we can then divide by two and take
that index in the color array. This color is used to fill the tile with a solid
color in the lower canvas. We can then paint the tile on the upper canvas, which
will allow the color of the lower canvas to peek through the transparent pixels.
Animation support has not yet been added (but animations are still visible in
the demo to the left of the map rendering). This is an exciting start, as we can
clearly see what the game will look like in the browser. This commit also does
not cover any additional level metadata (e.g. author, difficulty, hints); that
will be addressed in future commits and added to the demo.
2012-03-15 23:30:20 -04:00
|
|
|
/**
|
|
|
|
* Create the overlaying canvas for masked elements and return a 2d context
|
|
|
|
*
|
|
|
|
* @return {CanvasRenderingContext2d} 2d context for new canvas element
|
|
|
|
*/
|
|
|
|
'private _getObjCanvas': function()
|
|
|
|
{
|
|
|
|
var canvas = this._ctx.canvas,
|
|
|
|
canvas_obj = document.createElement( 'canvas' );
|
|
|
|
|
|
|
|
// mimic the dimensions and positions of the original canvas
|
|
|
|
canvas_obj.style.position = 'absolute';
|
|
|
|
canvas_obj.width = canvas.width;
|
|
|
|
canvas_obj.height = canvas.height;
|
|
|
|
canvas_obj.style.left = ( canvas.offsetLeft + 'px' );
|
|
|
|
canvas_obj.style.top = ( canvas.offsetTop + 'px' );
|
|
|
|
|
|
|
|
// append the new canvas to the DOM under the same parent
|
|
|
|
canvas.parentNode.appendChild( canvas_obj );
|
|
|
|
|
|
|
|
return canvas_obj.getContext( '2d' );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Render the provided map
|
|
|
|
*
|
|
|
|
* @param {Map} map map to render
|
|
|
|
*
|
|
|
|
* @return {MapRender} self
|
|
|
|
*/
|
|
|
|
'public render': function( map )
|
|
|
|
{
|
|
|
|
if ( !( Class.isA( ltjs.Map, map ) ) )
|
|
|
|
{
|
|
|
|
throw TypeError( 'Invalid Map provided' );
|
|
|
|
}
|
|
|
|
|
|
|
|
var objs = map.getObjects(),
|
|
|
|
size = map.getDimensions(),
|
|
|
|
i = objs.length,
|
|
|
|
tiles = this._tiles,
|
|
|
|
|
|
|
|
// get the width and height from one of the tiles
|
|
|
|
t = this._tiles.dirt.data,
|
|
|
|
w = t.width,
|
|
|
|
h = t.height;
|
|
|
|
|
|
|
|
// render each object (remember, we're dealing with columns, not rows;
|
|
|
|
// see Map.getObjects())
|
|
|
|
while ( i-- )
|
|
|
|
{
|
|
|
|
var oid = objs[ i ],
|
|
|
|
tid = this._objMap[ oid ],
|
|
|
|
x = ( Math.floor( i / size[ 0 ] ) * w ),
|
|
|
|
y = ( ( i % size[ 1 ] ) * h );
|
|
|
|
|
|
|
|
// tunnels are handled a bit differently than other objects
|
|
|
|
if ( this._isTunnel( oid ) )
|
|
|
|
{
|
|
|
|
this._renderTunnel( oid, x, y );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._drawTile( tid, x, y );
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Draw the tile identified by the given id
|
|
|
|
*
|
|
|
|
* The tile will be drawn to the appropriate canvas depending on whether or
|
|
|
|
* not it has been masked. If it does have a mask, it will be drawn to the
|
|
|
|
* overlaying canvas and the dirt tile will be drawn underneath it.
|
|
|
|
*
|
|
|
|
* @param {string} tid tile id
|
|
|
|
* @param {number} x left position
|
|
|
|
* @param {number} y top position
|
|
|
|
*
|
|
|
|
* @return {undefined}
|
|
|
|
*/
|
|
|
|
'private _drawTile': function( tid, x, y )
|
|
|
|
{
|
|
|
|
var tile = this._tiles[ tid ],
|
|
|
|
ctx = ( tile.masked ) ? this._ctxObj : this._ctx;
|
|
|
|
|
2012-03-15 23:42:28 -04:00
|
|
|
ctx.putImageData( this._tiles[ tid ].first.data, x, y );
|
Initial map rendering support
The next major step for the clone is the loading and parsing of LVL files
(maps). This is especially imporant for the purpose of ensuring that users can
continue to use the maps the know and love (and possibly created themselves),
rather than having to recreate them in the clone.
The maps are concatenated into a single fixed-width file and loaded (in the
original sources) into the TLEVEL struct (LTANK.H). The main thing to note about
this data is the manner in which the object data (the playfield) is stored. The
TPLAYFIELD type (defined as a 16x16 multidimensional signed char array) is
formatted as [x][y], meaning that it is an array of *columns*, not rows. While
at first confusing, this does not complicate matters any.
This commit adds initial rendering support for the playfield via MapRender and
is demonstrated in the same demo file as LtgLoader. After loading a tile set,
the user can load an LVL file. The rendering is done using two canvas elements,
the second of which is created by MapRender itself and overlayed atop of the
original canvas. Unmasked tiles are rendered to the bottom canvas and masked
tiles to the upper, allowing us to move game objects without having to redraw
underlying tiles. This is also necessary as the context putImageData() method
overwrites any existing data rather than leaving values corresponding to the
transparent pixels in tact.
This commit also added support for tunnel coloring - each set of tunnels has its
own distinct color. The color values were taken from ColorList in LTANK2.C in
the original sources rather than using CSS color names (e.g. 'red', 'blue',
'magenta') because different environments may assign slightly different colors
to those values (as an example, FireFox does not use #00FF00 for 'green').
Tunnels themselves are identified by a bitmask (0x40), so we can get the tunnel
id by XORing with that mask. The ids are incremented by two in the LVL data
(e.g. 0x40 for index 1, 0x42 for index 2), so we can then divide by two and take
that index in the color array. This color is used to fill the tile with a solid
color in the lower canvas. We can then paint the tile on the upper canvas, which
will allow the color of the lower canvas to peek through the transparent pixels.
Animation support has not yet been added (but animations are still visible in
the demo to the left of the map rendering). This is an exciting start, as we can
clearly see what the game will look like in the browser. This commit also does
not cover any additional level metadata (e.g. author, difficulty, hints); that
will be addressed in future commits and added to the demo.
2012-03-15 23:30:20 -04:00
|
|
|
|
|
|
|
if ( tile.masked )
|
|
|
|
{
|
|
|
|
this._ctx.putImageData( this._tiles.dirt.data, x, y );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns whether the given object id is a tunnel
|
|
|
|
*
|
|
|
|
* @param {number} oid object id
|
|
|
|
*
|
|
|
|
* @return {boolean} TRUE if object is a tunnel, otherwise false
|
|
|
|
*/
|
|
|
|
'private _isTunnel': function( oid )
|
|
|
|
{
|
|
|
|
return ( oid & this.__self.$( '_TMASK' ) );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Render the given tunnel
|
|
|
|
*
|
|
|
|
* The tunnel background color (which will peek through the mask) is
|
|
|
|
* rendered to the base canvas, whereas the tunnel tile itself is rendered
|
|
|
|
* on the overlaying canvas.
|
|
|
|
*
|
|
|
|
* @param {number} oid tunnel object id
|
|
|
|
* @param {number} x left position
|
|
|
|
* @param {number} y top position
|
|
|
|
*
|
|
|
|
* @return {undefined}
|
|
|
|
*/
|
|
|
|
'private _renderTunnel': function( oid, x, y )
|
|
|
|
{
|
|
|
|
// get the tunnel id by stripping off the tunnel bitmask and grab the
|
|
|
|
// associated color
|
|
|
|
var tunnel_id = ( ( +oid ^ this.__self.$( '_TMASK' ) ) / 2 ),
|
2012-03-16 18:51:29 -04:00
|
|
|
color = this._tunnelColors[ tunnel_id ] || 'black',
|
|
|
|
tdata = this._tiles.tunnel.data;
|
Initial map rendering support
The next major step for the clone is the loading and parsing of LVL files
(maps). This is especially imporant for the purpose of ensuring that users can
continue to use the maps the know and love (and possibly created themselves),
rather than having to recreate them in the clone.
The maps are concatenated into a single fixed-width file and loaded (in the
original sources) into the TLEVEL struct (LTANK.H). The main thing to note about
this data is the manner in which the object data (the playfield) is stored. The
TPLAYFIELD type (defined as a 16x16 multidimensional signed char array) is
formatted as [x][y], meaning that it is an array of *columns*, not rows. While
at first confusing, this does not complicate matters any.
This commit adds initial rendering support for the playfield via MapRender and
is demonstrated in the same demo file as LtgLoader. After loading a tile set,
the user can load an LVL file. The rendering is done using two canvas elements,
the second of which is created by MapRender itself and overlayed atop of the
original canvas. Unmasked tiles are rendered to the bottom canvas and masked
tiles to the upper, allowing us to move game objects without having to redraw
underlying tiles. This is also necessary as the context putImageData() method
overwrites any existing data rather than leaving values corresponding to the
transparent pixels in tact.
This commit also added support for tunnel coloring - each set of tunnels has its
own distinct color. The color values were taken from ColorList in LTANK2.C in
the original sources rather than using CSS color names (e.g. 'red', 'blue',
'magenta') because different environments may assign slightly different colors
to those values (as an example, FireFox does not use #00FF00 for 'green').
Tunnels themselves are identified by a bitmask (0x40), so we can get the tunnel
id by XORing with that mask. The ids are incremented by two in the LVL data
(e.g. 0x40 for index 1, 0x42 for index 2), so we can then divide by two and take
that index in the color array. This color is used to fill the tile with a solid
color in the lower canvas. We can then paint the tile on the upper canvas, which
will allow the color of the lower canvas to peek through the transparent pixels.
Animation support has not yet been added (but animations are still visible in
the demo to the left of the map rendering). This is an exciting start, as we can
clearly see what the game will look like in the browser. This commit also does
not cover any additional level metadata (e.g. author, difficulty, hints); that
will be addressed in future commits and added to the demo.
2012-03-15 23:30:20 -04:00
|
|
|
|
|
|
|
// fill tile with the appropriate background color for this tile
|
|
|
|
this._ctx.fillStyle = color;
|
2012-03-16 18:51:29 -04:00
|
|
|
this._ctx.fillRect( x, y, tdata.width, tdata.height );
|
Initial map rendering support
The next major step for the clone is the loading and parsing of LVL files
(maps). This is especially imporant for the purpose of ensuring that users can
continue to use the maps the know and love (and possibly created themselves),
rather than having to recreate them in the clone.
The maps are concatenated into a single fixed-width file and loaded (in the
original sources) into the TLEVEL struct (LTANK.H). The main thing to note about
this data is the manner in which the object data (the playfield) is stored. The
TPLAYFIELD type (defined as a 16x16 multidimensional signed char array) is
formatted as [x][y], meaning that it is an array of *columns*, not rows. While
at first confusing, this does not complicate matters any.
This commit adds initial rendering support for the playfield via MapRender and
is demonstrated in the same demo file as LtgLoader. After loading a tile set,
the user can load an LVL file. The rendering is done using two canvas elements,
the second of which is created by MapRender itself and overlayed atop of the
original canvas. Unmasked tiles are rendered to the bottom canvas and masked
tiles to the upper, allowing us to move game objects without having to redraw
underlying tiles. This is also necessary as the context putImageData() method
overwrites any existing data rather than leaving values corresponding to the
transparent pixels in tact.
This commit also added support for tunnel coloring - each set of tunnels has its
own distinct color. The color values were taken from ColorList in LTANK2.C in
the original sources rather than using CSS color names (e.g. 'red', 'blue',
'magenta') because different environments may assign slightly different colors
to those values (as an example, FireFox does not use #00FF00 for 'green').
Tunnels themselves are identified by a bitmask (0x40), so we can get the tunnel
id by XORing with that mask. The ids are incremented by two in the LVL data
(e.g. 0x40 for index 1, 0x42 for index 2), so we can then divide by two and take
that index in the color array. This color is used to fill the tile with a solid
color in the lower canvas. We can then paint the tile on the upper canvas, which
will allow the color of the lower canvas to peek through the transparent pixels.
Animation support has not yet been added (but animations are still visible in
the demo to the left of the map rendering). This is an exciting start, as we can
clearly see what the game will look like in the browser. This commit also does
not cover any additional level metadata (e.g. author, difficulty, hints); that
will be addressed in future commits and added to the demo.
2012-03-15 23:30:20 -04:00
|
|
|
|
|
|
|
// render the tile to the overlay canvas
|
2012-03-16 18:51:29 -04:00
|
|
|
this._ctxObj.putImageData( tdata, x, y );
|
Initial map rendering support
The next major step for the clone is the loading and parsing of LVL files
(maps). This is especially imporant for the purpose of ensuring that users can
continue to use the maps the know and love (and possibly created themselves),
rather than having to recreate them in the clone.
The maps are concatenated into a single fixed-width file and loaded (in the
original sources) into the TLEVEL struct (LTANK.H). The main thing to note about
this data is the manner in which the object data (the playfield) is stored. The
TPLAYFIELD type (defined as a 16x16 multidimensional signed char array) is
formatted as [x][y], meaning that it is an array of *columns*, not rows. While
at first confusing, this does not complicate matters any.
This commit adds initial rendering support for the playfield via MapRender and
is demonstrated in the same demo file as LtgLoader. After loading a tile set,
the user can load an LVL file. The rendering is done using two canvas elements,
the second of which is created by MapRender itself and overlayed atop of the
original canvas. Unmasked tiles are rendered to the bottom canvas and masked
tiles to the upper, allowing us to move game objects without having to redraw
underlying tiles. This is also necessary as the context putImageData() method
overwrites any existing data rather than leaving values corresponding to the
transparent pixels in tact.
This commit also added support for tunnel coloring - each set of tunnels has its
own distinct color. The color values were taken from ColorList in LTANK2.C in
the original sources rather than using CSS color names (e.g. 'red', 'blue',
'magenta') because different environments may assign slightly different colors
to those values (as an example, FireFox does not use #00FF00 for 'green').
Tunnels themselves are identified by a bitmask (0x40), so we can get the tunnel
id by XORing with that mask. The ids are incremented by two in the LVL data
(e.g. 0x40 for index 1, 0x42 for index 2), so we can then divide by two and take
that index in the color array. This color is used to fill the tile with a solid
color in the lower canvas. We can then paint the tile on the upper canvas, which
will allow the color of the lower canvas to peek through the transparent pixels.
Animation support has not yet been added (but animations are still visible in
the demo to the left of the map rendering). This is an exciting start, as we can
clearly see what the game will look like in the browser. This commit also does
not cover any additional level metadata (e.g. author, difficulty, hints); that
will be addressed in future commits and added to the demo.
2012-03-15 23:30:20 -04:00
|
|
|
}
|
|
|
|
} );
|