Spaces:
Running
Running
function Player(x, y, __map, __game) { | |
/* private variables */ | |
var __x = x; | |
var __y = y; | |
var __color = "#0f0"; | |
var __lastMoveDirection = ''; | |
var __display = __map._display; | |
/* unexposed variables */ | |
this._canMove = false; | |
/* wrapper */ | |
function wrapExposedMethod(f, player) { | |
return function () { | |
var args = arguments; | |
return __game._callUnexposedMethod(function () { | |
return f.apply(player, args); | |
}); | |
}; | |
}; | |
/* exposed getters/setters */ | |
this.getX = function () { return __x; }; | |
this.getY = function () { return __y; }; | |
this.getColor = function () { return __color; }; | |
this.getLastMoveDirection = function() { return __lastMoveDirection; }; | |
this.setColor = wrapExposedMethod(function (c) { | |
__color = c; | |
__display.drawAll(__map); | |
}); | |
/* unexposed methods */ | |
// (used for teleporters) | |
this._moveTo = function (dynamicObject) { | |
if (__game._isPlayerCodeRunning()) { throw 'Forbidden method call: player._moveTo()';} | |
// no safety checks or anything | |
// this method is about as safe as a war zone | |
__x = dynamicObject.getX(); | |
__y = dynamicObject.getY(); | |
__display.drawAll(__map); | |
// play teleporter sound | |
__game.sound.playSound('blip'); | |
}; | |
this._afterMove = function (x, y) { | |
if (__game._isPlayerCodeRunning()) { throw 'Forbidden method call: player._afterMove()';} | |
var player = this; | |
this._hasTeleported = false; // necessary to prevent bugs with teleportation | |
__map._hideChapter(); | |
__map._moveAllDynamicObjects(); | |
var onTransport = false; | |
// check for collision with transport object | |
for (var i = 0; i < __map.getDynamicObjects().length; i++) { | |
var object = __map.getDynamicObjects()[i]; | |
if (object.getX() === x && object.getY() === y) { | |
var objectDef = __map._getObjectDefinition(object.getType()); | |
if (objectDef.transport) { | |
onTransport = true; | |
} | |
} | |
} | |
// check for collision with static object UNLESS | |
// we are on a transport | |
if (!onTransport) { | |
var objectName = __map._getGrid()[x][y].type; | |
var objectDef = __map._getObjectDefinition(objectName); | |
if (objectDef.type === 'item') { | |
this._pickUpItem(objectName, objectDef); | |
} else if (objectDef.onCollision) { | |
__game.validateCallback(function () { | |
objectDef.onCollision(player); | |
}); | |
} | |
} | |
// check for collision with any lines on the map | |
__map.testLineCollisions(this); | |
// don't run checkObjective if validation has already failed to prevent duplicate `Validation failed` errors | |
if (!__map._callbackValidationFailed) { | |
// check for nonstandard victory condition (e.g. DOM level) | |
__game._checkObjective() | |
} | |
}; | |
this._pickUpItem = function (itemName, object) { | |
if (__game._isPlayerCodeRunning()) { throw 'Forbidden method call: player._pickUpItem()';} | |
var player = this; | |
__game.addToInventory(itemName); | |
__map._removeItemFromMap(__x, __y, itemName); | |
__map.refresh(); | |
__game.sound.playSound('pickup'); | |
if (object.onPickUp) { | |
__game.validateCallback(function () { | |
object.onPickUp(player); | |
}); | |
} | |
}; | |
/* exposed methods */ | |
this.atLocation = wrapExposedMethod(function (x, y) { | |
return (__x === x && __y === y); | |
}, this); | |
this.move = wrapExposedMethod(function (direction, fromKeyboard) { | |
if (!this._canMove) { // mainly for key delay | |
return false; | |
} | |
if (fromKeyboard) { | |
// clear any status text | |
__map._status = ""; | |
if (__map._overrideKeys[direction]) { | |
try { | |
__game.validateCallback(__map._overrideKeys[direction], true); | |
__map.refresh(); | |
this._canMove = false; | |
__map._reenableMovementForPlayer(this); // (key delay can vary by map) | |
this._afterMove(__x, __y); | |
} catch (e) { | |
} | |
return; | |
} | |
} | |
var new__x; | |
var new__y; | |
if (direction === 'up') { | |
new__x = __x; | |
new__y = __y - 1; | |
} | |
else if (direction === 'down') { | |
new__x = __x; | |
new__y = __y + 1; | |
} | |
else if (direction === 'left') { | |
new__x = __x - 1; | |
new__y = __y; | |
} | |
else if (direction === 'right') { | |
new__x = __x + 1; | |
new__y = __y; | |
} | |
else if (direction === 'rest') { | |
new__x = __x; | |
new__y = __y; | |
} | |
else if (direction === 'funcPhone') { | |
__game.usePhone(); | |
return; | |
} | |
if (__map._canMoveTo(new__x, new__y)) { | |
__x = new__x; | |
__y = new__y; | |
__map.refresh(); | |
this._canMove = false; | |
__lastMoveDirection = direction; | |
this._afterMove(__x, __y); | |
__map._reenableMovementForPlayer(this); // (key delay can vary by map) | |
} else { | |
// play bump sound | |
__game.sound.playSound('select'); | |
} | |
}, this); | |
this.killedBy = wrapExposedMethod(function (killer) { | |
__game.sound.playSound('hurt'); | |
__game._restartLevel(); | |
__map.displayChapter('You have been killed by \n' + killer + '!', 'death'); | |
}, this); | |
this.hasItem = wrapExposedMethod(function (itemName) { | |
return __game.checkInventory(itemName); | |
}, this); | |
this.removeItem = wrapExposedMethod(function (itemName) { | |
var object = __game.objects[itemName]; | |
__game.removeFromInventory(itemName); | |
__game.sound.playSound('blip'); | |
}, this); | |
this.setPhoneCallback = wrapExposedMethod(function(func) { | |
this._phoneFunc = func; | |
}, this); | |
// call secureObject to prevent user code from tampering with private attributes | |
__game.secureObject(this,"player"); | |
} | |