Skip to content

Instantly share code, notes, and snippets.

@tlhunter
Created November 5, 2015 06:39
Show Gist options
  • Save tlhunter/887807a01ca3701e3213 to your computer and use it in GitHub Desktop.
Save tlhunter/887807a01ca3701e3213 to your computer and use it in GitHub Desktop.
Observing and interfering with player-world interaction
'use strict';
/**
* Represents a single player
*/
let Player = function(x, y, health) {
this.events = {
encroach: [],
enter: [],
exit: []
};
this.position = {
x: x,
y: y
};
this.health = health;
};
/**
* Executes a callback when a certain type of event fires
*/
Player.prototype.addObserver = function(event, callback) {
this.events[event].push(callback);
};
/**
* Removes the specified observer
*/
Player.prototype.removeObserver = function(event, callback) {
let observers = this.events[event];
for (let i = 0; i < observers.length; i++) {
if (observers[i] === callback) {
observers.splice(i, 1);
break;
}
}
};
Player.prototype.modifyHealth = function(health_mod) {
this.health += health_mod;
if (this.health <= 0) {
console.log('PLAYER HAS DIED.');
return true;
}
return false;
};
/**
* Returns displayable information about our player
*/
Player.prototype.toString = function() {
return "X: " + this.position.x + ", Y: " + this.position.y + ", HP: " + this.health;
};
/**
* Attempts to move a player
*/
Player.prototype.move = function(x_offset, y_offset) {
if (this.health <= 0) {
return console.log('CANNOT MOVE, PLAYER IS DEAD');
}
let block = false;
for (let handler of this.events.exit) {
let gonnaBlock = handler(this.position);
if (gonnaBlock) {
block = true;
}
}
if (this.health <= 0) { return; }
if (block) { console.log('NO EXIT'); return console.log(this.toString()); }
let target = {
x: this.position.x + x_offset,
y: this.position.y + y_offset
};
console.log('ATTEMPT MOVE TO X: ' + target.x + ', Y: ' + target.y)
for (let handler of this.events.encroach) {
let gonnaBlock = handler(target);
if (gonnaBlock) {
block = true;
}
}
if (this.health <= 0) { return; }
if (block) { console.log('NO ENCROACH'); return console.log(this.toString()); }
for (let handler of this.events.enter) {
handler(target);
}
if (this.health <= 0) { return; }
this.position = target;
console.log(this.toString());
};
/**
* Keeps track of a collection of enemies
*/
let Enemies = function() {
this.enemies = [];
};
/**
* Adds an enemy to the collection
*/
Enemies.prototype.add = function(x, y, attack) {
this.enemies.push({
x: x,
y: y,
attack: attack
});
};
/**
* Observes the player for encroach events (the player attempts to collide with enemy)
*/
Enemies.prototype.observe = function(player) {
const self = this;
player.addObserver('encroach', function(coord) {
let block = false;
for (let enemy of self.enemies) {
if (enemy.x === coord.x && enemy.y === coord.y) {
block = true;
//enemy.health -= player.attack;
player.modifyHealth(-1 * enemy.attack);
}
}
return block;
});
};
/**
* A collection of items
*/
let Items = function() {
this.items = [];
};
/**
* Adds a new item
*/
Items.prototype.add = function(x, y, health_mod) {
this.items.push({
x: x,
y: y,
health_mod: health_mod
});
};
/**
* Tracks if a player enters a tile with an item, applies item health mod and destroys item
*/
Items.prototype.observe = function(player) {
const self = this;
player.addObserver('enter', function(coord) {
for (let i = 0; i < self.items.length; i++) {
let item = self.items[i];
if (item.x === coord.x && item.y === coord.y) {
console.log('ITEM AFFECT HEALTH', item.health_mod);
player.modifyHealth(item.health_mod);
self.items.splice(i, 1);
}
}
return false;
});
};
/**
* A collection of traps
*/
let Traps = function() {
this.traps = [];
};
/**
* Adds a new trap
*
* @param damage The amount of damage caused to the player
* @param stuck Ratio of difficulty of player leaving trap
*/
Traps.prototype.add = function(x, y, damage, stuck) {
this.traps.push({
x: x,
y: y,
damage: damage,
stuck: stuck
});
};
/**
* If a player enters a trap, they will receive damage for the trap
* If a player exits a trap, we check to see if stuck, preventing them from leaving and damaging
*/
Traps.prototype.observe = function(player) {
const self = this;
player.addObserver('enter', function(coord) {
for (let trap of self.traps) {
if (trap.x === coord.x && trap.y === coord.y) {
player.modifyHealth(-1 * trap.damage);
console.log('TRAP DAMAGE', trap.damage);
}
}
return false;
});
player.addObserver('exit', function(coord) {
let block = false;
for (let trap of self.traps) {
if (trap.x === coord.x && trap.y === coord.y && trap.stuck >= Math.random()) {
console.log('TRAP STUCK', trap.stuck, trap.damage);
player.modifyHealth(-1 * trap.damage);
block = true;
}
}
return block;
});
};
// Initialize game
let enemies = new Enemies();
let items = new Items();
let traps = new Traps();
let player = new Player(10, 10, 100);
enemies.observe(player);
items.observe(player);
traps.observe(player);
enemies.add(9, 10, 5); // Gnoll
enemies.add(11, 10, 25); // Dragon
items.add(10, 9, 10); // Potion
items.add(10, 8, -50); // Poison
traps.add(10, 6, 10, 0.0); // Explosion
traps.add(10, 5, 2, 0.9); // Tar Pit
// Player moves around a bit
player.move(-1, 0); // West, into Gnoll
player.move(-1, 0); // West, into Gnoll
player.move(-1, 0); // West, into Gnoll
player.move(1, 0); // East, into Dragon
player.move(0, -1); // North, into Potion
player.move(0, -1); // North, into Poison
player.move(0, -1); // North
player.move(0, -1); // North, into Explosion
player.move(0, -1); // North, into Tar Pit
player.move(1, 0); // East
player.move(1, 0); // East
player.move(1, 0); // East
player.move(1, 0); // East
player.move(1, 0); // East
console.log("FINISHED.", player.toString());
@tlhunter
Copy link
Author

tlhunter commented Nov 5, 2015

ATTEMPT MOVE TO X: 9, Y: 10
NO ENCROACH
X: 10, Y: 10, HP: 95
ATTEMPT MOVE TO X: 9, Y: 10
NO ENCROACH
X: 10, Y: 10, HP: 90
ATTEMPT MOVE TO X: 9, Y: 10
NO ENCROACH
X: 10, Y: 10, HP: 85
ATTEMPT MOVE TO X: 11, Y: 10
NO ENCROACH
X: 10, Y: 10, HP: 60
ATTEMPT MOVE TO X: 10, Y: 9
ITEM AFFECT HEALTH 10
X: 10, Y: 9, HP: 70
ATTEMPT MOVE TO X: 10, Y: 8
ITEM AFFECT HEALTH -50
X: 10, Y: 8, HP: 20
ATTEMPT MOVE TO X: 10, Y: 7
X: 10, Y: 7, HP: 20
ATTEMPT MOVE TO X: 10, Y: 6
TRAP DAMAGE 10
X: 10, Y: 6, HP: 10
ATTEMPT MOVE TO X: 10, Y: 5
TRAP DAMAGE 2
X: 10, Y: 5, HP: 8
TRAP STUCK 0.9 2
NO EXIT
X: 10, Y: 5, HP: 6
TRAP STUCK 0.9 2
NO EXIT
X: 10, Y: 5, HP: 4
TRAP STUCK 0.9 2
NO EXIT
X: 10, Y: 5, HP: 2
TRAP STUCK 0.9 2
PLAYER HAS DIED.
CANNOT MOVE, PLAYER IS DEAD
FINISHED. X: 10, Y: 5, HP: 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment