From 47ecce5e92cb397a040e753941839568952969d5 Mon Sep 17 00:00:00 2001 From: Juraj Michalek Date: Tue, 29 Dec 2015 10:42:51 +0100 Subject: [PATCH] persist game state --- data/images/gfx64/button.png | Bin 8832 -> 18594 bytes index.html | 371 +------------------------- js/app/game-state.js | 366 +++++++++++++++++++++++++ js/app/level-selector.js | 42 ++- js/save-manager-1.0.2/save-manager.js | 1 + 5 files changed, 410 insertions(+), 370 deletions(-) create mode 100644 js/app/game-state.js create mode 100644 js/save-manager-1.0.2/save-manager.js diff --git a/data/images/gfx64/button.png b/data/images/gfx64/button.png index df5c23d5443eedf63c15b0c83fa521c5907574d4..5fbb734baeb638ea1c19186f9879fa14ce835f29 100644 GIT binary patch literal 18594 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 delta 8796 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 + + diff --git a/js/app/game-state.js b/js/app/game-state.js new file mode 100644 index 0000000..5b3ade9 --- /dev/null +++ b/js/app/game-state.js @@ -0,0 +1,366 @@ +var state = new Kiwi.State('state'); + + +state.preload = function() { + this.addJSON('level1', 'data/levels/level-01.json'); + this.addJSON('level2', 'data/levels/level-02.json'); + this.addJSON('level3', 'data/levels/level-03.json'); + this.addJSON('level4', 'data/levels/level-04.json'); + this.addJSON('level5', 'data/levels/level-05.json'); + this.addJSON('level6', 'data/levels/level-06.json'); + this.addJSON('level7', 'data/levels/level-07.json'); + this.addJSON('level8', 'data/levels/level-08.json'); + this.addJSON('level9', 'data/levels/level-09.json'); + this.addJSON('level10', 'data/levels/level-10.json'); + this.addJSON('level11', 'data/levels/level-11.json'); + this.addJSON('level12', 'data/levels/level-12.json'); + this.addSpriteSheet('base', './data/images/gfx64/tiles.png', 64, 64); + this.addSpriteSheet('character', './data/images/gfx64/marble_black.png', 80, 80 ); + this.addSpriteSheet('oneWay', './data/images/gfx64/st_oneway.png', 64, 64 ); + this.addSpriteSheet('finishMarker', './data/images/gfx64/finish_marker.png', 64, 64 ); + this.addSpriteSheet('button', './data/images/gfx64/button.png', 128, 64 ); + this.addSpriteSheet('teleport', './data/images/gfx64/st_spitter_idle.png', 64, 64); + this.addSpriteSheet('box', './data/images/gfx64/st_box_wood.png', 64, 64); + this.addSpriteSheet('switch', './data/images/gfx64/st_switch.png', 64, 64); + this.addSpriteSheet('laserBeam', './data/images/gfx64/it_laser.png', 64, 64); + this.addSpriteSheet('laser', './data/images/gfx64/st_laser.png', 64, 64); +} + +state.velocityX = 64; +state.velocityY = 64; + +state.create = function() { + var level = levels[this.game.levelIndex - 1]; + this.tilemap = new Kiwi.GameObjects.Tilemap.TileMap(this, 'level' + this.game.levelIndex.toString(), this.textures.base); + + this.character = new Kiwi.GameObjects.Sprite(this, this.textures.character, 0, 0); + this.character.initialX = 2*64; + this.character.initialY = 64; + this.character.initialVelocityX = 0; + this.character.initialVelocityY = this.velocityY; + // Hitbox is detecting collision in future step. + // This is little bit counter intuitive. + // You have to make collision box smaller at least one step. + this.character.box.hitbox = new Kiwi.Geom.Rectangle( 12, 12, 58, 58 ); + this.character.physics = this.character.components.add( new Kiwi.Components.ArcadePhysics( this.character, this.character.box ) ); + + this.character.animation.add('walking', [ 0, 1 ], 0.2, true); + this.character.animation.add('idle', [ 2, 3, 4, 5, 6, 5, 4, 3 ], 0.2, true); + this.character.animation.add('failed', [ 11, 10, 9, 8, 7, 8, 9, 10], 0.2, true); + + this.redirectorGroup = new Kiwi.Group( this ); + + this.finishMarker = new Kiwi.GameObjects.Sprite(this, this.textures.finishMarker, 6*64, 4*64); + this.finishMarker.animation.add('idle', [ 0, 1, 2, 3, 2, 1 ], 0.3, true); + this.finishMarker.animation.play('idle', true); + + // Ground layer + this.addChild(this.tilemap.layers[0]); + + // Load level specific data + level.create(this); + + // Fix character coordinates and speed + this.resetCharacter(); + + this.addChild(this.finishMarker); + + // Walls layer + this.addChild(this.tilemap.layers[1]); + + // Add action objects + this.addChild(this.redirectorGroup); + + this.addChild(this.character); + + // Sky layer + this.addChild(this.tilemap.layers[2]); + + // Create collision layer + for(var i = 21; i < this.tilemap.tileTypes.length; i++) { + this.tilemap.tileTypes[i].allowCollisions = Kiwi.Components.ArcadePhysics.ANY; + } + + this.keyboard = this.game.input.keyboard; + + this.leftKey = this.keyboard.addKey(Kiwi.Input.Keycodes.LEFT, true); + this.rightKey = this.keyboard.addKey(Kiwi.Input.Keycodes.RIGHT, true); + //Prevent the down key from scrolling the page + this.keyboard.addKey(Kiwi.Input.Keycodes.DOWN, true); + + this.stageState = 'init'; + + this.myButton = new Kiwi.GameObjects.Textfield( this, "Start", 6*64+16, 60, "#000", 32, 'normal', 'Impact' ); + this.myButtonSprite = new Kiwi.GameObjects.Sprite(this, this.textures.button, 6*64, 50); + this.myButtonSprite.input.onUp.add( this.buttonReleased, this ); + + this.character.input.onUp.add( this.buttonReleased, this ); +} + +state.buttonReleased = function(sprite) { + if (this.stageState == 'init') { + this.myButton.text = '...'; + this.activateScene(); + } else if (this.stageState == 'stop') { + this.resetStage(); + this.myButton.text = 'Start' + this.stageState = 'init'; + } else if (this.stageState == 'complete') { + game.levelStatus = 'complete'; + game.states.switchState('levelSelector'); + } +} + +state.resetCharacter = function () { + this.character.physics.velocity.x = 0; + this.character.physics.velocity.y = 0; + this.character.x = this.character.initialX - 8; + this.character.y = this.character.initialY - 8; +} + +/** + * Reset all objects that should be back in the original position. + * Dragable redirectors are left on original place. + */ +state.resetStage = function() { + this.resetCharacter(); + var redirectors = this.redirectorGroup.members; + for ( var i = 0; i < redirectors.length; i++ ) { + var redirector = redirectors[i]; + if (redirector.type == 'box') { + redirector.x = redirector.initialX; + redirector.y = redirector.initialY; + } else if (redirector.type == 'switch') { + redirector.cellIndex = redirector.initialCellIndex; + } else if (redirector.type == 'laserBeam') { + redirector.visible = redirector.initialVisible; + } else if (redirector.type == 'laser') { + redirector.animation.play(redirector.initialAnimation, true); + } + } +} + +state.startedDrag = function(sprite) { + sprite.formerX = sprite.x; + sprite.formerY = sprite.y; +} + +/** + * Reverse effect of drag operaion. Set original coordinates. + */ +state.resetDrag = function(sprite) { + sprite.x = sprite.formerX; + sprite.y = sprite.formerY; +} + +/** + * Get tile index from specified coordinates. + */ +state.getTileIndex = function(x, y) { + var tile = this.tilemap.layers[0].getTileFromXY(x / 64 , y / 64); + if (tile == null) { + return 0; + } + return tile.index; +} + +/** + * Perform adjustments of coordinates for drop operation. + * Make sure that object is dropped on valid place and check + * collision with other objects. In case of failure revert + * to former coordinates. + */ +state.stoppedDrag = function(sprite) { + if (sprite.x % 64 > 32) { + sprite.x += 64; + } + if (sprite.y % 64 > 32) { + sprite.y += 64; + } + sprite.x = sprite.x - sprite.x % 64; + sprite.y = sprite.y - sprite.y % 64; + + // Make sure that we drop tile only on valid ground + if (this.getTileIndex(sprite.x, sprite.y) == 0) { + this.resetDrag(sprite); + } else { + // Make sure that we are not dropping on another redirector object + var redirectors = this.redirectorGroup.members; + for ( var i = 0; i < redirectors.length; i++ ) { + var redirector = redirectors[i]; + + // Skip comparision of self + if (sprite === redirector) { + continue; + } + + if ((sprite.x == redirector.x) && (sprite.y == redirector.y)) { + this.resetDrag(sprite); + break; + } + } + } +} + +state.activateScene = function () { + this.character.physics.velocity.x = this.character.initialVelocityX; + this.character.physics.velocity.y = this.character.initialVelocityY; + this.stageState = 'running'; +} + +state.update = function () { + //Update all the gameobjects + Kiwi.State.prototype.update.call(this); + + //Update physics + this.checkCollision(); + + this.updateCharacterAnimation(); +} + +state.updateCharacterAnimation = function () { + + if(( this.character.physics.velocity.y != 0 ) || (this.character.physics.velocity.x != 0)) { + this.character.animation.play('walking', false); + } else { + if (this.stageState == 'stop') { + this.character.animation.play('failed', false); + } else { + this.character.animation.play('idle', false); + } + } +} + +state.turnOff = function(items) { + for (var i=0; i!=items.length; i++) { + var item = items[i]; + if (item.type == 'laserBeam') { + item.visible = false; + } else if (item.type == 'switch') { + item.cellIndex = 2; + } else { + item.animation.play('idle'); + } + } +} + +state.turnOn = function(items) { + for (var i=0; i!=items.length; i++) { + var item = items[i]; + if (item.type == 'laserBeam') { + item.visible = true; + } else if (item.type == 'switch') { + item.cellIndex = 0; + } else { + item.animation.play('burning'); + } + } +} + +/** + * Create effect based on type of redirector. + */ +state.applyRedirectorMechanics = function(tileX, tileY, redirector) { + var isRecalculationRequired = false; + var redirectorTileX = Math.round(redirector.x/64); + var redirectorTileY = Math.round(redirector.y/64); + + // Box has hit regions around. Compute based on vector of player + if (redirector.type == 'box') { + tileX+=this.character.physics.velocity.x/64; + tileY+=this.character.physics.velocity.y/64; + } + + // Check for hit + if ((tileX != redirectorTileX ) || (tileY != redirectorTileY)) { + return; + } + + if (redirector.type == 'vector') { + this.character.physics.velocity.x = redirector.affectVelocityX; + this.character.physics.velocity.y = redirector.affectVelocityY; + } else if (redirector.type == 'teleport') { + this.character.x = redirector.affectedX - 8; + this.character.y = redirector.affectedY - 8; + } else if (redirector.type == 'box') { + // Move tile when it is possible + if (this.getTileIndex(redirector.x + this.character.physics.velocity.x, redirector.y + this.character.physics.velocity.y) != 0) { + redirector.x += this.character.physics.velocity.x; + redirector.y += this.character.physics.velocity.y; + } + // Bounce + this.character.physics.velocity.x = -this.character.physics.velocity.x; + this.character.physics.velocity.y = -this.character.physics.velocity.y; + + // Bounce from box should relaunch direction calculation + // This is for the case when box lies close to redirector + isRecalculationRequired = true; + } else if (redirector.type == 'switch') { + // Flip the switch + if (redirector.cellIndex == 0) { + redirector.cellIndex = 2; + this.turnOff(redirector.linkedItems); + } else { + redirector.cellIndex = 0; + this.turnOn(redirector.linkedItems); + } + } else if (redirector.type == 'laserBeam') { + if (redirector.visible) { + this.character.physics.velocity.x = 0; + this.character.physics.velocity.y = 0; + } + } + + // Correction of coordinates + this.character.y = Math.round(this.character.y); + this.character.x = Math.round(this.character.x); + return isRecalculationRequired; +} + +/** + * Resolve collisions between the character and the first layer. + */ +state.checkCollision = function () { + this.tilemap.layers[1].physics.overlapsTiles( this.character, true ); + + if ((this.character.physics.velocity.x == 0) && (this.character.physics.velocity.y == 0)) { + if (this.stageState == 'running') { + this.stageState = 'stop'; + this.myButton.text = 'Restart' + } + return; + } + + // Make collision detection only when ball is fully on the same tile + var positionX = Math.round(this.character.x) + 8; + var positionY = Math.round(this.character.y) + 8; + if ((Math.round(positionX) % 64 != 0) || (Math.round(positionY)% 64 != 0)) { + return; + } + + var isRecalculationRequired = false; + var redirectors = this.redirectorGroup.members; + for ( var i = 0; i < redirectors.length; i++ ) { + if (this.applyRedirectorMechanics(Math.round(positionX/64), Math.round(positionY/64), redirectors[i])) { + isRecalculationRequired = true; + } + } + + // Make the second round of calculation in case of hit of box + if (isRecalculationRequired) { + for ( var i = 0; i < redirectors.length; i++ ) { + this.applyRedirectorMechanics(Math.round(positionX/64), Math.round(positionY/64), redirectors[i]); + } + } + + if (((Math.round(positionX/64) == Math.round(this.finishMarker.x/64) )) && (Math.round(positionY/64) == Math.round(this.finishMarker.y/64))) { + this.stageState = 'complete'; + this.myButton.text = 'Next->' + this.addChild( this.myButtonSprite ); + this.addChild( this.myButton ); + + this.character.physics.velocity.x = 0; + this.character.physics.velocity.y = 0; + } + +} diff --git a/js/app/level-selector.js b/js/app/level-selector.js index bd2cc4d..1d6ca67 100644 --- a/js/app/level-selector.js +++ b/js/app/level-selector.js @@ -1,23 +1,55 @@ var levelSelectorState = new Kiwi.State('levelSelector'); +/** + * Save status of locks. + */ +levelSelectorState.save = function() { + this.game.saveManager.add('levelStatus', this.levelStatus); + this.game.saveManager.save(); +} + levelSelectorState.preload = function() { this.addSpriteSheet('button', './data/images/gfx64/button.png', 128, 64 ); + + if (this.game.saveManager.exists('levelStatus')) { + this.levelStatus = this.game.saveManager.getData('levelStatus'); + } else { + this.levelStatus = ['unlocked', 'locked', 'locked', 'locked', 'locked', 'locked', 'locked', 'locked', 'locked', + 'locked', 'locked', 'locked' + ]; + this.save(); + } } levelSelectorState.create = function() { var counterX = 0; var counterY = 0; + + // Unlock next level when previous was completed + if (game.levelStatus == 'complete') { + if (game.levelIndex < 12) { + this.levelStatus[game.levelIndex] = 'unlocked'; + game.levelStatus = 'none'; + this.save(); + } + } + for (var i=1; i 4) { + if (counterX > 3) { counterX = 0; counterY++; } diff --git a/js/save-manager-1.0.2/save-manager.js b/js/save-manager-1.0.2/save-manager.js new file mode 100644 index 0000000..b1ef8c3 --- /dev/null +++ b/js/save-manager-1.0.2/save-manager.js @@ -0,0 +1 @@ +Kiwi.Plugins.SaveGame={name:"SaveGame",version:"1.0.2",minimumKiwiVersion:"1.0.0"};Kiwi.PluginManager.register(Kiwi.Plugins.SaveGame);Kiwi.Plugins.SaveGame.create=function(e){var t=new Kiwi.Plugins.SaveGame.SaveManager(e);e.saveManager=t;return e.saveManager};Kiwi.Plugins.SaveGame.SaveManager=function(e){this.game=e};Kiwi.Plugins.SaveGame.SaveManager.prototype.objType=function(){return"SaveManager"};Kiwi.Plugins.SaveGame.SaveManager.prototype.boot=function(){this.localStorage=new Kiwi.Plugins.SaveGame.LocalStorage(this.game);this.current=this.localStorage};Kiwi.Plugins.SaveGame.SaveManager.prototype.switchCurrent=function(e){if(typeof e==="undefined")return;switch(e){case Kiwi.Plugins.SaveGame.SaveManager.LOCAL_STORAGE:this.current=this.localStorage;break}};Object.defineProperty(Kiwi.Plugins.SaveGame.SaveManager.prototype,"add",{get:function(){return this.current.add.bind(this.current)},enumerable:true,configurable:true});Object.defineProperty(Kiwi.Plugins.SaveGame.SaveManager.prototype,"edit",{get:function(){return this.current.edit.bind(this.current)},enumerable:true,configurable:true});Object.defineProperty(Kiwi.Plugins.SaveGame.SaveManager.prototype,"remove",{get:function(){return this.current.remove.bind(this.current)},enumerable:true,configurable:true});Object.defineProperty(Kiwi.Plugins.SaveGame.SaveManager.prototype,"getData",{get:function(){return this.current.getData.bind(this.current)},enumerable:true,configurable:true});Object.defineProperty(Kiwi.Plugins.SaveGame.SaveManager.prototype,"save",{get:function(){return this.current.save.bind(this.current)},enumerable:true,configurable:true});Object.defineProperty(Kiwi.Plugins.SaveGame.SaveManager.prototype,"exists",{get:function(){return this.current.exists.bind(this.current)},enumerable:true,configurable:true});Kiwi.Plugins.SaveGame.SaveManager.LOCAL_STORAGE=1;Kiwi.Plugins.SaveGame.LocalStorage=function(e){this.game=e;this._data={};this._supported=Kiwi.DEVICE.localStorage;if(this.supported)this._retrieveData()};Object.defineProperty(Kiwi.Plugins.SaveGame.LocalStorage.prototype,"data",{get:function(){return this._data},enumerable:true,configurable:true});Object.defineProperty(Kiwi.Plugins.SaveGame.LocalStorage.prototype,"supported",{get:function(){return this._supported},enumerable:true,configurable:true});Kiwi.Plugins.SaveGame.LocalStorage.prototype.objType=function(){return"LocalStorage"};Kiwi.Plugins.SaveGame.LocalStorage.prototype._retrieveData=function(){if(localStorage.getItem(this.game.stage.name)!==null){var e=localStorage.getItem(this.game.stage.name);this._data=JSON.parse(e)}else{this._create()}};Kiwi.Plugins.SaveGame.LocalStorage.prototype._create=function(){try{this._data={name:this.game.stage.name};localStorage.setItem(this.game.stage.name,JSON.stringify(this._data))}catch(e){console.log("Can not use localstorage due to memory limitations.");this._supported=false}};Kiwi.Plugins.SaveGame.LocalStorage.prototype.add=function(e,t,n){if(typeof n=="undefined")n=false;if(this.supported===true){this._data[e]=t;if(n===true){return this.save()}else{return true}}return false};Kiwi.Plugins.SaveGame.LocalStorage.prototype.edit=function(e,t,n){if(typeof n=="undefined")n=false;if(this.supported===true){if(this._data[e]!==null){this._data[e]=t;if(n===true){this.save()}else{return true}}}return false};Kiwi.Plugins.SaveGame.LocalStorage.prototype.getData=function(e){if(this.supported===true){if(typeof this._data[e]!=="undefined"){return this._data[e]}}return null};Kiwi.Plugins.SaveGame.LocalStorage.prototype.exists=function(e){return this._data[e]!==undefined};Kiwi.Plugins.SaveGame.LocalStorage.prototype.remove=function(e,t){if(typeof t=="undefined")t=false;if(this.supported===true){if(this._data[e]!==null){delete this._data[e];if(t===true){this.save()}else{return true}}}};Kiwi.Plugins.SaveGame.LocalStorage.prototype.clear=function(e){if(typeof e=="undefined")e=false;if(this.supported===true){this._data={};if(e===true)this.save()}};Kiwi.Plugins.SaveGame.LocalStorage.prototype.save=function(){try{localStorage.setItem([this.game.stage.name],JSON.stringify(this._data));return true}catch(e){console.log("Localstorage is full. Could not update.");return false}};Kiwi.Plugins.SaveGame.LocalStorage.prototype.load=function(){if(this.supported===true){this._data=JSON.parse(localStorage.getItem(this.game.stage.name));return true}return false} \ No newline at end of file