mirror of
https://github.com/ysoftdevs/pf2016.git
synced 2026-01-14 07:44:02 +01:00
393 lines
13 KiB
JavaScript
393 lines
13 KiB
JavaScript
var state = new Kiwi.State('state');
|
|
|
|
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]);
|
|
|
|
this.backButton = new Kiwi.GameObjects.Sprite(this, this.textures.base, 0, 0);
|
|
this.backButton.cellIndex = 24;
|
|
this.backButton.input.onUp.add(this.backButtonReleased, this);
|
|
this.addChild(this.backButton);
|
|
|
|
// 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.character.input.onUp.add( this.buttonReleased, this );
|
|
}
|
|
|
|
state.backButtonReleased = function(sprite, mouse) {
|
|
if ((mouse.x > 48) && (mouse.y > 48)) {
|
|
return;
|
|
}
|
|
this.stageState == 'none'
|
|
game.states.switchState('levelSelector');
|
|
}
|
|
|
|
state.buttonReleased = function(sprite) {
|
|
if (this.stageState == 'init') {
|
|
this.activateScene();
|
|
} else if (this.stageState == 'stop') {
|
|
this.resetStage();
|
|
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';
|
|
}
|
|
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.stageComplete();
|
|
}
|
|
|
|
}
|
|
|
|
state.displayCongratulation = function() {
|
|
var message = "Next";
|
|
var messageWidth = 100;
|
|
if (this.game.levelIndex == 12) {
|
|
message = "PF 2016";
|
|
messageWidth = 144;
|
|
}
|
|
|
|
var messageBox = new Kiwi.Plugins.Primitives.Rectangle( {
|
|
x: 3*64,
|
|
y: 72,
|
|
alpha: 0.5,
|
|
state: this,
|
|
width: 320,
|
|
height: 200,
|
|
color: '063500',
|
|
strokeColor: '050e20',
|
|
centerOnTransform: false
|
|
} );
|
|
|
|
var nextButton = new Kiwi.Plugins.Primitives.Rectangle( {
|
|
x: 5*64,
|
|
y: 200,
|
|
alpha: 0.5,
|
|
state: this,
|
|
width: messageWidth,
|
|
height: 50,
|
|
color: '2160e1',
|
|
strokeColor: '050e20',
|
|
centerOnTransform: false
|
|
} );
|
|
var congratulationText = new Kiwi.GameObjects.Textfield( this, "Congratulations", 4*64, 100, "#fbd712", 32, 'normal', 'Impact' );
|
|
var nextButtonText = new Kiwi.GameObjects.Textfield( this, message, 5*64+16, 204, "#fbd712", 32, 'normal', 'Impact' );
|
|
nextButton.input.onUp.add( this.buttonReleased, this );
|
|
|
|
this.addChild(messageBox);
|
|
this.addChild(congratulationText)
|
|
this.addChild(nextButton);
|
|
this.addChild(nextButtonText);
|
|
}
|
|
|
|
state.stageComplete = function() {
|
|
this.stageState = 'complete';
|
|
|
|
this.timer = this.game.time.clock.createTimer('time', 1, 1, true);
|
|
|
|
this.timer.createTimerEvent( Kiwi.Time.TimerEvent.TIMER_STOP, this.displayCongratulation, this );
|
|
|
|
this.character.physics.velocity.x = 0;
|
|
this.character.physics.velocity.y = 0;
|
|
}
|