diff --git a/project.xml b/project.xml index e406eb8..63a896c 100755 --- a/project.xml +++ b/project.xml @@ -14,6 +14,7 @@ + diff --git a/server.hxml b/server.hxml index 7a1392c..e2720f0 100755 --- a/server.hxml +++ b/server.hxml @@ -5,4 +5,5 @@ -cp src/common/haxe -cp src/server/haxe -cp src-gen/haxe --neko target/server.n \ No newline at end of file +-neko target/server.n +-D proto_debug \ No newline at end of file diff --git a/src/client/haxe/ru/m/tankz/core/PlayerTank.hx b/src/client/haxe/ru/m/tankz/core/PlayerTank.hx index ea8ca4d..082c8be 100755 --- a/src/client/haxe/ru/m/tankz/core/PlayerTank.hx +++ b/src/client/haxe/ru/m/tankz/core/PlayerTank.hx @@ -13,8 +13,8 @@ class PlayerTank extends Tank { private var keyBinding:Map; private var moveQueue:Array; - public function new(id:Int, x:Float, y:Float, keyBinding:Map) { - super(id, x, y); + public function new(personId:Int, id:Int, x:Float, y:Float, direction:Direction, keyBinding:Map) { + super(personId, id, x, y, direction); this.keyBinding = keyBinding; moveQueue = new Array(); Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); diff --git a/src/client/haxe/ru/m/tankz/engine/ClientEngine.hx b/src/client/haxe/ru/m/tankz/engine/ClientEngine.hx index acde717..3663469 100644 --- a/src/client/haxe/ru/m/tankz/engine/ClientEngine.hx +++ b/src/client/haxe/ru/m/tankz/engine/ClientEngine.hx @@ -1,10 +1,9 @@ package ru.m.tankz.engine; import ru.m.tankz.core.Direction; -import ru.m.tankz.core.Tank.TankAction; +import ru.m.tankz.core.Tank; import flash.ui.Keyboard; import ru.m.tankz.core.PlayerTank; -import ru.m.tankz.core.ITank; class ClientEngine extends Engine { @@ -14,9 +13,9 @@ class ClientEngine extends Engine { super(); } - override private function buildTank(id:Int, x:Float, y:Float):ITank { - return if (id == personId) { - new PlayerTank(id, x, y, [ + override private function buildTank(personId:Int, id:Int, x:Float, y:Float, direction:Direction):Tank { + return if (this.personId == personId) { + new PlayerTank(personId, id, x, y, direction, [ Keyboard.A => TankAction.MOVE(Direction.LEFT), Keyboard.S => TankAction.MOVE(Direction.BOTTOM), Keyboard.W => TankAction.MOVE(Direction.TOP), @@ -24,7 +23,7 @@ class ClientEngine extends Engine { Keyboard.SPACE => TankAction.SHOT ]); } else { - super.buildTank(id, x, y); + super.buildTank(personId, id, x, y, direction); } } } diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index 6a6fb8c..58ac37d 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -1,5 +1,7 @@ package ru.m.tankz.render; +import ru.m.tankz.core.Bullet; +import ru.m.tankz.core.Tank; import flash.display.Sprite; import flash.display.Graphics; import haxework.gui.SpriteView; @@ -46,22 +48,23 @@ class Render extends SpriteView implements IRender { var g:Graphics = tankLayer.graphics; g.clear(); - for (tank in game.tanks) { - g.beginFill(0xff0000); - g.drawRect(tank.x, tank.y, tank.width, tank.height); - g.endFill(); - g.beginFill(0x990000); - g.drawRect( - tank.x + tank.width / 2 - tank.width / 8 + tank.direction.x * tank.width / 4, - tank.y + tank.height / 2 - tank.height / 8 + tank.direction.y * tank.height / 4, - tank.width / 4, - tank.height / 4 - ); - g.endFill(); - for (bullet in tank.bullets) { + for (e in game.mobileEntities) { + if (Std.is(e, Tank)) { g.beginFill(0xff0000); - g.drawRect(bullet.x, bullet.y, bullet.width, bullet.height); + g.drawRect(e.x, e.y, e.width, e.height); + g.endFill(); + g.beginFill(0x990000); + g.drawRect( + e.x + e.width / 2 - e.width / 8 + e.direction.x * e.width / 4, + e.y + e.height / 2 - e.height / 8 + e.direction.y * e.height / 4, + e.width / 4, + e.height / 4 + ); + g.endFill(); + } else if (Std.is(e, Bullet)) { + g.beginFill(0xff0000); + g.drawRect(e.x, e.y, e.width, e.height); g.endFill(); } } diff --git a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx index 4bf3013..eb4ebb1 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -1,9 +1,5 @@ package ru.m.tankz.view.frames; -import ru.m.tankz.core.MobileEntity; -import ru.m.tankz.core.Direction; -import ru.m.tankz.proto.GameObjectType; -import ru.m.tankz.proto.GameChangeType; import ru.m.tankz.engine.ClientEngine; import protohx.Message; import ru.m.tankz.proto.GameUpdateResponse; @@ -33,7 +29,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand var persons = Provider.get(GameData).game.persons; name.text = person.name; engine.personId = person.id; - engine.init(persons, DEFAULT.CONFIG); + engine.init(DEFAULT.CONFIG); content.addEventListener(Event.ENTER_FRAME, updateGame); Provider.get(IConnection).packetHandler.addListener(this); render.draw(engine); @@ -51,57 +47,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand } public function onGameUpdateResponse(packet:GameUpdateResponse):Void { - for (change in packet.changes) { - switch (change.type) { - case GameChangeType.DIRECTION: - switch (change.objectType) { - case GameObjectType.TANK: - for (tank in engine.tanks) { - if (tank.id == change.objectId) { - tank.direction = new Direction(change.directionX, change.directionY); - break; - } - } - } - case GameChangeType.MOVED: - switch (change.objectType) { - case GameObjectType.TANK: - for (tank in engine.tanks) { - if (tank.id == change.objectId) { - tank.x = change.x; - tank.y = change.y; - break; - } - } - case GameObjectType.BULLET: - for (tank in engine.tanks) { - if (tank.id == change.parentObjectId) { - for (bullet in tank.bullets) { - if (bullet.id == change.objectId) { - bullet.x = change.x; - bullet.y = change.y; - break; - } - } - break; - } - } - } - case GameChangeType.APPEND: - switch (change.objectType) { - case GameObjectType.BULLET: - for (tank in engine.tanks) { - if (tank.id == change.parentObjectId) { - var bullet = new MobileEntity(change.objectId, change.x, change.y, 0, new Direction(change.directionX, change.directionY)); - bullet.width = 10; - bullet.height = 10; - tank.bullets.push(bullet); - break; - } - } - } - } - } + engine.updateFromChanges(packet.changes); render.draw(engine); } diff --git a/src/common/haxe/ru/m/core/connect/BaseConnection.hx b/src/common/haxe/ru/m/core/connect/BaseConnection.hx index ca8802a..8ae00c1 100755 --- a/src/common/haxe/ru/m/core/connect/BaseConnection.hx +++ b/src/common/haxe/ru/m/core/connect/BaseConnection.hx @@ -42,11 +42,11 @@ class BaseConnection implements IConnection { } } public function send(packet:Message):Void { - //L.d("Send", Type.getClassName(Type.getClass(packet)).split(".").pop()); + #if proto_debug L.d("Send", Type.getClassName(Type.getClass(packet)).split(".").pop()); #end } public function receive(packet:Message):Void { - //L.d("Receive", Type.getClassName(Type.getClass(packet)).split(".").pop()); + #if proto_debug L.d("Receive", Type.getClassName(Type.getClass(packet)).split(".").pop()); #end var name = "on" + Type.getClassName(Type.getClass(packet)).split(".").pop(); packetHandler.dispatch(function(h) { var method = Reflect.field(h, name); diff --git a/src/common/haxe/ru/m/core/connect/neko/NekoWebConnection.hx b/src/common/haxe/ru/m/core/connect/neko/NekoWebConnection.hx index d771399..1bda625 100644 --- a/src/common/haxe/ru/m/core/connect/neko/NekoWebConnection.hx +++ b/src/common/haxe/ru/m/core/connect/neko/NekoWebConnection.hx @@ -17,7 +17,7 @@ class NekoWebConnection extends NekoConnection { } override public function send(packet:Message):Void { - //L.d("Send", Type.getClassName(Type.getClass(packet)).split(".").pop()); + #if proto_debug L.d("Send", Type.getClassName(Type.getClass(packet)).split(".").pop()); #end try { var data = WebSocketTools.packet2string(packet, builder); writeData(data, socket); diff --git a/src/common/haxe/ru/m/tankz/core/Bullet.hx b/src/common/haxe/ru/m/tankz/core/Bullet.hx new file mode 100644 index 0000000..32f0780 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/core/Bullet.hx @@ -0,0 +1,13 @@ +package ru.m.tankz.core; + +class Bullet extends MobileEntity { + + public var personId(default, null):Int; + + public function new(personId:Int, id:Int, x:Float, y:Float, speed:Float, direction:Direction) { + super(id, x, y, speed, direction); + this.personId = personId; + this.width = 10; + this.height = 10; + } +} diff --git a/src/common/haxe/ru/m/tankz/core/ITank.hx b/src/common/haxe/ru/m/tankz/core/ITank.hx deleted file mode 100755 index c316fae..0000000 --- a/src/common/haxe/ru/m/tankz/core/ITank.hx +++ /dev/null @@ -1,8 +0,0 @@ -package ru.m.tankz.core; - -interface ITank extends IMobileEntity { - public var bullets:Array; - - public function shot():Void; - public function destroyBullet(bullet:IMobileEntity):Void; -} diff --git a/src/common/haxe/ru/m/tankz/core/MobileEntity.hx b/src/common/haxe/ru/m/tankz/core/MobileEntity.hx index 09fe936..8451111 100755 --- a/src/common/haxe/ru/m/tankz/core/MobileEntity.hx +++ b/src/common/haxe/ru/m/tankz/core/MobileEntity.hx @@ -1,6 +1,8 @@ package ru.m.tankz.core; class MobileEntity extends Entity implements IMobileEntity { + private static var idCounter:Int = 0; + public var id(default, null):Int; public var mx(default, default):Float = 0; @@ -9,9 +11,9 @@ class MobileEntity extends Entity implements IMobileEntity { public var speed(default, null):Float = 0; public var direction(default, default):Direction; - public function new(id:Int, x:Float, y:Float, speed:Float, direction:Direction = null) { + public function new(id:Int = 0, x:Float = 0, y:Float = 0, speed:Float = 0, direction:Direction = null) { super(x, y); - this.id = id; + this.id = id == 0 ? ++idCounter : id; this.speed = speed; this.direction = direction == null ? Direction.BOTTOM : direction; } diff --git a/src/common/haxe/ru/m/tankz/core/Tank.hx b/src/common/haxe/ru/m/tankz/core/Tank.hx index f3d7a71..93ca9a2 100755 --- a/src/common/haxe/ru/m/tankz/core/Tank.hx +++ b/src/common/haxe/ru/m/tankz/core/Tank.hx @@ -5,30 +5,28 @@ enum TankAction { SHOT; } -class Tank extends MobileEntity implements ITank { +class Tank extends MobileEntity { - private static var bulletIdCounter:Int = -1; + public var personId(default, null):Int; - public var bullets:Array; + public var bulletsCount:Int = 0; - public function new(id:Int, x:Float, y:Float) { - super(id, x, y, 4); - this.id = id; - bullets = new Array(); + public function new(personId:Int, id:Int, x:Float, y:Float, direction:Directiondo apt-g) { + super(id, x, y, 4, direction); + this.personId = personId; width = 34; height = 34; } - public function shot():Void { - if (bullets.length >= 5) return; - var bullet = new MobileEntity(bulletIdCounter--, x + width / 2 - 5, y + height / 2 - 5, 6, direction); - bullet.width = 10; - bullet.height = 10; + public function shot():Null { + if (bulletsCount >= 5) return null; + var bullet = new Bullet(personId, 0, x + width / 2 - 5, y + height / 2 - 5, 6, direction); bullet.move(direction); - bullets.push(bullet); + bulletsCount++; + return bullet; } - public function destroyBullet(bullet:IMobileEntity):Void { - bullets.remove(bullet); + public function onDestroyBullet():Void { + bulletsCount--; } } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 80f930e..b2b4ac8 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -1,5 +1,9 @@ package ru.m.tankz.engine; +import ru.m.tankz.core.Bullet; +import ru.m.tankz.proto.GameObjectType; +import ru.m.tankz.proto.GameChangeType; +import ru.m.tankz.proto.GameChange; import ru.m.tankz.proto.Person; import ru.m.tankz.core.Direction; import ru.m.tankz.core.IMobileEntity; @@ -7,14 +11,15 @@ import ru.m.tankz.core.IMobileEntity; import ru.m.tankz.config.TankzConfig; import ru.m.tankz.core.Tank; import ru.m.tankz.map.TankzMap; -import ru.m.tankz.core.ITank; import ru.m.tankz.map.ITankzMap; class Engine implements IEngine { public var config(default, default):TankzConfig; public var map(default, null):ITankzMap; - public var tanks(default, null):Array; + + public var tanks(default, null):Map; + public var mobileEntities(default, null):Map; private var x_limit:Float; private var y_limit:Float; @@ -22,87 +27,144 @@ class Engine implements IEngine { public function new() {} public function clear():Void { - tanks = []; + tanks = new Map(); } - private function buildTank(id:Int, x:Float, y:Float):ITank { - return new Tank(id, x, y); + private function buildTank(personId:Int, id:Int, x:Float, y:Float, direction:Direction):Tank { + return new Tank(personId, id, x, y, direction); } - public function init(persons:Array, config:TankzConfig):Void { + public function init(config:TankzConfig):Void { this.config = config; map = new TankzMap(config.map); - tanks = []; - for (person in persons) { - var x = 0; - var y = 100 * persons.indexOf(person); - tanks.push(buildTank(person.id, x, y)); - } + tanks = new Map(); + mobileEntities = new Map(); x_limit = map.gridWidth * map.cellWidth; y_limit = map.gridHeight * map.cellHeight; } - public function update():Void { - for (tank in tanks) { - if (tank.direction.x != 0) { - tank.y = Math.round((tank.y + tank.height / 2) / config.map.cellHeight) * config.map.cellHeight - tank.height / 2; - } - if (tank.direction.y != 0) { - tank.x = Math.round((tank.x + tank.width / 2) / config.map.cellWidth) * config.map.cellWidth - tank.width / 2; - } - tank.x += tank.mx; - tank.y += tank.my; + public function initTanks(persons:Array):Array { + var changes = new Array(); + for (person in persons) { + var x = 0; + var y = 100 * persons.indexOf(person); + var tank = buildTank(person.id, 0, x, y, Direction.BOTTOM); + this.tanks.set(tank.personId, tank); + this.mobileEntities.set(tank.id, tank); + changes.push(new GameChange() + .setType(GameChangeType.APPEND) + .setObjectType(GameObjectType.TANK) + .setPersonId(tank.personId) + .setObjectId(tank.id) + .setX(tank.x) + .setY(tank.y) + .setDirectionX(tank.direction.x) + .setDirectionY(tank.direction.y) + ); + } + return changes; + } - /*var tankR = new Rectangle(tank.x, tank.y, tank.width, tank.height); - - for (t in tanks) if (t != tank) { - var r = new Rectangle(t.x, t.y, t.width, t.height); - if (tankR.intersects(r)) { - if (tank.direction.x > 0) { - if (tank.x + tank.width > t.x) tank.x = t.x - tank.width; - } else if (tank.direction.x < 0) { - if (tank.x < t.x + t.width) tank.x = t.x + t.width; + public function updateFromChanges(changes:Array):Void { + for (change in changes) { + switch (change.type) { + case GameChangeType.APPEND: + switch (change.objectType) { + case GameObjectType.TANK: + var tank:Tank = buildTank(change.personId, change.objectId, change.x, change.y, new Direction(change.directionY, change.directionY)); + mobileEntities.set(tank.id, tank); + tanks.set(tank.personId, tank); + case GameObjectType.BULLET: + var bullet:Bullet = new Bullet(change.personId, change.objectId, change.x, change.y, 0, new Direction(change.directionY, change.directionY)); + mobileEntities.set(bullet.id, bullet); } - if (tank.direction.y > 0) { - if (tank.y + tank.height > t.y) tank.y = t.y - tank.height; - } else if (tank.direction.y < 0) { - if (tank.y < t.y + t.height) tank.y = t.y + t.height; - } - } - }*/ - - if (tank.x < 0) tank.x = 0; - if (tank.x + tank.width > x_limit) tank.x = x_limit - tank.width; - if (tank.y < 0) tank.y = 0; - if (tank.y + tank.height > y_limit) tank.y = y_limit - tank.height; - - updateBullets(tank); + case GameChangeType.DESTROED: + mobileEntities.remove(change.objectId); + case GameChangeType.DIRECTION: + var target = mobileEntities.get(change.objectId); + target.direction = new Direction(change.directionX, change.directionY); + case GameChangeType.MOVED: + var target = mobileEntities.get(change.objectId); + target.x = change.x; + target.y = change.y; + case GameChangeType.MODIFIED: + // + } } } - private function updateBullets(tank:ITank):Void { - for (bullet in tank.bullets) { - bullet.x += bullet.mx; - bullet.y += bullet.my; + public function update():Array { + var changes = new Array(); - /*var bulletR = new Rectangle(bullet.x, bullet.y, bullet.width, bullet.height); + for (entiny in mobileEntities) { + var objectType = -1; + var personId = Reflect.hasField(entiny, "personId") ? Reflect.field(entiny, "personId") : -1; + if (Std.is(entiny, Tank)) objectType = GameObjectType.TANK; + if (Std.is(entiny, Bullet)) objectType = GameObjectType.BULLET; - var i = 0; - while (i < tanks.length) { - var t = tanks[i++]; - if (t != tank) { + if (objectType == GameObjectType.TANK) { + if (entiny.direction.x != 0) { + entiny.y = Math.round((entiny.y + entiny.height / 2) / config.map.cellHeight) * config.map.cellHeight - entiny.height / 2; + } + if (entiny.direction.y != 0) { + entiny.x = Math.round((entiny.x + entiny.width / 2) / config.map.cellWidth) * config.map.cellWidth - entiny.width / 2; + } + } + + if (entiny.mx != 0 || entiny.my != 0) { + entiny.x += entiny.mx; + entiny.y += entiny.my; + + /*var tankR = new Rectangle(tank.x, tank.y, tank.width, tank.height); + + for (t in tanks) if (t != tank) { var r = new Rectangle(t.x, t.y, t.width, t.height); - if (bulletR.intersects(r)) { - tank.destroyBullet(bullet); - tanks.remove(t); - i--; + if (tankR.intersects(r)) { + if (tank.direction.x > 0) { + if (tank.x + tank.width > t.x) tank.x = t.x - tank.width; + } else if (tank.direction.x < 0) { + if (tank.x < t.x + t.width) tank.x = t.x + t.width; + } + if (tank.direction.y > 0) { + if (tank.y + tank.height > t.y) tank.y = t.y - tank.height; + } else if (tank.direction.y < 0) { + if (tank.y < t.y + t.height) tank.y = t.y + t.height; + } + } + }*/ + + if (objectType == GameObjectType.TANK) { + if (entiny.x < 0) entiny.x = 0; + if (entiny.x + entiny.width > x_limit) entiny.x = x_limit - entiny.width; + if (entiny.y < 0) entiny.y = 0; + if (entiny.y + entiny.height > y_limit) entiny.y = y_limit - entiny.height; + } + + + changes.push(new GameChange() + .setType(GameChangeType.MOVED) + .setObjectType(objectType) + .setPersonId(personId) + .setObjectId(entiny.id) + .setX(entiny.x) + .setY(entiny.y) + ); + + if (objectType == GameObjectType.BULLET) { + if (entiny.x < 0 || entiny.x + entiny.width > x_limit || entiny.y < 0 || entiny.y + entiny.height > y_limit) { + mobileEntities.remove(entiny.id); + var tank = tanks.get(personId); + tank.onDestroyBullet(); + changes.push(new GameChange() + .setType(GameChangeType.DESTROED) + .setObjectType(objectType) + .setPersonId(personId) + .setObjectId(entiny.id) + ); } } - }*/ - - if (bullet.x < 0 || bullet.x + bullet.width > x_limit || bullet.y < 0 || bullet.y + bullet.height > y_limit) { - tank.destroyBullet(bullet); } } + return changes; } } diff --git a/src/common/haxe/ru/m/tankz/engine/IEngine.hx b/src/common/haxe/ru/m/tankz/engine/IEngine.hx index c9e4faf..f2d796e 100755 --- a/src/common/haxe/ru/m/tankz/engine/IEngine.hx +++ b/src/common/haxe/ru/m/tankz/engine/IEngine.hx @@ -1,16 +1,21 @@ package ru.m.tankz.engine; +import ru.m.tankz.proto.GameChange; +import ru.m.tankz.core.IMobileEntity; +import ru.m.tankz.core.Tank; import ru.m.tankz.proto.Person; import ru.m.tankz.config.TankzConfig; -import ru.m.tankz.core.ITank; import ru.m.tankz.map.ITankzMap; interface IEngine { public var config(default, default):TankzConfig; public var map(default, null):ITankzMap; - public var tanks(default, null):Array; + public var tanks(default, null):Map; + public var mobileEntities(default, null):Map; public function clear():Void; - public function init(persons:Array, config:TankzConfig):Void; - public function update():Void; + public function init(config:TankzConfig):Void; + public function initTanks(persons:Array):Array; + public function updateFromChanges(changes:Array):Void; + public function update():Array; } diff --git a/src/common/proto/base.proto b/src/common/proto/base.proto index f0b1b32..93a46ca 100755 --- a/src/common/proto/base.proto +++ b/src/common/proto/base.proto @@ -126,8 +126,8 @@ enum GameChangeType { message GameChange { required GameChangeType type = 1; required GameObjectType objectType = 2; - required int32 objectId = 3; - optional int32 parentObjectId = 4; + optional int32 personId = 3; + required int32 objectId = 4; optional float x = 5; optional float y = 6; optional int32 directionX = 7; diff --git a/src/server/haxe/ru/m/tankz/server/game/GameManager.hx b/src/server/haxe/ru/m/tankz/server/game/GameManager.hx index 332f7f1..627c5af 100644 --- a/src/server/haxe/ru/m/tankz/server/game/GameManager.hx +++ b/src/server/haxe/ru/m/tankz/server/game/GameManager.hx @@ -52,14 +52,6 @@ class NekoTimer { } } -/** - * - **/ -typedef ObjectState = { - var x:Float; - var y:Float; -} - /** * **/ @@ -115,10 +107,12 @@ class GameManager { public function start() { game.setState(GameState.STARTED); engine = new Engine(); - engine.init(game.persons, DEFAULT.CONFIG); + engine.init(DEFAULT.CONFIG); + var changes = engine.initTanks(game.persons); timer = new NekoTimer(30); timer.run = update; broadcast(new StartGameResponse().setGame(game)); + broadcast(new GameUpdateResponse().setChanges(changes)); } public function stop() { @@ -133,83 +127,40 @@ class GameManager { } public function action(person:Person, action:GameActionRequest) { - for (tank in engine.tanks) { - if (tank.id == person.id) { - switch (action.type) { - case GameActionType.SHOT: - tank.shot(); - var bullet = tank.bullets.slice(0).pop(); - changes.push(new GameChange() - .setType(GameChangeType.APPEND) - .setObjectType(GameObjectType.BULLET) - .setParentObjectId(tank.id) - .setObjectId(bullet.id) - .setX(bullet.x) - .setY(bullet.y) - .setDirectionX(bullet.direction.x) - .setDirectionY(bullet.direction.y) - ); - case GameActionType.MOVE: - tank.move(new Direction(action.directionX, action.directionY)); - changes.push(new GameChange() - .setType(GameChangeType.DIRECTION) - .setObjectType(GameObjectType.TANK) - .setObjectId(tank.id) - .setDirectionX(tank.direction.x) - .setDirectionY(tank.direction.y) - ); - case GameActionType.STOP: - tank.stop(); + var tank = engine.tanks.get(person.id); + switch (action.type) { + case GameActionType.SHOT: + var bullet = tank.shot(); + if (bullet != null) { + engine.mobileEntities.set(bullet.id, bullet); + changes.push(new GameChange() + .setType(GameChangeType.APPEND) + .setObjectType(GameObjectType.BULLET) + .setPersonId(bullet.personId) + .setObjectId(bullet.id) + .setX(bullet.x) + .setY(bullet.y) + .setDirectionX(bullet.direction.x) + .setDirectionY(bullet.direction.y) + ); } - } + case GameActionType.MOVE: + tank.move(new Direction(action.directionX, action.directionY)); + changes.push(new GameChange() + .setType(GameChangeType.DIRECTION) + .setObjectType(GameObjectType.TANK) + .setPersonId(tank.personId) + .setObjectId(tank.id) + .setDirectionX(tank.direction.x) + .setDirectionY(tank.direction.y) + ); + case GameActionType.STOP: + tank.stop(); } } private function update() { - var states = new Map(); - for (tank in engine.tanks) { - states.set(tank.id, { - x: tank.x, - y: tank.y - }); - for (bullet in tank.bullets) { - states.set(bullet.id, { - x: bullet.x, - y: bullet.y - }); - } - } - engine.update(); - var changes = new Array(); - for (tank in engine.tanks) { - if (states.exists(tank.id)) { - var state = states.get(tank.id); - if (state.x != tank.x || state.y != tank.y) { - changes.push(new GameChange() - .setType(GameChangeType.MOVED) - .setObjectType(GameObjectType.TANK) - .setObjectId(tank.id) - .setX(tank.x) - .setY(tank.y) - ); - } - for (bullet in tank.bullets) { - if (states.exists(bullet.id)) { - var state = states.get(bullet.id); - if (state.x != bullet.x || state.y != bullet.y) { - changes.push(new GameChange() - .setType(GameChangeType.MOVED) - .setObjectType(GameObjectType.BULLET) - .setParentObjectId(tank.id) - .setObjectId(bullet.id) - .setX(bullet.x) - .setY(bullet.y) - ); - } - } - } - } - } + var changes = engine.update(); changes = this.changes.concat(changes); this.changes = []; if (changes.length > 0) {