From 507320414f17ddd168fb7de0eff586391ad812b8 Mon Sep 17 00:00:00 2001 From: shmyga Date: Wed, 17 Jan 2018 21:58:30 +0300 Subject: [PATCH 01/22] [render] update --- src/client/haxe/ru/m/tankz/render/IRender.hx | 10 - src/client/haxe/ru/m/tankz/render/Render.hx | 252 ++++-------------- .../haxe/ru/m/tankz/render/RenderItem.hx | 131 +++++++++ .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 17 +- .../haxe/ru/m/tankz/core/MobileEntity.hx | 9 +- src/common/haxe/ru/m/tankz/core/Tank.hx | 7 +- src/common/haxe/ru/m/tankz/engine/Engine.hx | 8 +- src/common/haxe/ru/m/tankz/map/Brick.hx | 11 + 8 files changed, 219 insertions(+), 226 deletions(-) delete mode 100755 src/client/haxe/ru/m/tankz/render/IRender.hx create mode 100644 src/client/haxe/ru/m/tankz/render/RenderItem.hx diff --git a/src/client/haxe/ru/m/tankz/render/IRender.hx b/src/client/haxe/ru/m/tankz/render/IRender.hx deleted file mode 100755 index d8a3810..0000000 --- a/src/client/haxe/ru/m/tankz/render/IRender.hx +++ /dev/null @@ -1,10 +0,0 @@ -package ru.m.tankz.render; - -import ru.m.tankz.engine.Engine; -import haxework.gui.IView; - - -interface IRender extends IView { - public function draw(game:Engine):Void; - public function reset():Void; -} diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index 858a7f7..df8e95c 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -1,12 +1,9 @@ package ru.m.tankz.render; -import ru.m.tankz.core.MobileEntity; +import flash.display.DisplayObject; +import Type.ValueType; +import ru.m.tankz.render.RenderItem; import ru.m.tankz.engine.Engine; -import ru.m.tankz.core.Entity; -import ru.m.tankz.map.Brick; -import ru.m.geom.Direction; -import flash.geom.Matrix; -import openfl.Assets; import ru.m.tankz.core.Bullet; import ru.m.tankz.core.Tank; import flash.display.Sprite; @@ -14,64 +11,18 @@ import flash.display.Graphics; import haxework.gui.SpriteView; -interface IState { - public function update(object:T):Bool; -} - -class BrickState implements IState { - private var type:Int; - - public function new() {} - - public function update(object:Brick):Bool { - if (type != object.config.type) { - type = object.config.type; - return true; - } - return false; - } -} - -class EntityState implements IState { - private var x:Float; - private var y:Float; - private var d:Direction; - private var type:Int; - - public function new() {} - - public function update(object:Entity):Bool { - if (x != object.rect.x || y != object.rect.y || !d.equals(object.rect.direction)) { - x = object.rect.x; - y = object.rect.y; - d = object.rect.direction; - return true; - } - if (Std.is(object, Tank)) { - var tank:Tank = cast object; - if (tank.config.type != type) { - type = tank.config.type; - return true; - } - } - return false; - } -} - - -class Render extends SpriteView implements IRender { +class Render extends SpriteView { private var backgroundLayer:Sprite; private var groundLayer:Sprite; private var entryLayer:Sprite; private var upLayer:Sprite; - private var layersForUpdate:Map; - private var states:Map>; + private var background:Sprite; + private var items:Map>; public function new() { super(); - layersForUpdate = new Map(); backgroundLayer = new Sprite(); groundLayer = new Sprite(); entryLayer = new Sprite(); @@ -83,160 +34,61 @@ class Render extends SpriteView implements IRender { reset(); } - private function invalidateLayers(game:Engine):Void { - for (brick in game.map.bricks) { - if (!states.exists(brick.key)) { - states[brick.key] = new BrickState(); - } - if (states.get(brick.key).update(brick)) { - layersForUpdate[groundLayer] = true; - layersForUpdate[upLayer] = true; - } - } - layersForUpdate[groundLayer] = true; //ToDo: - for (entry in game.entities) { - if (!states.exists(entry.key)) { - states[entry.key] = new EntityState(); - } - if (states.get(entry.key).update(entry)) { - layersForUpdate[entryLayer] = true; - } - } - for (key in game.removedEntities) { - if (states.exists(key)) { - states.remove(key); - layersForUpdate[entryLayer] = true; - } - } - } - private function drawBackground(game:Engine):Void { var mapWidth = game.map.gridWidth * game.map.cellWidth; var mapHeight = game.map.gridHeight * game.map.cellHeight; - - if (layersForUpdate[backgroundLayer]) { - var g:Graphics = backgroundLayer.graphics; - g.clear(); - g.beginFill(0x000000); - g.drawRect(0, 0, mapWidth, mapHeight); - g.endFill(); - if (contentSize) { - width = mapWidth; - height = mapHeight; - } - layersForUpdate[backgroundLayer] = false; - } - } - - private function drawMap(game:Engine):Void { - if (layersForUpdate[groundLayer] || layersForUpdate[upLayer]) { - groundLayer.graphics.clear(); - upLayer.graphics.clear(); - for (brick in game.map.bricks) if (!brick.destroyed) { - var g:Graphics = null; - if (brick.config.layer < 3) { - g = groundLayer.graphics; - } else if (brick.config.layer >= 3) { - g = upLayer.graphics; - } - if (g != null) { - g.beginBitmapFill(Assets.getBitmapData('resources/images/map/map_${brick.config.type}.png')); - g.drawRect( - brick.rect.x, - brick.rect.y, - brick.rect.width, - brick.rect.height - ); - for (cell in brick.cells.iterator()) { - if (cell.destroyed) { - g.beginFill(0x000000); - g.drawRect( - cell.rect.x, - cell.rect.y, - cell.rect.width, - cell.rect.height - ); - } - } - g.endFill(); - } - } - - // Debug cells - /*var g = groundLayer.graphics; - for (c in game.map.grid.cells.iterator()) { - var color:Int = 0x000000; - if (c.armor == 1) { - color = 0xffcc00; - } else if (c.armor > 1) { - color = 0x606060; - } else if (c.layer == 0) { - color = 0xffff90; - } else if (c.layer == 1) { - color = 0x0000ff; - }else if (c.layer > 1) { - color = 0x00ff00; - } - g.beginFill(color); - g.drawRect(c.rect.x, c.rect.y, c.rect.width, c.rect.height); - g.endFill(); - } - layersForUpdate[groundLayer] = false; - layersForUpdate[upLayer] = false;*/ - } - } - - public function drawEntities(game:Engine):Void { - if (layersForUpdate[entryLayer]) { - var g:Graphics = entryLayer.graphics; - g.clear(); - for (ent in game.entities) { - var image:String = null; - if (Std.is(ent, Tank)) { - var tank:Tank = cast ent; - image = 'resources/images/tank/${tank.config.group}/tank_${tank.config.group.charAt(0)}${tank.config.type}_${tank.index}-0.png'; - } else if (Std.is(ent, Bullet)) { - var bullet:Bullet = cast ent; - image = 'resources/images/bullet/bullet_${bullet.config.piercing > 1 ? 1 : 0}.png'; - } else { - image = 'ERROR'; // ToDo: - } - var m = new Matrix(); - if (Std.is(ent, MobileEntity)) { - m.rotate(calcRotate(cast(ent, MobileEntity).direction)); - } - m.translate(ent.rect.x, ent.rect.y); - g.beginBitmapFill(Assets.getBitmapData(image), m, true, true); - g.drawRect(ent.rect.x, ent.rect.y, ent.rect.width, ent.rect.height); - g.endFill(); - } - layersForUpdate[entryLayer] = false; + var g:Graphics = backgroundLayer.graphics; + g.clear(); + g.beginFill(0x000000); + g.drawRect(0, 0, mapWidth, mapHeight); + g.endFill(); + if (contentSize) { + width = mapWidth; + height = mapHeight; } } public function draw(game:Engine):Void { - invalidateLayers(game); - drawBackground(game); - drawMap(game); - drawEntities(game); + for (brick in game.map.bricks) { + if (!items.exists(brick.key)) { + items[brick.key] = new BrickItem(brick); + if (brick.config.layer > 2) { + upLayer.addChild(items[brick.key].view); + } else { + groundLayer.addChild(items[brick.key].view); + } + } + } + for (entity in game.entities) { + if (!items.exists(entity.key)) { + items[entity.key] = switch (Type.typeof(entity)) { + case ValueType.TClass(Tank): cast new TankItem(cast entity); + case ValueType.TClass(Bullet): cast new BulletItem(cast entity); + case x: null; + } + entryLayer.addChild(items[entity.key].view); + } + } + for (key in game.removedEntities) { + if (items.exists(key)) { + var view:DisplayObject = items[key].view; + view.parent.removeChild(view); + items.remove(key); + } + } + for (item in items) { + item.update(); + } + if (background == null) { + drawBackground(game); + } } public function reset():Void { - states = new Map>(); - layersForUpdate[backgroundLayer] = true; - } - - private function calcRotate(direction:Direction):Float { - return (if (direction == Direction.RIGHT) { - 0; - } else if (direction == Direction.LEFT) { - 180; - } else if (direction == Direction.TOP) { - 270; - } else if (direction == Direction.BOTTOM) { - 90; - } else { - 0; - }) * (Math.PI / 180); + items = new Map>(); + if (background != null) { + backgroundLayer.removeChild(background); + background = null; + } } } diff --git a/src/client/haxe/ru/m/tankz/render/RenderItem.hx b/src/client/haxe/ru/m/tankz/render/RenderItem.hx new file mode 100644 index 0000000..290fbfc --- /dev/null +++ b/src/client/haxe/ru/m/tankz/render/RenderItem.hx @@ -0,0 +1,131 @@ +package ru.m.tankz.render; + +import flash.display.DisplayObject; +import flash.display.Shape; +import ru.m.geom.Direction; +import ru.m.geom.Rectangle; +import ru.m.tankz.core.Bullet; +import ru.m.tankz.map.Brick; +import openfl.Assets; +import ru.m.tankz.core.Tank; +import flash.display.Bitmap; + + +typedef TRectangle = { + var rect(default, null):Rectangle; +} + + +class RenderItem { + + public var value(default, null):T; + public var view(default, null):DisplayObject; + + private var bitmap:Bitmap; + + public function new(value:T) { + this.value = value; + this.bitmap = new Bitmap(); + this.view = bitmap; + redraw(); + } + + public function redraw():Void { + bitmap.bitmapData = Assets.getBitmapData(getImage()); + } + + public function update():Void { + var rect = value.rect; + view.rotation = calcRotate(rect.direction); + view.x = rect.x - rect.width * (rect.direction.x + 1) / 2 + rect.width * (rect.direction.y + 1) / 2 + 0.5 * rect.width; + view.y = rect.y - rect.height * (rect.direction.x + 1) / 2 - rect.height * (rect.direction.y + 1) / 2 + 1.5 * rect.height; + } + + private function getImage():String { + return 'ERROR'; + } + + private static function calcRotate(direction:Direction):Float { + return (if (direction == Direction.RIGHT) { + 0; + } else if (direction == Direction.LEFT) { + 180; + } else if (direction == Direction.TOP) { + 270; + } else if (direction == Direction.BOTTOM) { + 90; + } else { + 0; + }); + } +} + + +class BrickItem extends RenderItem { + + private var shape:Shape; + private var broken:Int; + + public function new(value:Brick) { + this.shape = new Shape(); + super(value); + this.view = shape; + } + + override public function redraw():Void { + var image = Assets.getBitmapData(getImage()); + var g = shape.graphics; + g.clear(); + if (value.destroyed) return; + g.beginBitmapFill(image); + g.drawRect(0, 0, value.rect.width, value.rect.height); + for (c in value.cells) { + if (c.destroyed) { + g.beginFill(0x000000); + g.drawRect(c.rect.x - value.rect.x, c.rect.y - value.rect.y, c.rect.width, c.rect.height); + } + } + g.endFill(); + } + + override public function update():Void { + super.update(); + var b = value.broken; + if (b != this.broken) { + this.broken = b; + redraw(); + } + } + + override private function getImage():String { + return 'resources/images/map/map_${value.config.type}.png'; + } +} + + + +class TankItem extends RenderItem { + + private var type:Int; + + override private function getImage():String { + return 'resources/images/tank/${value.config.group}/tank_${value.config.group.charAt(0)}${value.config.type}_${value.index}-0.png'; + } + + override public function update():Void { + super.update(); + var t = value.config.type; + if (t != this.type) { + this.type = t; + redraw(); + } + } +} + + +class BulletItem extends RenderItem { + + override private function getImage():String { + return 'resources/images/bullet/bullet_${value.config.piercing > 1 ? 1 : 0}.png'; + } +} 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 df0cb27..943483d 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -1,5 +1,6 @@ package ru.m.tankz.view.frames; +import haxe.Timer; import ru.m.tankz.config.ConfigBundle; import ru.m.tankz.proto.core.GameType; import ru.m.tankz.proto.core.Game; @@ -23,6 +24,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand private var engine:Engine; private var controls:Map; + private var timer:Timer; public function init():Void { engine = new Engine(); @@ -33,24 +35,33 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand var game:Game = Provider.get(Game); engine.init(ConfigBundle.get(GameType.CLASSIC, 0)); engine.initTanks(game.players); - content.addEventListener(Event.ENTER_FRAME, updateGame); + content.addEventListener(Event.ENTER_FRAME, redraw); for (index in 0...game.players.length) { var playerId:Int = game.players[index].id; controls.set(playerId, PlayerControl.forPlayer(index, playerId, engine)); } Provider.get(IConnection).packetHandler.addListener(this); render.draw(engine); + timer = new Timer(10); + timer.run = updateEngine; } public function onHide():Void { Provider.get(IConnection).packetHandler.removeListener(this); - content.removeEventListener(Event.ENTER_FRAME, updateGame); + if (timer != null) { + timer.stop(); + timer = null; + } + content.removeEventListener(Event.ENTER_FRAME, redraw); engine.clear(); render.reset(); } - private function updateGame(_):Void { + private function updateEngine():Void { engine.update(); + } + + private function redraw(_):Void { render.draw(engine); } diff --git a/src/common/haxe/ru/m/tankz/core/MobileEntity.hx b/src/common/haxe/ru/m/tankz/core/MobileEntity.hx index 0d7f963..db470a2 100755 --- a/src/common/haxe/ru/m/tankz/core/MobileEntity.hx +++ b/src/common/haxe/ru/m/tankz/core/MobileEntity.hx @@ -10,24 +10,21 @@ class MobileEntity extends Entity { public var layer(default, null):Int; public var speed(default, null):Float; - public var direction(default, default):Direction; public function new(rect:Rectangle, speed:Float, direction:Direction) { super(rect); this.speed = speed; - this.direction = direction; this.layer = 0; this.mx = 0; this.my = 0; } public function move(direction:Direction):Void { - if (this.direction != direction) { + if (this.rect.direction != direction) { this.rect.direction = direction; - this.direction = direction; } - mx = direction.x * speed; - my = direction.y * speed; + mx = rect.direction.x * speed; + my = rect.direction.y * speed; } public function stop():Void { diff --git a/src/common/haxe/ru/m/tankz/core/Tank.hx b/src/common/haxe/ru/m/tankz/core/Tank.hx index ebefd36..7dab410 100755 --- a/src/common/haxe/ru/m/tankz/core/Tank.hx +++ b/src/common/haxe/ru/m/tankz/core/Tank.hx @@ -28,8 +28,9 @@ class Tank extends MobileEntity { } private function set_config(value:TankConfig):TankConfig { + var d = rect.direction; rect = new Rectangle(rect.x, rect.y, value.width, value.height); - rect.direction = direction; + rect.direction = d; speed = value.speed; config = value; return value; @@ -38,8 +39,8 @@ class Tank extends MobileEntity { public function shot():Null { if (bulletsCounter >= config.bullets) return null; var bullet = new Bullet(id, config, config.bullet); - bullet.rect.center = rect.center.add(new Point(rect.width / 4 * direction.x, rect.height / 4 * direction.y)); - bullet.move(direction); + bullet.rect.center = rect.center.add(new Point(rect.width / 4 * rect.direction.x, rect.height / 4 * rect.direction.y)); + bullet.move(rect.direction); bulletsCounter++; return bullet; } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 43063d7..35471e5 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -39,7 +39,7 @@ class Engine { private function buildTank(index:Int, config:TankConfig, point:SpawnPoint):Tank { var tank = new Tank(index, config); tank.rect.center = new Point((point.x + 1) * map.cellWidth, (point.y + 1) * map.cellHeight); - tank.direction = Direction.fromString(point.direction); + tank.rect.direction = Direction.fromString(point.direction); return tank; } @@ -66,8 +66,8 @@ class Engine { .setObjectId(tank.id) .setX(tank.rect.x) .setY(tank.rect.y) - .setDirectionX(tank.direction.x) - .setDirectionY(tank.direction.y) + .setDirectionX(tank.rect.direction.x) + .setDirectionY(tank.rect.direction.y) ); } @@ -214,7 +214,7 @@ class Engine { } for (other in entities.iterator()) { - if (other != ent) { + if (other != ent && other != null) { if (other.rect.intersection2(side)) { //if (ent.rect.intersection(other.rect)) { var funName = 'collision${ent.type}${other.type}'; diff --git a/src/common/haxe/ru/m/tankz/map/Brick.hx b/src/common/haxe/ru/m/tankz/map/Brick.hx index 094e784..d94fcd5 100644 --- a/src/common/haxe/ru/m/tankz/map/Brick.hx +++ b/src/common/haxe/ru/m/tankz/map/Brick.hx @@ -24,6 +24,7 @@ class Brick implements IKey { public var rect(default, null):Rectangle; public var cells(default, null):HashMap; + public var broken(get, null):Int; public var destroyed(get, set):Bool; public function new(mapConfig:MapConfig, config:BrickConfig, cellX:Int, cellY:Int, cells:HashMap) { @@ -40,6 +41,16 @@ class Brick implements IKey { ); } + public function get_broken():Int { + var i:Int = 0; + for (c in cells.iterator()) { + if (c.destroyed) { + i++; + } + } + return i; + } + public function get_destroyed():Bool { var i = 0; var result:Bool = false; From b9e3eba1fd3009766c8792f18857f86b721c2782 Mon Sep 17 00:00:00 2001 From: shmyga Date: Thu, 18 Jan 2018 15:58:18 +0300 Subject: [PATCH 02/22] [bot] added --- .../haxe/ru/m/tankz/core/PlayerControl.hx | 14 ++--- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 2 +- src/common/haxe/ru/m/tankz/bot/Bot.hx | 54 +++++++++++++++++++ src/common/haxe/ru/m/tankz/engine/Engine.hx | 40 +++++++++++--- 4 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 src/common/haxe/ru/m/tankz/bot/Bot.hx diff --git a/src/client/haxe/ru/m/tankz/core/PlayerControl.hx b/src/client/haxe/ru/m/tankz/core/PlayerControl.hx index cb5be6d..8630501 100644 --- a/src/client/haxe/ru/m/tankz/core/PlayerControl.hx +++ b/src/client/haxe/ru/m/tankz/core/PlayerControl.hx @@ -12,14 +12,14 @@ import flash.Lib; class PlayerControl { private var engine:Engine; - private var id:Int; + private var tankId:Int; private var keyBinding:Map; private var moveQueue:Array; private var shotTimer:Timer; - public function new(id:Int, engine:Engine, keyBinding:Map) { - this.id = id; + public function new(tankId:Int, engine:Engine, keyBinding:Map) { + this.tankId = tankId; this.engine = engine; this.keyBinding = keyBinding; moveQueue = new Array(); @@ -44,7 +44,7 @@ class PlayerControl { case _: } if (event.keyCode == Keyboard.U) { - engine.action(id, TankAction.LEVEL_UP(1)); + engine.action(tankId, TankAction.LEVEL_UP(1)); } } @@ -69,18 +69,18 @@ class PlayerControl { private function updateMove():Void { if (moveQueue.length == 0) { - engine.action(id, TankAction.STOP); + engine.action(tankId, TankAction.STOP); } else { switch (keyBinding.get(moveQueue[0])) { case TankAction.MOVE(direction): - engine.action(id, TankAction.MOVE(direction)); + engine.action(tankId, TankAction.MOVE(direction)); case _: } } } private function shot():Void { - engine.action(id, TankAction.SHOT); + engine.action(tankId, TankAction.SHOT); } public static function forPlayer(index:Int, tankId:Int, engine:Engine):PlayerControl { 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 943483d..b086fc6 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -38,7 +38,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand content.addEventListener(Event.ENTER_FRAME, redraw); for (index in 0...game.players.length) { var playerId:Int = game.players[index].id; - controls.set(playerId, PlayerControl.forPlayer(index, playerId, engine)); + controls.set(engine.playerTanks.get(playerId).id, PlayerControl.forPlayer(index, playerId, engine)); } Provider.get(IConnection).packetHandler.addListener(this); render.draw(engine); diff --git a/src/common/haxe/ru/m/tankz/bot/Bot.hx b/src/common/haxe/ru/m/tankz/bot/Bot.hx new file mode 100644 index 0000000..736e700 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/bot/Bot.hx @@ -0,0 +1,54 @@ +package ru.m.tankz.bot; + +import ru.m.geom.Direction; +import haxe.Timer; +import ru.m.tankz.map.Grid.GridCell; +import ru.m.tankz.core.Tank; +import Type.ValueType; +import ru.m.tankz.core.Entity; +import ru.m.tankz.engine.Engine; + +class Bot implements EngineListener { + + public var tankId(default, null):Int; + private var engine:Engine; + + private var shotTimer:Timer; + + public function new(engine:Engine, tankId:Int) { + this.engine = engine; + this.tankId = tankId; + } + + public function onCollision(entity:Entity, with:Dynamic):Void { + if (entity.id == tankId) { + switch (Type.typeof(with)) { + case ValueType.TClass(Tank): turn(); + case ValueType.TClass(GridCell): turn(); + case _: + } + } + } + + public function start():Void { + engine.action(tankId, TankAction.MOVE(Direction.BOTTOM)); + shotTimer = new Timer(1000); + shotTimer.run = shot; + } + + public function shot():Void { + engine.action(tankId, TankAction.SHOT); + } + + public function turn():Void { + engine.action(tankId, TankAction.MOVE(Direction.TOP)); + } + + public function dispose():Void { + if (shotTimer != null) { + shotTimer.stop(); + shotTimer = null; + } + engine = null; + } +} diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 35471e5..9c88737 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -1,8 +1,7 @@ package ru.m.tankz.engine; -import haxe.macro.Type.Ref; +import ru.m.tankz.bot.Bot; import haxe.Constraints.Function; -import ru.m.geom.Rectangle; import ru.m.geom.Line; import ru.m.tankz.core.MobileEntity; import ru.m.tankz.core.Entity; @@ -27,13 +26,20 @@ class Engine { public var entities(default, null):Map; public var removedEntities(default, null):Array; - private var playerTanks(default, null):Map; + public var playerTanks(default, null):Map; private var time:Float; - public function new() {} + public var listeners(default, null):Array; + + private var bots:Map; + + public function new() { + listeners = []; + } public function clear():Void { playerTanks = new Map(); + bots = new Map(); } private function buildTank(index:Int, config:TankConfig, point:SpawnPoint):Tank { @@ -47,6 +53,7 @@ class Engine { this.config = config; map = new LevelMap(config.map); playerTanks = new Map(); + bots = new Map(); entities = new Map(); removedEntities = new Array(); time = Date.now().getTime(); @@ -75,12 +82,16 @@ class Engine { var point:SpawnPoint = config.getSpawnPoint(EntityType.BOT, index); var tank = buildTank(0, config.getTank('bot', 0), point); entities.set(tank.id, tank); + var bot = new Bot(this, tank.id); + bots.set(tank.id, bot); + listeners.push(bot); + bot.start(); } return changes; } - public function action(playerId:Int, action:TankAction):Void { - var tank:Tank = playerTanks.get(playerId); + public function action(tankId:Int, action:TankAction):Void { + var tank:Tank = cast entities.get(tankId); switch (action) { case TankAction.MOVE(direction): tank.move(direction); @@ -176,6 +187,12 @@ class Engine { tank.onDestroyBullet(); } } + if (bots.exists(entity.id)) { + var bot:Bot = bots.get(entity.id); + bot.dispose(); + listeners.remove(bot); + bots.remove(entity.id); + } } public function update():Array { @@ -209,6 +226,7 @@ class Engine { if (cell.layer >= entity.layer && cell.layer < 3) { entity.rect.lean(cell.rect); collision = true; + for (listener in listeners) listener.onCollision(ent, cell); break; } } @@ -220,7 +238,11 @@ class Engine { var funName = 'collision${ent.type}${other.type}'; var fun:Function = Reflect.field(this, funName); if (fun != null) { - collision = Reflect.callMethod(this, fun, [ent, other]) || collision; + var c = Reflect.callMethod(this, fun, [ent, other]); + if (c) { + for (listener in listeners) listener.onCollision(ent, other); + } + collision = c || collision; } } } @@ -256,3 +278,7 @@ class Engine { return changes; } } + +interface EngineListener { + public function onCollision(entity:Entity, with:Dynamic):Void; +} \ No newline at end of file From 5915f315edd8b79e0cb5e88d1f93f2307194c33a Mon Sep 17 00:00:00 2001 From: shmyga Date: Thu, 18 Jan 2018 22:29:50 +0300 Subject: [PATCH 03/22] [bot] fixes --- package.json | 2 +- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 3 ++- src/common/haxe/ru/m/tankz/bot/Bot.hx | 18 +++++++++++++++++- src/common/haxe/ru/m/tankz/engine/Engine.hx | 3 ++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d59f69b..ea8da24 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tankz", - "version": "0.0.6", + "version": "0.0.7", "private": true, "devDependencies": { "ansi-colors": "^1.0.1", 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 b086fc6..c7e4ebd 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -38,7 +38,8 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand content.addEventListener(Event.ENTER_FRAME, redraw); for (index in 0...game.players.length) { var playerId:Int = game.players[index].id; - controls.set(engine.playerTanks.get(playerId).id, PlayerControl.forPlayer(index, playerId, engine)); + var tankId:Int = engine.playerTanks.get(playerId).id; + controls.set(tankId, PlayerControl.forPlayer(index, tankId, engine)); } Provider.get(IConnection).packetHandler.addListener(this); render.draw(engine); diff --git a/src/common/haxe/ru/m/tankz/bot/Bot.hx b/src/common/haxe/ru/m/tankz/bot/Bot.hx index 736e700..00e3f35 100644 --- a/src/common/haxe/ru/m/tankz/bot/Bot.hx +++ b/src/common/haxe/ru/m/tankz/bot/Bot.hx @@ -14,6 +14,7 @@ class Bot implements EngineListener { private var engine:Engine; private var shotTimer:Timer; + private var turnTimer:Timer; public function new(engine:Engine, tankId:Int) { this.engine = engine; @@ -34,6 +35,8 @@ class Bot implements EngineListener { engine.action(tankId, TankAction.MOVE(Direction.BOTTOM)); shotTimer = new Timer(1000); shotTimer.run = shot; + turnTimer = new Timer(3000); + turnTimer.run = turn; } public function shot():Void { @@ -41,7 +44,16 @@ class Bot implements EngineListener { } public function turn():Void { - engine.action(tankId, TankAction.MOVE(Direction.TOP)); + engine.action(tankId, TankAction.MOVE(randomDirection())); + } + + private function randomDirection():Direction { + return [ + Direction.TOP, + Direction.BOTTOM, + Direction.LEFT, + Direction.RIGHT, + ][Math.floor(Math.random() * 4)]; } public function dispose():Void { @@ -49,6 +61,10 @@ class Bot implements EngineListener { shotTimer.stop(); shotTimer = null; } + if (turnTimer != null) { + turnTimer.stop(); + turnTimer = null; + } engine = null; } } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 9c88737..d36b537 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -91,6 +91,7 @@ class Engine { } public function action(tankId:Int, action:TankAction):Void { + if (!entities.exists(tankId)) return; var tank:Tank = cast entities.get(tankId); switch (action) { case TankAction.MOVE(direction): @@ -184,7 +185,7 @@ class Engine { removedEntities.push(entity.key); if (Std.is(entity, Bullet)) { var tank:Tank = cast entities.get(cast(entity, Bullet).tankId); - tank.onDestroyBullet(); + if (tank != null) tank.onDestroyBullet(); } } if (bots.exists(entity.id)) { From f1bb6514adca61477e459f0bbc83fbf163763a4d Mon Sep 17 00:00:00 2001 From: shmyga Date: Sat, 20 Jan 2018 12:47:05 +0300 Subject: [PATCH 04/22] [common] added control --- .../tankz/{core => control}/PlayerControl.hx | 29 +++++------ .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 6 +-- src/common/haxe/ru/m/tankz/bot/Bot.hx | 34 ++++++------- src/common/haxe/ru/m/tankz/control/Control.hx | 44 +++++++++++++++++ src/common/haxe/ru/m/tankz/core/Tank.hx | 18 +------ src/common/haxe/ru/m/tankz/engine/Engine.hx | 48 +++++++++---------- 6 files changed, 97 insertions(+), 82 deletions(-) rename src/client/haxe/ru/m/tankz/{core => control}/PlayerControl.hx (79%) create mode 100644 src/common/haxe/ru/m/tankz/control/Control.hx diff --git a/src/client/haxe/ru/m/tankz/core/PlayerControl.hx b/src/client/haxe/ru/m/tankz/control/PlayerControl.hx similarity index 79% rename from src/client/haxe/ru/m/tankz/core/PlayerControl.hx rename to src/client/haxe/ru/m/tankz/control/PlayerControl.hx index 8630501..96923ca 100644 --- a/src/client/haxe/ru/m/tankz/core/PlayerControl.hx +++ b/src/client/haxe/ru/m/tankz/control/PlayerControl.hx @@ -1,26 +1,21 @@ -package ru.m.tankz.core; +package ru.m.tankz.control; +import ru.m.tankz.control.Control; import haxe.Timer; import ru.m.geom.Direction; import flash.events.FocusEvent; import flash.ui.Keyboard; -import ru.m.tankz.engine.Engine; -import ru.m.tankz.core.Tank.TankAction; import flash.events.KeyboardEvent; import flash.Lib; -class PlayerControl { - - private var engine:Engine; - private var tankId:Int; +class PlayerControl extends Control { private var keyBinding:Map; private var moveQueue:Array; private var shotTimer:Timer; - public function new(tankId:Int, engine:Engine, keyBinding:Map) { - this.tankId = tankId; - this.engine = engine; + public function new(tankId:Int, keyBinding:Map) { + super(tankId); this.keyBinding = keyBinding; moveQueue = new Array(); Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); @@ -44,7 +39,7 @@ class PlayerControl { case _: } if (event.keyCode == Keyboard.U) { - engine.action(tankId, TankAction.LEVEL_UP(1)); + action(TankAction.LEVEL_UP(1)); } } @@ -69,24 +64,24 @@ class PlayerControl { private function updateMove():Void { if (moveQueue.length == 0) { - engine.action(tankId, TankAction.STOP); + action(TankAction.STOP); } else { switch (keyBinding.get(moveQueue[0])) { case TankAction.MOVE(direction): - engine.action(tankId, TankAction.MOVE(direction)); + action(TankAction.MOVE(direction)); case _: } } } private function shot():Void { - engine.action(tankId, TankAction.SHOT); + action(TankAction.SHOT); } - public static function forPlayer(index:Int, tankId:Int, engine:Engine):PlayerControl { + public static function forPlayer(index:Int, tankId:Int):PlayerControl { switch (index) { case 0: - return new PlayerControl(tankId, engine, [ + return new PlayerControl(tankId, [ Keyboard.A => TankAction.MOVE(Direction.LEFT), Keyboard.S => TankAction.MOVE(Direction.BOTTOM), Keyboard.W => TankAction.MOVE(Direction.TOP), @@ -94,7 +89,7 @@ class PlayerControl { Keyboard.SPACE => TankAction.SHOT ]); case 1: - return new PlayerControl(tankId, engine, [ + return new PlayerControl(tankId, [ Keyboard.LEFT => TankAction.MOVE(Direction.LEFT), Keyboard.DOWN => TankAction.MOVE(Direction.BOTTOM), Keyboard.UP => TankAction.MOVE(Direction.TOP), 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 c7e4ebd..ede9f0c 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -4,7 +4,7 @@ import haxe.Timer; import ru.m.tankz.config.ConfigBundle; import ru.m.tankz.proto.core.GameType; import ru.m.tankz.proto.core.Game; -import ru.m.tankz.core.PlayerControl; +import ru.m.tankz.control.PlayerControl; import ru.m.tankz.engine.Engine; import protohx.Message; import ru.m.tankz.proto.pack.GameUpdateResponse; @@ -23,12 +23,10 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand public static inline var ID = "game"; private var engine:Engine; - private var controls:Map; private var timer:Timer; public function init():Void { engine = new Engine(); - controls = new Map(); } public function onShow():Void { @@ -39,7 +37,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand for (index in 0...game.players.length) { var playerId:Int = game.players[index].id; var tankId:Int = engine.playerTanks.get(playerId).id; - controls.set(tankId, PlayerControl.forPlayer(index, tankId, engine)); + engine.bindControl(PlayerControl.forPlayer(index, tankId)); } Provider.get(IConnection).packetHandler.addListener(this); render.draw(engine); diff --git a/src/common/haxe/ru/m/tankz/bot/Bot.hx b/src/common/haxe/ru/m/tankz/bot/Bot.hx index 00e3f35..babcae1 100644 --- a/src/common/haxe/ru/m/tankz/bot/Bot.hx +++ b/src/common/haxe/ru/m/tankz/bot/Bot.hx @@ -1,38 +1,32 @@ package ru.m.tankz.bot; +import ru.m.tankz.control.Control; import ru.m.geom.Direction; import haxe.Timer; import ru.m.tankz.map.Grid.GridCell; import ru.m.tankz.core.Tank; import Type.ValueType; -import ru.m.tankz.core.Entity; -import ru.m.tankz.engine.Engine; -class Bot implements EngineListener { - public var tankId(default, null):Int; - private var engine:Engine; +class Bot extends Control { private var shotTimer:Timer; private var turnTimer:Timer; - public function new(engine:Engine, tankId:Int) { - this.engine = engine; - this.tankId = tankId; + public function new(tankId:Int) { + super(tankId); } - public function onCollision(entity:Entity, with:Dynamic):Void { - if (entity.id == tankId) { - switch (Type.typeof(with)) { - case ValueType.TClass(Tank): turn(); - case ValueType.TClass(GridCell): turn(); - case _: - } + override public function onCollision(with:Dynamic):Void { + switch (Type.typeof(with)) { + case ValueType.TClass(Tank): turn(); + case ValueType.TClass(GridCell): turn(); + case _: } } public function start():Void { - engine.action(tankId, TankAction.MOVE(Direction.BOTTOM)); + action(TankAction.MOVE(Direction.BOTTOM)); shotTimer = new Timer(1000); shotTimer.run = shot; turnTimer = new Timer(3000); @@ -40,11 +34,11 @@ class Bot implements EngineListener { } public function shot():Void { - engine.action(tankId, TankAction.SHOT); + action(TankAction.SHOT); } public function turn():Void { - engine.action(tankId, TankAction.MOVE(randomDirection())); + action(TankAction.MOVE(randomDirection())); } private function randomDirection():Direction { @@ -56,7 +50,8 @@ class Bot implements EngineListener { ][Math.floor(Math.random() * 4)]; } - public function dispose():Void { + override public function dispose():Void { + super.dispose(); if (shotTimer != null) { shotTimer.stop(); shotTimer = null; @@ -65,6 +60,5 @@ class Bot implements EngineListener { turnTimer.stop(); turnTimer = null; } - engine = null; } } diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx new file mode 100644 index 0000000..3abb1f0 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -0,0 +1,44 @@ +package ru.m.tankz.control; + +import ru.m.geom.Direction; + + +enum TankAction { + MOVE(direction:Direction); + LEVEL_UP(level:Int); + STOP; + SHOT; +} + + +class Control { + public var tankId(default, null):Int; + private var listener:ControlListener; + + public function new(tankId:Int) { + this.tankId = tankId; + } + + public function bind(listener:ControlListener):Void { + this.listener = listener; + } + + public function action(action:TankAction):Void { + if (listener != null) { + listener.onAction(tankId, action); + } + } + + public function onCollision(with:Dynamic):Void { + + } + + + public function dispose():Void { + listener = null; + } +} + +interface ControlListener { + public function onAction(tankId:Int, action:TankAction):Void; +} diff --git a/src/common/haxe/ru/m/tankz/core/Tank.hx b/src/common/haxe/ru/m/tankz/core/Tank.hx index 7dab410..f3cf48e 100755 --- a/src/common/haxe/ru/m/tankz/core/Tank.hx +++ b/src/common/haxe/ru/m/tankz/core/Tank.hx @@ -1,19 +1,12 @@ package ru.m.tankz.core; import ru.m.geom.Point; -import ru.m.tankz.config.Config.TankConfig; +import ru.m.tankz.config.Config; import ru.m.tankz.core.Bullet; import ru.m.geom.Rectangle; import ru.m.geom.Direction; -enum TankAction { - MOVE(direction:Direction); - LEVEL_UP(level:Int); - STOP; - SHOT; -} - class Tank extends MobileEntity { public var index(default, null):Int; public var config(default, set):TankConfig; @@ -45,15 +38,6 @@ class Tank extends MobileEntity { return bullet; } - override public function move(direction:Direction):Void { - // ToDo: spike - /*if (direction != this.direction) { - rect.x -= this.direction.x * 4; - rect.y -= this.direction.y * 4; - }*/ - super.move(direction); - } - public function onDestroyBullet():Void { bulletsCounter--; } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index d36b537..5660e73 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -1,5 +1,6 @@ package ru.m.tankz.engine; +import ru.m.tankz.control.Control; import ru.m.tankz.bot.Bot; import haxe.Constraints.Function; import ru.m.geom.Line; @@ -18,7 +19,7 @@ import ru.m.tankz.core.Tank; import ru.m.tankz.map.LevelMap; -class Engine { +class Engine implements ControlListener { public var config(default, default):Config; public var map(default, null):LevelMap; @@ -29,17 +30,13 @@ class Engine { public var playerTanks(default, null):Map; private var time:Float; - public var listeners(default, null):Array; + private var controls:Map; - private var bots:Map; - - public function new() { - listeners = []; - } + public function new() {} public function clear():Void { playerTanks = new Map(); - bots = new Map(); + controls = new Map(); } private function buildTank(index:Int, config:TankConfig, point:SpawnPoint):Tank { @@ -53,7 +50,7 @@ class Engine { this.config = config; map = new LevelMap(config.map); playerTanks = new Map(); - bots = new Map(); + controls = new Map(); entities = new Map(); removedEntities = new Array(); time = Date.now().getTime(); @@ -82,15 +79,19 @@ class Engine { var point:SpawnPoint = config.getSpawnPoint(EntityType.BOT, index); var tank = buildTank(0, config.getTank('bot', 0), point); entities.set(tank.id, tank); - var bot = new Bot(this, tank.id); - bots.set(tank.id, bot); - listeners.push(bot); + var bot = new Bot(tank.id); + bindControl(bot); bot.start(); } return changes; } - public function action(tankId:Int, action:TankAction):Void { + public function bindControl(control:Control):Void { + control.bind(this); + controls.set(control.tankId, control); + } + + public function onAction(tankId:Int, action:TankAction):Void { if (!entities.exists(tankId)) return; var tank:Tank = cast entities.get(tankId); switch (action) { @@ -188,11 +189,10 @@ class Engine { if (tank != null) tank.onDestroyBullet(); } } - if (bots.exists(entity.id)) { - var bot:Bot = bots.get(entity.id); - bot.dispose(); - listeners.remove(bot); - bots.remove(entity.id); + if (controls.exists(entity.id)) { + var control:Control = controls.get(entity.id); + control.dispose(); + controls.remove(entity.id); } } @@ -227,7 +227,9 @@ class Engine { if (cell.layer >= entity.layer && cell.layer < 3) { entity.rect.lean(cell.rect); collision = true; - for (listener in listeners) listener.onCollision(ent, cell); + if (controls.exists(entity.id)) { + controls.get(entity.id).onCollision(cell); + } break; } } @@ -241,7 +243,9 @@ class Engine { if (fun != null) { var c = Reflect.callMethod(this, fun, [ent, other]); if (c) { - for (listener in listeners) listener.onCollision(ent, other); + if (controls.exists(entity.id)) { + controls.get(entity.id).onCollision(other); + } } collision = c || collision; } @@ -279,7 +283,3 @@ class Engine { return changes; } } - -interface EngineListener { - public function onCollision(entity:Entity, with:Dynamic):Void; -} \ No newline at end of file From a4558aa2f2d2df64bb28086c47bef3401f7e567f Mon Sep 17 00:00:00 2001 From: shmyga Date: Sun, 21 Jan 2018 21:09:55 +0300 Subject: [PATCH 05/22] [common] added game package --- WORK.md | 13 +- .../haxe/ru/m/tankz/control/PlayerControl.hx | 10 +- src/client/haxe/ru/m/tankz/render/Render.hx | 4 +- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 42 ++- src/common/haxe/ru/m/tankz/config/Config.hx | 12 +- .../haxe/ru/m/tankz/config/ConfigBundle.hx | 6 +- src/common/haxe/ru/m/tankz/control/Control.hx | 8 +- src/common/haxe/ru/m/tankz/core/Eagle.hx | 11 + src/common/haxe/ru/m/tankz/core/EntityType.hx | 26 ++ src/common/haxe/ru/m/tankz/engine/Engine.hx | 278 ++++++------------ .../haxe/ru/m/tankz/game/ClassicGame.hx | 13 + src/common/haxe/ru/m/tankz/game/Game.hx | 69 +++++ src/common/haxe/ru/m/tankz/player/Player.hx | 14 + 13 files changed, 272 insertions(+), 234 deletions(-) create mode 100644 src/common/haxe/ru/m/tankz/core/Eagle.hx create mode 100644 src/common/haxe/ru/m/tankz/core/EntityType.hx create mode 100644 src/common/haxe/ru/m/tankz/game/ClassicGame.hx create mode 100644 src/common/haxe/ru/m/tankz/game/Game.hx create mode 100644 src/common/haxe/ru/m/tankz/player/Player.hx diff --git a/WORK.md b/WORK.md index 82368e4..eaba624 100644 --- a/WORK.md +++ b/WORK.md @@ -20,6 +20,12 @@ * bonuses 0% * eagle 0% +* game + * classic + * state 0% + * bot 5% + * player: 50% + * render * map 100% * tanks 100% @@ -34,6 +40,7 @@ * proto -* common - * bot 0% - * single game 20% \ No newline at end of file + +* webapp + * angular app 0% + * google analytics 0% \ No newline at end of file diff --git a/src/client/haxe/ru/m/tankz/control/PlayerControl.hx b/src/client/haxe/ru/m/tankz/control/PlayerControl.hx index 96923ca..f9b96c1 100644 --- a/src/client/haxe/ru/m/tankz/control/PlayerControl.hx +++ b/src/client/haxe/ru/m/tankz/control/PlayerControl.hx @@ -14,8 +14,8 @@ class PlayerControl extends Control { private var moveQueue:Array; private var shotTimer:Timer; - public function new(tankId:Int, keyBinding:Map) { - super(tankId); + public function new(keyBinding:Map) { + super(); this.keyBinding = keyBinding; moveQueue = new Array(); Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); @@ -78,10 +78,10 @@ class PlayerControl extends Control { action(TankAction.SHOT); } - public static function forPlayer(index:Int, tankId:Int):PlayerControl { + public static function forPlayer(index:Int):PlayerControl { switch (index) { case 0: - return new PlayerControl(tankId, [ + return new PlayerControl([ Keyboard.A => TankAction.MOVE(Direction.LEFT), Keyboard.S => TankAction.MOVE(Direction.BOTTOM), Keyboard.W => TankAction.MOVE(Direction.TOP), @@ -89,7 +89,7 @@ class PlayerControl extends Control { Keyboard.SPACE => TankAction.SHOT ]); case 1: - return new PlayerControl(tankId, [ + return new PlayerControl([ Keyboard.LEFT => TankAction.MOVE(Direction.LEFT), Keyboard.DOWN => TankAction.MOVE(Direction.BOTTOM), Keyboard.UP => TankAction.MOVE(Direction.TOP), diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index df8e95c..f1f72b6 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -69,13 +69,13 @@ class Render extends SpriteView { entryLayer.addChild(items[entity.key].view); } } - for (key in game.removedEntities) { + /*for (key in game.removedEntities) { if (items.exists(key)) { var view:DisplayObject = items[key].view; view.parent.removeChild(view); items.remove(key); } - } + }*/ for (item in items) { item.update(); } 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 ede9f0c..ec5edf4 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -1,18 +1,19 @@ package ru.m.tankz.view.frames; +import flash.events.Event; import haxe.Timer; +import haxework.gui.VGroupView; +import haxework.gui.ViewBuilder; +import haxework.provider.Provider; +import protohx.Message; +import ru.m.connect.IConnection; import ru.m.tankz.config.ConfigBundle; -import ru.m.tankz.proto.core.GameType; -import ru.m.tankz.proto.core.Game; import ru.m.tankz.control.PlayerControl; import ru.m.tankz.engine.Engine; -import protohx.Message; +import ru.m.tankz.game.ClassicGame; +import ru.m.tankz.game.Game; +import ru.m.tankz.player.Player; import ru.m.tankz.proto.pack.GameUpdateResponse; -import ru.m.connect.IConnection; -import haxework.gui.ViewBuilder; -import flash.events.Event; -import haxework.provider.Provider; -import haxework.gui.VGroupView; @:template("layout/frames/game.json", "layout/styles.json") @@ -22,25 +23,20 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand public static inline var ID = "game"; - private var engine:Engine; + private var game:Game; private var timer:Timer; public function init():Void { - engine = new Engine(); } public function onShow():Void { - var game:Game = Provider.get(Game); - engine.init(ConfigBundle.get(GameType.CLASSIC, 0)); - engine.initTanks(game.players); + game = new ClassicGame(ConfigBundle.get(ClassicGame.TYPE, 0)); + game.start([ + new Player(1) + ]); content.addEventListener(Event.ENTER_FRAME, redraw); - for (index in 0...game.players.length) { - var playerId:Int = game.players[index].id; - var tankId:Int = engine.playerTanks.get(playerId).id; - engine.bindControl(PlayerControl.forPlayer(index, tankId)); - } Provider.get(IConnection).packetHandler.addListener(this); - render.draw(engine); + render.draw(game.engine); timer = new Timer(10); timer.run = updateEngine; } @@ -52,21 +48,21 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand timer = null; } content.removeEventListener(Event.ENTER_FRAME, redraw); - engine.clear(); + game.dispose(); render.reset(); } private function updateEngine():Void { - engine.update(); + game.engine.update(); } private function redraw(_):Void { - render.draw(engine); + render.draw(game.engine); } public function onGameUpdateResponse(packet:GameUpdateResponse):Void { //engine.updateFromChanges(packet.changes); - render.draw(engine); + render.draw(game.engine); } public function onPacket(packet:Message):Void {} diff --git a/src/common/haxe/ru/m/tankz/config/Config.hx b/src/common/haxe/ru/m/tankz/config/Config.hx index 0301229..ca7d68a 100644 --- a/src/common/haxe/ru/m/tankz/config/Config.hx +++ b/src/common/haxe/ru/m/tankz/config/Config.hx @@ -1,14 +1,8 @@ package ru.m.tankz.config; -@:enum abstract EntityType(String) from String to String { - var PLAYER = 'player'; - var BOT = 'bot'; - var EAGLE = 'eagle'; -} - typedef SpawnPoint = { - var type:EntityType; + var type:String; var index:Int; var x:Int; var y:Int; @@ -55,7 +49,7 @@ class Config { public var bricks(default, null):Array; public var tanks(default, null):Array; - private var pointMap:Map>; + private var pointMap:Map>; private var brickMap:Map; private var tankMap:Map>; @@ -83,7 +77,7 @@ class Config { } } - public function getSpawnPoint(type:EntityType, index:Int):SpawnPoint { + public function getSpawnPoint(type:String, index:Int):SpawnPoint { return pointMap.get(type).get(index); } diff --git a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx index f8570b9..7c04983 100644 --- a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx +++ b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx @@ -1,9 +1,9 @@ package ru.m.tankz.config; +import ru.m.tankz.game.ClassicGame; import yaml.Parser; import openfl.Assets; import yaml.Yaml; -import ru.m.tankz.proto.core.GameType; import ru.m.tankz.config.Config; @@ -19,9 +19,9 @@ class ConfigBundle { return raw; } - public static function get(type:Int, level:Int):Config { + public static function get(type:String, level:Int):Config { switch (type) { - case GameType.CLASSIC: + case ClassicGame.TYPE: var source:ConfigSource = convert(Yaml.parse(Assets.getText('resources/config/config.yaml'), Parser.options().useObjects())); var bricksData:String = Assets.getText('resources/levels/level00${level}.txt'); var bricks:Array = []; diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx index 3abb1f0..94ea9ef 100644 --- a/src/common/haxe/ru/m/tankz/control/Control.hx +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -12,19 +12,17 @@ enum TankAction { class Control { - public var tankId(default, null):Int; + public var tankId(default, default):Int; private var listener:ControlListener; - public function new(tankId:Int) { - this.tankId = tankId; - } + public function new() {} public function bind(listener:ControlListener):Void { this.listener = listener; } public function action(action:TankAction):Void { - if (listener != null) { + if (tankId != 0 && listener != null) { listener.onAction(tankId, action); } } diff --git a/src/common/haxe/ru/m/tankz/core/Eagle.hx b/src/common/haxe/ru/m/tankz/core/Eagle.hx new file mode 100644 index 0000000..0f856ba --- /dev/null +++ b/src/common/haxe/ru/m/tankz/core/Eagle.hx @@ -0,0 +1,11 @@ +package ru.m.tankz.core; + +import ru.m.geom.Rectangle; + + +class Eagle extends Entity { + + public function new() { + super(new Rectangle(0, 0, 10, 10)); + } +} diff --git a/src/common/haxe/ru/m/tankz/core/EntityType.hx b/src/common/haxe/ru/m/tankz/core/EntityType.hx new file mode 100644 index 0000000..6b40605 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/core/EntityType.hx @@ -0,0 +1,26 @@ +package ru.m.tankz.core; + +import Type.ValueType; +import ru.m.tankz.map.Grid.GridCell; + + +enum EntityType { + EAGLE(eagle:Eagle); + TANK(tank:Tank); + BULLET(bullet:Bullet); + CELL(cell:GridCell); +} + + +class EntityTypeResolver { + + public static function of(entity:Dynamic):EntityType { + return switch (Type.typeof(entity)) { + case ValueType.TClass(Eagle): EntityType.EAGLE(cast entity); + case ValueType.TClass(Tank): EntityType.TANK(cast entity); + case ValueType.TClass(Bullet): EntityType.BULLET(cast entity); + case ValueType.TClass(GridCell): EntityType.CELL(cast entity); + case x: null; + } + } +} \ No newline at end of file diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 5660e73..1fac4f6 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -1,209 +1,139 @@ package ru.m.tankz.engine; -import ru.m.tankz.control.Control; -import ru.m.tankz.bot.Bot; -import haxe.Constraints.Function; import ru.m.geom.Line; -import ru.m.tankz.core.MobileEntity; -import ru.m.tankz.core.Entity; -import ru.m.geom.Direction; -import ru.m.tankz.config.Config.TankConfig; -import ru.m.geom.Point; -import ru.m.tankz.core.Bullet; -import ru.m.tankz.proto.game.GameObjectType; -import ru.m.tankz.proto.game.GameChangeType; -import ru.m.tankz.proto.game.GameChange; -import ru.m.tankz.proto.core.Player; import ru.m.tankz.config.Config; +import ru.m.tankz.control.Control; +import ru.m.tankz.core.Bullet; +import ru.m.tankz.core.Entity; +import ru.m.tankz.core.EntityType; +import ru.m.tankz.core.MobileEntity; import ru.m.tankz.core.Tank; import ru.m.tankz.map.LevelMap; -class Engine implements ControlListener { + +interface EngineListener { + public function onSpawn(entity:EntityType):Void; + public function onCollision(entity:EntityType, with:EntityType):Void; + public function onDestroy(entity:EntityType):Void; +} + + +class CollisionProcessor implements EngineListener { + + private var engine:Engine; + + public function new(engine:Engine) { + this.engine = engine; + } + + public function onSpawn(entity:EntityType):Void {} + + private function checkTankBullet(tank:Tank, bullet:Bullet):Bool { + return tank.config.group != bullet.tankConfig.group; + } + + public function onCollision(entity:EntityType, with:EntityType):Void { + switch (entity) { + case EntityType.TANK(tank1): + switch (with) { + case EntityType.TANK(tank2): + tank1.rect.lean(tank2.rect); + case EntityType.BULLET(bullet2): + if (checkTankBullet(tank1, bullet2)) { + engine.destroy(tank1); + engine.destroy(bullet2); + } + case EntityType.EAGLE(eagle): + tank1.rect.lean(eagle.rect); + case EntityType.CELL(cell): + tank1.rect.lean(cell.rect); + } + case EntityType.BULLET(bullet1): + switch (with) { + case EntityType.TANK(tank2): + if (checkTankBullet(tank2, bullet1)) { + engine.destroy(bullet1); + engine.destroy(tank2); + } + case EntityType.BULLET(bullet2): + engine.destroy(bullet1); + engine.destroy(bullet2); + case EntityType.EAGLE(eagle): + engine.destroy(bullet1); + engine.destroy(eagle); + case EntityType.CELL(cell): + engine.destroy(bullet1); + } + case _: + } + } + + public function onDestroy(entity:EntityType):Void { } +} + + +class Engine { public var config(default, default):Config; public var map(default, null):LevelMap; public var entities(default, null):Map; - public var removedEntities(default, null):Array; + public var listeners(default, null):Array; + + private var collision:CollisionProcessor; - public var playerTanks(default, null):Map; private var time:Float; - private var controls:Map; - - public function new() {} - - public function clear():Void { - playerTanks = new Map(); - controls = new Map(); - } - - private function buildTank(index:Int, config:TankConfig, point:SpawnPoint):Tank { - var tank = new Tank(index, config); - tank.rect.center = new Point((point.x + 1) * map.cellWidth, (point.y + 1) * map.cellHeight); - tank.rect.direction = Direction.fromString(point.direction); - return tank; - } - - public function init(config:Config):Void { + public function new(config:Config) { this.config = config; + listeners = []; map = new LevelMap(config.map); - playerTanks = new Map(); - controls = new Map(); entities = new Map(); - removedEntities = new Array(); time = Date.now().getTime(); + collision = new CollisionProcessor(this); + listeners.push(collision); } - public function initTanks(players:Array):Array { - var changes = new Array(); - for (index in 0...players.length) { - var player:Player = players[index]; - var point:SpawnPoint = config.getSpawnPoint(EntityType.PLAYER, index); - var tank = buildTank(index, config.getTank('player', 0), point); - playerTanks.set(player.id, tank); - entities.set(tank.id, tank); - changes.push(new GameChange() - .setType(GameChangeType.APPEND) - .setObjectType(GameObjectType.TANK) - .setObjectId(tank.id) - .setX(tank.rect.x) - .setY(tank.rect.y) - .setDirectionX(tank.rect.direction.x) - .setDirectionY(tank.rect.direction.y) - ); + public function spawn(entity:Entity):Void { + entities.set(entity.id, entity); + var type = EntityTypeResolver.of(entity); + for (l in listeners) l.onSpawn(type); + } + + public function destroy(entity:Entity):Void { + if (entities.exists(entity.id)) { + var type = EntityTypeResolver.of(entity); + for (l in listeners) l.onDestroy(type); + entities.remove(entity.id); } - - for (index in 1...4) { - var point:SpawnPoint = config.getSpawnPoint(EntityType.BOT, index); - var tank = buildTank(0, config.getTank('bot', 0), point); - entities.set(tank.id, tank); - var bot = new Bot(tank.id); - bindControl(bot); - bot.start(); - } - return changes; } - public function bindControl(control:Control):Void { - control.bind(this); - controls.set(control.tankId, control); - } - - public function onAction(tankId:Int, action:TankAction):Void { + public function action(tankId:Int, action:TankAction):Void { if (!entities.exists(tankId)) return; var tank:Tank = cast entities.get(tankId); switch (action) { case TankAction.MOVE(direction): tank.move(direction); - /*Provider.get(IConnection).send( - Map GameActionRequest() - .setType(GameActionType.MOVE) - .setDirectionX(direction.x) - .setDirectionY(direction.y) - );*/ case TankAction.LEVEL_UP(level): tank.config = config.getTank('player', Std.int(Math.min(tank.config.type + level, 3))); case TankAction.STOP: tank.stop(); - /*Provider.get(IConnection).send( - Map GameActionRequest() - .setType(GameActionType.STOP) - );*/ case TankAction.SHOT: var bullet = tank.shot(); if (bullet != null) { entities.set(bullet.id, bullet); } - /*Provider.get(IConnection).send( - Map GameActionRequest() - .setType(GameActionType.SHOT) - );*/ } } - /*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, Direction.from(change.directionX, change.directionY)); - mobileEntities.set(tank.id, tank); - tanks.set(tank.personId, tank); - case GameObjectType.BULLET: - var bullet:Bullet = Map Bullet(change.personId, change.objectId, change.x, change.y, 0, Direction.from(change.directionX, change.directionY)); - mobileEntities.set(bullet.id, bullet); - } - case GameChangeType.DESTROED: - mobileEntities.remove(change.objectId); - case GameChangeType.DIRECTION: - var target = mobileEntities.get(change.objectId); - target.direction = Direction.from(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 collisionTankTank(a:Tank, b:Tank):Bool { - a.rect.lean(b.rect); - return true; - } - - private function collisionBulletTank(a:Bullet, b:Tank):Bool { - if (a.tankConfig.group != b.config.group) { - removeEntity(a); - removeEntity(b); - return true; - } - return false; - } - - private function collisionTankBullet(a:Tank, b:Bullet):Bool { - if (a.config.group != b.tankConfig.group) { - removeEntity(a); - removeEntity(b); - return true; - } - return false; - } - - private function collisionBulletBullet(a:Bullet, b:Bullet):Bool { - removeEntity(a); - removeEntity(b); - return true; - } - - private function removeEntity(entity:Entity):Void { - if (entities.exists(entity.id)) { - entities.remove(entity.id); - removedEntities.push(entity.key); - if (Std.is(entity, Bullet)) { - var tank:Tank = cast entities.get(cast(entity, Bullet).tankId); - if (tank != null) tank.onDestroyBullet(); - } - } - if (controls.exists(entity.id)) { - var control:Control = controls.get(entity.id); - control.dispose(); - controls.remove(entity.id); - } - } - - public function update():Array { + public function update():Void { var newTime:Float = Date.now().getTime(); var d:Float = newTime - time; time = newTime; - var changes = new Array(); - for (ent in entities) if (Std.is(ent, MobileEntity)) { + var entityType:EntityType = EntityTypeResolver.of(ent); var entity:MobileEntity = cast ent; /*if (Std.is(entity, Tank)) { @@ -227,9 +157,8 @@ class Engine implements ControlListener { if (cell.layer >= entity.layer && cell.layer < 3) { entity.rect.lean(cell.rect); collision = true; - if (controls.exists(entity.id)) { - controls.get(entity.id).onCollision(cell); - } + var with = EntityTypeResolver.of(cell); + for (l in listeners) l.onCollision(entityType, with); break; } } @@ -237,18 +166,8 @@ class Engine implements ControlListener { for (other in entities.iterator()) { if (other != ent && other != null) { if (other.rect.intersection2(side)) { - //if (ent.rect.intersection(other.rect)) { - var funName = 'collision${ent.type}${other.type}'; - var fun:Function = Reflect.field(this, funName); - if (fun != null) { - var c = Reflect.callMethod(this, fun, [ent, other]); - if (c) { - if (controls.exists(entity.id)) { - controls.get(entity.id).onCollision(other); - } - } - collision = c || collision; - } + var with = EntityTypeResolver.of(other); + for (l in listeners) l.onCollision(entityType, with); } } } @@ -267,19 +186,10 @@ class Engine implements ControlListener { } } } - removeEntity(entity); } } - - /*changes.push(new GameChange() - .setType(GameChangeType.MOVED) - .setObjectType(objectType) - .setObjectId(entity.id) - .setX(entity.rect.x) - .setY(entity.rect.y) - );*/ } } - return changes; } + } diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx new file mode 100644 index 0000000..67706d3 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -0,0 +1,13 @@ +package ru.m.tankz.game; + +import ru.m.tankz.config.Config; + + +class ClassicGame extends Game { + + public static var TYPE(default, never):String = Type.getClassName(ClassicGame); + + public function new(config:Config) { + super(TYPE, config); + } +} diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx new file mode 100644 index 0000000..d7e2358 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -0,0 +1,69 @@ +package ru.m.tankz.game; + +import ru.m.tankz.core.EntityType; +import ru.m.geom.Direction; +import ru.m.geom.Point; +import ru.m.tankz.config.Config; +import ru.m.tankz.control.Control; +import ru.m.tankz.core.Tank; +import ru.m.tankz.engine.Engine; +import ru.m.tankz.player.Player; + + +class Game implements EngineListener implements ControlListener { + + public var type(default, null):String; + public var config(default, null):Config; + public var engine(default, null):Engine; + + + public function new(type:String, config:Config) { + this.type = type; + this.config = config; + this.engine = new Engine(config); + } + + private function buildTank(index:Int, config:TankConfig, point:SpawnPoint):Tank { + var tank = new Tank(index, config); + tank.rect.center = new Point((point.x + 1) * engine.map.cellWidth, (point.y + 1) * engine.map.cellHeight); + tank.rect.direction = Direction.fromString(point.direction); + return tank; + } + + public function start(players:Array):Void { + for (index in 0...players.length) { + var player:Player = players[index]; + var point:SpawnPoint = config.getSpawnPoint('player', index); + var tank = buildTank(index, config.getTank('player', 0), point); + engine.spawn(tank); + } + for (index in 1...4) { + var point:SpawnPoint = config.getSpawnPoint('bot', index); + var tank = buildTank(0, config.getTank('bot', 0), point); + engine.spawn(tank); + /*var bot = new Bot(tank.id); + bindControl(bot); + bot.start();*/ + } + } + + public function onSpawn(entity:EntityType):Void { + + } + + public function onCollision(entity:EntityType, with:EntityType):Void { + + } + + public function onDestroy(entity:EntityType):Void { + + } + + public function onAction(tankId:Int, action:TankAction):Void { + engine.action(tankId, action); + } + + public function dispose():Void { + + } +} diff --git a/src/common/haxe/ru/m/tankz/player/Player.hx b/src/common/haxe/ru/m/tankz/player/Player.hx new file mode 100644 index 0000000..1bc6843 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/player/Player.hx @@ -0,0 +1,14 @@ +package ru.m.tankz.player; + +import ru.m.tankz.control.Control; + + +class Player extends Control { + + public var index(default, null):Int; + + public function new(index:Int) { + super(); + this.index = index; + } +} From 223ff5ba937b74d971d952695cc9ac3a34b9e386 Mon Sep 17 00:00:00 2001 From: shmyga Date: Sun, 21 Jan 2018 21:54:32 +0300 Subject: [PATCH 06/22] [common] added teams --- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 12 ++--- src/client/resources/config/config.yaml | 6 +-- src/common/haxe/ru/m/tankz/bot/Bot.hx | 8 ++-- src/common/haxe/ru/m/tankz/core/Bullet.hx | 11 +++-- src/common/haxe/ru/m/tankz/core/Tank.hx | 7 ++- src/common/haxe/ru/m/tankz/engine/Engine.hx | 2 +- .../haxe/ru/m/tankz/game/ClassicGame.hx | 47 ++++++++++++++++++- src/common/haxe/ru/m/tankz/game/Game.hx | 36 ++++++-------- src/common/haxe/ru/m/tankz/game/Player.hx | 17 +++++++ src/common/haxe/ru/m/tankz/game/Team.hx | 24 ++++++++++ src/common/haxe/ru/m/tankz/player/Player.hx | 14 ------ 11 files changed, 126 insertions(+), 58 deletions(-) create mode 100644 src/common/haxe/ru/m/tankz/game/Player.hx create mode 100644 src/common/haxe/ru/m/tankz/game/Team.hx delete mode 100644 src/common/haxe/ru/m/tankz/player/Player.hx 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 ec5edf4..04be35f 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -8,11 +8,8 @@ import haxework.provider.Provider; import protohx.Message; import ru.m.connect.IConnection; import ru.m.tankz.config.ConfigBundle; -import ru.m.tankz.control.PlayerControl; -import ru.m.tankz.engine.Engine; import ru.m.tankz.game.ClassicGame; import ru.m.tankz.game.Game; -import ru.m.tankz.player.Player; import ru.m.tankz.proto.pack.GameUpdateResponse; @@ -23,7 +20,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand public static inline var ID = "game"; - private var game:Game; + private var game:Game; private var timer:Timer; public function init():Void { @@ -31,9 +28,10 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand public function onShow():Void { game = new ClassicGame(ConfigBundle.get(ClassicGame.TYPE, 0)); - game.start([ - new Player(1) - ]); + game.start({ + humans: 1, + bots: 3, + }); content.addEventListener(Event.ENTER_FRAME, redraw); Provider.get(IConnection).packetHandler.addListener(this); render.draw(game.engine); diff --git a/src/client/resources/config/config.yaml b/src/client/resources/config/config.yaml index 1800afe..ac21f52 100644 --- a/src/client/resources/config/config.yaml +++ b/src/client/resources/config/config.yaml @@ -16,17 +16,17 @@ map: y: 24 direction: top - type: bot - index: 1 + index: 0 x: 0 y: 0 direction: bottom - type: bot - index: 2 + index: 1 x: 12 y: 0 direction: bottom - type: bot - index: 3 + index: 2 x: 24 y: 0 direction: bottom diff --git a/src/common/haxe/ru/m/tankz/bot/Bot.hx b/src/common/haxe/ru/m/tankz/bot/Bot.hx index babcae1..8c24f36 100644 --- a/src/common/haxe/ru/m/tankz/bot/Bot.hx +++ b/src/common/haxe/ru/m/tankz/bot/Bot.hx @@ -1,5 +1,7 @@ package ru.m.tankz.bot; +import ru.m.tankz.game.Game; +import ru.m.tankz.game.Player; import ru.m.tankz.control.Control; import ru.m.geom.Direction; import haxe.Timer; @@ -8,13 +10,13 @@ import ru.m.tankz.core.Tank; import Type.ValueType; -class Bot extends Control { +class Bot extends Player { private var shotTimer:Timer; private var turnTimer:Timer; - public function new(tankId:Int) { - super(tankId); + public function new(team:TeamId, index:Int) { + super(team, index); } override public function onCollision(with:Dynamic):Void { diff --git a/src/common/haxe/ru/m/tankz/core/Bullet.hx b/src/common/haxe/ru/m/tankz/core/Bullet.hx index 186ea02..0d53235 100644 --- a/src/common/haxe/ru/m/tankz/core/Bullet.hx +++ b/src/common/haxe/ru/m/tankz/core/Bullet.hx @@ -1,20 +1,21 @@ package ru.m.tankz.core; +import ru.m.tankz.game.Game; import ru.m.tankz.config.Config; import ru.m.geom.Rectangle; import ru.m.geom.Direction; class Bullet extends MobileEntity { + public var team(default, null):TeamId; public var tankId(default, null):Int; - public var tankConfig(default, null):TankConfig; public var config(default, null):BulletConfig; - public function new(tankId:Int, tankConfig:TankConfig, config:BulletConfig) { + public function new(tank:Tank) { + this.team = tank.team; + this.config = tank.config.bullet; super(new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT); - this.tankId = tankId; - this.tankConfig = tankConfig; - this.config = config; + this.tankId = tank.id; this.layer = 2; } } diff --git a/src/common/haxe/ru/m/tankz/core/Tank.hx b/src/common/haxe/ru/m/tankz/core/Tank.hx index f3cf48e..49bb3ba 100755 --- a/src/common/haxe/ru/m/tankz/core/Tank.hx +++ b/src/common/haxe/ru/m/tankz/core/Tank.hx @@ -1,5 +1,6 @@ package ru.m.tankz.core; +import ru.m.tankz.game.Game; import ru.m.geom.Point; import ru.m.tankz.config.Config; import ru.m.tankz.core.Bullet; @@ -8,14 +9,16 @@ import ru.m.geom.Direction; class Tank extends MobileEntity { + public var team(default, null):TeamId; public var index(default, null):Int; public var config(default, set):TankConfig; private var bulletsCounter:Int = 0; - public function new(index:Int, config: TankConfig) { + public function new(index:Int, team:TeamId, config:TankConfig) { super(new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT); this.index = index; + this.team = team; this.config = config; this.layer = 1; } @@ -31,7 +34,7 @@ class Tank extends MobileEntity { public function shot():Null { if (bulletsCounter >= config.bullets) return null; - var bullet = new Bullet(id, config, config.bullet); + var bullet = new Bullet(this); bullet.rect.center = rect.center.add(new Point(rect.width / 4 * rect.direction.x, rect.height / 4 * rect.direction.y)); bullet.move(rect.direction); bulletsCounter++; diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 1fac4f6..940d9f1 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -30,7 +30,7 @@ class CollisionProcessor implements EngineListener { public function onSpawn(entity:EntityType):Void {} private function checkTankBullet(tank:Tank, bullet:Bullet):Bool { - return tank.config.group != bullet.tankConfig.group; + return tank.team != bullet.team; } public function onCollision(entity:EntityType, with:EntityType):Void { diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index 67706d3..a2ab163 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -1,13 +1,56 @@ package ru.m.tankz.game; +import ru.m.tankz.bot.Bot; +import ru.m.tankz.game.Game; import ru.m.tankz.config.Config; -class ClassicGame extends Game { +typedef ClassicGameSettings = { > GameSettings, + var humans:Int; + var bots:Int; +} - public static var TYPE(default, never):String = Type.getClassName(ClassicGame); + +class ClassicGame extends Game { + + public static var TYPE(default, never):GameType = Type.getClassName(ClassicGame); public function new(config:Config) { super(TYPE, config); } + + override public function start(settings:ClassicGameSettings):Void { + super.start(settings); + var humans = new Team('player', settings.humans, 3); + for (index in 0...humans.size) { + var player = new Player(humans.id, index); + player.bind(this); + humans.players.push(player); + } + var bots = new Team('bot', settings.bots, 20); + for (index in 0...bots.size) { + var bot = new Bot(bots.id, 0); + bot.bind(this); + bots.players.push(bot); + } + teams = new Map(); + teams.set(humans.id, humans); + teams.set(bots.id, bots); + + for (player in humans.players) { + var point:SpawnPoint = config.getSpawnPoint(humans.type, 0); + var tank = buildTank(0, humans.id, config.getTank(humans.type, 0), point); + engine.spawn(tank); + player.tankId = tank.id; + } + + for (player in bots.players) { + var index = bots.players.indexOf(player); + var point:SpawnPoint = config.getSpawnPoint(bots.type, index); + var tank = buildTank(0, bots.id, config.getTank(bots.type, 0), point); + engine.spawn(tank); + player.tankId = tank.id; + cast(player, Bot).start(); + } + } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index d7e2358..2dbf112 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -7,44 +7,38 @@ import ru.m.tankz.config.Config; import ru.m.tankz.control.Control; import ru.m.tankz.core.Tank; import ru.m.tankz.engine.Engine; -import ru.m.tankz.player.Player; + +typedef GameType = String; +typedef TeamId = Int; -class Game implements EngineListener implements ControlListener { +typedef GameSettings = {} - public var type(default, null):String; + +class Game implements EngineListener implements ControlListener { + + public var type(default, null):GameType; + public var teams(default, null):Map; public var config(default, null):Config; public var engine(default, null):Engine; + public var settings(default, null):G; - public function new(type:String, config:Config) { + public function new(type:GameType, config:Config) { this.type = type; this.config = config; this.engine = new Engine(config); } - private function buildTank(index:Int, config:TankConfig, point:SpawnPoint):Tank { - var tank = new Tank(index, config); + private function buildTank(index:Int, teamId:TeamId, config:TankConfig, point:SpawnPoint):Tank { + var tank = new Tank(index, teamId, config); tank.rect.center = new Point((point.x + 1) * engine.map.cellWidth, (point.y + 1) * engine.map.cellHeight); tank.rect.direction = Direction.fromString(point.direction); return tank; } - public function start(players:Array):Void { - for (index in 0...players.length) { - var player:Player = players[index]; - var point:SpawnPoint = config.getSpawnPoint('player', index); - var tank = buildTank(index, config.getTank('player', 0), point); - engine.spawn(tank); - } - for (index in 1...4) { - var point:SpawnPoint = config.getSpawnPoint('bot', index); - var tank = buildTank(0, config.getTank('bot', 0), point); - engine.spawn(tank); - /*var bot = new Bot(tank.id); - bindControl(bot); - bot.start();*/ - } + public function start(settings:G):Void { + this.settings = settings; } public function onSpawn(entity:EntityType):Void { diff --git a/src/common/haxe/ru/m/tankz/game/Player.hx b/src/common/haxe/ru/m/tankz/game/Player.hx new file mode 100644 index 0000000..81bd953 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/game/Player.hx @@ -0,0 +1,17 @@ +package ru.m.tankz.game; + +import ru.m.tankz.game.Game; +import ru.m.tankz.control.Control; + + +class Player extends Control { + + public var index(default, null):Int; + public var team(default, null):TeamId; + + public function new(team:TeamId, index:Int) { + super(); + this.team = team; + this.index = index; + } +} diff --git a/src/common/haxe/ru/m/tankz/game/Team.hx b/src/common/haxe/ru/m/tankz/game/Team.hx new file mode 100644 index 0000000..21aca40 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/game/Team.hx @@ -0,0 +1,24 @@ +package ru.m.tankz.game; + +import ru.m.tankz.game.Player; +import ru.m.tankz.game.Game; + + +class Team { + + public var id(default, null):TeamId; + public var type(default, null):String; + public var size(default, null):Int; + public var life(default, default):Int; + public var players(default, null):Array; + + private static var i:Int = 0; + + public function new(type:String, size:Int, life:Int) { + this.id = ++i; + this.type = type; + this.size = size; + this.life = life; + this.players = []; + } +} diff --git a/src/common/haxe/ru/m/tankz/player/Player.hx b/src/common/haxe/ru/m/tankz/player/Player.hx deleted file mode 100644 index 1bc6843..0000000 --- a/src/common/haxe/ru/m/tankz/player/Player.hx +++ /dev/null @@ -1,14 +0,0 @@ -package ru.m.tankz.player; - -import ru.m.tankz.control.Control; - - -class Player extends Control { - - public var index(default, null):Int; - - public function new(index:Int) { - super(); - this.index = index; - } -} From ce343148c755dba6138624cbdb09fde099ca242a Mon Sep 17 00:00:00 2001 From: shmyga Date: Mon, 22 Jan 2018 12:41:40 +0300 Subject: [PATCH 07/22] [common] split player and control --- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 3 ++ src/common/haxe/ru/m/tankz/bot/Bot.hx | 45 ++++++++++--------- src/common/haxe/ru/m/tankz/control/Control.hx | 4 ++ .../haxe/ru/m/tankz/game/ClassicGame.hx | 7 ++- src/common/haxe/ru/m/tankz/game/Game.hx | 24 ++++++++-- src/common/haxe/ru/m/tankz/game/Player.hx | 35 +++++++++++++-- 6 files changed, 85 insertions(+), 33 deletions(-) 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 04be35f..b929ea0 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -1,5 +1,6 @@ package ru.m.tankz.view.frames; +import ru.m.tankz.control.PlayerControl; import flash.events.Event; import haxe.Timer; import haxework.gui.VGroupView; @@ -32,6 +33,8 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand humans: 1, bots: 3, }); + game.setControl('player', 0, PlayerControl.forPlayer(0)); + //game.setControl('player', 1, PlayerControl.forPlayer(1)); content.addEventListener(Event.ENTER_FRAME, redraw); Provider.get(IConnection).packetHandler.addListener(this); render.draw(game.engine); diff --git a/src/common/haxe/ru/m/tankz/bot/Bot.hx b/src/common/haxe/ru/m/tankz/bot/Bot.hx index 8c24f36..ccb217b 100644 --- a/src/common/haxe/ru/m/tankz/bot/Bot.hx +++ b/src/common/haxe/ru/m/tankz/bot/Bot.hx @@ -1,7 +1,5 @@ package ru.m.tankz.bot; -import ru.m.tankz.game.Game; -import ru.m.tankz.game.Player; import ru.m.tankz.control.Control; import ru.m.geom.Direction; import haxe.Timer; @@ -10,13 +8,13 @@ import ru.m.tankz.core.Tank; import Type.ValueType; -class Bot extends Player { +class Bot extends Control { private var shotTimer:Timer; private var turnTimer:Timer; - public function new(team:TeamId, index:Int) { - super(team, index); + public function new() { + super(); } override public function onCollision(with:Dynamic):Void { @@ -27,12 +25,27 @@ class Bot extends Player { } } - public function start():Void { + override public function start():Void { action(TankAction.MOVE(Direction.BOTTOM)); - shotTimer = new Timer(1000); - shotTimer.run = shot; - turnTimer = new Timer(3000); - turnTimer.run = turn; + if (shotTimer == null) { + shotTimer = new Timer(1000); + shotTimer.run = shot; + } + if (turnTimer == null) { + turnTimer = new Timer(3000); + turnTimer.run = turn; + } + } + + override public function stop():Void { + if (shotTimer != null) { + shotTimer.stop(); + shotTimer = null; + } + if (turnTimer != null) { + turnTimer.stop(); + turnTimer = null; + } } public function shot():Void { @@ -51,16 +64,4 @@ class Bot extends Player { Direction.RIGHT, ][Math.floor(Math.random() * 4)]; } - - override public function dispose():Void { - super.dispose(); - if (shotTimer != null) { - shotTimer.stop(); - shotTimer = null; - } - if (turnTimer != null) { - turnTimer.stop(); - turnTimer = null; - } - } } diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx index 94ea9ef..202630b 100644 --- a/src/common/haxe/ru/m/tankz/control/Control.hx +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -31,8 +31,12 @@ class Control { } + public function start():Void {} + + public function stop():Void {} public function dispose():Void { + stop(); listener = null; } } diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index a2ab163..908b9f6 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import ru.m.tankz.control.Control; import ru.m.tankz.bot.Bot; import ru.m.tankz.game.Game; import ru.m.tankz.config.Config; @@ -24,13 +25,12 @@ class ClassicGame extends Game { var humans = new Team('player', settings.humans, 3); for (index in 0...humans.size) { var player = new Player(humans.id, index); - player.bind(this); humans.players.push(player); } var bots = new Team('bot', settings.bots, 20); for (index in 0...bots.size) { - var bot = new Bot(bots.id, 0); - bot.bind(this); + var bot = new Player(bots.id, 0, new Bot()); + bot.control.bind(this); bots.players.push(bot); } teams = new Map(); @@ -50,7 +50,6 @@ class ClassicGame extends Game { var tank = buildTank(0, bots.id, config.getTank(bots.type, 0), point); engine.spawn(tank); player.tankId = tank.id; - cast(player, Bot).start(); } } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 2dbf112..f326772 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -15,13 +15,13 @@ typedef TeamId = Int; typedef GameSettings = {} -class Game implements EngineListener implements ControlListener { +class Game implements EngineListener implements ControlListener { public var type(default, null):GameType; public var teams(default, null):Map; public var config(default, null):Config; public var engine(default, null):Engine; - public var settings(default, null):G; + public var settings(default, null):S; public function new(type:GameType, config:Config) { @@ -37,10 +37,26 @@ class Game implements EngineListener implements ControlListener return tank; } - public function start(settings:G):Void { + public function start(settings:S):Void { this.settings = settings; } + public function setControl(teamType:String, index:Int, control:Control):Void { + for (team in teams.iterator()) { + if (team.type == teamType) { + L.w('XXX', 'players: ${team.players}'); + var player = team.players[index]; + if (player.control != null) { + player.control.dispose(); + } + player.control = control; + player.control.bind(this); + break; + } + } + } + + public function onSpawn(entity:EntityType):Void { } @@ -53,10 +69,12 @@ class Game implements EngineListener implements ControlListener } + public function onAction(tankId:Int, action:TankAction):Void { engine.action(tankId, action); } + public function dispose():Void { } diff --git a/src/common/haxe/ru/m/tankz/game/Player.hx b/src/common/haxe/ru/m/tankz/game/Player.hx index 81bd953..4dc81e3 100644 --- a/src/common/haxe/ru/m/tankz/game/Player.hx +++ b/src/common/haxe/ru/m/tankz/game/Player.hx @@ -1,17 +1,44 @@ package ru.m.tankz.game; -import ru.m.tankz.game.Game; import ru.m.tankz.control.Control; +import ru.m.tankz.game.Game; -class Player extends Control { +class Player { public var index(default, null):Int; public var team(default, null):TeamId; + public var tankId(default, set):Int; + public var control(default, set):Control; - public function new(team:TeamId, index:Int) { - super(); + public function new(team:TeamId, index:Int, control:Control=null) { this.team = team; this.index = index; + this.control = control; + } + + public function set_tankId(value:Int):Int { + tankId = value; + if (control != null) { + control.tankId = tankId; + if (tankId != 0) { + control.start(); + } else { + control.stop(); + } + } + return tankId; + } + + public function set_control(value:Control):Control { + if (control != null) control.dispose(); + control = value; + if (control != null) { + control.tankId = tankId; + if (tankId != 0) { + control.start(); + } + } + return control; } } From 981a4b5bab11f6240f50be2c563e1e6994cbf65b Mon Sep 17 00:00:00 2001 From: shmyga Date: Mon, 22 Jan 2018 22:31:45 +0300 Subject: [PATCH 08/22] [common] spawn system --- .../haxe/ru/m/tankz/render/RenderItem.hx | 8 +- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 11 +- src/client/resources/config/config.yaml | 70 +++++---- src/common/haxe/ru/m/tankz/bot/Bot.hx | 12 +- src/common/haxe/ru/m/tankz/config/Config.hx | 41 +++--- .../haxe/ru/m/tankz/config/ConfigBundle.hx | 3 +- src/common/haxe/ru/m/tankz/control/Control.hx | 3 +- src/common/haxe/ru/m/tankz/core/Bullet.hx | 4 +- src/common/haxe/ru/m/tankz/core/Tank.hx | 8 +- src/common/haxe/ru/m/tankz/engine/Engine.hx | 4 +- .../haxe/ru/m/tankz/game/ClassicGame.hx | 43 +----- src/common/haxe/ru/m/tankz/game/Game.hx | 137 ++++++++++++++++-- src/common/haxe/ru/m/tankz/game/Player.hx | 8 +- src/common/haxe/ru/m/tankz/game/Team.hx | 13 +- 14 files changed, 228 insertions(+), 137 deletions(-) diff --git a/src/client/haxe/ru/m/tankz/render/RenderItem.hx b/src/client/haxe/ru/m/tankz/render/RenderItem.hx index 290fbfc..984d794 100644 --- a/src/client/haxe/ru/m/tankz/render/RenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/RenderItem.hx @@ -106,10 +106,14 @@ class BrickItem extends RenderItem { class TankItem extends RenderItem { - private var type:Int; + private var type:String; override private function getImage():String { - return 'resources/images/tank/${value.config.group}/tank_${value.config.group.charAt(0)}${value.config.type}_${value.index}-0.png'; + var group = value.config.group; + var index = value.playerId.index; + if (group == 'human') group = 'player'; + if (group == 'bot') index = 0; + return 'resources/images/tank/${group}/tank_${group.charAt(0)}${value.config.type}_${index}-0.png'; } override public function update():Void { 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 b929ea0..7f5415f 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -21,7 +21,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand public static inline var ID = "game"; - private var game:Game; + private var game:Game; private var timer:Timer; public function init():Void { @@ -29,12 +29,9 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand public function onShow():Void { game = new ClassicGame(ConfigBundle.get(ClassicGame.TYPE, 0)); - game.start({ - humans: 1, - bots: 3, - }); - game.setControl('player', 0, PlayerControl.forPlayer(0)); - //game.setControl('player', 1, PlayerControl.forPlayer(1)); + game.start(); + game.setControl({team:'human', index:0}, PlayerControl.forPlayer(0)); + game.setControl({team:'human', index:1}, PlayerControl.forPlayer(1)); content.addEventListener(Event.ENTER_FRAME, redraw); Provider.get(IConnection).packetHandler.addListener(this); render.draw(game.engine); diff --git a/src/client/resources/config/config.yaml b/src/client/resources/config/config.yaml index ac21f52..ab91b0a 100644 --- a/src/client/resources/config/config.yaml +++ b/src/client/resources/config/config.yaml @@ -3,33 +3,7 @@ map: cellHeight: 22 gridWidth: 26 gridHeight: 26 - bricks: null - points: - - type: player - index: 0 - x: 8 - y: 24 - direction: top - - type: player - index: 1 - x: 16 - y: 24 - direction: top - - type: bot - index: 0 - x: 0 - y: 0 - direction: bottom - - type: bot - index: 1 - x: 12 - y: 0 - direction: bottom - - type: bot - index: 2 - x: 24 - y: 0 - direction: bottom + bricks: [] bricks: # border @@ -61,6 +35,46 @@ bricks: layer: 2 armor: 1 +teams: + - id: human + size: 2 + spawnInterval: 0 + points: + - type: eagle + index: -1 + x: 12 + y: 24 + direction: top + - type: tank + index: 0 + x: 8 + y: 24 + direction: top + - type: tank + index: 1 + x: 16 + y: 24 + direction: top + - id: bot + size: 6 + spawnInterval: 1000 + points: + - type: tank + index: -1 + x: 0 + y: 0 + direction: bottom + - type: tank + index: -1 + x: 12 + y: 0 + direction: bottom + - type: tank + index: -1 + x: 24 + y: 0 + direction: bottom + bullet: &bullet width: 12 height: 12 @@ -68,7 +82,7 @@ bullet: &bullet piercing: 1 tanks: - player: + human: - type: 0 width: 36 height: 36 diff --git a/src/common/haxe/ru/m/tankz/bot/Bot.hx b/src/common/haxe/ru/m/tankz/bot/Bot.hx index ccb217b..0eeaa98 100644 --- a/src/common/haxe/ru/m/tankz/bot/Bot.hx +++ b/src/common/haxe/ru/m/tankz/bot/Bot.hx @@ -1,11 +1,9 @@ package ru.m.tankz.bot; +import ru.m.tankz.core.EntityType; import ru.m.tankz.control.Control; import ru.m.geom.Direction; import haxe.Timer; -import ru.m.tankz.map.Grid.GridCell; -import ru.m.tankz.core.Tank; -import Type.ValueType; class Bot extends Control { @@ -17,10 +15,10 @@ class Bot extends Control { super(); } - override public function onCollision(with:Dynamic):Void { - switch (Type.typeof(with)) { - case ValueType.TClass(Tank): turn(); - case ValueType.TClass(GridCell): turn(); + override public function onCollision(with:EntityType):Void { + switch (with) { + case EntityType.TANK(_): turn(); + case EntityType.CELL(_): turn(); case _: } } diff --git a/src/common/haxe/ru/m/tankz/config/Config.hx b/src/common/haxe/ru/m/tankz/config/Config.hx index ca7d68a..72894dd 100644 --- a/src/common/haxe/ru/m/tankz/config/Config.hx +++ b/src/common/haxe/ru/m/tankz/config/Config.hx @@ -14,9 +14,7 @@ typedef MapConfig = { var cellHeight:Float; var gridWidth:Int; var gridHeight:Int; - var bricks:Array; - var points:Array; } typedef BrickConfig = { @@ -35,7 +33,7 @@ typedef BulletConfig = { typedef TankConfig = { var group:String; - var type:Int; + var type:String; var width:Float; var height:Float; var speed:Float; @@ -44,48 +42,57 @@ typedef TankConfig = { } +typedef TeamConfig = { + var id:String; + var size:Int; + var spawnInterval:Int; + var points:Array; +} + + class Config { public var map(default, null):MapConfig; public var bricks(default, null):Array; public var tanks(default, null):Array; + public var teams(default, null):Array; - private var pointMap:Map>; private var brickMap:Map; - private var tankMap:Map>; + private var tankMap:Map>; + private var teamMap:Map; - public function new(map:MapConfig, bricks:Array, tanks:Array) { + public function new(map:MapConfig, bricks:Array, teams:Array, tanks:Array) { this.map = map; this.bricks = bricks; + this.teams = teams; this.tanks = tanks; init(); } private function init() { - pointMap = new Map(); - for (item in map.points) { - if (!pointMap.exists(item.type)) pointMap.set(item.type, new Map()); - pointMap.get(item.type).set(item.index, item); - } brickMap = new Map(); for (item in bricks) { brickMap.set(item.type, item); } + teamMap = new Map(); + for (team in teams) { + teamMap.set(team.id, team); + } tankMap = new Map(); for (item in tanks) { - if (!tankMap.exists(item.group)) tankMap.set(item.group, new Map()); + if (!tankMap.exists(item.group)) tankMap.set(item.group, new Map()); tankMap.get(item.group).set(item.type, item); } } - public function getSpawnPoint(type:String, index:Int):SpawnPoint { - return pointMap.get(type).get(index); - } - public function getBrick(type:Int):BrickConfig { return brickMap.get(type); } - public function getTank(group:String, type:Int):TankConfig { + public function getTeam(id:String):TeamConfig { + return teamMap.get(id); + } + + public function getTank(group:String, type:String):TankConfig { return tankMap.get(group).get(type); } } diff --git a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx index 7c04983..d8e8b3e 100644 --- a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx +++ b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx @@ -10,6 +10,7 @@ import ru.m.tankz.config.Config; typedef ConfigSource = { var map: MapConfig; var bricks: Array; + var teams: Array; var tanks: Dynamic>; } @@ -41,7 +42,7 @@ class ConfigBundle { tanks.push(item); } } - return new Config(source.map, source.bricks, tanks); + return new Config(source.map, source.bricks, source.teams, tanks); case _: return null; } diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx index 202630b..c7d7ce8 100644 --- a/src/common/haxe/ru/m/tankz/control/Control.hx +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -1,5 +1,6 @@ package ru.m.tankz.control; +import ru.m.tankz.core.EntityType; import ru.m.geom.Direction; @@ -27,7 +28,7 @@ class Control { } } - public function onCollision(with:Dynamic):Void { + public function onCollision(with:EntityType):Void { } diff --git a/src/common/haxe/ru/m/tankz/core/Bullet.hx b/src/common/haxe/ru/m/tankz/core/Bullet.hx index 0d53235..b0f68e2 100644 --- a/src/common/haxe/ru/m/tankz/core/Bullet.hx +++ b/src/common/haxe/ru/m/tankz/core/Bullet.hx @@ -7,12 +7,12 @@ import ru.m.geom.Direction; class Bullet extends MobileEntity { - public var team(default, null):TeamId; + public var playerId(default, null):PlayerId; public var tankId(default, null):Int; public var config(default, null):BulletConfig; public function new(tank:Tank) { - this.team = tank.team; + this.playerId = tank.playerId; this.config = tank.config.bullet; super(new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT); this.tankId = tank.id; diff --git a/src/common/haxe/ru/m/tankz/core/Tank.hx b/src/common/haxe/ru/m/tankz/core/Tank.hx index 49bb3ba..8e9bc16 100755 --- a/src/common/haxe/ru/m/tankz/core/Tank.hx +++ b/src/common/haxe/ru/m/tankz/core/Tank.hx @@ -9,16 +9,14 @@ import ru.m.geom.Direction; class Tank extends MobileEntity { - public var team(default, null):TeamId; - public var index(default, null):Int; + public var playerId(default, null):PlayerId; public var config(default, set):TankConfig; private var bulletsCounter:Int = 0; - public function new(index:Int, team:TeamId, config:TankConfig) { + public function new(playerId:PlayerId, config:TankConfig) { super(new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT); - this.index = index; - this.team = team; + this.playerId = playerId; this.config = config; this.layer = 1; } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 940d9f1..1a36dc3 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -30,7 +30,7 @@ class CollisionProcessor implements EngineListener { public function onSpawn(entity:EntityType):Void {} private function checkTankBullet(tank:Tank, bullet:Bullet):Bool { - return tank.team != bullet.team; + return tank.playerId.team != bullet.playerId.team; } public function onCollision(entity:EntityType, with:EntityType):Void { @@ -116,7 +116,7 @@ class Engine { case TankAction.MOVE(direction): tank.move(direction); case TankAction.LEVEL_UP(level): - tank.config = config.getTank('player', Std.int(Math.min(tank.config.type + level, 3))); + tank.config = config.getTank('player', Std.string(Std.int(Math.min(Std.parseInt(tank.config.type) + level, 3)))); case TankAction.STOP: tank.stop(); case TankAction.SHOT: diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index 908b9f6..4156886 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -1,18 +1,11 @@ package ru.m.tankz.game; -import ru.m.tankz.control.Control; import ru.m.tankz.bot.Bot; import ru.m.tankz.game.Game; import ru.m.tankz.config.Config; -typedef ClassicGameSettings = { > GameSettings, - var humans:Int; - var bots:Int; -} - - -class ClassicGame extends Game { +class ClassicGame extends Game { public static var TYPE(default, never):GameType = Type.getClassName(ClassicGame); @@ -20,36 +13,10 @@ class ClassicGame extends Game { super(TYPE, config); } - override public function start(settings:ClassicGameSettings):Void { - super.start(settings); - var humans = new Team('player', settings.humans, 3); - for (index in 0...humans.size) { - var player = new Player(humans.id, index); - humans.players.push(player); - } - var bots = new Team('bot', settings.bots, 20); - for (index in 0...bots.size) { - var bot = new Player(bots.id, 0, new Bot()); - bot.control.bind(this); - bots.players.push(bot); - } - teams = new Map(); - teams.set(humans.id, humans); - teams.set(bots.id, bots); - - for (player in humans.players) { - var point:SpawnPoint = config.getSpawnPoint(humans.type, 0); - var tank = buildTank(0, humans.id, config.getTank(humans.type, 0), point); - engine.spawn(tank); - player.tankId = tank.id; - } - - for (player in bots.players) { - var index = bots.players.indexOf(player); - var point:SpawnPoint = config.getSpawnPoint(bots.type, index); - var tank = buildTank(0, bots.id, config.getTank(bots.type, 0), point); - engine.spawn(tank); - player.tankId = tank.id; + override public function start():Void { + super.start(); + for (player in teams.get('bot').players) { + setControl(player.id, new Bot()); } } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index f326772..0291df4 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import haxe.Timer; import ru.m.tankz.core.EntityType; import ru.m.geom.Direction; import ru.m.geom.Point; @@ -9,43 +10,142 @@ import ru.m.tankz.core.Tank; import ru.m.tankz.engine.Engine; typedef GameType = String; -typedef TeamId = Int; + +typedef TeamId = String; + +typedef PlayerId = { + var team:TeamId; + var index:Int; +} -typedef GameSettings = {} +typedef SpawnTask = { + var point:SpawnPoint; + var playerId:PlayerId; +} -class Game implements EngineListener implements ControlListener { +class Spawner { + + private var config:TeamConfig; + private var runner:SpawnTask -> Void; + private var queue:Array; + private var timer:Timer; + + private var indexedPoints:Map; + private var anyPoints:Array; + private var index:Int; + + public function new(config:TeamConfig, runner:SpawnTask -> Void) { + this.config = config; + this.runner = runner; + queue = []; + indexedPoints = new Map(); + anyPoints = []; + for (point in config.points) { + if (point.type == 'tank') { + if (point.index > -1) { + indexedPoints.set(point.index, point); + } else { + anyPoints.push(point); + } + } + } + } + + public function push(playerId:PlayerId):Void { + var point:SpawnPoint = null; + if (indexedPoints.exists(playerId.index)) { + point = indexedPoints.get(playerId.index); + } else { + point = anyPoints[index++]; + if (index >= anyPoints.length) index = 0; + } + if (point != null) { + queue.push({playerId:playerId, point:point}); + run(); + } + } + + private function run():Void { + if (timer == null) { + timer = new Timer(config.spawnInterval); + timer.run = spawn; + } + } + + private function spawn():Void { + if (queue.length == 0) { + if (timer != null) { + timer.stop(); + timer = null; + } + } else { + runner(queue.shift()); + } + } +} + + +class Game implements EngineListener implements ControlListener { public var type(default, null):GameType; public var teams(default, null):Map; public var config(default, null):Config; public var engine(default, null):Engine; - public var settings(default, null):S; + private var spawners:Map; public function new(type:GameType, config:Config) { this.type = type; this.config = config; this.engine = new Engine(config); + engine.listeners.push(this); } - private function buildTank(index:Int, teamId:TeamId, config:TankConfig, point:SpawnPoint):Tank { - var tank = new Tank(index, teamId, config); + public function getPlayer(playerId:PlayerId):Player { + return teams.get(playerId.team).players[playerId.index]; + } + + private function buildTank(playerId:PlayerId, config:TankConfig, point:SpawnPoint):Tank { + var tank = new Tank(playerId, config); tank.rect.center = new Point((point.x + 1) * engine.map.cellWidth, (point.y + 1) * engine.map.cellHeight); tank.rect.direction = Direction.fromString(point.direction); return tank; } - public function start(settings:S):Void { - this.settings = settings; + public function start():Void { + teams = new Map(); + spawners = new Map(); + for (teamConfig in config.teams) { + var team = new Team(teamConfig); + for (index in 0...team.config.size) { + var player = new Player({team:team.id, index:index}); + team.players.push(player); + teams.set(team.id, team); + } + spawners.set(team.id, new Spawner(team.config, spawn)); + } + + for (team in teams) { + for (player in team.players) { + var point = team.config.points[0]; + spawners.get(team.id).push(player.id); + } + } } - public function setControl(teamType:String, index:Int, control:Control):Void { + private function spawn(task:SpawnTask):Void { + var tank = buildTank(task.playerId, config.getTank(task.playerId.team, '0'), task.point); + var player:Player = teams.get(task.playerId.team).players[task.playerId.index]; + player.tankId = tank.id; + engine.spawn(tank); + } + + public function setControl(playerId:PlayerId, control:Control):Void { for (team in teams.iterator()) { - if (team.type == teamType) { - L.w('XXX', 'players: ${team.players}'); - var player = team.players[index]; + if (team.id == playerId.team) { + var player = team.players[playerId.index]; if (player.control != null) { player.control.dispose(); } @@ -62,11 +162,20 @@ class Game implements EngineListener implements ControlListener } public function onCollision(entity:EntityType, with:EntityType):Void { - + switch (entity) { + case EntityType.TANK(tank): + var control = getPlayer(tank.playerId).control; + if (control != null) control.onCollision(with); + case x: + } } public function onDestroy(entity:EntityType):Void { - + switch (entity) { + case EntityType.TANK(tank): + spawners.get(tank.playerId.team).push(tank.playerId); + case x: + } } diff --git a/src/common/haxe/ru/m/tankz/game/Player.hx b/src/common/haxe/ru/m/tankz/game/Player.hx index 4dc81e3..af78f4e 100644 --- a/src/common/haxe/ru/m/tankz/game/Player.hx +++ b/src/common/haxe/ru/m/tankz/game/Player.hx @@ -6,14 +6,12 @@ import ru.m.tankz.game.Game; class Player { - public var index(default, null):Int; - public var team(default, null):TeamId; + public var id(default, null):PlayerId; public var tankId(default, set):Int; public var control(default, set):Control; - public function new(team:TeamId, index:Int, control:Control=null) { - this.team = team; - this.index = index; + public function new(id:PlayerId, control:Control=null) { + this.id = id; this.control = control; } diff --git a/src/common/haxe/ru/m/tankz/game/Team.hx b/src/common/haxe/ru/m/tankz/game/Team.hx index 21aca40..49bf57c 100644 --- a/src/common/haxe/ru/m/tankz/game/Team.hx +++ b/src/common/haxe/ru/m/tankz/game/Team.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import ru.m.tankz.config.Config.TeamConfig; import ru.m.tankz.game.Player; import ru.m.tankz.game.Game; @@ -7,18 +8,14 @@ import ru.m.tankz.game.Game; class Team { public var id(default, null):TeamId; - public var type(default, null):String; - public var size(default, null):Int; - public var life(default, default):Int; + public var config(default, null):TeamConfig; public var players(default, null):Array; private static var i:Int = 0; - public function new(type:String, size:Int, life:Int) { - this.id = ++i; - this.type = type; - this.size = size; - this.life = life; + public function new(config:TeamConfig) { + this.id = config.id; + this.config = config; this.players = []; } } From 0e809812e796be51898c81d8722ec0beb8f02cba Mon Sep 17 00:00:00 2001 From: shmyga Date: Tue, 23 Jan 2018 14:00:50 +0300 Subject: [PATCH 09/22] [common] Render implement EngineListener --- src/client/haxe/ru/m/tankz/render/Render.hx | 57 +++++++++++++------ .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 13 ++++- .../haxe/ru/m/tankz/view/frames/StartFrame.hx | 25 ++++---- .../config/{config.yaml => classic.yaml} | 2 +- src/common/haxe/ru/m/tankz/config/Config.hx | 4 +- .../haxe/ru/m/tankz/config/ConfigBundle.hx | 4 +- src/common/haxe/ru/m/tankz/engine/Engine.hx | 12 +++- .../haxe/ru/m/tankz/game/ClassicGame.hx | 2 +- src/common/haxe/ru/m/tankz/game/Game.hx | 4 +- 9 files changed, 79 insertions(+), 44 deletions(-) rename src/client/resources/config/{config.yaml => classic.yaml} (98%) diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index f1f72b6..93122e0 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -1,5 +1,6 @@ package ru.m.tankz.render; +import ru.m.tankz.core.EntityType; import flash.display.DisplayObject; import Type.ValueType; import ru.m.tankz.render.RenderItem; @@ -11,7 +12,7 @@ import flash.display.Graphics; import haxework.gui.SpriteView; -class Render extends SpriteView { +class Render extends SpriteView implements EngineListener { private var backgroundLayer:Sprite; private var groundLayer:Sprite; @@ -59,23 +60,6 @@ class Render extends SpriteView { } } } - for (entity in game.entities) { - if (!items.exists(entity.key)) { - items[entity.key] = switch (Type.typeof(entity)) { - case ValueType.TClass(Tank): cast new TankItem(cast entity); - case ValueType.TClass(Bullet): cast new BulletItem(cast entity); - case x: null; - } - entryLayer.addChild(items[entity.key].view); - } - } - /*for (key in game.removedEntities) { - if (items.exists(key)) { - var view:DisplayObject = items[key].view; - view.parent.removeChild(view); - items.remove(key); - } - }*/ for (item in items) { item.update(); } @@ -91,4 +75,41 @@ class Render extends SpriteView { background = null; } } + + + public function onSpawn(entity:EntityType):Void { + switch(entity) { + case EntityType.TANK(tank): + var item = new TankItem(tank); + items.set(tank.key, item); + entryLayer.addChild(item.view); + item.update(); + case EntityType.BULLET(bullet): + var item = new BulletItem(bullet); + items.set(bullet.key, item); + entryLayer.addChild(item.view); + item.update(); + case _: + } + } + + public function onCollision(entity:EntityType, with:EntityType):Void { + + } + + public function onDestroy(entity:EntityType):Void { + switch(entity) { + case EntityType.TANK(tank): + if (items.exists(tank.key)) { + entryLayer.removeChild(items.get(tank.key).view); + items.remove(tank.key); + } + case EntityType.BULLET(bullet): + if (items.exists(bullet.key)) { + entryLayer.removeChild(items.get(bullet.key).view); + items.remove(bullet.key); + } + case _: + } + } } 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 7f5415f..cc7084e 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -1,5 +1,6 @@ package ru.m.tankz.view.frames; +import ru.m.tankz.config.Config; import ru.m.tankz.control.PlayerControl; import flash.events.Event; import haxe.Timer; @@ -28,10 +29,16 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand } public function onShow():Void { - game = new ClassicGame(ConfigBundle.get(ClassicGame.TYPE, 0)); + var config:Config = Provider.get(Config); + game = switch (config.type) { + case ClassicGame.TYPE: new ClassicGame(config); + case x: throw 'Unsupported game type "${x}"'; + } + game.engine.listeners.push(render); game.start(); - game.setControl({team:'human', index:0}, PlayerControl.forPlayer(0)); - game.setControl({team:'human', index:1}, PlayerControl.forPlayer(1)); + for (index in 0...game.config.getTeam('human').size) { + game.setControl({team:'human', index:index}, PlayerControl.forPlayer(index)); + } content.addEventListener(Event.ENTER_FRAME, redraw); Provider.get(IConnection).packetHandler.addListener(this); render.draw(game.engine); diff --git a/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx b/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx index ebccba6..51486b9 100644 --- a/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx @@ -1,8 +1,8 @@ package ru.m.tankz.view.frames; -import ru.m.tankz.proto.core.GameType; -import ru.m.tankz.proto.core.Player; -import ru.m.tankz.proto.core.Game; +import ru.m.tankz.config.Config; +import ru.m.tankz.game.ClassicGame; +import ru.m.tankz.config.ConfigBundle; import haxework.gui.frame.IFrameSwitcher; import haxework.provider.Provider; import haxework.gui.ButtonView; @@ -21,23 +21,18 @@ class StartFrame extends VGroupView implements ViewBuilder { public function onPress(view:ButtonView):Void { switch (view.id) { - case "start_1p": + case 'start_1p': startGame(1); - case "start_2p": + case 'start_2p': startGame(2); } } - private function startGame(playersCount:Int):Void { - var game = new Game(); - game.type = GameType.CLASSIC; - for (i in 0...playersCount) { - var player = new Player(); - player.id = i; - game.players.push(player); - } - game.id = 1; - Provider.set(Game, game); + private function startGame(players:Int):Void { + var config = ConfigBundle.get(ClassicGame.TYPE, 0); + config.getTeam('human').size = players; + config.getTeam('bot').size = 2 + 2 * players; + Provider.set(Config, config); Provider.get(IFrameSwitcher).change(GameFrame.ID); } } diff --git a/src/client/resources/config/config.yaml b/src/client/resources/config/classic.yaml similarity index 98% rename from src/client/resources/config/config.yaml rename to src/client/resources/config/classic.yaml index ab91b0a..5d3048f 100644 --- a/src/client/resources/config/config.yaml +++ b/src/client/resources/config/classic.yaml @@ -57,7 +57,7 @@ teams: direction: top - id: bot size: 6 - spawnInterval: 1000 + spawnInterval: 3000 points: - type: tank index: -1 diff --git a/src/common/haxe/ru/m/tankz/config/Config.hx b/src/common/haxe/ru/m/tankz/config/Config.hx index 72894dd..d0b1a2d 100644 --- a/src/common/haxe/ru/m/tankz/config/Config.hx +++ b/src/common/haxe/ru/m/tankz/config/Config.hx @@ -51,6 +51,7 @@ typedef TeamConfig = { class Config { + public var type(default, null):String; public var map(default, null):MapConfig; public var bricks(default, null):Array; public var tanks(default, null):Array; @@ -60,7 +61,8 @@ class Config { private var tankMap:Map>; private var teamMap:Map; - public function new(map:MapConfig, bricks:Array, teams:Array, tanks:Array) { + public function new(type:String, map:MapConfig, bricks:Array, teams:Array, tanks:Array) { + this.type = type; this.map = map; this.bricks = bricks; this.teams = teams; diff --git a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx index d8e8b3e..64827d3 100644 --- a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx +++ b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx @@ -23,7 +23,7 @@ class ConfigBundle { public static function get(type:String, level:Int):Config { switch (type) { case ClassicGame.TYPE: - var source:ConfigSource = convert(Yaml.parse(Assets.getText('resources/config/config.yaml'), Parser.options().useObjects())); + var source:ConfigSource = convert(Yaml.parse(Assets.getText('resources/config/${type}.yaml'), Parser.options().useObjects())); var bricksData:String = Assets.getText('resources/levels/level00${level}.txt'); var bricks:Array = []; for (line in ~/\s+/g.split(bricksData)) { @@ -42,7 +42,7 @@ class ConfigBundle { tanks.push(item); } } - return new Config(source.map, source.bricks, source.teams, tanks); + return new Config(type, source.map, source.bricks, source.teams, tanks); case _: return null; } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 1a36dc3..db46851 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -104,6 +104,12 @@ class Engine { public function destroy(entity:Entity):Void { if (entities.exists(entity.id)) { var type = EntityTypeResolver.of(entity); + switch (type) { + case EntityType.BULLET(bullet): + var tank:Tank = cast entities.get(bullet.tankId); + if (tank != null) tank.onDestroyBullet(); + case _: + } for (l in listeners) l.onDestroy(type); entities.remove(entity.id); } @@ -122,7 +128,7 @@ class Engine { case TankAction.SHOT: var bullet = tank.shot(); if (bullet != null) { - entities.set(bullet.id, bullet); + spawn(bullet); } } } @@ -192,4 +198,8 @@ class Engine { } } + public function dispose():Void { + listeners = []; + entities = new Map(); + } } diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index 4156886..9a13d7c 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -7,7 +7,7 @@ import ru.m.tankz.config.Config; class ClassicGame extends Game { - public static var TYPE(default, never):GameType = Type.getClassName(ClassicGame); + public static var TYPE(default, never):GameType = 'classic'; public function new(config:Config) { super(TYPE, config); diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 0291df4..06ea91f 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -138,8 +138,8 @@ class Game implements EngineListener implements ControlListener { private function spawn(task:SpawnTask):Void { var tank = buildTank(task.playerId, config.getTank(task.playerId.team, '0'), task.point); var player:Player = teams.get(task.playerId.team).players[task.playerId.index]; - player.tankId = tank.id; engine.spawn(tank); + player.tankId = tank.id; } public function setControl(playerId:PlayerId, control:Control):Void { @@ -185,6 +185,6 @@ class Game implements EngineListener implements ControlListener { public function dispose():Void { - + engine.dispose(); } } From bcdefce2c987e09cfc6649ac643c33eed7d22d72 Mon Sep 17 00:00:00 2001 From: shmyga Date: Tue, 23 Jan 2018 20:49:54 +0300 Subject: [PATCH 10/22] [common] added eagle spawn --- src/client/haxe/ru/m/tankz/render/Render.hx | 10 +++ .../haxe/ru/m/tankz/render/RenderItem.hx | 11 +++ src/client/resources/config/classic.yaml | 2 +- src/common/haxe/ru/m/tankz/core/Eagle.hx | 2 +- src/common/haxe/ru/m/tankz/game/Game.hx | 90 ++++--------------- src/common/haxe/ru/m/tankz/game/Spawner.hx | 83 +++++++++++++++++ 6 files changed, 123 insertions(+), 75 deletions(-) create mode 100644 src/common/haxe/ru/m/tankz/game/Spawner.hx diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index 93122e0..29fc348 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -89,6 +89,11 @@ class Render extends SpriteView implements EngineListener { items.set(bullet.key, item); entryLayer.addChild(item.view); item.update(); + case EntityType.EAGLE(eagle): + var item = new EagleItem(eagle); + items.set(eagle.key, item); + entryLayer.addChild(item.view); + item.update(); case _: } } @@ -109,6 +114,11 @@ class Render extends SpriteView implements EngineListener { entryLayer.removeChild(items.get(bullet.key).view); items.remove(bullet.key); } + case EntityType.EAGLE(eagle): + if (items.exists(eagle.key)) { + cast(items.get(eagle.key), EagleItem).destoyed = true; + items.get(eagle.key).redraw(); + } case _: } } diff --git a/src/client/haxe/ru/m/tankz/render/RenderItem.hx b/src/client/haxe/ru/m/tankz/render/RenderItem.hx index 984d794..c61271c 100644 --- a/src/client/haxe/ru/m/tankz/render/RenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/RenderItem.hx @@ -1,5 +1,6 @@ package ru.m.tankz.render; +import ru.m.tankz.core.Eagle; import flash.display.DisplayObject; import flash.display.Shape; import ru.m.geom.Direction; @@ -133,3 +134,13 @@ class BulletItem extends RenderItem { return 'resources/images/bullet/bullet_${value.config.piercing > 1 ? 1 : 0}.png'; } } + + +class EagleItem extends RenderItem { + + public var destoyed(default, default):Bool; + + override private function getImage():String { + return 'resources/images/eagle/eagle-${destoyed ? 1 : 0}.png'; + } +} diff --git a/src/client/resources/config/classic.yaml b/src/client/resources/config/classic.yaml index 5d3048f..622c7cf 100644 --- a/src/client/resources/config/classic.yaml +++ b/src/client/resources/config/classic.yaml @@ -44,7 +44,7 @@ teams: index: -1 x: 12 y: 24 - direction: top + direction: right - type: tank index: 0 x: 8 diff --git a/src/common/haxe/ru/m/tankz/core/Eagle.hx b/src/common/haxe/ru/m/tankz/core/Eagle.hx index 0f856ba..e1fb93b 100644 --- a/src/common/haxe/ru/m/tankz/core/Eagle.hx +++ b/src/common/haxe/ru/m/tankz/core/Eagle.hx @@ -6,6 +6,6 @@ import ru.m.geom.Rectangle; class Eagle extends Entity { public function new() { - super(new Rectangle(0, 0, 10, 10)); + super(new Rectangle(0, 0, 44, 44)); } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 06ea91f..63ee8e0 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -1,14 +1,17 @@ package ru.m.tankz.game; -import haxe.Timer; -import ru.m.tankz.core.EntityType; +import ru.m.tankz.game.Spawner; +import ru.m.tankz.core.Entity; +import ru.m.tankz.core.Eagle; import ru.m.geom.Direction; import ru.m.geom.Point; import ru.m.tankz.config.Config; import ru.m.tankz.control.Control; +import ru.m.tankz.core.EntityType; import ru.m.tankz.core.Tank; import ru.m.tankz.engine.Engine; + typedef GameType = String; typedef TeamId = String; @@ -19,74 +22,6 @@ typedef PlayerId = { } -typedef SpawnTask = { - var point:SpawnPoint; - var playerId:PlayerId; -} - - -class Spawner { - - private var config:TeamConfig; - private var runner:SpawnTask -> Void; - private var queue:Array; - private var timer:Timer; - - private var indexedPoints:Map; - private var anyPoints:Array; - private var index:Int; - - public function new(config:TeamConfig, runner:SpawnTask -> Void) { - this.config = config; - this.runner = runner; - queue = []; - indexedPoints = new Map(); - anyPoints = []; - for (point in config.points) { - if (point.type == 'tank') { - if (point.index > -1) { - indexedPoints.set(point.index, point); - } else { - anyPoints.push(point); - } - } - } - } - - public function push(playerId:PlayerId):Void { - var point:SpawnPoint = null; - if (indexedPoints.exists(playerId.index)) { - point = indexedPoints.get(playerId.index); - } else { - point = anyPoints[index++]; - if (index >= anyPoints.length) index = 0; - } - if (point != null) { - queue.push({playerId:playerId, point:point}); - run(); - } - } - - private function run():Void { - if (timer == null) { - timer = new Timer(config.spawnInterval); - timer.run = spawn; - } - } - - private function spawn():Void { - if (queue.length == 0) { - if (timer != null) { - timer.stop(); - timer = null; - } - } else { - runner(queue.shift()); - } - } -} - - class Game implements EngineListener implements ControlListener { public var type(default, null):GameType; @@ -109,11 +44,15 @@ class Game implements EngineListener implements ControlListener { private function buildTank(playerId:PlayerId, config:TankConfig, point:SpawnPoint):Tank { var tank = new Tank(playerId, config); - tank.rect.center = new Point((point.x + 1) * engine.map.cellWidth, (point.y + 1) * engine.map.cellHeight); - tank.rect.direction = Direction.fromString(point.direction); + applyPoint(tank, point); return tank; } + private function applyPoint(entity:Entity, point:SpawnPoint):Void { + entity.rect.center = new Point((point.x + 1) * engine.map.cellWidth, (point.y + 1) * engine.map.cellHeight); + entity.rect.direction = Direction.fromString(point.direction); + } + public function start():Void { teams = new Map(); spawners = new Map(); @@ -129,9 +68,14 @@ class Game implements EngineListener implements ControlListener { for (team in teams) { for (player in team.players) { - var point = team.config.points[0]; spawners.get(team.id).push(player.id); } + var eaglePoint = spawners.get(team.id).getPoint('eagle'); + if (eaglePoint != null) { + var eagle = new Eagle(); + applyPoint(eagle, eaglePoint); + engine.spawn(eagle); + } } } diff --git a/src/common/haxe/ru/m/tankz/game/Spawner.hx b/src/common/haxe/ru/m/tankz/game/Spawner.hx new file mode 100644 index 0000000..7db2992 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/game/Spawner.hx @@ -0,0 +1,83 @@ +package ru.m.tankz.game; + + +import haxe.Timer; +import ru.m.tankz.game.Game; +import ru.m.tankz.config.Config; + + +typedef SpawnTask = { + var point:SpawnPoint; + var playerId:PlayerId; +} + + +class Spawner { + + private var config:TeamConfig; + private var runner:SpawnTask -> Void; + private var queue:Array; + private var timer:Timer; + + private var indexedPoints:Map; + private var anyPoints:Array; + private var index:Int; + + public function new(config:TeamConfig, runner:SpawnTask -> Void) { + this.config = config; + this.runner = runner; + queue = []; + indexedPoints = new Map(); + anyPoints = []; + for (point in config.points) { + if (point.type == 'tank') { + if (point.index > -1) { + indexedPoints.set(point.index, point); + } else { + anyPoints.push(point); + } + } + } + } + + public function getPoint(type:String, index:Int=-1):Null { + for (point in config.points) { + if (point.type == type && point.index == index) { + return point; + } + } + return null; + } + + public function push(playerId:PlayerId):Void { + var point:SpawnPoint = null; + if (indexedPoints.exists(playerId.index)) { + point = indexedPoints.get(playerId.index); + } else { + point = anyPoints[index++]; + if (index >= anyPoints.length) index = 0; + } + if (point != null) { + queue.push({playerId:playerId, point:point}); + run(); + } + } + + private function run():Void { + if (timer == null) { + timer = new Timer(config.spawnInterval); + timer.run = spawn; + } + } + + private function spawn():Void { + if (queue.length == 0) { + if (timer != null) { + timer.stop(); + timer = null; + } + } else { + runner(queue.shift()); + } + } +} \ No newline at end of file From 36c5f161fe3565a3d3ee022e575865a6e3fe2ed1 Mon Sep 17 00:00:00 2001 From: shmyga Date: Thu, 25 Jan 2018 14:20:30 +0300 Subject: [PATCH 11/22] [common] update control binding --- src/common/haxe/ru/m/tankz/bot/Bot.hx | 3 ++- src/common/haxe/ru/m/tankz/control/Control.hx | 18 ++++++++++-------- src/common/haxe/ru/m/tankz/engine/Engine.hx | 2 +- src/common/haxe/ru/m/tankz/game/Game.hx | 4 ++-- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/common/haxe/ru/m/tankz/bot/Bot.hx b/src/common/haxe/ru/m/tankz/bot/Bot.hx index 0eeaa98..03b4bbf 100644 --- a/src/common/haxe/ru/m/tankz/bot/Bot.hx +++ b/src/common/haxe/ru/m/tankz/bot/Bot.hx @@ -24,7 +24,8 @@ class Bot extends Control { } override public function start():Void { - action(TankAction.MOVE(Direction.BOTTOM)); + var tank = handler.entities.get(tankId); + action(TankAction.MOVE(tank.rect.direction)); if (shotTimer == null) { shotTimer = new Timer(1000); shotTimer.run = shot; diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx index c7d7ce8..482ca90 100644 --- a/src/common/haxe/ru/m/tankz/control/Control.hx +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -1,5 +1,6 @@ package ru.m.tankz.control; +import ru.m.tankz.core.Entity; import ru.m.tankz.core.EntityType; import ru.m.geom.Direction; @@ -14,17 +15,17 @@ enum TankAction { class Control { public var tankId(default, default):Int; - private var listener:ControlListener; + private var handler:ControlHandler; public function new() {} - public function bind(listener:ControlListener):Void { - this.listener = listener; + public function bind(handler:ControlHandler):Void { + this.handler = handler; } public function action(action:TankAction):Void { - if (tankId != 0 && listener != null) { - listener.onAction(tankId, action); + if (tankId != 0 && handler != null) { + handler.action(tankId, action); } } @@ -38,10 +39,11 @@ class Control { public function dispose():Void { stop(); - listener = null; + handler = null; } } -interface ControlListener { - public function onAction(tankId:Int, action:TankAction):Void; +interface ControlHandler { + public var entities(default, null):Map; + public function action(tankId:Int, action:TankAction):Void; } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index db46851..1a49ac8 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -73,7 +73,7 @@ class CollisionProcessor implements EngineListener { } -class Engine { +class Engine implements ControlHandler { public var config(default, default):Config; public var map(default, null):LevelMap; diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 63ee8e0..a7d0fb6 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -22,7 +22,7 @@ typedef PlayerId = { } -class Game implements EngineListener implements ControlListener { +class Game implements EngineListener { public var type(default, null):GameType; public var teams(default, null):Map; @@ -94,7 +94,7 @@ class Game implements EngineListener implements ControlListener { player.control.dispose(); } player.control = control; - player.control.bind(this); + player.control.bind(engine); break; } } From 7ac181ed5a71bb6a15fce082895757655aa1c1c8 Mon Sep 17 00:00:00 2001 From: shmyga Date: Thu, 25 Jan 2018 22:55:39 +0300 Subject: [PATCH 12/22] [common] added GameState --- src/client/haxe/ru/m/tankz/Client.hx | 6 +- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 18 +- .../haxe/ru/m/tankz/view/frames/StartFrame.hx | 11 +- src/client/resources/config/classic.yaml | 3 - src/client/resources/fonts/8-BIT WONDER.TTF | Bin 14328 -> 0 bytes src/client/resources/fonts/8-BIT WONDER.eot | Bin 14536 -> 0 bytes src/client/resources/fonts/8-BIT WONDER.svg | 161 ------------------ src/client/resources/fonts/8-BIT WONDER.woff | Bin 4892 -> 0 bytes src/common/haxe/ru/m/tankz/config/Config.hx | 6 +- .../haxe/ru/m/tankz/config/ConfigBundle.hx | 12 +- .../haxe/ru/m/tankz/config/MapBundle.hx | 22 +++ src/common/haxe/ru/m/tankz/engine/Engine.hx | 3 +- .../haxe/ru/m/tankz/game/ClassicGame.hx | 40 ++++- src/common/haxe/ru/m/tankz/game/Game.hx | 16 +- src/common/haxe/ru/m/tankz/game/GameState.hx | 24 +++ src/common/haxe/ru/m/tankz/map/LevelMap.hx | 7 +- 16 files changed, 121 insertions(+), 208 deletions(-) delete mode 100644 src/client/resources/fonts/8-BIT WONDER.TTF delete mode 100644 src/client/resources/fonts/8-BIT WONDER.eot delete mode 100644 src/client/resources/fonts/8-BIT WONDER.svg delete mode 100644 src/client/resources/fonts/8-BIT WONDER.woff create mode 100644 src/common/haxe/ru/m/tankz/config/MapBundle.hx create mode 100644 src/common/haxe/ru/m/tankz/game/GameState.hx diff --git a/src/client/haxe/ru/m/tankz/Client.hx b/src/client/haxe/ru/m/tankz/Client.hx index 79cbc5f..4257b0e 100755 --- a/src/client/haxe/ru/m/tankz/Client.hx +++ b/src/client/haxe/ru/m/tankz/Client.hx @@ -1,5 +1,7 @@ package ru.m.tankz; +import ru.m.tankz.game.ClassicGame; +import ru.m.tankz.game.Game; import flash.ui.Keyboard; import flash.events.KeyboardEvent; import flash.text.Font; @@ -10,8 +12,6 @@ import haxework.resources.IResources; import haxework.gui.VGroupView; import haxework.gui.ViewBuilder; import haxework.gui.ButtonView; -import flash.display.Sprite; -import haxework.gui.IGroupView; import ru.m.tankz.PacketBuilder; import haxework.log.JSLogger; import haxework.gui.frame.IFrameSwitcher; @@ -74,6 +74,8 @@ class Client implements IConnectionHandler { view.switcher.change(StartFrame.ID); } }); + + Provider.setFactory(Game, ClassicGame, ClassicGame.TYPE); } public function onPress(view:ButtonView):Void { 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 cc7084e..08fbd75 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -1,6 +1,6 @@ package ru.m.tankz.view.frames; -import ru.m.tankz.config.Config; +import ru.m.tankz.game.GameState; import ru.m.tankz.control.PlayerControl; import flash.events.Event; import haxe.Timer; @@ -9,8 +9,6 @@ import haxework.gui.ViewBuilder; import haxework.provider.Provider; import protohx.Message; import ru.m.connect.IConnection; -import ru.m.tankz.config.ConfigBundle; -import ru.m.tankz.game.ClassicGame; import ru.m.tankz.game.Game; import ru.m.tankz.proto.pack.GameUpdateResponse; @@ -29,15 +27,15 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand } public function onShow():Void { - var config:Config = Provider.get(Config); - game = switch (config.type) { - case ClassicGame.TYPE: new ClassicGame(config); - case x: throw 'Unsupported game type "${x}"'; + var state:GameState = Provider.get(GameState); + game = Provider.build(Game, state.type); + if (game == null) { + throw 'Unsupported game type "${state.type}"'; } game.engine.listeners.push(render); - game.start(); - for (index in 0...game.config.getTeam('human').size) { - game.setControl({team:'human', index:index}, PlayerControl.forPlayer(index)); + game.start(state); + for (human in state.players['human'].iterator()) { + game.setControl({team:'human', index:human.index}, PlayerControl.forPlayer(human.index)); } content.addEventListener(Event.ENTER_FRAME, redraw); Provider.get(IConnection).packetHandler.addListener(this); diff --git a/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx b/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx index 51486b9..3bb257b 100644 --- a/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx @@ -1,14 +1,14 @@ package ru.m.tankz.view.frames; -import ru.m.tankz.config.Config; +import ru.m.tankz.game.GameState; import ru.m.tankz.game.ClassicGame; -import ru.m.tankz.config.ConfigBundle; import haxework.gui.frame.IFrameSwitcher; import haxework.provider.Provider; import haxework.gui.ButtonView; import haxework.gui.ViewBuilder; import haxework.gui.VGroupView; + @:template("layout/frames/start.json", "layout/styles.json") class StartFrame extends VGroupView implements ViewBuilder { @@ -28,11 +28,8 @@ class StartFrame extends VGroupView implements ViewBuilder { } } - private function startGame(players:Int):Void { - var config = ConfigBundle.get(ClassicGame.TYPE, 0); - config.getTeam('human').size = players; - config.getTeam('bot').size = 2 + 2 * players; - Provider.set(Config, config); + private function startGame(humans:Int):Void { + Provider.set(GameState, ClassicGame.buildState(0, humans)); Provider.get(IFrameSwitcher).change(GameFrame.ID); } } diff --git a/src/client/resources/config/classic.yaml b/src/client/resources/config/classic.yaml index 622c7cf..498e7bd 100644 --- a/src/client/resources/config/classic.yaml +++ b/src/client/resources/config/classic.yaml @@ -3,7 +3,6 @@ map: cellHeight: 22 gridWidth: 26 gridHeight: 26 - bricks: [] bricks: # border @@ -37,7 +36,6 @@ bricks: teams: - id: human - size: 2 spawnInterval: 0 points: - type: eagle @@ -56,7 +54,6 @@ teams: y: 24 direction: top - id: bot - size: 6 spawnInterval: 3000 points: - type: tank diff --git a/src/client/resources/fonts/8-BIT WONDER.TTF b/src/client/resources/fonts/8-BIT WONDER.TTF deleted file mode 100644 index 6d9b3972e185bb15dfa5555eb8e3accd796b50b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14328 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 - -!"#$%&'()*+,-./0123456789:;å<>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghijklmnopqrstuvwxyz|{}~ \ No newline at end of file diff --git a/src/client/resources/fonts/8-BIT WONDER.woff b/src/client/resources/fonts/8-BIT WONDER.woff deleted file mode 100644 index 5902288477f0bc4664db24fd823d3875c42282e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4892 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 diff --git a/src/common/haxe/ru/m/tankz/config/Config.hx b/src/common/haxe/ru/m/tankz/config/Config.hx index d0b1a2d..de6b6cd 100644 --- a/src/common/haxe/ru/m/tankz/config/Config.hx +++ b/src/common/haxe/ru/m/tankz/config/Config.hx @@ -14,7 +14,6 @@ typedef MapConfig = { var cellHeight:Float; var gridWidth:Int; var gridHeight:Int; - var bricks:Array; } typedef BrickConfig = { @@ -31,9 +30,12 @@ typedef BulletConfig = { } -typedef TankConfig = { +typedef TankType = { var group:String; var type:String; +} + +typedef TankConfig = { > TankType, var width:Float; var height:Float; var speed:Float; diff --git a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx index 64827d3..dde0f4c 100644 --- a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx +++ b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx @@ -20,20 +20,10 @@ class ConfigBundle { return raw; } - public static function get(type:String, level:Int):Config { + public static function get(type:String):Config { switch (type) { case ClassicGame.TYPE: var source:ConfigSource = convert(Yaml.parse(Assets.getText('resources/config/${type}.yaml'), Parser.options().useObjects())); - var bricksData:String = Assets.getText('resources/levels/level00${level}.txt'); - var bricks:Array = []; - for (line in ~/\s+/g.split(bricksData)) { - for (c in line.split('')) { - if (c.length > 0) { - bricks.push(source.bricks[Std.parseInt(c) + 1]); - } - } - } - source.map.bricks = bricks; var tanks:Array = []; for (group in Reflect.fields(source.tanks)) { var data:Array = Reflect.field(source.tanks, group); diff --git a/src/common/haxe/ru/m/tankz/config/MapBundle.hx b/src/common/haxe/ru/m/tankz/config/MapBundle.hx new file mode 100644 index 0000000..66f1f12 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/config/MapBundle.hx @@ -0,0 +1,22 @@ +package ru.m.tankz.config; + +import openfl.Assets; +import ru.m.tankz.game.Game; +import ru.m.tankz.config.Config; + + +class MapBundle { + + public static function get(type:GameType, config:Config, level:Int):Array { + var bricksData:String = Assets.getText('resources/levels/level00${level}.txt'); + var bricks:Array = []; + for (line in ~/\s+/g.split(bricksData)) { + for (c in line.split('')) { + if (c.length > 0) { + bricks.push(config.bricks[Std.parseInt(c) + 1]); + } + } + } + return bricks; + } +} diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 1a49ac8..ea449ae 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -122,7 +122,8 @@ class Engine implements ControlHandler { case TankAction.MOVE(direction): tank.move(direction); case TankAction.LEVEL_UP(level): - tank.config = config.getTank('player', Std.string(Std.int(Math.min(Std.parseInt(tank.config.type) + level, 3)))); + // ToDo: + tank.config = config.getTank('human', Std.string(Std.int(Math.min(Std.parseInt(tank.config.type) + level, 3)))); case TankAction.STOP: tank.stop(); case TankAction.SHOT: diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index 9a13d7c..ff2cbe2 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import ru.m.tankz.game.GameState.PlayerState; import ru.m.tankz.bot.Bot; import ru.m.tankz.game.Game; import ru.m.tankz.config.Config; @@ -9,14 +10,43 @@ class ClassicGame extends Game { public static var TYPE(default, never):GameType = 'classic'; - public function new(config:Config) { - super(TYPE, config); + public static var HUMAN(default, never):TeamId = 'human'; + public static var BOT(default, never):TeamId = 'bot'; + + public function new() { + super(TYPE); } - override public function start():Void { - super.start(); - for (player in teams.get('bot').players) { + override public function start(state:GameState):Void { + super.start(state); + for (player in teams.get(BOT).players) { setControl(player.id, new Bot()); } } + + public static function buildState(level:Int, humans:Int):GameState { + var state = new GameState(); + state.type = TYPE; + state.level = level; + state.players[HUMAN] = new Map(); + state.players[BOT] = new Map(); + for (i in 0...humans) { + state.players[HUMAN][i] = { + index:i, + tank:{ + group: HUMAN, + type: '1' + }, + life:3, + }; + } + for (i in 0...humans*2+2) { + state.players[BOT][i] = { + index:i, + tank:null, + life:-1, + }; + } + return state; + } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index a7d0fb6..618609c 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -1,5 +1,7 @@ package ru.m.tankz.game; +import ru.m.tankz.config.ConfigBundle; +import ru.m.tankz.config.MapBundle; import ru.m.tankz.game.Spawner; import ru.m.tankz.core.Entity; import ru.m.tankz.core.Eagle; @@ -25,15 +27,16 @@ typedef PlayerId = { class Game implements EngineListener { public var type(default, null):GameType; + public var state(default, null):GameState; public var teams(default, null):Map; public var config(default, null):Config; public var engine(default, null):Engine; private var spawners:Map; - public function new(type:GameType, config:Config) { + public function new(type:GameType) { this.type = type; - this.config = config; + this.config = ConfigBundle.get(type); this.engine = new Engine(config); engine.listeners.push(this); } @@ -53,13 +56,16 @@ class Game implements EngineListener { entity.rect.direction = Direction.fromString(point.direction); } - public function start():Void { + public function start(state:GameState):Void { + this.state = state; + var bricks = MapBundle.get(type, config, state.level); + engine.map.setData(bricks); teams = new Map(); spawners = new Map(); for (teamConfig in config.teams) { var team = new Team(teamConfig); - for (index in 0...team.config.size) { - var player = new Player({team:team.id, index:index}); + for (playerState in state.players.get(team.id)) { + var player = new Player({team:team.id, index:playerState.index}); team.players.push(player); teams.set(team.id, team); } diff --git a/src/common/haxe/ru/m/tankz/game/GameState.hx b/src/common/haxe/ru/m/tankz/game/GameState.hx new file mode 100644 index 0000000..fbd018e --- /dev/null +++ b/src/common/haxe/ru/m/tankz/game/GameState.hx @@ -0,0 +1,24 @@ +package ru.m.tankz.game; + +import ru.m.tankz.game.Game; +import ru.m.tankz.config.Config; + + +typedef PlayerState = { + var index:Int; + var tank:TankType; + var life:Int; +} + + +class GameState { + public var type:GameType; + public var level:Int; + public var players:Map>; + + public function new() { + type = null; + level = -1; + players = new Map(); + } +} diff --git a/src/common/haxe/ru/m/tankz/map/LevelMap.hx b/src/common/haxe/ru/m/tankz/map/LevelMap.hx index 554353f..ec59d39 100755 --- a/src/common/haxe/ru/m/tankz/map/LevelMap.hx +++ b/src/common/haxe/ru/m/tankz/map/LevelMap.hx @@ -28,13 +28,18 @@ class LevelMap { gridWidth = config.gridWidth; gridHeight = config.gridHeight; bricksMap = new HashMap(); + bricks = []; grid = new Grid( Std.int(cellWidth / 2), Std.int(cellHeight / 2), Std.int(cellWidth * gridWidth), Std.int(cellHeight * gridHeight) ); - bricks = Lambda.array(Lambda.mapi(config.bricks, function(i:Int, brickConfig:BrickConfig):Brick { + } + + public function setData(data:Array):Void { + bricksMap = new HashMap(); + bricks = Lambda.array(Lambda.mapi(data, function(i:Int, brickConfig:BrickConfig):Brick { var cellX = Std.int(i % gridWidth); var cellY = Std.int(Math.floor(i / gridHeight)); var cells:HashMap = new HashMap(); From d72d7e8c81cb89464053b94080899c48229904ce Mon Sep 17 00:00:00 2001 From: shmyga Date: Fri, 26 Jan 2018 12:01:38 +0300 Subject: [PATCH 13/22] [common] added control to PlayerState --- .../{PlayerControl.hx => HumanControl.hx} | 27 +++++++++++-------- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 4 --- .../ru/m/tankz/bot/{Bot.hx => BotControl.hx} | 12 +++++---- src/common/haxe/ru/m/tankz/control/Control.hx | 14 +++++++++- .../haxe/ru/m/tankz/game/ClassicGame.hx | 22 ++++++++------- src/common/haxe/ru/m/tankz/game/Game.hx | 11 ++++++++ src/common/haxe/ru/m/tankz/game/GameState.hx | 10 +++++++ 7 files changed, 69 insertions(+), 31 deletions(-) rename src/client/haxe/ru/m/tankz/control/{PlayerControl.hx => HumanControl.hx} (85%) rename src/common/haxe/ru/m/tankz/bot/{Bot.hx => BotControl.hx} (78%) diff --git a/src/client/haxe/ru/m/tankz/control/PlayerControl.hx b/src/client/haxe/ru/m/tankz/control/HumanControl.hx similarity index 85% rename from src/client/haxe/ru/m/tankz/control/PlayerControl.hx rename to src/client/haxe/ru/m/tankz/control/HumanControl.hx index f9b96c1..0a7e287 100644 --- a/src/client/haxe/ru/m/tankz/control/PlayerControl.hx +++ b/src/client/haxe/ru/m/tankz/control/HumanControl.hx @@ -8,15 +8,20 @@ import flash.ui.Keyboard; import flash.events.KeyboardEvent; import flash.Lib; -class PlayerControl extends Control { - private var keyBinding:Map; +typedef KeyBinding = Map; + + +class HumanControl extends Control { + public static var TYPE(default, never):ControlType = 'human'; + + private var keyBinding:KeyBinding; private var moveQueue:Array; private var shotTimer:Timer; - public function new(keyBinding:Map) { - super(); - this.keyBinding = keyBinding; + public function new(index:Int) { + super({type:TYPE, index:index}); + this.keyBinding = resolve(index); moveQueue = new Array(); Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); Lib.current.stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); @@ -78,26 +83,26 @@ class PlayerControl extends Control { action(TankAction.SHOT); } - public static function forPlayer(index:Int):PlayerControl { + private static function resolve(index:Int):KeyBinding { switch (index) { case 0: - return new PlayerControl([ + return [ Keyboard.A => TankAction.MOVE(Direction.LEFT), Keyboard.S => TankAction.MOVE(Direction.BOTTOM), Keyboard.W => TankAction.MOVE(Direction.TOP), Keyboard.D => TankAction.MOVE(Direction.RIGHT), Keyboard.SPACE => TankAction.SHOT - ]); + ]; case 1: - return new PlayerControl([ + return [ Keyboard.LEFT => TankAction.MOVE(Direction.LEFT), Keyboard.DOWN => TankAction.MOVE(Direction.BOTTOM), Keyboard.UP => TankAction.MOVE(Direction.TOP), Keyboard.RIGHT => TankAction.MOVE(Direction.RIGHT), Keyboard.NUMPAD_0 => TankAction.SHOT - ]); + ]; case _: - throw 'Invalid player index ${index}'; + throw 'Invalid control index ${index}'; } } } 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 08fbd75..e304d12 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -1,7 +1,6 @@ package ru.m.tankz.view.frames; import ru.m.tankz.game.GameState; -import ru.m.tankz.control.PlayerControl; import flash.events.Event; import haxe.Timer; import haxework.gui.VGroupView; @@ -34,9 +33,6 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand } game.engine.listeners.push(render); game.start(state); - for (human in state.players['human'].iterator()) { - game.setControl({team:'human', index:human.index}, PlayerControl.forPlayer(human.index)); - } content.addEventListener(Event.ENTER_FRAME, redraw); Provider.get(IConnection).packetHandler.addListener(this); render.draw(game.engine); diff --git a/src/common/haxe/ru/m/tankz/bot/Bot.hx b/src/common/haxe/ru/m/tankz/bot/BotControl.hx similarity index 78% rename from src/common/haxe/ru/m/tankz/bot/Bot.hx rename to src/common/haxe/ru/m/tankz/bot/BotControl.hx index 03b4bbf..1ad360a 100644 --- a/src/common/haxe/ru/m/tankz/bot/Bot.hx +++ b/src/common/haxe/ru/m/tankz/bot/BotControl.hx @@ -6,13 +6,14 @@ import ru.m.geom.Direction; import haxe.Timer; -class Bot extends Control { +class BotControl extends Control { + public static var TYPE(default, never):ControlType = 'bot'; private var shotTimer:Timer; private var turnTimer:Timer; - public function new() { - super(); + public function new(index:Int) { + super({type:TYPE, index:index}); } override public function onCollision(with:EntityType):Void { @@ -24,8 +25,9 @@ class Bot extends Control { } override public function start():Void { - var tank = handler.entities.get(tankId); - action(TankAction.MOVE(tank.rect.direction)); + //var tank = handler.entities.get(tankId); + //action(TankAction.MOVE(tank.rect.direction)); + action(TankAction.MOVE(Direction.BOTTOM)); // ToDo: hardcode bot start direction if (shotTimer == null) { shotTimer = new Timer(1000); shotTimer.run = shot; diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx index 482ca90..45abfe7 100644 --- a/src/common/haxe/ru/m/tankz/control/Control.hx +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -13,11 +13,23 @@ enum TankAction { } +typedef ControlType = String; + + +typedef ControlId = { + var type:ControlType; + var index:Int; +} + + class Control { + public var id:ControlId; public var tankId(default, default):Int; private var handler:ControlHandler; - public function new() {} + public function new(id:ControlId) { + this.id = id; + } public function bind(handler:ControlHandler):Void { this.handler = handler; diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index ff2cbe2..b520eb2 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -1,9 +1,7 @@ package ru.m.tankz.game; import ru.m.tankz.game.GameState.PlayerState; -import ru.m.tankz.bot.Bot; import ru.m.tankz.game.Game; -import ru.m.tankz.config.Config; class ClassicGame extends Game { @@ -17,13 +15,6 @@ class ClassicGame extends Game { super(TYPE); } - override public function start(state:GameState):Void { - super.start(state); - for (player in teams.get(BOT).players) { - setControl(player.id, new Bot()); - } - } - public static function buildState(level:Int, humans:Int):GameState { var state = new GameState(); state.type = TYPE; @@ -37,13 +28,24 @@ class ClassicGame extends Game { group: HUMAN, type: '1' }, + control:{ + type: 'human', + index: i + }, life:3, }; } for (i in 0...humans*2+2) { state.players[BOT][i] = { index:i, - tank:null, + tank:{ + group: BOT, + type: '1' + }, + control:{ + type: 'bot', + index: i + }, life:-1, }; } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 618609c..eec14f8 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -1,5 +1,7 @@ package ru.m.tankz.game; +import ru.m.tankz.bot.BotControl; +import ru.m.tankz.control.HumanControl; import ru.m.tankz.config.ConfigBundle; import ru.m.tankz.config.MapBundle; import ru.m.tankz.game.Spawner; @@ -68,6 +70,15 @@ class Game implements EngineListener { var player = new Player({team:team.id, index:playerState.index}); team.players.push(player); teams.set(team.id, team); + if (playerState.control != null) { + var control = switch (playerState.control.type) { + case HumanControl.TYPE: new HumanControl(playerState.control.index); + case BotControl.TYPE: new BotControl(playerState.control.index); + case _: throw 'Unsupported control type: "${playerState.control.type}"'; + } + player.control = control; + player.control.bind(engine); + } } spawners.set(team.id, new Spawner(team.config, spawn)); } diff --git a/src/common/haxe/ru/m/tankz/game/GameState.hx b/src/common/haxe/ru/m/tankz/game/GameState.hx index fbd018e..a619a6f 100644 --- a/src/common/haxe/ru/m/tankz/game/GameState.hx +++ b/src/common/haxe/ru/m/tankz/game/GameState.hx @@ -4,10 +4,20 @@ import ru.m.tankz.game.Game; import ru.m.tankz.config.Config; +typedef ControlType = String; + + +typedef ControId = { + var type:ControlType; + var index:Int; +} + + typedef PlayerState = { var index:Int; var tank:TankType; var life:Int; + var control:ControId; } From 6a00ee83d75cd68675cdfb5c518d60feb53302af Mon Sep 17 00:00:00 2001 From: shmyga Date: Fri, 26 Jan 2018 14:38:36 +0300 Subject: [PATCH 14/22] [client] LevelFrame --- src/client/haxe/layout/frames/level.json | 21 +++++++++++ src/client/haxe/layout/main.json | 4 +++ src/client/haxe/layout/other.json | 13 ++++--- src/client/haxe/ru/m/tankz/render/Render.hx | 9 ++++- .../haxe/ru/m/tankz/view/frames/LevelFrame.hx | 35 +++++++++++++++++++ .../haxe/ru/m/tankz/view/frames/StartFrame.hx | 2 +- .../ru/m/tankz/view/frames/list/GameView.hx | 33 ----------------- .../ru/m/tankz/view/frames/list/LevelView.hx | 24 +++++++++++++ .../ru/m/tankz/view/frames/list/PersonView.hx | 19 ---------- .../classic.yaml => classic/config.yaml} | 2 ++ .../{ => classic}/levels/level000.txt | 0 .../{ => classic}/levels/level001.txt | 0 .../{ => classic}/levels/level002.txt | 0 .../{ => classic}/levels/level003.txt | 0 .../{ => classic}/levels/level004.txt | 0 .../{ => classic}/levels/level005.txt | 0 .../{ => classic}/levels/level006.txt | 0 .../{ => classic}/levels/level007.txt | 0 .../{ => classic}/levels/level008.txt | 0 .../{ => classic}/levels/level009.txt | 0 .../{ => classic}/levels/level010.txt | 0 .../{ => classic}/levels/level011.txt | 0 .../{ => classic}/levels/level012.txt | 0 .../{ => classic}/levels/level013.txt | 0 .../{ => classic}/levels/level014.txt | 0 .../{ => classic}/levels/level015.txt | 0 .../{ => classic}/levels/level016.txt | 0 .../{ => classic}/levels/level017.txt | 0 .../{ => classic}/levels/level018.txt | 0 .../{ => classic}/levels/level019.txt | 0 .../{ => classic}/levels/level020.txt | 0 .../{ => classic}/levels/level021.txt | 0 .../{ => classic}/levels/level022.txt | 0 .../{ => classic}/levels/level023.txt | 0 .../{ => classic}/levels/level024.txt | 0 .../{ => classic}/levels/level025.txt | 0 .../{ => classic}/levels/level026.txt | 0 .../{ => classic}/levels/level027.txt | 0 .../{ => classic}/levels/level028.txt | 0 .../{ => classic}/levels/level029.txt | 0 .../{ => classic}/levels/level030.txt | 0 .../{ => classic}/levels/level031.txt | 0 .../{ => classic}/levels/level032.txt | 0 .../{ => classic}/levels/level033.txt | 0 .../{ => classic}/levels/level034.txt | 0 .../{ => classic}/levels/level035.txt | 0 src/common/haxe/ru/m/tankz/config/Config.hx | 4 ++- .../haxe/ru/m/tankz/config/ConfigBundle.hx | 5 +-- .../config/{MapBundle.hx => LevelBundle.hx} | 10 ++++-- src/common/haxe/ru/m/tankz/game/Game.hx | 4 +-- 50 files changed, 120 insertions(+), 65 deletions(-) create mode 100644 src/client/haxe/layout/frames/level.json create mode 100644 src/client/haxe/ru/m/tankz/view/frames/LevelFrame.hx delete mode 100755 src/client/haxe/ru/m/tankz/view/frames/list/GameView.hx create mode 100755 src/client/haxe/ru/m/tankz/view/frames/list/LevelView.hx delete mode 100755 src/client/haxe/ru/m/tankz/view/frames/list/PersonView.hx rename src/client/resources/{config/classic.yaml => classic/config.yaml} (99%) rename src/client/resources/{ => classic}/levels/level000.txt (100%) rename src/client/resources/{ => classic}/levels/level001.txt (100%) rename src/client/resources/{ => classic}/levels/level002.txt (100%) rename src/client/resources/{ => classic}/levels/level003.txt (100%) rename src/client/resources/{ => classic}/levels/level004.txt (100%) rename src/client/resources/{ => classic}/levels/level005.txt (100%) rename src/client/resources/{ => classic}/levels/level006.txt (100%) rename src/client/resources/{ => classic}/levels/level007.txt (100%) rename src/client/resources/{ => classic}/levels/level008.txt (100%) rename src/client/resources/{ => classic}/levels/level009.txt (100%) rename src/client/resources/{ => classic}/levels/level010.txt (100%) rename src/client/resources/{ => classic}/levels/level011.txt (100%) rename src/client/resources/{ => classic}/levels/level012.txt (100%) rename src/client/resources/{ => classic}/levels/level013.txt (100%) rename src/client/resources/{ => classic}/levels/level014.txt (100%) rename src/client/resources/{ => classic}/levels/level015.txt (100%) rename src/client/resources/{ => classic}/levels/level016.txt (100%) rename src/client/resources/{ => classic}/levels/level017.txt (100%) rename src/client/resources/{ => classic}/levels/level018.txt (100%) rename src/client/resources/{ => classic}/levels/level019.txt (100%) rename src/client/resources/{ => classic}/levels/level020.txt (100%) rename src/client/resources/{ => classic}/levels/level021.txt (100%) rename src/client/resources/{ => classic}/levels/level022.txt (100%) rename src/client/resources/{ => classic}/levels/level023.txt (100%) rename src/client/resources/{ => classic}/levels/level024.txt (100%) rename src/client/resources/{ => classic}/levels/level025.txt (100%) rename src/client/resources/{ => classic}/levels/level026.txt (100%) rename src/client/resources/{ => classic}/levels/level027.txt (100%) rename src/client/resources/{ => classic}/levels/level028.txt (100%) rename src/client/resources/{ => classic}/levels/level029.txt (100%) rename src/client/resources/{ => classic}/levels/level030.txt (100%) rename src/client/resources/{ => classic}/levels/level031.txt (100%) rename src/client/resources/{ => classic}/levels/level032.txt (100%) rename src/client/resources/{ => classic}/levels/level033.txt (100%) rename src/client/resources/{ => classic}/levels/level034.txt (100%) rename src/client/resources/{ => classic}/levels/level035.txt (100%) rename src/common/haxe/ru/m/tankz/config/{MapBundle.hx => LevelBundle.hx} (62%) diff --git a/src/client/haxe/layout/frames/level.json b/src/client/haxe/layout/frames/level.json new file mode 100644 index 0000000..4da14f3 --- /dev/null +++ b/src/client/haxe/layout/frames/level.json @@ -0,0 +1,21 @@ +{ + "pWidth": 100, "pHeight": 100, + "views": [ + { + "id":"levels", "@type":"haxework.gui.list.VListView", + "factory": "@class:ru.m.tankz.view.frames.list.LevelView", + "pWidth":100, + "pHeight":100, + "paddings":10, + "scroll":{ + "@type":"haxework.gui.list.VScrollView", + "width":10, "pHeight":100, + "skin":{"@type":"haxework.gui.list.VScrollSkin"} + }, + "skin": { + "@type": "haxework.gui.skin.ColorSkin", + "color": "0x000000", "alpha": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/src/client/haxe/layout/main.json b/src/client/haxe/layout/main.json index fcbeaca..b475189 100755 --- a/src/client/haxe/layout/main.json +++ b/src/client/haxe/layout/main.json @@ -15,6 +15,10 @@ "id": "start", "@type": "ru.m.tankz.view.frames.StartFrame" }, + { + "id": "level", + "@type": "ru.m.tankz.view.frames.LevelFrame" + }, { "id": "game", "@type": "ru.m.tankz.view.frames.GameFrame" diff --git a/src/client/haxe/layout/other.json b/src/client/haxe/layout/other.json index bf66831..d798e31 100644 --- a/src/client/haxe/layout/other.json +++ b/src/client/haxe/layout/other.json @@ -1,13 +1,18 @@ { - "person": { + "level": { "width": 440, "height": 44, + "margins": 5, "views": [ { - "id": "nameLabel", + "id": "label", "@type": "haxework.gui.LabelView", - "pWidth": 100, "height": 44, "text": "Выбор персонажа", + "pWidth": 100, "pHeight": 100, "text": "", "@style": "label" } - ] + ], + "skin": { + "@type": "haxework.gui.skin.ColorSkin", + "color": "0x000000", "alpha": 0.2 + } } } \ No newline at end of file diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index 29fc348..a585d83 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -1,5 +1,6 @@ package ru.m.tankz.render; +import flash.display.DisplayObjectContainer; import ru.m.tankz.core.EntityType; import flash.display.DisplayObject; import Type.ValueType; @@ -68,15 +69,21 @@ class Render extends SpriteView implements EngineListener { } } + private function clearLayer(layer:DisplayObjectContainer) { + while (layer.numChildren > 0) layer.removeChildAt(0); + } + public function reset():Void { items = new Map>(); if (background != null) { backgroundLayer.removeChild(background); background = null; } + clearLayer(entryLayer); + clearLayer(groundLayer); + clearLayer(upLayer); } - public function onSpawn(entity:EntityType):Void { switch(entity) { case EntityType.TANK(tank): diff --git a/src/client/haxe/ru/m/tankz/view/frames/LevelFrame.hx b/src/client/haxe/ru/m/tankz/view/frames/LevelFrame.hx new file mode 100644 index 0000000..a379872 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/view/frames/LevelFrame.hx @@ -0,0 +1,35 @@ +package ru.m.tankz.view.frames; + +import ru.m.tankz.config.ConfigBundle; +import haxework.gui.frame.IFrameSwitcher; +import ru.m.tankz.game.GameState; +import haxework.provider.Provider; +import haxework.gui.list.ListView; +import haxework.gui.ViewBuilder; +import haxework.gui.VGroupView; + + +interface LevelFrameLayout { + var levels(default, null):ListView; +} + + +@:template("layout/frames/level.json", "layout/styles.json") +class LevelFrame extends VGroupView implements ViewBuilder implements LevelFrameLayout implements ListViewListener { + public static inline var ID = "level"; + + public function init():Void { + levels.dispatcher.addListener(this); + } + + public function onShow():Void { + var state = Provider.get(GameState); + var c = ConfigBundle.get(state.type).levels; + levels.data = [for (i in 0...c) i]; + } + + public function onListItemClick(item:IListItemView):Void { + Provider.get(GameState).level = item.data; + Provider.get(IFrameSwitcher).change(GameFrame.ID); + } +} diff --git a/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx b/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx index 3bb257b..ba0ef4d 100644 --- a/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx @@ -30,6 +30,6 @@ class StartFrame extends VGroupView implements ViewBuilder { private function startGame(humans:Int):Void { Provider.set(GameState, ClassicGame.buildState(0, humans)); - Provider.get(IFrameSwitcher).change(GameFrame.ID); + Provider.get(IFrameSwitcher).change(LevelFrame.ID); } } diff --git a/src/client/haxe/ru/m/tankz/view/frames/list/GameView.hx b/src/client/haxe/ru/m/tankz/view/frames/list/GameView.hx deleted file mode 100755 index c7f5e4d..0000000 --- a/src/client/haxe/ru/m/tankz/view/frames/list/GameView.hx +++ /dev/null @@ -1,33 +0,0 @@ -package ru.m.tankz.view.frames.list; - -import ru.m.tankz.proto.Person; -import ru.m.tankz.proto.Game; -import haxework.gui.list.ListView.IListItemView; -import haxework.gui.LabelView; -import haxework.gui.skin.ColorSkin; -import haxework.gui.HGroupView; - -class GameView extends HGroupView implements IListItemView { - - public var item_index(default, default):Int; - public var data(default, set):Game; - - private var nameLabel:LabelView; - - public function new() { - super(); - pWidth = 100; - height = 50; - skin = new ColorSkin(0xffffff); - - nameLabel = new LabelView(); - addView(nameLabel); - } - - private function set_data(value:Game):Game { - this.data = value; - var persons:String = Lambda.map(this.data.persons, function(p:Person) return p.name).join(","); - nameLabel.text = "Game_" + this.data.id + "(" + persons + ")"; - return this.data; - } -} \ No newline at end of file diff --git a/src/client/haxe/ru/m/tankz/view/frames/list/LevelView.hx b/src/client/haxe/ru/m/tankz/view/frames/list/LevelView.hx new file mode 100755 index 0000000..072fed4 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/view/frames/list/LevelView.hx @@ -0,0 +1,24 @@ +package ru.m.tankz.view.frames.list; + +import haxework.gui.ViewBuilder; +import haxework.gui.HGroupView; +import haxework.gui.LabelView; +import haxework.gui.list.ListView.IListItemView; + + +interface LevelViewLayout { + var label(default, null):LabelView; +} + +@:template("layout/other.json@level", "layout/styles.json") +class LevelView extends HGroupView implements ViewBuilder implements IListItemView implements LevelViewLayout { + + public var item_index(default, default):Int; + public var data(default, set):Int; + + private function set_data(value:Int):Int { + data = value; + label.text = 'Level ${data}'; + return data; + } +} \ No newline at end of file diff --git a/src/client/haxe/ru/m/tankz/view/frames/list/PersonView.hx b/src/client/haxe/ru/m/tankz/view/frames/list/PersonView.hx deleted file mode 100755 index 4d2dbe0..0000000 --- a/src/client/haxe/ru/m/tankz/view/frames/list/PersonView.hx +++ /dev/null @@ -1,19 +0,0 @@ -package ru.m.tankz.view.frames.list; - -import haxework.gui.ViewBuilder; -import haxework.gui.list.ListView.IListItemView; -import ru.m.tankz.proto.Person; -import haxework.gui.HGroupView; - -@:template("layout/other.json@person", "layout/styles.json") -class PersonView extends HGroupView implements ViewBuilder implements IListItemView { - - public var item_index(default, default):Int; - public var data(default, set):Person; - - private function set_data(value:Person):Person { - this.data = value; - nameLabel.text = this.data.name; - return this.data; - } -} \ No newline at end of file diff --git a/src/client/resources/config/classic.yaml b/src/client/resources/classic/config.yaml similarity index 99% rename from src/client/resources/config/classic.yaml rename to src/client/resources/classic/config.yaml index 498e7bd..64254a8 100644 --- a/src/client/resources/config/classic.yaml +++ b/src/client/resources/classic/config.yaml @@ -1,3 +1,5 @@ +levels: 36 + map: cellWidth: 22 cellHeight: 22 diff --git a/src/client/resources/levels/level000.txt b/src/client/resources/classic/levels/level000.txt similarity index 100% rename from src/client/resources/levels/level000.txt rename to src/client/resources/classic/levels/level000.txt diff --git a/src/client/resources/levels/level001.txt b/src/client/resources/classic/levels/level001.txt similarity index 100% rename from src/client/resources/levels/level001.txt rename to src/client/resources/classic/levels/level001.txt diff --git a/src/client/resources/levels/level002.txt b/src/client/resources/classic/levels/level002.txt similarity index 100% rename from src/client/resources/levels/level002.txt rename to src/client/resources/classic/levels/level002.txt diff --git a/src/client/resources/levels/level003.txt b/src/client/resources/classic/levels/level003.txt similarity index 100% rename from src/client/resources/levels/level003.txt rename to src/client/resources/classic/levels/level003.txt diff --git a/src/client/resources/levels/level004.txt b/src/client/resources/classic/levels/level004.txt similarity index 100% rename from src/client/resources/levels/level004.txt rename to src/client/resources/classic/levels/level004.txt diff --git a/src/client/resources/levels/level005.txt b/src/client/resources/classic/levels/level005.txt similarity index 100% rename from src/client/resources/levels/level005.txt rename to src/client/resources/classic/levels/level005.txt diff --git a/src/client/resources/levels/level006.txt b/src/client/resources/classic/levels/level006.txt similarity index 100% rename from src/client/resources/levels/level006.txt rename to src/client/resources/classic/levels/level006.txt diff --git a/src/client/resources/levels/level007.txt b/src/client/resources/classic/levels/level007.txt similarity index 100% rename from src/client/resources/levels/level007.txt rename to src/client/resources/classic/levels/level007.txt diff --git a/src/client/resources/levels/level008.txt b/src/client/resources/classic/levels/level008.txt similarity index 100% rename from src/client/resources/levels/level008.txt rename to src/client/resources/classic/levels/level008.txt diff --git a/src/client/resources/levels/level009.txt b/src/client/resources/classic/levels/level009.txt similarity index 100% rename from src/client/resources/levels/level009.txt rename to src/client/resources/classic/levels/level009.txt diff --git a/src/client/resources/levels/level010.txt b/src/client/resources/classic/levels/level010.txt similarity index 100% rename from src/client/resources/levels/level010.txt rename to src/client/resources/classic/levels/level010.txt diff --git a/src/client/resources/levels/level011.txt b/src/client/resources/classic/levels/level011.txt similarity index 100% rename from src/client/resources/levels/level011.txt rename to src/client/resources/classic/levels/level011.txt diff --git a/src/client/resources/levels/level012.txt b/src/client/resources/classic/levels/level012.txt similarity index 100% rename from src/client/resources/levels/level012.txt rename to src/client/resources/classic/levels/level012.txt diff --git a/src/client/resources/levels/level013.txt b/src/client/resources/classic/levels/level013.txt similarity index 100% rename from src/client/resources/levels/level013.txt rename to src/client/resources/classic/levels/level013.txt diff --git a/src/client/resources/levels/level014.txt b/src/client/resources/classic/levels/level014.txt similarity index 100% rename from src/client/resources/levels/level014.txt rename to src/client/resources/classic/levels/level014.txt diff --git a/src/client/resources/levels/level015.txt b/src/client/resources/classic/levels/level015.txt similarity index 100% rename from src/client/resources/levels/level015.txt rename to src/client/resources/classic/levels/level015.txt diff --git a/src/client/resources/levels/level016.txt b/src/client/resources/classic/levels/level016.txt similarity index 100% rename from src/client/resources/levels/level016.txt rename to src/client/resources/classic/levels/level016.txt diff --git a/src/client/resources/levels/level017.txt b/src/client/resources/classic/levels/level017.txt similarity index 100% rename from src/client/resources/levels/level017.txt rename to src/client/resources/classic/levels/level017.txt diff --git a/src/client/resources/levels/level018.txt b/src/client/resources/classic/levels/level018.txt similarity index 100% rename from src/client/resources/levels/level018.txt rename to src/client/resources/classic/levels/level018.txt diff --git a/src/client/resources/levels/level019.txt b/src/client/resources/classic/levels/level019.txt similarity index 100% rename from src/client/resources/levels/level019.txt rename to src/client/resources/classic/levels/level019.txt diff --git a/src/client/resources/levels/level020.txt b/src/client/resources/classic/levels/level020.txt similarity index 100% rename from src/client/resources/levels/level020.txt rename to src/client/resources/classic/levels/level020.txt diff --git a/src/client/resources/levels/level021.txt b/src/client/resources/classic/levels/level021.txt similarity index 100% rename from src/client/resources/levels/level021.txt rename to src/client/resources/classic/levels/level021.txt diff --git a/src/client/resources/levels/level022.txt b/src/client/resources/classic/levels/level022.txt similarity index 100% rename from src/client/resources/levels/level022.txt rename to src/client/resources/classic/levels/level022.txt diff --git a/src/client/resources/levels/level023.txt b/src/client/resources/classic/levels/level023.txt similarity index 100% rename from src/client/resources/levels/level023.txt rename to src/client/resources/classic/levels/level023.txt diff --git a/src/client/resources/levels/level024.txt b/src/client/resources/classic/levels/level024.txt similarity index 100% rename from src/client/resources/levels/level024.txt rename to src/client/resources/classic/levels/level024.txt diff --git a/src/client/resources/levels/level025.txt b/src/client/resources/classic/levels/level025.txt similarity index 100% rename from src/client/resources/levels/level025.txt rename to src/client/resources/classic/levels/level025.txt diff --git a/src/client/resources/levels/level026.txt b/src/client/resources/classic/levels/level026.txt similarity index 100% rename from src/client/resources/levels/level026.txt rename to src/client/resources/classic/levels/level026.txt diff --git a/src/client/resources/levels/level027.txt b/src/client/resources/classic/levels/level027.txt similarity index 100% rename from src/client/resources/levels/level027.txt rename to src/client/resources/classic/levels/level027.txt diff --git a/src/client/resources/levels/level028.txt b/src/client/resources/classic/levels/level028.txt similarity index 100% rename from src/client/resources/levels/level028.txt rename to src/client/resources/classic/levels/level028.txt diff --git a/src/client/resources/levels/level029.txt b/src/client/resources/classic/levels/level029.txt similarity index 100% rename from src/client/resources/levels/level029.txt rename to src/client/resources/classic/levels/level029.txt diff --git a/src/client/resources/levels/level030.txt b/src/client/resources/classic/levels/level030.txt similarity index 100% rename from src/client/resources/levels/level030.txt rename to src/client/resources/classic/levels/level030.txt diff --git a/src/client/resources/levels/level031.txt b/src/client/resources/classic/levels/level031.txt similarity index 100% rename from src/client/resources/levels/level031.txt rename to src/client/resources/classic/levels/level031.txt diff --git a/src/client/resources/levels/level032.txt b/src/client/resources/classic/levels/level032.txt similarity index 100% rename from src/client/resources/levels/level032.txt rename to src/client/resources/classic/levels/level032.txt diff --git a/src/client/resources/levels/level033.txt b/src/client/resources/classic/levels/level033.txt similarity index 100% rename from src/client/resources/levels/level033.txt rename to src/client/resources/classic/levels/level033.txt diff --git a/src/client/resources/levels/level034.txt b/src/client/resources/classic/levels/level034.txt similarity index 100% rename from src/client/resources/levels/level034.txt rename to src/client/resources/classic/levels/level034.txt diff --git a/src/client/resources/levels/level035.txt b/src/client/resources/classic/levels/level035.txt similarity index 100% rename from src/client/resources/levels/level035.txt rename to src/client/resources/classic/levels/level035.txt diff --git a/src/common/haxe/ru/m/tankz/config/Config.hx b/src/common/haxe/ru/m/tankz/config/Config.hx index de6b6cd..0d5536b 100644 --- a/src/common/haxe/ru/m/tankz/config/Config.hx +++ b/src/common/haxe/ru/m/tankz/config/Config.hx @@ -54,6 +54,7 @@ typedef TeamConfig = { class Config { public var type(default, null):String; + public var levels(default, null):Int; public var map(default, null):MapConfig; public var bricks(default, null):Array; public var tanks(default, null):Array; @@ -63,8 +64,9 @@ class Config { private var tankMap:Map>; private var teamMap:Map; - public function new(type:String, map:MapConfig, bricks:Array, teams:Array, tanks:Array) { + public function new(type:String, levels:Int, map:MapConfig, bricks:Array, teams:Array, tanks:Array) { this.type = type; + this.levels = levels; this.map = map; this.bricks = bricks; this.teams = teams; diff --git a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx index dde0f4c..0163002 100644 --- a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx +++ b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx @@ -8,6 +8,7 @@ import ru.m.tankz.config.Config; typedef ConfigSource = { + var levels:Int; var map: MapConfig; var bricks: Array; var teams: Array; @@ -23,7 +24,7 @@ class ConfigBundle { public static function get(type:String):Config { switch (type) { case ClassicGame.TYPE: - var source:ConfigSource = convert(Yaml.parse(Assets.getText('resources/config/${type}.yaml'), Parser.options().useObjects())); + var source:ConfigSource = convert(Yaml.parse(Assets.getText('resources/${type}/config.yaml'), Parser.options().useObjects())); var tanks:Array = []; for (group in Reflect.fields(source.tanks)) { var data:Array = Reflect.field(source.tanks, group); @@ -32,7 +33,7 @@ class ConfigBundle { tanks.push(item); } } - return new Config(type, source.map, source.bricks, source.teams, tanks); + return new Config(type, source.levels, source.map, source.bricks, source.teams, tanks); case _: return null; } diff --git a/src/common/haxe/ru/m/tankz/config/MapBundle.hx b/src/common/haxe/ru/m/tankz/config/LevelBundle.hx similarity index 62% rename from src/common/haxe/ru/m/tankz/config/MapBundle.hx rename to src/common/haxe/ru/m/tankz/config/LevelBundle.hx index 66f1f12..dd4361f 100644 --- a/src/common/haxe/ru/m/tankz/config/MapBundle.hx +++ b/src/common/haxe/ru/m/tankz/config/LevelBundle.hx @@ -5,10 +5,16 @@ import ru.m.tankz.game.Game; import ru.m.tankz.config.Config; -class MapBundle { +class LevelBundle { + + private static function formatLevel(level:Int):String { + var result = Std.string(level); + while (result.length < 3) result = '0${result}'; + return result; + } public static function get(type:GameType, config:Config, level:Int):Array { - var bricksData:String = Assets.getText('resources/levels/level00${level}.txt'); + var bricksData:String = Assets.getText('resources/${type}/levels/level${formatLevel(level)}.txt'); var bricks:Array = []; for (line in ~/\s+/g.split(bricksData)) { for (c in line.split('')) { diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index eec14f8..dfc3dbe 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -3,7 +3,7 @@ package ru.m.tankz.game; import ru.m.tankz.bot.BotControl; import ru.m.tankz.control.HumanControl; import ru.m.tankz.config.ConfigBundle; -import ru.m.tankz.config.MapBundle; +import ru.m.tankz.config.LevelBundle; import ru.m.tankz.game.Spawner; import ru.m.tankz.core.Entity; import ru.m.tankz.core.Eagle; @@ -60,7 +60,7 @@ class Game implements EngineListener { public function start(state:GameState):Void { this.state = state; - var bricks = MapBundle.get(type, config, state.level); + var bricks = LevelBundle.get(type, config, state.level); engine.map.setData(bricks); teams = new Map(); spawners = new Map(); From 24373aa85a248fe41ff05e29f3b037cec4c10f78 Mon Sep 17 00:00:00 2001 From: shmyga Date: Sun, 28 Jan 2018 14:20:41 +0300 Subject: [PATCH 15/22] [build] up haxe dependencies --- build/prepare.js | 13 ++----------- config/deploy.rb | 2 +- package.json | 9 +++++++++ project.xml | 8 +++++--- src/client/haxe/ru/m/tankz/Client.hx | 2 +- tasks/haxe.js | 17 ++++++++++++++++- 6 files changed, 34 insertions(+), 17 deletions(-) diff --git a/build/prepare.js b/build/prepare.js index c9485ff..91e0bf0 100755 --- a/build/prepare.js +++ b/build/prepare.js @@ -1,23 +1,14 @@ const AdobeAir = require('../tasks/adobeAir'); const Haxe = require('../tasks/haxe'); const FlashPlayer = require('../tasks/flashplayer'); - -const packages = [ - {name:'openfl', version:'6.5.3'}, - {name:'lime', version:'5.9.1'}, - {name:'promhx', version:'1.1.0'}, - {name:'protohx', version:'0.4.6'}, - {name:'yaml', version:'1.3.0'}, - {name:'haxework', git:'git@bitbucket.org:shmyga/haxework.git'}, - {name:'orm', version:'2.1.0'}, -]; +const packageInfo = require('../package.json'); const prepareOne = (value) => { switch (value) { case Haxe.ID: const haxe = new Haxe(); - return haxe.prepare().then(() => haxe.install(packages)); + return haxe.prepare().then(() => haxe.install(packageInfo.haxeDependencies)); case AdobeAir.ID: return new AdobeAir().prepare(); case FlashPlayer.ID: diff --git a/config/deploy.rb b/config/deploy.rb index fa74c84..a09244b 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -6,7 +6,7 @@ user = 'holop' # git set :application, app -set :repo_url, "git@bitbucket.org:shmyga/#{app}.git" +set :repo_url, "git@bitbucket.org:infernalgames/#{app}.git" set :user, user set :deploy_to, "/home/#{user}/repo/#{app}" diff --git a/package.json b/package.json index ea8da24..ad3769d 100755 --- a/package.json +++ b/package.json @@ -26,5 +26,14 @@ "unzip-stream": "^0.2.1", "vinyl-fs": "^3.0.1", "yargs": "^10.0.3" + }, + "haxeDependencies": { + "lime": "6.0.1", + "openfl": "7.0.0", + "promhx": "1.1.0", + "protohx": "0.4.6", + "yaml": "1.3.0", + "haxework": "git@bitbucket.org:shmyga/haxework.git", + "orm": "2.1.0" } } diff --git a/project.xml b/project.xml index f2e7708..c75e7da 100755 --- a/project.xml +++ b/project.xml @@ -6,10 +6,12 @@ - - + + + + - + diff --git a/src/client/haxe/ru/m/tankz/Client.hx b/src/client/haxe/ru/m/tankz/Client.hx index 4257b0e..cb26644 100755 --- a/src/client/haxe/ru/m/tankz/Client.hx +++ b/src/client/haxe/ru/m/tankz/Client.hx @@ -61,7 +61,7 @@ class Client implements IConnectionHandler { Provider.set(IConnection, new ru.m.connect.js.JsConnection("localhost", 5001)); #end - Provider.get(IConnection).handler.addListener(this); + //Provider.get(IConnection).handler.addListener(this); view = new MainView(); Provider.set(IFrameSwitcher, view.switcher); diff --git a/tasks/haxe.js b/tasks/haxe.js index 3c889c7..d015314 100755 --- a/tasks/haxe.js +++ b/tasks/haxe.js @@ -76,6 +76,11 @@ class Haxe extends Sdk { return this.haxelib(args); }; + if (!Array.isArray(packages)) { + packages = Object.entries(packages).map(([k, v]) => ({name: k, version: v})); + } + console.log('packages', packages); + for (let pack of packages) { const args = []; let version = null; @@ -83,6 +88,11 @@ class Haxe extends Sdk { args.push('install', pack); } else if (typeof pack === 'object') { version = pack.version; + console.log('z', version.substr(0, 3)); + if (version.substr(0, 3) === 'git') { + pack.git = version; + version = null; + } if (pack.git) { args.push('git', pack.name, pack.git); if (pack.branch) args.push(pack.branch); @@ -93,7 +103,12 @@ class Haxe extends Sdk { args.push('--always'); } let path = `${this.path}/lib/${args[1]}`; - if (version) path += `/${version.replace(/\./g, ',')}`; + if (version) { + path += `/${version.replace(/\./g, ',')}`; + } else if (pack.git) { + path += '/git'; + } + console.log('p', path); if (!fs.existsSync(path)) { promise = promise.then(next(args)); } From 9ebed21c5f6798727e82e9b83a6774a42a90fb68 Mon Sep 17 00:00:00 2001 From: shmyga Date: Sun, 28 Jan 2018 16:05:57 +0300 Subject: [PATCH 16/22] [build] linux platform --- build/client.js | 30 ++++++++++--- package.json | 1 + .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 4 +- tasks/debug.js | 2 +- tasks/haxe.js | 4 +- tasks/tail.js | 43 +++++++++++++++++++ 6 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 tasks/tail.js diff --git a/build/client.js b/build/client.js index 7fdb160..ec5e7a5 100755 --- a/build/client.js +++ b/build/client.js @@ -10,6 +10,8 @@ const version = require('./version'); const prepare = require('./prepare'); const debug = require('../tasks/debug'); const webserver = require('gulp-webserver'); +const run = require('gulp-run'); +const tail = require('../tasks/tail'); const generate = () => function generate() { @@ -57,6 +59,7 @@ const webapp = function () { exports['client:flash:html'] = gulp.parallel(flashIndex, flashJs); exports['client:flash'] = gulp.series(prepare(Haxe.ID), generate(), build('flash'), exports['client:flash:html']); exports['client:html5'] = gulp.series(prepare(Haxe.ID), generate(), build('html5')); +exports['client:linux'] = gulp.series(prepare(Haxe.ID), generate(), build('linux')); exports['client:webapp'] = webapp; exports['client'] = gulp.series(prepare(Haxe.ID), generate(), gulp.parallel(build('flash'), build('html5')), exports['client:flash:html'], webapp); @@ -70,15 +73,32 @@ const testFlash = function() { }; const testHtml5 = function() { - return gulp.series(build('html5'), () => gulp.src('target/html5').pipe(webserver({ - host: 'localhost', port: 3000, - open: true, - fallback: 'index.html' - })))(); + return gulp.series( + build('html5'), + () => gulp.src('target/html5').pipe(webserver({ + host: 'localhost', port: 3000, + open: true, + fallback: 'index.html' + })) + )(); }; +const testLinux = function() { + const argv = yargs.argv; + return gulp.series( + build('linux'), + () => gulp.src('target/linux/tankz') + .pipe(run('./tankz', {cwd: 'target/linux', verbosity: 1})) + .pipe(tail(debug.log)) + .pipe(gulp.dest('target/log')) + )(); +}; + + + exports['client:flash:test'] = gulp.series(prepare(Haxe.ID, FlashPlayer.ID), testFlash); exports['client:html5:test'] = gulp.series(prepare(Haxe.ID), testHtml5); +exports['client:linux:test'] = gulp.series(prepare(Haxe.ID), testLinux); exports['client:test'] = exports['client:flash:test']; diff --git a/package.json b/package.json index ad3769d..92c56a9 100755 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "gulp-babel": "^7.0.0", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.1", + "gulp-run": "^1.7.1", "gulp-template": "^5.0.0", "gulp-uglify": "^3.0.0", "gulp-webserver": "^0.9.1", 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 e304d12..5821acc 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -34,14 +34,14 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand game.engine.listeners.push(render); game.start(state); content.addEventListener(Event.ENTER_FRAME, redraw); - Provider.get(IConnection).packetHandler.addListener(this); + //Provider.get(IConnection).packetHandler.addListener(this); render.draw(game.engine); timer = new Timer(10); timer.run = updateEngine; } public function onHide():Void { - Provider.get(IConnection).packetHandler.removeListener(this); + //Provider.get(IConnection).packetHandler.removeListener(this); if (timer != null) { timer.stop(); timer = null; diff --git a/tasks/debug.js b/tasks/debug.js index fe04b98..ddb80c4 100755 --- a/tasks/debug.js +++ b/tasks/debug.js @@ -44,4 +44,4 @@ module.exports = () => { }) }; -module.exports.log = log; \ No newline at end of file +module.exports.log = _log; diff --git a/tasks/haxe.js b/tasks/haxe.js index d015314..c7cbd4b 100755 --- a/tasks/haxe.js +++ b/tasks/haxe.js @@ -79,7 +79,6 @@ class Haxe extends Sdk { if (!Array.isArray(packages)) { packages = Object.entries(packages).map(([k, v]) => ({name: k, version: v})); } - console.log('packages', packages); for (let pack of packages) { const args = []; @@ -88,7 +87,6 @@ class Haxe extends Sdk { args.push('install', pack); } else if (typeof pack === 'object') { version = pack.version; - console.log('z', version.substr(0, 3)); if (version.substr(0, 3) === 'git') { pack.git = version; version = null; @@ -108,7 +106,6 @@ class Haxe extends Sdk { } else if (pack.git) { path += '/git'; } - console.log('p', path); if (!fs.existsSync(path)) { promise = promise.then(next(args)); } @@ -186,6 +183,7 @@ class Haxe extends Sdk { const result = { 'flash': `${buildDir}/flash/bin/*.swf`, 'html5': `${buildDir}/html5/bin/**/*`, + 'linux': `${buildDir}/linux/bin/**/*`, }[params.platform]; vfs.src(result).pipe(through.obj((file, enc, cb) => { file.debug = debug; diff --git a/tasks/tail.js b/tasks/tail.js new file mode 100644 index 0000000..b4ddeed --- /dev/null +++ b/tasks/tail.js @@ -0,0 +1,43 @@ +const through = require('through2'); +const colors = require('ansi-colors'); +const log = require('fancy-log'); + +const TAG = colors.green('[tail]'); + + +const { Writable } = require('stream'); +const { StringDecoder } = require('string_decoder'); + + +class StringWritable extends Writable { + constructor(handler, options) { + super(options); + this.handler = handler; + const state = this._writableState; + this._decoder = new StringDecoder(state.defaultEncoding); + this.data = ''; + } + _write(chunk, encoding, callback) { + if (encoding === 'buffer') { + chunk = this._decoder.write(chunk); + for (const line of chunk.split('\n')) if (line.length) { + this.handler(line); + } + } + this.data += chunk; + callback(); + } + _final(callback) { + this.data += this._decoder.end(); + callback(); + } +} + + +module.exports = (handler) => { + return through.obj(function (file, enc, callback) { + file.contents.pipe(new StringWritable(handler)); + this.push(file); + callback(); + }); +}; From 9eb21fae7d7426e3d10dbe217f0ed82c983db536 Mon Sep 17 00:00:00 2001 From: shmyga Date: Sun, 28 Jan 2018 19:04:39 +0300 Subject: [PATCH 17/22] [common] added Dota game type --- package.json | 2 +- project.xml | 38 ++--- src/client/haxe/layout/frames/start.json | 4 +- src/client/haxe/ru/m/tankz/Client.hx | 2 + .../haxe/ru/m/tankz/render/RenderItem.hx | 8 ++ .../haxe/ru/m/tankz/view/frames/StartFrame.hx | 30 +++- src/client/resources/dota/config.yaml | 134 ++++++++++++++++++ src/client/resources/dota/levels/level000.txt | 30 ++++ .../haxe/ru/m/tankz/config/ConfigBundle.hx | 23 ++- src/common/haxe/ru/m/tankz/game/DotaGame.hx | 56 ++++++++ src/common/haxe/ru/m/tankz/game/Game.hx | 7 +- src/common/haxe/ru/m/tankz/map/LevelMap.hx | 2 +- 12 files changed, 291 insertions(+), 45 deletions(-) create mode 100644 src/client/resources/dota/config.yaml create mode 100644 src/client/resources/dota/levels/level000.txt create mode 100644 src/common/haxe/ru/m/tankz/game/DotaGame.hx diff --git a/package.json b/package.json index 92c56a9..0d2d477 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tankz", - "version": "0.0.7", + "version": "0.1.0", "private": true, "devDependencies": { "ansi-colors": "^1.0.1", diff --git a/project.xml b/project.xml index c75e7da..66938b0 100755 --- a/project.xml +++ b/project.xml @@ -1,22 +1,22 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/client/haxe/layout/frames/start.json b/src/client/haxe/layout/frames/start.json index 6378242..9315e93 100644 --- a/src/client/haxe/layout/frames/start.json +++ b/src/client/haxe/layout/frames/start.json @@ -19,9 +19,9 @@ "@style": "button" }, { - "id": "start_lan", + "id": "dota", "@type": "haxework.gui.ButtonView", - "text": "Multiplayer", + "text": "DotA", "@style": "button" } ] diff --git a/src/client/haxe/ru/m/tankz/Client.hx b/src/client/haxe/ru/m/tankz/Client.hx index cb26644..4cdb55b 100755 --- a/src/client/haxe/ru/m/tankz/Client.hx +++ b/src/client/haxe/ru/m/tankz/Client.hx @@ -1,6 +1,7 @@ package ru.m.tankz; import ru.m.tankz.game.ClassicGame; +import ru.m.tankz.game.DotaGame; import ru.m.tankz.game.Game; import flash.ui.Keyboard; import flash.events.KeyboardEvent; @@ -76,6 +77,7 @@ class Client implements IConnectionHandler { }); Provider.setFactory(Game, ClassicGame, ClassicGame.TYPE); + Provider.setFactory(Game, DotaGame, DotaGame.TYPE); } public function onPress(view:ButtonView):Void { diff --git a/src/client/haxe/ru/m/tankz/render/RenderItem.hx b/src/client/haxe/ru/m/tankz/render/RenderItem.hx index c61271c..c51892b 100644 --- a/src/client/haxe/ru/m/tankz/render/RenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/RenderItem.hx @@ -113,6 +113,14 @@ class TankItem extends RenderItem { var group = value.config.group; var index = value.playerId.index; if (group == 'human') group = 'player'; + if (group == 'radiant') { + group = 'player'; + index = 0; + } + if (group == 'dire') { + group = 'player'; + index = 1; + } if (group == 'bot') index = 0; return 'resources/images/tank/${group}/tank_${group.charAt(0)}${value.config.type}_${index}-0.png'; } diff --git a/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx b/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx index ba0ef4d..67f0223 100644 --- a/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/StartFrame.hx @@ -1,7 +1,9 @@ package ru.m.tankz.view.frames; +import ru.m.tankz.game.Game; import ru.m.tankz.game.GameState; import ru.m.tankz.game.ClassicGame; +import ru.m.tankz.game.DotaGame; import haxework.gui.frame.IFrameSwitcher; import haxework.provider.Provider; import haxework.gui.ButtonView; @@ -9,27 +11,43 @@ import haxework.gui.ViewBuilder; import haxework.gui.VGroupView; +interface StartFrameLayout { + var start_1p(default, null):ButtonView; + var start_2p(default, null):ButtonView; + var dota(default, null):ButtonView; +} + + @:template("layout/frames/start.json", "layout/styles.json") -class StartFrame extends VGroupView implements ViewBuilder { +class StartFrame extends VGroupView implements ViewBuilder implements StartFrameLayout { public static inline var ID = "start"; public function init() { start_1p.onPress = this; start_2p.onPress = this; + dota.onPress = this; } public function onPress(view:ButtonView):Void { switch (view.id) { case 'start_1p': - startGame(1); + startGame(ClassicGame.TYPE, 1); case 'start_2p': - startGame(2); + startGame(ClassicGame.TYPE, 2); + case 'dota': + startGame(DotaGame.TYPE, 2); } } - private function startGame(humans:Int):Void { - Provider.set(GameState, ClassicGame.buildState(0, humans)); - Provider.get(IFrameSwitcher).change(LevelFrame.ID); + private function startGame(type:GameType, humans:Int):Void { + switch (type) { + case ClassicGame.TYPE: + Provider.set(GameState, ClassicGame.buildState(0, humans)); + Provider.get(IFrameSwitcher).change(LevelFrame.ID); + case DotaGame.TYPE: + Provider.set(GameState, DotaGame.buildState(0, humans)); + Provider.get(IFrameSwitcher).change(GameFrame.ID); + } } } diff --git a/src/client/resources/dota/config.yaml b/src/client/resources/dota/config.yaml new file mode 100644 index 0000000..5d8c19a --- /dev/null +++ b/src/client/resources/dota/config.yaml @@ -0,0 +1,134 @@ +levels: 36 + +map: + cellWidth: 22 + cellHeight: 22 + gridWidth: 40 + gridHeight: 30 + +bricks: + # border + - type: -1 + layer: 2 + armor: -1 + # none + - type: 0 + layer: 0 + armor: 0 + # ace + - type: 1 + layer: 0 + armor: 0 + # bush + - type: 2 + layer: 3 + armor: 0 + # water + - type: 3 + layer: 1 + armor: 0 + # armor + - type: 4 + layer: 2 + armor: 2 + # brick + - type: 5 + layer: 2 + armor: 1 + +teams: + - id: radiant + spawnInterval: 0 + points: + - type: eagle + index: -1 + x: 0 + y: 28 + direction: right + - type: tank + index: 0 + x: 0 + y: 0 + direction: top + - type: tank + index: 1 + x: 6 + y: 10 + direction: top + - type: tank + index: 2 + x: 6 + y: 16 + direction: top + - type: tank + index: 3 + x: 6 + y: 22 + direction: top + - type: tank + index: 4 + x: 10 + y: 28 + direction: top + - id: dire + spawnInterval: 0 + points: + - type: eagle + index: -1 + x: 38 + y: 0 + direction: right + - type: tank + index: 0 + x: 38 + y: 28 + direction: bottom + - type: tank + index: 1 + x: 32 + y: 18 + direction: bottom + - type: tank + index: 2 + x: 32 + y: 12 + direction: bottom + - type: tank + index: 3 + x: 32 + y: 6 + direction: bottom + - type: tank + index: 4 + x: 28 + y: 0 + direction: bottom + + +bullet: &bullet + width: 12 + height: 12 + speed: 0 + piercing: 1 + +tanks: + radiant: &tanks + - type: 0 + width: 36 + height: 36 + speed: 2.5 + bullet: + <<: *bullet + speed: 8.0 + bullets: 1 + + - type: 1 + width: 40 + height: 36 + speed: 3.0 + bullet: + <<: *bullet + speed: 8.5 + bullets: 1 + dire: + - <<: *tanks diff --git a/src/client/resources/dota/levels/level000.txt b/src/client/resources/dota/levels/level000.txt new file mode 100644 index 0000000..65ec086 --- /dev/null +++ b/src/client/resources/dota/levels/level000.txt @@ -0,0 +1,30 @@ +0000000000000000000000000000000000005500 +0000000000000000000000000000000000005500 +0000000000000000000000000000000000005555 +0000000000000000000000000000000000005555 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +5555000000000000000000000000000000000000 +5555000000000000000000000000000000000000 +0055000000000000000000000000000000000000 +0055000000000000000000000000000000000000 diff --git a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx index 0163002..e37fba7 100644 --- a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx +++ b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx @@ -22,20 +22,15 @@ class ConfigBundle { } public static function get(type:String):Config { - switch (type) { - case ClassicGame.TYPE: - var source:ConfigSource = convert(Yaml.parse(Assets.getText('resources/${type}/config.yaml'), Parser.options().useObjects())); - var tanks:Array = []; - for (group in Reflect.fields(source.tanks)) { - var data:Array = Reflect.field(source.tanks, group); - for (item in data) { - item.group = group; - tanks.push(item); - } - } - return new Config(type, source.levels, source.map, source.bricks, source.teams, tanks); - case _: - return null; + var source:ConfigSource = convert(Yaml.parse(Assets.getText('resources/${type}/config.yaml'), Parser.options().useObjects())); + var tanks:Array = []; + for (group in Reflect.fields(source.tanks)) { + var data:Array = Reflect.field(source.tanks, group); + for (item in data) { + item.group = group; + tanks.push(item); + } } + return new Config(type, source.levels, source.map, source.bricks, source.teams, tanks); } } diff --git a/src/common/haxe/ru/m/tankz/game/DotaGame.hx b/src/common/haxe/ru/m/tankz/game/DotaGame.hx new file mode 100644 index 0000000..c4ed959 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/game/DotaGame.hx @@ -0,0 +1,56 @@ +package ru.m.tankz.game; + +import ru.m.tankz.game.Game; +import ru.m.tankz.game.GameState; + + +class DotaGame extends Game { + + public static var TYPE(default, never):GameType = 'dota'; + + public static var RADIANT(default, never):TeamId = 'radiant'; + public static var DIRE(default, never):TeamId = 'dire'; + + private static var TEAM_SIZE(default, never):Int = 5; + + public function new() { + super(TYPE); + } + + public static function buildState(level:Int, humans:Int):GameState { + var state = new GameState(); + state.type = TYPE; + state.level = level; + state.players[RADIANT] = new Map(); + state.players[DIRE] = new Map(); + for (i in 0...TEAM_SIZE) { + state.players[RADIANT][i] = { + index:i, + tank:{ + group: RADIANT, + type: '1' + }, + control:{ + type: 'bot', + index: i + }, + life:-1, + }; + } + for (i in 0...TEAM_SIZE) { + state.players[DIRE][i] = { + index:i, + tank:{ + group: DIRE, + type: '1' + }, + control:{ + type: 'bot', + index: i + }, + life:-1, + }; + } + return state; + } +} diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index dfc3dbe..26eb49a 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -74,10 +74,13 @@ class Game implements EngineListener { var control = switch (playerState.control.type) { case HumanControl.TYPE: new HumanControl(playerState.control.index); case BotControl.TYPE: new BotControl(playerState.control.index); + case 'none': null; case _: throw 'Unsupported control type: "${playerState.control.type}"'; } - player.control = control; - player.control.bind(engine); + if (control != null) { + player.control = control; + player.control.bind(engine); + } } } spawners.set(team.id, new Spawner(team.config, spawn)); diff --git a/src/common/haxe/ru/m/tankz/map/LevelMap.hx b/src/common/haxe/ru/m/tankz/map/LevelMap.hx index ec59d39..b91d7fe 100755 --- a/src/common/haxe/ru/m/tankz/map/LevelMap.hx +++ b/src/common/haxe/ru/m/tankz/map/LevelMap.hx @@ -41,7 +41,7 @@ class LevelMap { bricksMap = new HashMap(); bricks = Lambda.array(Lambda.mapi(data, function(i:Int, brickConfig:BrickConfig):Brick { var cellX = Std.int(i % gridWidth); - var cellY = Std.int(Math.floor(i / gridHeight)); + var cellY = Std.int(Math.floor(i / gridWidth)); var cells:HashMap = new HashMap(); var point:Point = new Point(cellX * 2, cellY * 2); if (brickConfig.layer > 0 || brickConfig.armor > 0) { From 69d2e266cd8a158b942922b668073cc6e085901e Mon Sep 17 00:00:00 2001 From: shmyga Date: Sun, 28 Jan 2018 19:10:29 +0300 Subject: [PATCH 18/22] [client] render fix --- src/client/haxe/ru/m/tankz/render/Render.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index a585d83..bdc16ae 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -51,7 +51,7 @@ class Render extends SpriteView implements EngineListener { } public function draw(game:Engine):Void { - for (brick in game.map.bricks) { + for (brick in game.map.bricks) if (brick.config.type > 0) { if (!items.exists(brick.key)) { items[brick.key] = new BrickItem(brick); if (brick.config.layer > 2) { From 46836a8bcbdf7d0ad2e34564565e1200464ca852 Mon Sep 17 00:00:00 2001 From: shmyga Date: Mon, 29 Jan 2018 22:06:07 +0300 Subject: [PATCH 19/22] [common] added game progress --- package.json | 2 +- src/client/haxe/layout/frames/game.json | 4 ++ .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 58 +++++++++++++-- src/common/haxe/ru/m/tankz/core/Eagle.hx | 6 +- .../haxe/ru/m/tankz/game/ClassicGame.hx | 8 +-- src/common/haxe/ru/m/tankz/game/DotaGame.hx | 8 +-- src/common/haxe/ru/m/tankz/game/Game.hx | 71 ++++++++++++++++--- src/common/haxe/ru/m/tankz/game/GameState.hx | 11 ++- 8 files changed, 139 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 0d2d477..f281feb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tankz", - "version": "0.1.0", + "version": "0.2.0", "private": true, "devDependencies": { "ansi-colors": "^1.0.1", diff --git a/src/client/haxe/layout/frames/game.json b/src/client/haxe/layout/frames/game.json index 19ea442..338c97c 100644 --- a/src/client/haxe/layout/frames/game.json +++ b/src/client/haxe/layout/frames/game.json @@ -1,6 +1,10 @@ { "pWidth": 100, "pHeight": 100, "views": [ + { + "id": "state", "@type": "haxework.gui.LabelView", "@style": "label", + "pWidth": 100, "height": 20 + }, { "id": "render", "@type": "ru.m.tankz.render.Render", "contentSize": true 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 5821acc..10e89c6 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -1,19 +1,30 @@ package ru.m.tankz.view.frames; -import ru.m.tankz.game.GameState; +import haxe.ds.Option; +import haxe.ds.Option; import flash.events.Event; import haxe.Timer; +import haxework.gui.frame.IFrameSwitcher; +import haxework.gui.LabelView; import haxework.gui.VGroupView; import haxework.gui.ViewBuilder; import haxework.provider.Provider; import protohx.Message; import ru.m.connect.IConnection; import ru.m.tankz.game.Game; +import ru.m.tankz.game.GameState; import ru.m.tankz.proto.pack.GameUpdateResponse; +import ru.m.tankz.render.Render; + + +interface GameFrameLayout { + var state(default, null):LabelView; + var render(default, null):Render; +} @:template("layout/frames/game.json", "layout/styles.json") -class GameFrame extends VGroupView implements ViewBuilder implements IPacketHandler { +class GameFrame extends VGroupView implements ViewBuilder implements IPacketHandler implements GameFrameLayout { private static inline var TAG = "GameFrame"; @@ -26,18 +37,53 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand } public function onShow():Void { - var state:GameState = Provider.get(GameState); - game = Provider.build(Game, state.type); + var s:GameState = Provider.get(GameState); + game = Provider.build(Game, s.type); if (game == null) { - throw 'Unsupported game type "${state.type}"'; + throw 'Unsupported game type "${s.type}"'; } game.engine.listeners.push(render); - game.start(state); + game.start(s).then(onGameStateChange).endThen(onGameComplete); content.addEventListener(Event.ENTER_FRAME, redraw); //Provider.get(IConnection).packetHandler.addListener(this); render.draw(game.engine); timer = new Timer(10); timer.run = updateEngine; + state.text = stateString(s); + } + + private function stateString(state:GameState):String { + var result:Array = []; + for (teamId in state.teams.keys()) { + var ts:TeamState = state.teams[teamId]; + if (ts.lose) { + result.push('${teamId}: LOSE'); + } else if (ts.life > -1) { + result.push('${teamId}: ${ts.life}'); + } else { + for (index in ts.players.keys()) { + var ps:PlayerState = ts.players[index]; + if (ps.life > -1) { + result.push('${teamId}${index}: ${ps.life}'); + } + } + } + } + return result.join(' '); + } + + private function onGameStateChange(s:GameState):GameState { + state.text = stateString(s); + return s; + } + + private function onGameComplete(result:Option):Void { + switch (result) { + case Option.Some(s): + state.text = stateString(s); + case Option.None: + } + Provider.get(IFrameSwitcher).change(StartFrame.ID); } public function onHide():Void { diff --git a/src/common/haxe/ru/m/tankz/core/Eagle.hx b/src/common/haxe/ru/m/tankz/core/Eagle.hx index e1fb93b..16c6489 100644 --- a/src/common/haxe/ru/m/tankz/core/Eagle.hx +++ b/src/common/haxe/ru/m/tankz/core/Eagle.hx @@ -1,11 +1,15 @@ package ru.m.tankz.core; +import ru.m.tankz.game.Game; import ru.m.geom.Rectangle; class Eagle extends Entity { - public function new() { + public var team(default, null):TeamId; + + public function new(team:TeamId) { super(new Rectangle(0, 0, 44, 44)); + this.team = team; } } diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index b520eb2..f685c4c 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -19,10 +19,10 @@ class ClassicGame extends Game { var state = new GameState(); state.type = TYPE; state.level = level; - state.players[HUMAN] = new Map(); - state.players[BOT] = new Map(); + state.teams[HUMAN] = {life: -1, players: new Map(), lose: false}; + state.teams[BOT] = {life: 20, players: new Map(), lose: false}; for (i in 0...humans) { - state.players[HUMAN][i] = { + state.teams[HUMAN].players[i] = { index:i, tank:{ group: HUMAN, @@ -36,7 +36,7 @@ class ClassicGame extends Game { }; } for (i in 0...humans*2+2) { - state.players[BOT][i] = { + state.teams[BOT].players[i] = { index:i, tank:{ group: BOT, diff --git a/src/common/haxe/ru/m/tankz/game/DotaGame.hx b/src/common/haxe/ru/m/tankz/game/DotaGame.hx index c4ed959..723163b 100644 --- a/src/common/haxe/ru/m/tankz/game/DotaGame.hx +++ b/src/common/haxe/ru/m/tankz/game/DotaGame.hx @@ -21,10 +21,10 @@ class DotaGame extends Game { var state = new GameState(); state.type = TYPE; state.level = level; - state.players[RADIANT] = new Map(); - state.players[DIRE] = new Map(); + state.teams[RADIANT] = {life: 20, players: new Map(), lose: false}; + state.teams[DIRE] = {life: 20, players: new Map(), lose: false}; for (i in 0...TEAM_SIZE) { - state.players[RADIANT][i] = { + state.teams[RADIANT].players[i] = { index:i, tank:{ group: RADIANT, @@ -38,7 +38,7 @@ class DotaGame extends Game { }; } for (i in 0...TEAM_SIZE) { - state.players[DIRE][i] = { + state.teams[DIRE].players[i] = { index:i, tank:{ group: DIRE, diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 26eb49a..700101e 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -1,19 +1,23 @@ package ru.m.tankz.game; -import ru.m.tankz.bot.BotControl; -import ru.m.tankz.control.HumanControl; -import ru.m.tankz.config.ConfigBundle; -import ru.m.tankz.config.LevelBundle; -import ru.m.tankz.game.Spawner; -import ru.m.tankz.core.Entity; -import ru.m.tankz.core.Eagle; +import haxe.Timer; +import promhx.Deferred; +import promhx.Stream; import ru.m.geom.Direction; import ru.m.geom.Point; +import ru.m.tankz.bot.BotControl; import ru.m.tankz.config.Config; +import ru.m.tankz.config.ConfigBundle; +import ru.m.tankz.config.LevelBundle; import ru.m.tankz.control.Control; +import ru.m.tankz.control.HumanControl; +import ru.m.tankz.core.Eagle; +import ru.m.tankz.core.Entity; import ru.m.tankz.core.EntityType; import ru.m.tankz.core.Tank; import ru.m.tankz.engine.Engine; +import ru.m.tankz.game.GameState; +import ru.m.tankz.game.Spawner; typedef GameType = String; @@ -35,6 +39,8 @@ class Game implements EngineListener { public var engine(default, null):Engine; private var spawners:Map; + private var deferred:Deferred; + private var stream:Stream; public function new(type:GameType) { this.type = type; @@ -58,7 +64,8 @@ class Game implements EngineListener { entity.rect.direction = Direction.fromString(point.direction); } - public function start(state:GameState):Void { + public function start(state:GameState):Stream { + this.deferred = new Deferred(); this.state = state; var bricks = LevelBundle.get(type, config, state.level); engine.map.setData(bricks); @@ -66,7 +73,7 @@ class Game implements EngineListener { spawners = new Map(); for (teamConfig in config.teams) { var team = new Team(teamConfig); - for (playerState in state.players.get(team.id)) { + for (playerState in state.teams.get(team.id).players) { var player = new Player({team:team.id, index:playerState.index}); team.players.push(player); teams.set(team.id, team); @@ -92,11 +99,13 @@ class Game implements EngineListener { } var eaglePoint = spawners.get(team.id).getPoint('eagle'); if (eaglePoint != null) { - var eagle = new Eagle(); + var eagle = new Eagle(team.id); applyPoint(eagle, eaglePoint); engine.spawn(eagle); } } + + return stream = deferred.stream(); } private function spawn(task:SpawnTask):Void { @@ -106,6 +115,20 @@ class Game implements EngineListener { player.tankId = tank.id; } + private function complete():Void { + for (team in teams.iterator()) { + for (player in team.players) { + player.control.dispose(); + } + } + var timer = new Timer(5000); + timer.run = function() { + timer.stop(); + deferred.resolve(state); + stream.end(); + } + } + public function setControl(playerId:PlayerId, control:Control):Void { for (team in teams.iterator()) { if (team.id == playerId.team) { @@ -134,10 +157,36 @@ class Game implements EngineListener { } } + private function calcTeamLife(ts:TeamState):Int { + return Lambda.fold(ts.players, function(ps, t) return t + ps.life, ts.life); + } + public function onDestroy(entity:EntityType):Void { switch (entity) { case EntityType.TANK(tank): - spawners.get(tank.playerId.team).push(tank.playerId); + var respawn:Bool = false; + var teamState:TeamState = state.teams[tank.playerId.team]; + if (teamState.life > 0) { + teamState.life--; + respawn = true; + } else { + var playerState:PlayerState = teamState.players[tank.playerId.index]; + if (playerState.life > 0) { + playerState.life--; + respawn = true; + } + } + if (respawn) { + spawners.get(tank.playerId.team).push(tank.playerId); + } else if (calcTeamLife(teamState) < 1) { + state.teams[tank.playerId.team].lose = true; + complete(); + } + deferred.resolve(state); + case EntityType.EAGLE(eagle): + state.teams[eagle.team].lose = true; + complete(); + deferred.resolve(state); case x: } } diff --git a/src/common/haxe/ru/m/tankz/game/GameState.hx b/src/common/haxe/ru/m/tankz/game/GameState.hx index a619a6f..ae192e7 100644 --- a/src/common/haxe/ru/m/tankz/game/GameState.hx +++ b/src/common/haxe/ru/m/tankz/game/GameState.hx @@ -21,14 +21,21 @@ typedef PlayerState = { } +typedef TeamState = { + var players:Map; + var life:Int; + var lose:Bool; +} + + class GameState { public var type:GameType; public var level:Int; - public var players:Map>; + public var teams:Map; public function new() { type = null; level = -1; - players = new Map(); + teams = new Map(); } } From d3ef6e426692aaf24e909361f5f03ef3321a7167 Mon Sep 17 00:00:00 2001 From: shmyga Date: Tue, 30 Jan 2018 08:02:19 +0300 Subject: [PATCH 20/22] [build] added deb task --- build/client.js | 22 ++++++++++++++++++++++ package.json | 1 + src/client/tankz.desktop | 7 +++++++ 3 files changed, 30 insertions(+) create mode 100644 src/client/tankz.desktop diff --git a/build/client.js b/build/client.js index ec5e7a5..57a173c 100755 --- a/build/client.js +++ b/build/client.js @@ -12,6 +12,7 @@ const debug = require('../tasks/debug'); const webserver = require('gulp-webserver'); const run = require('gulp-run'); const tail = require('../tasks/tail'); +const deb = require('gulp-debian'); const generate = () => function generate() { @@ -56,12 +57,33 @@ const webapp = function () { return gulp.src('src/webapp/*').pipe(gulp.dest('target')); }; + +const buildDeb = function() { + return gulp.src('target/linux/**') + .pipe(deb({ + package: 'tankz', + version: version, + section: 'base', + priority: 'optional', + architecture: 'all', + maintainer: 'shmyga ', + description: 'Tank\'z', + changelog: [], + _target: '/opt/tankz', + _out: 'target', + _clean: false, + _verbose: true + })); +}; + + exports['client:flash:html'] = gulp.parallel(flashIndex, flashJs); exports['client:flash'] = gulp.series(prepare(Haxe.ID), generate(), build('flash'), exports['client:flash:html']); exports['client:html5'] = gulp.series(prepare(Haxe.ID), generate(), build('html5')); exports['client:linux'] = gulp.series(prepare(Haxe.ID), generate(), build('linux')); exports['client:webapp'] = webapp; exports['client'] = gulp.series(prepare(Haxe.ID), generate(), gulp.parallel(build('flash'), build('html5')), exports['client:flash:html'], webapp); +exports['client:deb'] = buildDeb; diff --git a/package.json b/package.json index f281feb..a01743f 100755 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "gulp-babel": "^7.0.0", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.1", + "gulp-debian": "^0.1.9", "gulp-run": "^1.7.1", "gulp-template": "^5.0.0", "gulp-uglify": "^3.0.0", diff --git a/src/client/tankz.desktop b/src/client/tankz.desktop new file mode 100644 index 0000000..c94915e --- /dev/null +++ b/src/client/tankz.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Application +Comment=Tank'z game +Exec=/opt/tankz/tankz +Icon=/usr/tankz/resources/images/tank/player/tank_p3_0-0.png +Name=Tank'z From f69c7af618dffb746ac2035aa285c8e1fa5c5658 Mon Sep 17 00:00:00 2001 From: shmyga Date: Tue, 30 Jan 2018 14:10:09 +0300 Subject: [PATCH 21/22] [build] deb package --- build/client.js | 34 +++++++++++-------- .../usr/share/applications/tankz.desktop | 9 +++++ src/client/tankz.desktop | 7 ---- 3 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 src/client/debian/usr/share/applications/tankz.desktop delete mode 100644 src/client/tankz.desktop diff --git a/build/client.js b/build/client.js index 57a173c..82763a8 100755 --- a/build/client.js +++ b/build/client.js @@ -58,8 +58,10 @@ const webapp = function () { }; -const buildDeb = function() { - return gulp.src('target/linux/**') +const buildDeb = gulp.series( + () => gulp.src('src/client/debian/**/*').pipe(gulp.dest('target/debian')), + () => gulp.src('target/linux/**/*').pipe(gulp.dest('target/debian/usr/share/tankz')), + () => gulp.src('target/debian/*') .pipe(deb({ package: 'tankz', version: version, @@ -69,12 +71,17 @@ const buildDeb = function() { maintainer: 'shmyga ', description: 'Tank\'z', changelog: [], - _target: '/opt/tankz', + postinst: [ + 'if [ "$1" = "configure" ] && [ -x "`which update-menus 2>/dev/null`" ] ; then\n' + + ' update-menus\n' + + 'fi' + ], + _target: '/', _out: 'target', _clean: false, _verbose: true - })); -}; + })) +); exports['client:flash:html'] = gulp.parallel(flashIndex, flashJs); @@ -105,16 +112,13 @@ const testHtml5 = function() { )(); }; -const testLinux = function() { - const argv = yargs.argv; - return gulp.series( - build('linux'), - () => gulp.src('target/linux/tankz') - .pipe(run('./tankz', {cwd: 'target/linux', verbosity: 1})) - .pipe(tail(debug.log)) - .pipe(gulp.dest('target/log')) - )(); -}; +const testLinux = gulp.series( + build('linux'), + () => gulp.src('target/linux/tankz') + .pipe(run('./tankz', {cwd: 'target/linux', verbosity: 1})) + .pipe(tail(debug.log)) + .pipe(gulp.dest('target/log')) +); diff --git a/src/client/debian/usr/share/applications/tankz.desktop b/src/client/debian/usr/share/applications/tankz.desktop new file mode 100644 index 0000000..88dba30 --- /dev/null +++ b/src/client/debian/usr/share/applications/tankz.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Application +Comment=Tank'z game +Exec=bash -c 'cd "/usr/share/tankz" && ./tankz' +Icon=/usr/share/tankz/resources/images/tank/player/tank_p3_0-0.png +Name=Tank'z +Categories=Game +Terminal=false diff --git a/src/client/tankz.desktop b/src/client/tankz.desktop deleted file mode 100644 index c94915e..0000000 --- a/src/client/tankz.desktop +++ /dev/null @@ -1,7 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Type=Application -Comment=Tank'z game -Exec=/opt/tankz/tankz -Icon=/usr/tankz/resources/images/tank/player/tank_p3_0-0.png -Name=Tank'z From 38e2a39c4ae8b84d1e42b125b66678b1bfc050b1 Mon Sep 17 00:00:00 2001 From: shmyga Date: Tue, 30 Jan 2018 22:04:48 +0300 Subject: [PATCH 22/22] [common] game next function --- build/client.js | 9 ++- package.json | 2 +- src/client/haxe/ru/m/tankz/Client.hx | 2 +- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 42 +++++++--- .../haxe/ru/m/tankz/game/ClassicGame.hx | 22 +++++- src/common/haxe/ru/m/tankz/game/Game.hx | 79 ++++++++++++++----- src/common/haxe/ru/m/tankz/game/Spawner.hx | 6 ++ 7 files changed, 124 insertions(+), 38 deletions(-) diff --git a/build/client.js b/build/client.js index 82763a8..ebb49f7 100755 --- a/build/client.js +++ b/build/client.js @@ -89,8 +89,15 @@ exports['client:flash'] = gulp.series(prepare(Haxe.ID), generate(), build('flash exports['client:html5'] = gulp.series(prepare(Haxe.ID), generate(), build('html5')); exports['client:linux'] = gulp.series(prepare(Haxe.ID), generate(), build('linux')); exports['client:webapp'] = webapp; -exports['client'] = gulp.series(prepare(Haxe.ID), generate(), gulp.parallel(build('flash'), build('html5')), exports['client:flash:html'], webapp); exports['client:deb'] = buildDeb; +exports['client'] = gulp.series( + prepare(Haxe.ID), + generate(), + gulp.parallel(build('flash'), build('html5'), build('linux')), + exports['client:flash:html'], + webapp, + buildDeb, +); diff --git a/package.json b/package.json index a01743f..acb1743 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tankz", - "version": "0.2.0", + "version": "0.2.1", "private": true, "devDependencies": { "ansi-colors": "^1.0.1", diff --git a/src/client/haxe/ru/m/tankz/Client.hx b/src/client/haxe/ru/m/tankz/Client.hx index 4cdb55b..a90df2d 100755 --- a/src/client/haxe/ru/m/tankz/Client.hx +++ b/src/client/haxe/ru/m/tankz/Client.hx @@ -63,10 +63,10 @@ class Client implements IConnectionHandler { #end //Provider.get(IConnection).handler.addListener(this); - view = new MainView(); Provider.set(IFrameSwitcher, view.switcher); Root.bind(view); + view.content.stage.stageFocusRect = false; //view.logout.onPress = this; view.switcher.change(StartFrame.ID); 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 10e89c6..dff3100 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -33,11 +33,13 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand private var game:Game; private var timer:Timer; - public function init():Void { - } + public function init():Void {} public function onShow():Void { - var s:GameState = Provider.get(GameState); + start(Provider.get(GameState)); + } + + private function start(s:GameState):Void { game = Provider.build(Game, s.type); if (game == null) { throw 'Unsupported game type "${s.type}"'; @@ -52,8 +54,23 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand state.text = stateString(s); } + private function stop():Void { + //Provider.get(IConnection).packetHandler.removeListener(this); + if (timer != null) { + timer.stop(); + timer = null; + } + content.removeEventListener(Event.ENTER_FRAME, redraw); + if (game != null) { + game.dispose(); + game = null; + } + render.reset(); + } + private function stateString(state:GameState):String { var result:Array = []; + result.push('Level: ${state.level}'); for (teamId in state.teams.keys()) { var ts:TeamState = state.teams[teamId]; if (ts.lose) { @@ -69,7 +86,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand } } } - return result.join(' '); + return '[ ${result.join(' | ')} ]'; } private function onGameStateChange(s:GameState):GameState { @@ -83,18 +100,17 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand state.text = stateString(s); case Option.None: } - Provider.get(IFrameSwitcher).change(StartFrame.ID); + switch (game.next()) { + case Option.Some(s): + stop(); + start(s); + case Option.None: + Provider.get(IFrameSwitcher).change(StartFrame.ID); + } } public function onHide():Void { - //Provider.get(IConnection).packetHandler.removeListener(this); - if (timer != null) { - timer.stop(); - timer = null; - } - content.removeEventListener(Event.ENTER_FRAME, redraw); - game.dispose(); - render.reset(); + stop(); } private function updateEngine():Void { diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index f685c4c..976df36 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import haxe.ds.Option; import ru.m.tankz.game.GameState.PlayerState; import ru.m.tankz.game.Game; @@ -11,6 +12,9 @@ class ClassicGame extends Game { public static var HUMAN(default, never):TeamId = 'human'; public static var BOT(default, never):TeamId = 'bot'; + private static var HUMAN_LIFE(default, never):Int = 3; + private static var BOT_LIFE(default, never):Int = 20; + public function new() { super(TYPE); } @@ -20,7 +24,7 @@ class ClassicGame extends Game { state.type = TYPE; state.level = level; state.teams[HUMAN] = {life: -1, players: new Map(), lose: false}; - state.teams[BOT] = {life: 20, players: new Map(), lose: false}; + state.teams[BOT] = {life: BOT_LIFE, players: new Map(), lose: false}; for (i in 0...humans) { state.teams[HUMAN].players[i] = { index:i, @@ -32,7 +36,7 @@ class ClassicGame extends Game { type: 'human', index: i }, - life:3, + life:HUMAN_LIFE, }; } for (i in 0...humans*2+2) { @@ -51,4 +55,18 @@ class ClassicGame extends Game { } return state; } + + override public function next():Option { + if (!state.teams[HUMAN].lose) { + state.level++; + if (state.level >= config.levels) state.level = 0; + state.teams[BOT].lose = false; + state.teams[BOT].life = BOT_LIFE; + for (ps in state.teams[HUMAN].players) { + if (ps.life > 0) ps.life++; + } + return Option.Some(state); + } + return Option.None; + } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 700101e..07c0684 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import haxe.ds.Option; import haxe.Timer; import promhx.Deferred; import promhx.Stream; @@ -95,7 +96,9 @@ class Game implements EngineListener { for (team in teams) { for (player in team.players) { - spawners.get(team.id).push(player.id); + if (trySpawn(player.id)) { + spawners.get(team.id).push(player.id); + } } var eaglePoint = spawners.get(team.id).getPoint('eagle'); if (eaglePoint != null) { @@ -109,15 +112,23 @@ class Game implements EngineListener { } private function spawn(task:SpawnTask):Void { - var tank = buildTank(task.playerId, config.getTank(task.playerId.team, '0'), task.point); - var player:Player = teams.get(task.playerId.team).players[task.playerId.index]; - engine.spawn(tank); - player.tankId = tank.id; + getPlayer(task.playerId).tankId = 0; + if (trySpawn(task.playerId, true)) { + var tank = buildTank(task.playerId, config.getTank(task.playerId.team, '0'), task.point); + var player:Player = getPlayer(task.playerId); + engine.spawn(tank); + player.tankId = tank.id; + } else if (!isTeamAlive(task.playerId.team)) { + state.teams[task.playerId.team].lose = true; + complete(); + } + deferred.resolve(state); } private function complete():Void { for (team in teams.iterator()) { for (player in team.players) { + player.control.action(TankAction.STOP); player.control.dispose(); } } @@ -157,28 +168,51 @@ class Game implements EngineListener { } } - private function calcTeamLife(ts:TeamState):Int { - return Lambda.fold(ts.players, function(ps, t) return t + ps.life, ts.life); + private function isTeamAlive(team:TeamId):Bool { + var ts:TeamState = state.teams[team]; + var life:Int = Lambda.fold(ts.players, function(ps, t) return t + ps.life, ts.life); + if (life > 0) { + return true; + } else { + for (player in teams[team].players) { + if (player.tankId > 0) { + return true; + } + } + if (spawners[team].active) { + return true; + } + } + return false; + } + + private function trySpawn(player:PlayerId, spawn:Bool = false):Bool { + var ts:TeamState = state.teams[player.team]; + var ps:PlayerState = ts.players[player.index]; + var result = false; + if (ps.life > -1) { + if (ps.life > 0) { + if (spawn) ps.life--; + result = true; + } + } else if (ts.life > -1) { + if (ts.life > 0) { + if (spawn) ts.life--; + result = true; + } + } + return result; } public function onDestroy(entity:EntityType):Void { switch (entity) { case EntityType.TANK(tank): - var respawn:Bool = false; - var teamState:TeamState = state.teams[tank.playerId.team]; - if (teamState.life > 0) { - teamState.life--; - respawn = true; - } else { - var playerState:PlayerState = teamState.players[tank.playerId.index]; - if (playerState.life > 0) { - playerState.life--; - respawn = true; - } - } + getPlayer(tank.playerId).tankId = 0; + var respawn:Bool = trySpawn(tank.playerId); if (respawn) { spawners.get(tank.playerId.team).push(tank.playerId); - } else if (calcTeamLife(teamState) < 1) { + } + if (!isTeamAlive(tank.playerId.team)) { state.teams[tank.playerId.team].lose = true; complete(); } @@ -197,6 +231,11 @@ class Game implements EngineListener { } + public function next():Option { + return Option.None; + } + + public function dispose():Void { engine.dispose(); } diff --git a/src/common/haxe/ru/m/tankz/game/Spawner.hx b/src/common/haxe/ru/m/tankz/game/Spawner.hx index 7db2992..3d41b87 100644 --- a/src/common/haxe/ru/m/tankz/game/Spawner.hx +++ b/src/common/haxe/ru/m/tankz/game/Spawner.hx @@ -14,6 +14,8 @@ typedef SpawnTask = { class Spawner { + public var active(get, never):Bool; + private var config:TeamConfig; private var runner:SpawnTask -> Void; private var queue:Array; @@ -80,4 +82,8 @@ class Spawner { runner(queue.shift()); } } + + private function get_active():Bool { + return queue.length > 0; + } } \ No newline at end of file