/**
*
* @module GameObjects
* @submodule Tilemap
*
*/
module Kiwi.GameObjects.Tilemap {
/**
* GameObject that contains the information held for a single Layer of Tiles, along with methods to handle the rendering of those Tiles.
* A TileMapLayer should not be directly created, but instead should be created through a TileMap object instead.
*
* @class TileMapLayer
* @extends Kiwi.Entity
* @namespace Kiwi.GameObjects.Tilemap
* @constructor
* @param tilemap {Kiwi.GameObjects.Tilemap.TileMap} The TileMap that this layer belongs to.
* @param name {String} The name of this TileMapLayer.
* @param atlas {Kiwi.Textures.TextureAtlas} The texture atlas that should be used when rendering this TileMapLayer onscreen.
* @param data {Number[]} The information about the tiles.
* @param tw {Number} The width of a single tile in pixels. Usually the same as the TileMap unless told otherwise.
* @param th {Number} The height of a single tile in pixels. Usually the same as the TileMap unless told otherwise.
* @param [x=0] {Number} The x coordinate of the tilemap in pixels.
* @param [y=0] {Number} The y coordinate of the tilemap in pixels.
* @param [w=0] {Number} The width of the whole tilemap in tiles. Usually the same as the TileMap unless told otherwise.
* @param [h=0] {Number} The height of the whole tilemap in tiles. Usually the same as the TileMap unless told otherwise.
* @return {TileMapLayer}
*/
export class TileMapLayer extends Kiwi.Entity {
constructor(tilemap: Kiwi.GameObjects.Tilemap.TileMap, name: string, atlas: Kiwi.Textures.TextureAtlas, data: number[], tw: number, th: number, x: number= 0, y: number= 0, w:number=0, h:number=0) {
super(tilemap.state, x, y);
//Request the Shared Texture Atlas renderer.
if (this.game.renderOption === Kiwi.RENDERER_WEBGL) {
this.glRenderer = this.game.renderer.requestSharedRenderer("TextureAtlasRenderer");
}
this.name = name;
this.atlas = atlas;
this.tilemap = tilemap;
this._data = data;
this.tileWidth = tw;
this.tileHeight = th;
this.width = w;
this.height = h;
this._corner1 = new Kiwi.Geom.Point(0,0);
this._corner2 = new Kiwi.Geom.Point(0,0);
this._corner3 = new Kiwi.Geom.Point(0,0);
this._corner4 = new Kiwi.Geom.Point(0,0);
this.physics = this.components.add(new Kiwi.Components.ArcadePhysics(this, null));
this.physics.immovable = true;
}
/**
* The physics component contained on the Tilemap. Use for basic collisions between People and Tiles.
* Note: That tilemap layers a immovable and collisions with tiles are set on the individual TileTypes that are contained on the TileMap.
* @property physics
* @type ArcadePhysics
* @public
*/
public physics: Kiwi.Components.ArcadePhysics;
/**
* Returns the type of child that this is.
* @type Number
* @return {Number} returns the type of child that the entity is
* @public
*/
public childType(): number {
return Kiwi.TILE_LAYER;
}
/**
* The type of object that it is.
* @method objType
* @return {String} "TileMapLayer"
* @public
*/
public objType() {
return "TileMapLayer";
}
/**
* The tilemap that this TileMapLayer is a part of.
* @property tilemap
* @type TileMap
* @public
*/
public tilemap: Kiwi.GameObjects.Tilemap.TileMap;
/**
* Properties about that this TileMapLayer has when it was created from a JSON file.
* @property properties
* @type Object
* @public
*/
public properties: any = {};
/**
* The width of this TileMap in tiles.
* @property width
* @type Number
* @public
*/
public width: number;
/**
* The height of this TileMap in tiles.
* @property height
* @type Number
* @public
*/
public height: number;
/**
* The width of a single tile.
* @property tileWidth
* @type Number
* @public
*/
public tileWidth: number;
/**
* The height of a single tile.
* @property tileHeight
* @type Number
* @public
*/
public tileHeight: number;
/**
* The texture atlas that should be used when rendering.
* @property atlas
* @type Kiwi.Textures.TextureAtlas
* @public
*/
public atlas: Kiwi.Textures.TextureAtlas;
/**
* The width of the layer in pixels. This property is READ ONLY.
* @property widthInPixels
* @type number
* @public
*/
public get widthInPixels(): number {
return this.width * this.tilemap.tileWidth;
}
/**
* The height of the layer in pixels. This property is READ ONLY.
* @property heightInPixels
* @type number
* @public
*/
public get heightInPixels(): number {
return this.height * this.tilemap.tileHeight;
}
/**
* Override function to prevent unwanted inherited behaviour. Do not call.
*
* Because TileMapLayer extends Entity, it has a cellIndex parameter. However, it does not use a single atlas index, so this parameter is meaningless. It has deliberately been set to do nothing.
* @property cellIndex
* @type number
* @public
* @deprecated Not functional on this object.
* @since 1.1.0
*/
public get cellIndex():number {
return null;
}
public set cellIndex( val: number ) {}
// Methods altered because TileMapLayer has its own width and height properties:
public scaleToWidth(value: number) {
this.scale = value / this.widthInPixels;
}
public scaleToHeight(value: number) {
this.scale = value / this.heightInPixels;
}
public centerAnchorPoint() {
this.anchorPointX = this.widthInPixels * 0.5;
this.anchorPointY = this.heightInPixels * 0.5;
}
/**
* A list containing all the types of tiles found on this TileMapLayer.
* @property _data
* @type number[]
* @private
*/
private _data: number[];
/**
* Returns the total number of tiles. Either for a particular type if passed, otherwise of any type if not passed.
* @method countTiles
* @param [type] {Number} The type of tile you want to count.
* @return {Number} The number of tiles on this layer.
* @public
*/
public countTiles(type?:number):number {
var cnt = 0;
for (var i = 0; i < this._data.length; i++) {
if (type == undefined && this._data[i] !== 0) cnt++;
else if (type === this._data[i]) cnt++;
}
return cnt;
}
/**
* The orientation of the of tilemap.
* TileMaps can be either 'orthogonal' (normal) or 'isometric'.
* @property orientation
* @type String
* @default 'orthogonal'
* @public
*/
public orientation: string = ORTHOGONAL;
/**
*-----------------------
* Getting Tiles
*-----------------------
*/
/**
* A list containing all of the types of tiles found on this TileMapLayer. This is READ ONLY.
* @property tileData
* @type number[]
* @public
*/
public get tileData(): number[] {
return this._data;
}
/**
* Returns the index of the tile based on the x and y coordinates of the tile passed.
* If no tile is a the coordinates given then -1 is returned instead.
* Coordinates are in tiles not pixels.
* @method getIndexFromXY
* @param x {Number} The x coordinate of the Tile you would like to retrieve.
* @param y {Number} The y coordinate of the Tile you would like to retrieve.
* @return {Number} Either the index of the tile retrieved or -1 if none was found.
* @public
*/
public getIndexFromXY(x: number, y: number): number {
var num = x + y * this.width;
//Does the index exist?
if (num < 0 || num >= this._data.length) return -1;
else return num;
}
/**
* Returns the TileType for a tile that is at a particular set of coordinates passed.
* If no tile is found the null is returned instead.
* Coordinates passed are in tiles.
* @method getTileFromXY
* @param x {Number}
* @param y {Number}
* @return {Number} The tile
* @public
*/
public getTileFromXY(x: number, y: number): TileType {
var t = this.getIndexFromXY(x, y);
return (t !== -1) ? this.tilemap.tileTypes[ this._data[t] ] : null;
}
/**
* Returns the index of the tile based on the x and y pixel coordinates that are passed.
* If no tile is a the coordinates given then -1 is returned instead.
* Coordinates are in pixels not tiles and use the world coordinates of the tilemap.
* Note: Currently only working for ORTHOGONAL TileMaps.
*
* @method getIndexFromCoords
* @param x {Number} The x coordinate of the Tile you would like to retrieve.
* @param y {Number} The y coordinate of the Tile you would like to retrieve.
* @return {Number} Either the index of the tile retrieved or -1 if none was found.
* @public
*/
public getIndexFromCoords(x: number, y: number): number {
//Not with the bounds?
if (x > this.transform.worldX + this.widthInPixels || y > this.transform.worldY + this.heightInPixels || x < this.transform.worldX || y < this.transform.worldY)
return -1;
//Is so get the tile
var tx = Kiwi.Utils.GameMath.snapToFloor(x - this.transform.worldX, this.tileWidth) / this.tileWidth;
var ty = Kiwi.Utils.GameMath.snapToFloor(y - this.transform.worldY, this.tileHeight) / this.tileHeight;
return this.getIndexFromXY(tx, ty);
}
/**
* Returns the TileType for a tile that is at a particular coordinate passed.
* If no tile is found then null is returned instead.
* Coordinates passed are in pixels and use the world coordinates of the tilemap.
* Note: Currently only working for ORTHOGONAL TileMaps.
*
* @method getTileFromCoords
* @param x {Number}
* @param y {Number}
* @return {Number} The tile
* @public
*/
public getTileFromCoords(x: number, y: number): TileType {
var t = this.getIndexFromCoords(x, y);
return (t !== -1) ? this.tilemap.tileTypes[ this._data[t] ] : null;
}
/**
* Returns the indexes of every tile of a type you pass.
* @method getIndexsByType
* @param type {Number}
* @return {Number[]}
* @public
*/
public getIndexesByType(type:number):number[] {
var tiles = [];
for (var i = 0; i < this._data.length; i++) {
if (this._data[i] == type) tiles.push(i);
}
return tiles;
}
/**
*-----------------------
* Tiles Manipulation
*-----------------------
*/
/**
* Sets the tile to be used at the coordinates provided.
* Can be used to override a tile that may already exist at the location.
* @method setTile
* @param x {Number} The coordinate of the tile on the x axis.
* @param y {Number} The coordinate of the tile on the y axis.
* @param tileType {Number} The type of tile that should be now used.
* @return {Boolean} If a tile was changed or not.
* @public
*/
public setTile(x: number, y: number, tileType:number):boolean {
var x = this.getIndexFromXY(x, y);
if (x !== -1) {
this._data[x] = tileType;
return true;
}
return false;
}
/**
* Sets the tile to be used at the index provided.
* Can be used to override a tile that may already exist at the location.
* @method setTileByIndex
* @param index {Number} The index of the tile that you want to change.
* @param tileType {Number} The new tile type to be used at that position.
* @public
*/
public setTileByIndex(index: number, tileType: number) {
this._data[index] = tileType;
}
/**
* Randomizes the types of tiles used in an area of the layer. You can choose which types of tiles to use, and the area.
* Default tile types used are everyone avaiable.
* @method randomizeTiles
* @param [types] {Number[]} A list of TileTypes that can be used. Default is every tiletype on the TileMap.
* @param [x=0] {Number} The starting tile on the x axis to fill.
* @param [y=0] {Number} The starting tile on the y axis to fill.
* @param [width=this.width] {Number} How far across you want to go.
* @param [height=this.height] {Number} How far down you want to go.
* @public
*/
public randomizeTiles(types?: number[], x: number= 0, y: number= 0, width: number= this.width, height: number= this.height) {
if (types == undefined) {
types = [];
var i = 0;
while (i++ < this.tilemap.tileTypes.length) {
types.push(i);
}
}
for (var j = y; j < y + height; j++) {
for (var i = x; i < x + width; i++) {
var tile = this.getIndexFromXY(i, j);
if (tile !== -1) this._data[tile] = this.game.rnd.pick(types);
}
}
}
/**
* Makes all of the tiles in the area specified a single type that is passed.
* @method fill
* @param type {Number} The type of tile you want to fill in the area with.
* @param [x=0] {Number} The starting tile on the x axis to fill.
* @param [y=0] {Number} The starting tile on the y axis to fill.
* @param [width=this.width] {Number} How far across you want to go.
* @param [height=this.height] {Number} How far down you want to go.
* @public
*/
public fill(type: number, x: number= 0, y: number= 0, width: number= this.width, height: number= this.height) {
for (var j = y; j < y + height; j++) {
for (var i = x; i < x + width; i++) {
var tile = this.getIndexFromXY(i, j);
if (tile !== -1) this._data[tile ] = type;
}
}
}
/**
* Replaces all tiles of typeA to typeB in the area specified. If no area is specified then it is on the whole layer.
* @method replaceTiles
* @param typeA {Number} The type of tile you want to be replaced.
* @param typeB {Number} The type of tile you want to be used instead.
* @param [x=0] {Number} The starting tile on the x axis to fill.
* @param [y=0] {Number} The starting tile on the y axis to fill.
* @param [width=this.width] {Number} How far across you want to go.
* @param [height=this.height] {Number} How far down you want to go.
* @public
*/
public replaceTiles(typeA: number, typeB: number, x:number=0, y:number=0, width:number=this.width,height:number=this.height) {
for (var j = y; j < y + height; j++) {
for (var i = x; i < x + width; i++) {
var tile = this.getIndexFromXY(i, j);
if (tile !== -1 && this._data[tile] == typeA) this._data[tile] = typeB;
}
}
}
/**
* Swaps all the tiles that are typeA -> typeB and typeB -> typeA inside the area specified. If no area is specified then it is on the whole layer.
* @method swapTiles
* @param typeA {number} The type of tile you want to be replaced with typeB.
* @param typeB {number} The type of tile you want to be replaced with typeA.
* @param [x=0] {number} The starting tile on the x axis to fill.
* @param [y=0] {number} The starting tile on the y axis to fill.
* @param [width=this.width] {number} How far across you want to go.
* @param [height=this.height] {number} How far down you want to go.
* @public
*/
public swapTiles(typeA: number, typeB: number, x: number= 0, y: number= 0, width: number= this.width, height: number= this.height) {
for (var j = y; j < y + height; j++) {
for (var i = x; i < x + width; i++) {
var tile = this.getIndexFromXY(i, j);
if (tile !== -1) {
if (this._data[tile] == typeA) this._data[tile] = typeB;
else if (this._data[tile] == typeB) this._data[tile] = typeA;
}
}
}
}
/**
*-----------------------
* Get Tiles By Collision Methods
*-----------------------
*/
/**
* Returns the tiles which overlap with a provided entities hitbox component.
* Only collidable tiles on ANY side will be returned unless you pass a particular side.
* Note: Only designed to work with ORTHOGONAL types of tilemaps, results maybe unexpected for other types of tilemaps.
*
* @method getOverlappingTiles
* @param entity {Kiwi.Entity} The entity you would like to check for the overlap.
* @param [collisionType=ANY] {Number} The particular type of collidable tiles which you would like to check for.
* @return {Object[]} Returns an Array of Objects containing information about the tiles which were found. Index/X/Y information is contained within each Object.
* @public
*/
public getOverlappingTiles(entity: Kiwi.Entity, collisionType: number= Kiwi.Components.ArcadePhysics.ANY): any {
//Do they have a box?
if (entity.components.hasComponent("Box") == false)
return [];
//Get the box off them
var b: Kiwi.Geom.Rectangle = entity.components.getComponent('Box').worldHitbox;
//Is the person within the map's bounds?
if (b.left > this.transform.worldX + this.widthInPixels || b.right < this.transform.worldX || b.bottom < this.transform.worldY || b.top > this.transform.worldY + this.heightInPixels)
return [];
var worldX = this.transform.worldX;
var worldY = this.transform.worldY;
var nx = b.x - worldX;
var ny = b.y - worldY;
//Get starting location and now many tiles from there we will check.
var x = Kiwi.Utils.GameMath.snapToFloor(nx, this.tileWidth) / this.tileWidth;
var y = Kiwi.Utils.GameMath.snapToFloor(ny, this.tileHeight) / this.tileHeight;
var w = Kiwi.Utils.GameMath.snapToCeil(b.width, this.tileWidth) / this.tileWidth;
var h = Kiwi.Utils.GameMath.snapToCeil(b.height, this.tileHeight) / this.tileHeight;
//Add one, because we want to include the very end tile.
var tiles = this.getCollidableTiles(x, y, w + 1, h + 1, collisionType);
//Loop through the tiles and make sure they are actually overlapping with the Entity.
for (var i = 0; i < tiles.length; i++) {
var t = tiles[i];
if (t.x + worldX > b.right || t.x + this.tileWidth + worldX < b.left || t.y + worldY > b.bottom || t.y + this.tileHeight + worldY < t.top) {
tiles.splice(i, 1);
i--;
}
}
return tiles;
}
/**
* Returns the tiles which can collide with other objects (on ANY side unless otherwise specified) within an area provided.
* By default the area is the whole tilemap.
*
* @method getCollidableTiles
* @param [x=0] {Number} The x coordinate of the first tile to check.
* @param [y=0] {Number} The y coordinate of the first tile to check.
* @param [width=widthOfMap] {Number} The width from the x coordinate.
* @param [height=heightOfmap] {Number} The height from the y coordinate.
* @param [collisionType=ANY] {Number} The type of collidable tiles that should be return. By default ANY type of collidable tiles will be returned.
* @return {Object[]} Returns an Array of Objects containing information about the tiles which were found. Index/X/Y information is contained within each Object.
* @public
*/
public getCollidableTiles(x: number= 0, y: number= 0, width: number= this.width, height: number = this.height, collisionType: number= Kiwi.Components.ArcadePhysics.ANY): any {
var tiles = [];
//Make sure its within the map.
if (x > this.width || y > this.height) return;
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + width > this.width) width = this.width - x;
if (y + height > this.height) height = this.height - y;
//Loop through and of the tiles.
for (var j = y; j < y + height; j++) {
for (var i = x; i < x + width; i++) {
//Get the tile index.
var index = this.getIndexFromXY(i, j);
//Does that index exist? Should do but just in case.
if (index === -1) continue;
var type = this.tileData[index];
//If the collision type matches the one passed.
if ((this.tilemap.tileTypes[type].allowCollisions & collisionType) !== Kiwi.Components.ArcadePhysics.NONE) {
tiles.push({
index: index,
type: type,
x: i * this.tileWidth,
y: j * this.tileHeight
});
}
}
}
return tiles;
}
/**
* The update loop that is executed when this TileMapLayer is add to the Stage.
* @method update
* @public
*/
public update() {
super.update();
}
/**
*-----------------------
* Temp Properties used During Rendering
*-----------------------
*/
/**
* Used whilst rendering to calculate the number of tiles to be rendered on the X axis.
* Is updated each frame, via the _calculateBoundaries method.
* @property _maxX
* @type number
* @private
*/
private _maxX: number;
/**
* Used whilst rendering to calculate the number of tiles to be rendered on the Y axis.
* Is updated each frame, via the _calculateBoundaries method.
* @property _maxY
* @type number
* @private
*/
private _maxY: number;
/**
* Used whilst rendering to calculate which is the first tile to be rendered on the X axis.
* Is updated each frame, via the _calculateBoundaries method.
* @property _startX
* @type number
* @private
*/
private _startX: number;
/**
* Used whilst rendering to calculate which is the first tile to be rendered on the Y axis.
* Is updated each frame, via the _calculateBoundaries method.
* @property _startY
* @type number
* @private
*/
private _startY: number;
/**
* Temporary property that holds the tileType of the current tile being rendered.
* @property _temptype
* @type TileType
* @private
*/
private _temptype: TileType;
/**
* Corner values used internally.
* @property corner1
* @type {Kiwi.Geom.Point}
* @private
* @since 1.1.0
*/
private _corner1: Kiwi.Geom.Point;
/**
* Corner values used internally.
* @property corner2
* @type {Kiwi.Geom.Point}
* @private
* @since 1.1.0
*/
private _corner2: Kiwi.Geom.Point;
/**
* Corner values used internally.
* @property corner3
* @type {Kiwi.Geom.Point}
* @private
* @since 1.1.0
*/
private _corner3: Kiwi.Geom.Point;
/**
* Corner values used internally.
* @property corner4
* @type {Kiwi.Geom.Point}
* @private
* @since 1.1.0
*/
private _corner4: Kiwi.Geom.Point;
/**
* Used to calculate the position of the tilemap on the stage as well as how many tiles can fit on the screen.
* All coordinates calculated are stored as temporary properties (maxX/Y, startX/Y).
*
* @method _calculateBoundaries
* @param camera {Camera}
* @param matrix {Matrix}
* @private
*/
private _calculateBoundaries(camera: Kiwi.Camera, matrix: Kiwi.Geom.Matrix) {
//If we are calculating the coordinates for 'regular' then we can do that rather easy
if (this.orientation == ORTHOGONAL) {
// Account for camera and object transformation
// Initialise corners...
this._corner1.setTo(0, 0);
this._corner2.setTo(this.game.stage.width, 0);
this._corner3.setTo(this.game.stage.width, this.game.stage.height);
this._corner4.setTo(0, this.game.stage.height);
// Transform corners by camera...
this._corner1 = camera.transformPoint(this._corner1);
this._corner2 = camera.transformPoint(this._corner2);
this._corner3 = camera.transformPoint(this._corner3);
this._corner4 = camera.transformPoint(this._corner4);
// Transform corners by object...
var m = matrix.clone();
m.invert();
this._corner1 = m.transformPoint(this._corner1);
this._corner2 = m.transformPoint(this._corner2);
this._corner3 = m.transformPoint(this._corner3);
this._corner4 = m.transformPoint(this._corner4);
// Find min/max values in X and Y...
this._startX = Math.min(this._corner1.x, this._corner2.x, this._corner3.x, this._corner4.x);
this._startY = Math.min(this._corner1.y, this._corner2.y, this._corner3.y, this._corner4.y);
this._maxX = Math.max(this._corner1.x, this._corner2.x, this._corner3.x, this._corner4.x);
this._maxY = Math.max(this._corner1.y, this._corner2.y, this._corner3.y, this._corner4.y);
// Convert to tile units...
this._startX /= this.tileWidth;
this._startY /= this.tileHeight;
this._maxX /= this.tileWidth;
this._maxY /= this.tileHeight;
// Truncate units...
this._startX = Math.floor(this._startX);
this._startY = Math.floor(this._startY);
this._maxX = Math.ceil(this._maxX);
this._maxY = Math.ceil(this._maxY);
// Clamp values to tilemap range...
this._startX = Kiwi.Utils.GameMath.clamp(this._startX, this.width);
this._startY = Kiwi.Utils.GameMath.clamp(this._startY, this.height);
this._maxX = Kiwi.Utils.GameMath.clamp(this._maxX, this.width);
this._maxY = Kiwi.Utils.GameMath.clamp(this._maxY, this.height);
return;
}
//Otherwise we can't *just yet* so render the whole lot
if (this.orientation == ISOMETRIC) {
this._startX = 0;
this._startY = 0;
this._maxX = this.width;
this._maxY = this.height;
}
}
/**
* ChartToScreen maps a point in the game tile coordinates into screen pixel
* coordinates that indicate where the tile should be drawn.
* Note: This is for use in ISOMETRIC Tilemaps.
*
* @method chartToScreen
* @param chartPt {any} A Object containing x/y properties of the tile.
* @param tileW {Number} The width of the tile
* @param tileH {Number} The height of the tile
* @return {Object} With x/y properties of the location of the map onscreen.
* @public
*/
public chartToScreen(chartPt:any, tileW:number, tileH:number):any {
return { x:chartPt.x * tileW - chartPt.y * tileW,
y:chartPt.x * tileH / 2 + chartPt.y * tileH / 2 };
}
/**
* ScreenToChart maps a point in screen coordinates into the game tile chart
* coordinates for the tile on which the screen point falls on.
* This is for use in ISOMETRIC Tilemaps.
*
* @method screenToChart
* @param scrPt {any} An object containing x/y coordinates of the point on the screen you want to convert to tile coordinates.
* @param tileW {Number} The width of a single tile.
* @param tileH {Number} The height of a single tile.
* @return {Object} With x/y properties of the location of tile on the screen.
* @public
*/
public screenToChart(scrPt:any, tileW:number, tileH:number):any {
var column = Math.floor(scrPt.x / tileW);
var row = Math.floor((scrPt.y - column * (tileH / 2)) / tileH);
return { x:column + row, y:row };
}
/**
* The render loop which is used when using the Canvas renderer.
* @method render
* @param camera {Camera}
* @public
*/
public render(camera: Kiwi.Camera) {
//When not to render the map.
if (this.visible === false || this.alpha < 0.1 || this.exists === false) {
return;
}
//Get the context.
var ctx = this.game.stage.ctx;
ctx.save();
//Make the map alphed out.
if (this.alpha > 0 && this.alpha <= 1) {
ctx.globalAlpha = this.alpha;
}
// Transform
var t: Kiwi.Geom.Transform = this.transform;
var m: Kiwi.Geom.Matrix = t.getConcatenatedMatrix();
ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);
this._calculateBoundaries(camera, m);
for (var y = this._startY; y < this._maxY; y++) {
for (var x = this._startX; x < this._maxX; x++) {
if ( (this._temptype = this.getTileFromXY(x, y)) && this._temptype.cellIndex !== -1 ) {
var cell = this.atlas.cells[this._temptype.cellIndex];
var drawX:number;
var drawY:number;
if (this.orientation == ISOMETRIC) {
// Isometric maps
var offsetX = this._temptype.offset.x;
var offsetY = this._temptype.offset.y;
var w = this.tileWidth * (this.width * 2 - 1 );
var h = this.tileHeight * this.height;
// We want <0,0>'s horizontal center point to be in the screen center, hence the -tileWidth/2.
var shiftX = this.tileWidth / 2;
var screenPos = this.chartToScreen(
{ x:x , y:y },
this.tileWidth/2,
this.tileHeight);
drawX = screenPos.x + this._temptype.offset.x - shiftX;
drawY = screenPos.y - (cell.h - this.tileHeight) + this._temptype.offset.y;
} else {
// Orthogonal maps
drawX = x * this.tileWidth + this._temptype.offset.x;
drawY = y * this.tileHeight - (cell.h - this.tileHeight) + this._temptype.offset.y;
}
ctx.drawImage(
this.atlas.image,
cell.x,
cell.y,
cell.w,
cell.h,
drawX,
drawY,
cell.w,
cell.h
);
}
}
}
ctx.restore();
return true;
}
public renderGL(gl: WebGLRenderingContext, camera: Kiwi.Camera, params: any = null) {
//Setup
var vertexItems = [];
//Create the point objects.
var pt1 = new Kiwi.Geom.Point();
var pt2 = new Kiwi.Geom.Point();
var pt3 = new Kiwi.Geom.Point();
var pt4 = new Kiwi.Geom.Point();
//Transform/Matrix
var t: Kiwi.Geom.Transform = this.transform;
var m: Kiwi.Geom.Matrix = t.getConcatenatedMatrix();
//Find which ones we need to render.
this._calculateBoundaries(camera, m);
//Loop through the tiles.
for (var y = this._startY; y < this._maxY; y++) {
for (var x = this._startX; x < this._maxX; x++) {
//Get the tile type
this._temptype = this.getTileFromXY(x, y);
//Skip tiletypes that don't use a cellIndex.
if (this._temptype.cellIndex == -1) continue;
//Get the cell index
var cell = this.atlas.cells[this._temptype.cellIndex];
var tx;
var ty;
if (this.orientation == ISOMETRIC) {
// Isometric maps
var offsetX = this._temptype.offset.x;
var offsetY = this._temptype.offset.y;
var w = this.tileWidth * (this.width * 2 - 1);
var h = this.tileHeight * this.height;
// We want <0,0>'s horizontal center point to be in the screen center, hence the -tileWidth/2.
var shiftX = this.tileWidth / 2;
var screenPos = this.chartToScreen(
{ x:x , y:y },
this.tileWidth / 2,
this.tileHeight);
tx = screenPos.x + this._temptype.offset.x - shiftX;
ty = screenPos.y + this._temptype.offset.y;
} else {
// Orthogonal maps
tx = x * this.tileWidth + this._temptype.offset.x;
ty = y * this.tileHeight + this._temptype.offset.y;
}
//Set up the points
pt1.setTo(tx - t.rotPointX, ty - t.rotPointY - (cell.h - this.tileHeight));
pt2.setTo(tx + cell.w - t.rotPointX, ty - t.rotPointY - (cell.h - this.tileHeight));
pt3.setTo(tx + cell.w - t.rotPointX, ty + cell.h - t.rotPointY - (cell.h - this.tileHeight));
pt4.setTo(tx - t.rotPointX, ty + cell.h - t.rotPointY - (cell.h - this.tileHeight));
//Add on the matrix to the points
pt1 = m.transformPoint(pt1);
pt2 = m.transformPoint(pt2);
pt3 = m.transformPoint(pt3);
pt4 = m.transformPoint(pt4);
//Append to the xyuv array
vertexItems.push(
pt1.x + t.rotPointX, pt1.y + t.rotPointY, cell.x, cell.y, this.alpha, //Top Left Point
pt2.x + t.rotPointX, pt2.y + t.rotPointY, cell.x + cell.w, cell.y, this.alpha, //Top Right Point
pt3.x + t.rotPointX, pt3.y + t.rotPointY, cell.x + cell.w, cell.y + cell.h, this.alpha, //Bottom Right Point
pt4.x + t.rotPointX, pt4.y + t.rotPointY, cell.x, cell.y + cell.h, this.alpha //Bottom Left Point
);
}
}
//Concat points to the Renderer.
(<Kiwi.Renderers.TextureAtlasRenderer>this.glRenderer).concatBatch(vertexItems);
}
}
}