diff --git a/app/Game/Client/Collision/Detector.js b/app/Game/Client/Collision/Detector.js index 4aea3ad..20e16a4 100755 --- a/app/Game/Client/Collision/Detector.js +++ b/app/Game/Client/Collision/Detector.js @@ -4,14 +4,11 @@ define([ function (Parent) { - function Detector (player) { - Parent.call(this, player); + function Detector () { + Parent.call(this); } Detector.prototype = Object.create(Parent.prototype); - Detector.IDENTIFIER = Parent.IDENTIFIER; // Needed because otherwise it will not be - // inherited because it is not in prototype - return Detector; }); \ No newline at end of file diff --git a/app/Game/Core/Collision/Detector.js b/app/Game/Core/Collision/Detector.js index 81d4cd1..e4994f5 100755 --- a/app/Game/Core/Collision/Detector.js +++ b/app/Game/Core/Collision/Detector.js @@ -4,17 +4,11 @@ define([ function (Box2D) { - function Detector () { // FIXME evtl.bind(this) ? + function Detector () { this.listener = new Box2D.Dynamics.b2ContactListener(); - this.listener.chuckDetector = this; - this.listener.BeginContact = this.beginContact; - //this.listener.PostSolve = this.postSolve; - this.listener.EndContact = this.endContact; - } - - Detector.IDENTIFIER = { - TILE: "tile", - PLAYER: "player" + this.listener.BeginContact = this.beginContact.bind(this); + //this.listener.PostSolve = this.postSolve.bind(this); + this.listener.EndContact = this.endContact.bind(this); } Detector.prototype.getListener = function () { @@ -27,7 +21,9 @@ function (Box2D) { if (userDataA && userDataA.onCollisionChange) { userDataA.onCollisionChange(isColliding, point.GetFixtureB()); - } else if (userDataB && userDataB.onCollisionChange) { + } + + if (userDataB && userDataB.onCollisionChange) { userDataB.onCollisionChange(isColliding, point.GetFixtureA()); } } @@ -35,14 +31,24 @@ function (Box2D) { /** Extension **/ Detector.prototype.beginContact = function (point) { - this.chuckDetector.onCollisionChange(point, true); + this.onCollisionChange(point, true); } +/* Detector.prototype.postSolve = function (point, impulse) { + var userDataA = point.GetFixtureA().GetUserData(); + var userDataB = point.GetFixtureB().GetUserData(); + + if (userDataA && userDataA.onImpulse) { + userDataA.onImpulse(impulse, point.GetFixtureB()); + } else if (userDataB && userDataB.onImpulse) { + userDataB.onImpulse(impulse, point.GetFixtureA()); + } } +*/ Detector.prototype.endContact = function (point) { - this.chuckDetector.onCollisionChange(point, false); + this.onCollisionChange(point, false); } return Detector; diff --git a/app/Game/Core/GameObjects/Doll.js b/app/Game/Core/GameObjects/Doll.js index 6b3a23e..12214c6 100755 --- a/app/Game/Core/GameObjects/Doll.js +++ b/app/Game/Core/GameObjects/Doll.js @@ -60,6 +60,10 @@ function (Parent, Box2D, Settings, CollisionDetector, Item) { headShape.SetLocalPosition(new Box2D.Common.Math.b2Vec2(0, -(this.height - (this.width / 2)) / Settings.RATIO)); fixtureDef.shape = headShape; fixtureDef.isSensor = false; + fixtureDef.userData = { + onCollisionChange: this.onImpact.bind(this) + } + this.body.CreateFixture(fixtureDef); var bodyShape = new Box2D.Collision.Shapes.b2PolygonShape(); @@ -270,30 +274,8 @@ function (Parent, Box2D, Settings, CollisionDetector, Item) { }; Doll.prototype.grab = function(item) { - this.holdingItem = item; this.positionHoldingItem(); - - - - /* - var item = null; - if (this.lookDirection == -1) { - item = this.reachableItems.left.shift(); - } else { - item = this.reachableItems.right.shift(); - } - - if(item) { - - this.holdingItem = item; - - this.positionHoldingItem(); - } - - - return item; - */ }; Doll.prototype.positionHoldingItem = function() { @@ -346,6 +328,10 @@ function (Parent, Box2D, Settings, CollisionDetector, Item) { } } + Doll.prototype.onImpact = function(isColliding, fixture) { + // overwrite if necessary + }; + Doll.prototype.onFixtureWithinReach = function(isColliding, side, fixture) { var item = fixture.GetBody().GetUserData(); if (!(item instanceof Item)) return; diff --git a/app/Game/Core/Physics/Engine.js b/app/Game/Core/Physics/Engine.js index 267ec85..53d2e22 100755 --- a/app/Game/Core/Physics/Engine.js +++ b/app/Game/Core/Physics/Engine.js @@ -1,10 +1,11 @@ define([ "Game/Config/Settings", "Lib/Vendor/Box2D", - "Game/" + GLOBALS.context + "/Collision/Detector" + "Game/" + GLOBALS.context + "/Collision/Detector", + "Lib/Utilities/NotificationCenter" ], -function (Settings, Box2D, CollisionDetector) { +function (Settings, Box2D, CollisionDetector, NotificationCenter) { function Engine () { this.world = new Box2D.Dynamics.b2World( @@ -14,6 +15,9 @@ function (Settings, Box2D, CollisionDetector) { this.world.SetWarmStarting(true); this.ground = null; this.lastStep = Date.now(); + this.worldQueue = []; + + NotificationCenter.on("engine/addToWorldQueue", this.addToWorldQueue, this); } Engine.prototype.getWorld = function () { @@ -24,9 +28,9 @@ function (Settings, Box2D, CollisionDetector) { return this.ground; } - Engine.prototype.setCollisionDetector = function (player) { + Engine.prototype.setCollisionDetector = function () { - var detector = new CollisionDetector(player); + var detector = new CollisionDetector(); this.world.SetContactListener(detector.getListener()); } @@ -36,12 +40,26 @@ function (Settings, Box2D, CollisionDetector) { return body; } + Engine.prototype.addToWorldQueue = function(callback) { + this.worldQueue.push(callback); + }; + + Engine.prototype.processWorldQueue = function() { + for (var i = 0; i < this.worldQueue.length; i++) { + this.worldQueue[i](); + }; + + this.worldQueue = []; + }; + Engine.prototype.update = function () { var stepLength = (Date.now() - this.lastStep) / 1000; this.world.Step(stepLength, Settings.BOX2D_VELOCITY_ITERATIONS, Settings.BOX2D_POSITION_ITERATIONS); this.lastStep = Date.now(); this.world.ClearForces(); + this.processWorldQueue(); } + return Engine; }); \ No newline at end of file diff --git a/app/Game/Core/Player.js b/app/Game/Core/Player.js index 7256c65..849d68d 100755 --- a/app/Game/Core/Player.js +++ b/app/Game/Core/Player.js @@ -1,12 +1,19 @@ define([ "Game/" + GLOBALS.context + "/GameObjects/Doll", - "Game/Config/Settings" + "Game/Config/Settings", + "Lib/Utilities/NotificationCenter" ], -function (Doll, Settings) { +function (Doll, Settings, NotificationCenter) { function Player (id, physicsEngine) { + this.stats = { + health: 100, + deaths: 0, + kills: 0 + } + this.physicsEngine = physicsEngine; this.playerController = null; this.doll; @@ -20,6 +27,9 @@ function (Doll, Settings) { }; Player.prototype.spawn = function (x, y) { + if(this.doll) { + this.doll.destroy(); + } this.doll = new Doll(this.physicsEngine, "doll-" + this.id, this); this.doll.spawn(x, y); this.isSpawned = true; @@ -64,6 +74,10 @@ function (Doll, Settings) { this.holdingItem = null; }; + Player.prototype.kill = function(killedBy) { + NotificationCenter.trigger("player/killed", this); + }; + Player.prototype.update = function () { if(this.doll) { diff --git a/app/Game/Server/Collision/Detector.js b/app/Game/Server/Collision/Detector.js index 4aea3ad..8576da9 100755 --- a/app/Game/Server/Collision/Detector.js +++ b/app/Game/Server/Collision/Detector.js @@ -4,14 +4,12 @@ define([ function (Parent) { - function Detector (player) { - Parent.call(this, player); + function Detector () { + Parent.call(this); } Detector.prototype = Object.create(Parent.prototype); - Detector.IDENTIFIER = Parent.IDENTIFIER; // Needed because otherwise it will not be - // inherited because it is not in prototype return Detector; }); \ No newline at end of file diff --git a/app/Game/Server/GameController.js b/app/Game/Server/GameController.js index 114c190..6439c44 100755 --- a/app/Game/Server/GameController.js +++ b/app/Game/Server/GameController.js @@ -23,6 +23,7 @@ function (Parent, PhysicsEngine, Settings, PlayerController, requestAnimFrame, N NotificationCenter.on('user/joined', this.userJoined, this); NotificationCenter.on('user/left', this.userLeft, this); // FIXME: refactor this.userLeft -> this.onUserLeft, even in core and client NotificationCenter.on('user/resetLevel', this.onResetLevel, this); + NotificationCenter.on('player/killed', this.spawnPlayer, this); console.checkpoint('starting game controller for channel ' + channel.name); } diff --git a/app/Game/Server/GameObjects/Doll.js b/app/Game/Server/GameObjects/Doll.js index 214e8d1..e930f47 100755 --- a/app/Game/Server/GameObjects/Doll.js +++ b/app/Game/Server/GameObjects/Doll.js @@ -1,8 +1,11 @@ define([ - "Game/Core/GameObjects/Doll" + "Game/Core/GameObjects/Doll", + "Game/Server/GameObjects/Item", + "Lib/Vendor/Box2D", + "Lib/Utilities/NotificationCenter" ], -function (Parent) { +function (Parent, Item, Box2D, NotificationCenter) { function Doll(physicsEngine, uid, player) { Parent.call(this, physicsEngine, uid, player); @@ -27,6 +30,46 @@ function (Parent) { return findItem(this.reachableItems.right); } } + + Doll.prototype.onImpact = function(isColliding, fixture) { + var self = this; + + Parent.prototype.onImpact.call(this, isColliding, fixture); + + if(isColliding) { + var otherBody = fixture.GetBody(); + if(otherBody) { + var item = otherBody.GetUserData(); + if(item instanceof Item) { + var itemVelocity = item.body.GetLinearVelocity(); + var itemMass = item.body.GetMass(); + + var ownVelocity = this.body.GetLinearVelocity(); + + var b2Math = Box2D.Common.Math.b2Math; + + var absItemVelocity = b2Math.AbsV(itemVelocity) + var max = 1; + + if(absItemVelocity.x > max || absItemVelocity.y > max) { + if(item.lastMoved && item.lastMoved.player != this.player) { + var damage = b2Math.SubtractVV(itemVelocity, ownVelocity); + damage.Abs(); + damage.Multiply(itemMass); + + var callback = function() { + self.player.addDamage(damage.Length() * 2, item.lastMoved.player); + } + + NotificationCenter.trigger("engine/addToWorldQueue", callback) + } + } + + item.setLastMovedBy(this.player); + } + } + } + } return Doll; diff --git a/app/Game/Server/Player.js b/app/Game/Server/Player.js index 7d06ea2..ca9841c 100755 --- a/app/Game/Server/Player.js +++ b/app/Game/Server/Player.js @@ -58,6 +58,15 @@ function (Parent, NotificationCenter) { } } }; + + Player.prototype.addDamage = function(damage, enemy) { + this.stats.health -= damage; + if(this.stats.health <= 0) { + this.stats.deaths++; + enemy.stats.kills++; + this.kill(); + } + }; return Player;