API Docs for: 0.1.0
Show:

File: src/zerk/class/game/engine/system/viewport.js

/**
 * Viewport System
 * 
 * Provides the interface for visualization.
 * 
 * @class viewport
 * @namespace zerk.game.engine.system
 * @extends zerk.game.engine.system
 * @module zerk
 **/
zerk.define({
	
	name: 'zerk.game.engine.system.viewport',
	extend: 'zerk.game.engine.system'
	
},{
	
	/**
	 * Name of the system
	 * 
	 * @property _name
	 * @type String
	 * @protected
	 **/
	_name: 'viewport',
	
	/**
	 * Thread that runs this system
	 * 
	 * @property _thread
	 * @type String
	 * @protected
	 **/
	_thread: 'render',
	
	/**
	 * Priority of this system
	 * 
	 * @property _priority
	 * @type Integer
	 * @protected
	 **/
	_priority: 100,
	
	/**
	 * Rendering timer
	 * 
	 * @property _timer
	 * @type DOMTimer
	 * @protected
	 **/
	/*
	 * TODO Can "_timer" be removed or is it used in requestAnimationFrame 
	 * 	fallback?
	 */
	_timer: null,
	
	/**
	 * The total number of frames rendered
	 * 
	 * @property _frameCount
	 * @type Integer
	 * @protected
	 **/
	_frameCount: 0,
	
	/**
	 * Counter used to calculate FPS
	 * 
	 * @property _fpsCounter
	 * @type Integer
	 * @protected
	 **/
	_fpsCounter: 0,
	
	/**
	 * Stores the second of the last FPS measuring
	 * 
	 * @property _fpsSecond
	 * @type Integer
	 * @protected
	 **/
	_fpsSecond: 0,
	
	/**
	 * The number of rendered frames per second
	 * 
	 * @property _fps
	 * @type Integer
	 * @protected
	 **/
	_fps: 0,
	
	/**
	 * Zoom factor
	 * 
	 * @property _zoom
	 * @type Float
	 * @protected
	 **/
	_zoom: 100,
	
	/*
	 * TODO Validate x,y,offsetX,offsetY to be named convenient
	 */
	
	/**
	 * Horizontal view position in pixels
	 * 
	 * @property _x
	 * @type Float
	 * @protected
	 **/
	_x: 0,
	
	/**
	 * Vertical view position in pixels
	 * 
	 * @property _y
	 * @type Float
	 * @protected
	 **/
	_y: 0,
	
	/**
	 * Horizontal view position in meters
	 * 
	 * @property _offsetX
	 * @type Float
	 * @protected
	 * @deprecated
	 **/
	_offsetX: 0,
	
	/**
	 * Vertical view position in meters
	 * 
	 * @property _offsetY
	 * @type Float
	 * @protected
	 * @deprecated
	 **/
	_offsetY: 0,
	
	/**
	 * Width of the viewport in pixels
	 * 
	 * @property _width
	 * @type Integer
	 * @protected
	 **/
	_width: 0,
	
	/**
	 * Height of the viewport in pixels
	 * 
	 * @property _height
	 * @type Integer
	 * @protected
	 **/
	_height: 0,
	
	/**
	 * Class constructor
	 * 
	 * @method init
	 * @param {zerk.game.engine} engine Game engine
	 * @param {Object} config System configuration
	 **/
	init: function(engine,config) {
		
		zerk.parent('zerk.game.engine.system.viewport').init.apply(
			this,
			arguments
		);
		
		this.createBuffers({
			display: {
				width: 640,
				height: 480,
				visible: true
			},
			body: {
				width: 1,
				height: 1,
				visible: this._config.showBodyBuffer
			},
			fixture: {
				width: 1,
				height: 1,
				visible: this._config.showFixtureBuffer
			}
		});
		
		var viewportSize=this.getBufferSize('display');
		
		// Sync viwport with canvas size
		this._width=viewportSize.width;
		this._height=viewportSize.height;
		
		this._log(
			'Scale '
			+this._x+':'+this._y
			+' at '
			+this._width+'x'+this._height
		);
		
		this._log('Ready');
		
	},
	
	/**
	 * Returns the configuration defaults of the system
	 * 
	 * @method _getConfigDefaults
	 * @return {Object} Default configuration
	 * @protected
	 **/
	_getConfigDefaults: function() {
		
		return {
			showBodyBuffer: false,
			showFixtureBuffer: false,
			showGrid: false,
			showWorldCenterIndicator: false,
			trackPlayer: false,
			// How many 1m boxes will be drawn on the grid
			gridOuterWidth: 50,
			gridOuterHeight: 50
		};
		
	},
	
	/**
	 * Returns true when the system is interested in given component
	 * 
	 * @method useComponent
	 * @param {String} name Component name
	 * @return {Boolean} True when the system is intereseted in given component
	 **/
	useComponent: function(name) {
		
		// The viewport is not interested in entities itself
		return false;
		
	},
	
	/**
	 * Starts the system
	 * 
	 * @method start
	 **/
	start: function() {
		
		zerk.parent('zerk.game.engine.system.viewport').start.apply(
			this,
			arguments
		);
		
		this._log('Started');
		
	},
	
	/**
	 * Stops the system
	 * 
	 * @method stop
	 **/
	stop: function() {
		
		zerk.parent('zerk.game.engine.system.viewport').stop.apply(
			this,
			arguments
		);
		
		this._log('Stopped ('+this._frameCount+' Frames)');
		
		this.reset();
		
	},
	
	/**
	 * Updates the system
	 * 
	 * @method update
	 **/
	update: function() {
		
		zerk.parent('zerk.game.engine.system.viewport').update.apply(
			this,
			arguments
		);
		
		this.bufferClear('display');
		
		// Sync view with player entity
		if (this._config.trackPlayer) {
			
			var players=this._engine.getEntitiesByTags('player');
			
			if (players.length>0) {
				
				this._setViewPosition(
					players[0].components.position.x,
					players[0].components.position.y
				);
				
			}
			
		}
		
		if (this._config.showGrid) {
			this._debugDrawGrid();
		}
		
		if (this._config.showWorldCenterIndicator) {
			this._renderWorldCenterIndicator();
		}
		
		
		// Increase frame counter
		this._frameCount++;
		
		// Calculate FPS
		var date=new Date();
		var second=date.getSeconds();
		
		if (second!=this._fpsSecond) {
			this._fps=this._fpsCounter;
			this._fpsCounter=0;
		}
		
		this._fpsSecond=second;
		
		this._fpsCounter++;
		
	},
	
	/**
	 * Reset the viewport
	 * 
	 * @method reset
	 **/
	reset: function() {
		
		this._frameCount=0;
		
	},
	
	/**
	 * Returns the horizontal view position in pixels
	 * 
	 * @method getX
	 * @return Float
	 **/
	getX: function() {
		
		return this._x;
		
	},

	/**
	 * Returns the vertical view position in pixels
	 * 
	 * @method getY
	 * @return Float
	 **/
	getY: function() {
		
		return this._y;
		
	},
	
	/**
	 * Sets the horizontal view position in pixels
	 * 
	 * @method setX
	 * @return Float
	 **/
	setX: function(value) {
		
		this._x=value;
		
	},

	/**
	 * Sets the vertical view position in pixels
	 * 
	 * @method setY
	 * @return Float
	 **/
	setY: function(value) {
		
		this._y=value;
		
	},
	
	/**
	 * Returns the horizontal view position in meters
	 * 
	 * @method getOffsetX
	 * @return Float
	 * @deprecated
	 **/
	getOffsetX: function() {
		
		return this._offsetX;
		
	},

	/**
	 * Returns the vertical view position in meters
	 * 
	 * @method getOffsetY
	 * @return Float
	 * @deprecated
	 **/
	getOffsetY: function() {
		
		return this._offsetY;
		
	},
	
	/**
	 * Returns the width of the viewport in pixels
	 * 
	 * @method getWidth
	 * @return Integer
	 **/
	getWidth: function() {
		
		return this._width;
		
	},
	
	/**
	 * Returns the height of the viewport in pixels
	 * 
	 * @method getHeight
	 * @return Integer
	 **/
	getHeight: function() {
		
		return this._height;
		
	},
	
	/**
	 * Scales given value by current zoom factor
	 * 
	 * @method toScaleX
	 * @param {Float} value Value
	 * @return {Float} Scaled value
	 **/
	toScaleX: function(value) {
		
		return (value/100)*this._zoom;
		
	},
	
	/**
	 * Scales given value by current zoom factor
	 * 
	 * @method toScaleY
	 * @param {Float} value Value
	 * @return {Float} Scaled value
	 **/
	toScaleY: function(value) {
		
		return (value/100)*this._zoom;
		
	},

	/**
	 * Un-scales given value by current zoom factor
	 * 
	 * @method fromScaleX
	 * @param {Float} value Value
	 * @return {Float} Scaled value
	 **/
	fromScaleX: function(value) {
		
		return (value/this._zoom)*100;
		
	},

	/**
	 * Un-scales given value by current zoom factor
	 * 
	 * @method fromScaleY
	 * @param {Float} value Value
	 * @return {Float} Scaled value
	 **/
	fromScaleY: function(value) {
		
		return (value/this._zoom)*100;
		
	},
	
	/**
	 * Increases current zoom factor by factor 10
	 * 
	 * @method zoomIn
	 **/
	zoomIn: function() {
		
		this._zoom+=(10*(this._zoom/100));
		
	},

	/**
	 * Decreases current zoom factor by factor 10
	 * 
	 * @method zoomOut
	 **/
	zoomOut: function() {
		
		this._zoom-=(10*(this._zoom/100));
		
	},
	
	/**
	 * Returns the current count of frames drawn per second
	 * 
	 * @method getFPS
	 * @return {Integer} FPS
	 **/
	getFPS: function() {
		
		return this._fps;
		
	},
	
	/**
	 * Return the current zoom factor
	 * 
	 * @method getZoom
	 * @return {Float} Zoom factor
	 **/
	getZoom: function() {
		
		return this._zoom;
		
	},
	
	/**
	 * Returns a list of all entities currently visible in the viewport
	 * 
	 * @method _getEntitiesInViewport
	 * @return {Array} Entity list
	 * @protected
	 **/
	getEntitiesInViewport: function() {
		
		var x1=zerk.helper.toMeter(
			this._x+this.fromScaleX(0-(this._width/2))
		);
		
		var y1=zerk.helper.toMeter(
			this._y+this.fromScaleY(0-(this._height/2))
		);
		
		var x2=zerk.helper.toMeter(
			this._x+this.fromScaleX(this._width-(this._width/2))
		);
		
		var y2=zerk.helper.toMeter(
			this._y+this.fromScaleY(this._height-(this._height/2))
		);
		
		return this._getSystem('physics').getEntitiesInArea(x1,y1,x2,y2);
		
	},
	
	/**
	 * @method _getCanvasX
	 * @param {Float} meter
	 * @param {Integer} pixel
	 * @return {Integer}
	 * @protected
	 **/
	/*
	 * TODO Document mehtod '_getCanvasX'
	 */
	_getCanvasX: function(meter,pixel) {
		
		if (typeof meter==='undefined') {
			
			meter=0;
			
		}
		
		if (typeof pixel==='undefined') {
			
			pixel=0;
			
		}
		
		var value=this.toScaleX(
			zerk.helper.fromMeter(meter)+pixel-this._x
		);
		
		return ~~(0.5+value+(this._width/2));
		
	},
	
	/**
	 * @method _getCanvasY
	 * @param {Float} meter
	 * @param {Integer} pixel
	 * @return {Integer}
	 * @protected
	 **/
	/*
	 * TODO Document mehtod '_getCanvasY'
	 */
	_getCanvasY: function(meter,pixel) {
		
		if (typeof meter==='undefined') {
			
			meter=0;
			
		}
		
		if (typeof pixel==='undefined') {
			
			pixel=0;
			
		}
		
		var value=this.toScaleX(
			zerk.helper.fromMeter(meter)+pixel-this._y
		);
		
		return ~~(0.5+value+(this._height/2));
		
	},
	
	/**
	 * Set the view position to a given world position
	 * 
	 * @method _setViewPosition
	 * @param {Float} x
	 * @param {Float} y
	 * @protected
	 **/
	_setViewPosition: function(x,y) {
		
		this._x=zerk.helper.fromMeter(x);
		this._y=zerk.helper.fromMeter(y);
		
	},
	
	/**
	 * Renders the world center indicator
	 * 
	 * @method _renderWorldCenterIndicator
	 * @protected
	 **/
	_renderWorldCenterIndicator: function() {
		
		this.drawLines(
			'display',
			[
				[
					this._getCanvasX(-0.5),
					this._getCanvasY(0),
					this._getCanvasX(0.5),
					this._getCanvasY(0)
				],
				[
					this._getCanvasX(0),
					this._getCanvasY(-0.5),
					this._getCanvasX(0),
					this._getCanvasY(0.5)
				]
			],
			'rgb(0,0,255)'
		);
		
	},
	
	/**
	 * Renders the grid
	 * 
	 * @method _debugDrawGrid
	 * @protected
	 **/
	/*
	 * TODO Rename method '_debugDrawGrid' more convenient
	 */
	_debugDrawGrid: function() {
		
		/*
		 * TODO Reactivate draw grid code
		 */
		
		/*
		var coord=0;
		var width=this._config.gridOuterWidth;
		var height=this._config.gridOuterHeight;
		var offsetX=-(this._config.gridOuterWidth/2);
		var offsetY=-(this._config.gridOuterHeight/2);
		
		// Draw grid
		this._context.beginPath();
		this._context.strokeStyle="#111111";
		this._context.lineWidth=1;
		
		for (var i=1;i<=this._config.gridOuterWidth;i++) {
			
			coord=i*1;
			this._context.moveTo(
				this._getCanvasX(offsetX+coord),
				this._getCanvasY(offsetY)
			);
			this._context.lineTo(
				this._getCanvasX(offsetX+coord),
				this._getCanvasY(offsetY+height)
			);
			this._context.stroke();
			
		}
		
		for (var i=1;i<=this._config.gridOuterHeight;i++) {
			
			coord=i*1;
			this._context.moveTo(
				this._getCanvasX(offsetX),
				this._getCanvasY(offsetY+coord)
			);
			this._context.lineTo(
				this._getCanvasX(offsetX+width),
				this._getCanvasY(offsetY+coord)
			);
			this._context.stroke();
			
		}
		
		// Draw axis
		
		this._context.beginPath();
		this._context.strokeStyle="#111111";
		this._context
			.moveTo(this._getCanvasX(offsetX),this._getCanvasY(offsetY));
		this._context.lineTo(
			this._getCanvasX(offsetX+width),
			this._getCanvasY(offsetY)
		);
		this._context
			.moveTo(this._getCanvasX(offsetX),this._getCanvasY(offsetY));
		this._context.lineTo(
			this._getCanvasX(offsetX),
			this._getCanvasY(offsetY+height)
		);
		this._context.stroke();
		*/
		
	}
	
});