Path: blob/main/public/games/files/algaes-escapade/js/lib/world.js
1036 views
/**1* Represents the game world, containing the game logic and sprites that2* require rendering3*4* @author David North5*/6include_once(['lib/camera.js','lib/player.js', 'lib/scorecard.js',7'lib/lever.js', 'lib/door.js', 'lib/gates/andGate.js',8'lib/gates/orGate.js', 'lib/gates/notGate.js', 'lib/block.js',9'lib/goal.js', 'lib/tooltip.js', 'lib/platform.js']);10function world()11{12//The maximum X velocity a player can trvel (heading right)13const MAX_X_VELOCITY = 200;1415//The maximum Y velocity a player can trvel (heading down)16const MAX_Y_VELOCITY = 400;1718//The minimum X velocity a player can trvel (heading left)19const MIN_X_VELOCITY = -250;2021//The minimum Y velocity a player can trvel (heading up)22const MIN_Y_VELOCITY = -350;2324/**25* @var boolean Whether the world has fully loaded26*/27var _hasLoaded;2829var _levelComplete;3031var _gameTime;3233var _scorecard;3435/**36* @var camera The camera to use37*/38var _camera;3940/**41* @var gamejs.sprite.Sprite Represents the bounding box (and background)42* of a level43*/44var _levelSprite;4546var _levelRect;4748/**49* @var player Represents the player50*/51var _p;5253/**54* @var gamejs.sprite.Group Represents all objects a player can55* interact with56*/57var _objects;5859var _goals;6061_levelSpriteCollission = function(playable){62var rightEdge = [63[this.rect.right, this.rect.top],64[this.rect.right, this.rect.bottom]65];6667var leftEdge = [68[this.rect.left, this.rect.top],69[this.rect.left, this.rect.bottom]70];7172var topEdge = [73[this.rect.left, this.rect.top],74[this.rect.right, this.rect.top]75];7677var bottomEdge = [78[this.rect.left, this.rect.bottom],79[this.rect.right, this.rect.bottom]80];8182//Test the left and right edges, setting as appropriate83if ( playable.rect.collideLine(rightEdge[0], rightEdge[1]) )84{85playable.rect.right = this.rect.right;86}87else if ( playable.rect.collideLine(leftEdge[0], leftEdge[1]) )88{89playable.rect.left = this.rect.left;90}9192//Test the top and bottom edges, setting as appropriate93if ( playable.rect.collideLine( topEdge[0], topEdge[1]) )94{95playable.rect.top = this.rect.top;96}97else if ( playable.rect.collideLine(bottomEdge[0], bottomEdge[1]) )98{99playable.rect.bottom = this.rect.bottom;100}101}102103/**104* Main initiation method. Must be called before using the object105*106* @param object mainSurface the surface that everything will be drawn to107*108* @return world109*/110this.init = function( levelNum, mainSurface )111{112this.clear();113114_levelSprite.image = gamejs.image.load('img/bg.png');115116var _size = _levelSprite.image.getSize();117_levelSprite.rect = new gamejs.Rect([0, 0], [_size[0], _size[1]]);118_levelRect = new gamejs.Rect([0, 0], [_size[0], _size[1]]);119120_objects.add(_levelSprite);121122_camera.setWidth( mainSurface.getSize()[0] );123_camera.setHeight( mainSurface.getSize()[1] );124125$.ajax({126"url": "js/lib/levels/level_"+levelNum+".js",127"dataType": "json",128"success": function(data){129_loadLevel(data);130_camera.focusOn(_p.getCurrentPlayable().rect, true);131_hasLoaded = true;132},133"error": function(jqXHR, textStatus, errorThrown){134throw errorThrown;135}136});137138return this;139}140141this.clear = function(){142if ( _objects instanceof gamejs.sprite.Group )143{144while( _objects.sprites().length )145{146var sprite = _objects.sprites()[0];147148if ( typeof(sprite.hide) == 'function' )149{150sprite.hide();151}152153sprite.kill();154sprite.remove(_objects);155};156}157158if ( _scorecard instanceof scorecard )159{160_scorecard.hide();161}162163_hasLoaded = false;164_levelComplete = false;165_gameTime = 0;166_scorecard = new scorecard();167_camera = new camera( this );168_levelSprite = new gamejs.sprite.Sprite();169_levelRect = new gamejs.Rect([0,0]);170_p = new player();171_objects = new gamejs.sprite.Group();172_goals = [];173174_levelSprite.handleCollision = _levelSpriteCollission;175}176177178this.getBoundingRect = function()179{180return _levelRect;181}182183this.getObjects = function()184{185return [ _p.getPlayables(), _objects ]186}187188this.getPlayer = function()189{190return _p;191}192193/**194* Handles user input and modifies the world objects accordingly195*196* @return world197*/198this.handleInput = function()199{200if ( _hasLoaded && !_camera.isAnimating())201{202var self = this;203204//Loop through each game event (key presses mouse movements etc)205gamejs.event.get().forEach(function(event){206if ( !_levelComplete )207{208var _currentPlayer = _p.getCurrentPlayable();209210_p.handleInput(event);211212if ( _p.getCurrentPlayable() != _currentPlayer )213{214_camera.focusOn(215_p.getCurrentPlayable().rect, true, true216);217}218219_objects.forEach(function(obj){220if ( typeof(obj.handleInput) == 'function' )221{222obj.handleInput(self, event);223}224});225}226});227}228229return this;230}231232/**233* Updates all objects within the world234*235* @param int msDuration The amount of time since the last update236*237* @return world238*/239this.update = function( msDuration )240{241if ( _hasLoaded && !_levelComplete )242{243_gameTime += msDuration;244245//Apply the gravitational pull of the world246_applyGravity( msDuration );247248//Apply updates to the player and any objects in the world249_p.update( msDuration );250_objects.update( msDuration );251252var colliders =253gamejs.sprite.groupCollide(_p.getPlayables(), _objects);254255for( var i = 0; i < colliders.length; i++ )256{257if ( typeof(colliders[i].b.handleCollision) == 'function' )258{259var isCurrentPlayer = false;260if ( colliders[i].a === _p.getCurrentPlayable() )261{262isCurrentPlayer = true;263}264265colliders[i].b.handleCollision(266colliders[i].a, isCurrentPlayer267);268}269}270271//Modify the camera position272_camera.update ( msDuration );273274_levelComplete = true;275for( var i = 0; i < _goals.length; i++ )276{277if ( !_goals[i].isActive() )278{279_levelComplete = false;280break;281}282}283284if ( _levelComplete )285{286for( var i = 0; i < _objects.sprites().length; i++ )287{288var obj = _objects.sprites()[i];289if ( obj instanceof tooltip )290{291obj.hide(false);292}293}294295_scorecard.setTimeTaken(_gameTime / 1000);296_scorecard.setClonesUsed(_p.getNumClones());297_scorecard.show();298}299}300301return this;302}303304/**305* Draws all objects within the world306*307* @return this308*/309this.draw = function ( mainSurface )310{311if ( _hasLoaded )312{313//Draw the level, collidables and non collidables, as these need314//to be behind the player315_objects.draw( mainSurface );316317//Draw the player at the forefront of the level318_p.draw( mainSurface );319}320321return this;322}323324/**325* Loads the level data from an array, filling the worls with collidables326* and ensuring it's playable327*/328var _loadLevel = function( data, input, output )329{330var _hasPlayer = false;331for ( var i = 0; i < data.length; i ++)332{333if ( data[i]['type'] == 'stats' )334{335_scorecard.setParForClones(data[i]['clonePar']);336_scorecard.setParForTime(data[i]['timePar']);337338if ( typeof(data[i]['lastLevel']) == 'boolean' )339{340_scorecard.setLastLevel(data[i]['lastLevel']);341}342else343{344_scorecard.setLastLevel(false);345}346}347else348{349var xAmount = 1;350var yAmount = 1;351352if ( typeof(data[i]['repeat-x']) != 'undefined')353{354xAmount = data[i]['repeat-x'];355}356357if ( typeof(data[i]['repeat-y']) != 'undefined')358{359yAmount = data[i]['repeat-y'];360}361362for ( var x = 0; x < xAmount; x++ )363{364for ( var y = 0; y < yAmount; y++ )365{366_addObjectToWorld(data[i], x, y, input, output);367}368}369}370}371}372373var _addObjectToWorld = function( data, x, y, input, output ){374var obj = null;375376if ( 'tooltip' == data['type'] )377{378obj = new tooltip();379obj.setText(data['text']);380_objects.add( obj );381}382else383{384switch ( data['type'] )385{386case 'block':387case 'wall':388data['type'] = 'block';389case 'andGate':390case 'orGate':391case 'notGate':392case 'lever':393case 'door':394case 'goal':395case 'platform':396var type = data['type'];397obj = new window[type]();398_objects.add( obj );399400if ( 'goal' === type )401{402_goals.push( obj );403}404break;405406case 'player':407obj = _p.getCurrentPlayable();408}409}410411if ( null != obj )412{413if ( obj instanceof io )414{415if ( typeof(data['outputs']) !== 'undefined' )416{417_loadLevel(data['outputs'], obj);418}419420if ( typeof(data['inputs']) !== 'undefined' )421{422_loadLevel(data['inputs'], null, obj)423}424425if ( typeof(input) !== 'undefined' && input != null )426{427obj.addInput(input);428}429430if ( typeof(output) !== 'undefined' && output != null )431{432obj.addOutput(output);433}434}435436if ( typeof(obj.setDimensions) != 'undefined' )437{438if ( typeof(data['width']) != 'undefined'439&& typeof(data['height']) != 'undefined' )440{441obj.setDimensions(data['width'], data['height']);442}443}444445var width = obj.rect.width;446var height = obj.rect.height;447448var xPos = (data['x'] + (width * x));449var yPos = (data['y'] + (height * y));450451obj.setPosition( xPos, yPos );452}453}454455/**456* Applies the gravitational pull of the world on all playables457*/458var _applyGravity = function( msDuration )459{460//Loop through each player and increase the Y velocity downward.461//If the player is jumping, this has the affect of slowing the462//player down. Otherwise the player is falling.463_p.getPlayables().forEach(function(obj){464var newVelocityY = obj.getVelocity().y465newVelocityY += Math.round(0.3 * msDuration);466467obj.setVelocity( obj.getVelocity().x, newVelocityY )468469//the velocity cannot exceed the maximums, so ensuer that the player470//is not falling too fast471_sanatiseVelocity(obj);472});473}474475/**476* Ensures that the player is not travelling too fast ion any direction477*/478var _sanatiseVelocity = function(obj)479{480//Get the current Velocity481var velocity = obj.getVelocity();482483//Make sure that the X velocity is not too slow or fast484velocity.x = Math.max( MIN_X_VELOCITY, velocity.x );485velocity.x = Math.min( MAX_X_VELOCITY, velocity.x );486487//Make sure that the Y velocity is not too slow or fast488velocity.y = Math.max( MIN_Y_VELOCITY, velocity.y );489velocity.y = Math.min( MAX_Y_VELOCITY, velocity.y );490491//Update the players velocity492obj.setVelocity( velocity.x, velocity.y );493}494}495496