diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index f79c089..3596b10 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -11,8 +11,8 @@ import promhx.Promise; import ru.m.animate.Animate; import ru.m.animate.OnceAnimate; import ru.m.geom.Point; +import ru.m.tankz.config.Config; import ru.m.tankz.core.EntityType; -import ru.m.tankz.engine.IEngine; import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.IGame; import ru.m.tankz.render.item.BonusRenderItem; @@ -57,13 +57,15 @@ class Render extends SpriteView implements IRender implements GameListener { return game; } - private function drawBackground(engine:IEngine):Void { + private function drawBackground(config:Config):Void { + var width = config.map.cellWidth * config.map.gridWidth; + var height = config.map.cellHeight * config.map.gridHeight; var g:Graphics = backgroundLayer.graphics; g.clear(); g.beginFill(0x000000); - g.drawRect(0, 0, engine.map.width, engine.map.height); + g.drawRect(0, 0, width, height); g.endFill(); - setContentSize(engine.map.width, engine.map.height); + setContentSize(width, height); } public function draw():Void { @@ -71,7 +73,7 @@ class Render extends SpriteView implements IRender implements GameListener { item.update(); } if (background == null) { - drawBackground(game.engine); + drawBackground(game.config); } } @@ -102,18 +104,20 @@ class Render extends SpriteView implements IRender implements GameListener { public function onGameEvent(event:GameEvent):Void { switch event { case START(_): - for (brick in game.engine.map.bricks) { - var item:IRenderItem = new BrickRenderItem(brick); + content.addEventListener(Event.ENTER_FRAME, onEnterFrame); + case COMPLETE(_, _): + content.removeEventListener(Event.ENTER_FRAME, onEnterFrame); + case SPAWN(BRICK(bricks)): + for (brick in bricks) { + var item:IRenderItem = new BrickRenderItem(brick.rect, brick.type); + var config = game.config.getBrick(brick.type); items[brick.id] = item; - if (brick.config.layer > 2) { + if (config.layer > 2) { upLayer.addChild(item.view); } else { groundLayer.addChild(item.view); } } - content.addEventListener(Event.ENTER_FRAME, onEnterFrame); - case COMPLETE(_, _): - content.removeEventListener(Event.ENTER_FRAME, onEnterFrame); case SPAWN(EAGLE(id, rect, teamId)): var item = new EagleRenderItem(rect); items.set(id, item); @@ -201,11 +205,12 @@ class Render extends SpriteView implements IRender implements GameListener { } items.remove(id); } - case DESTROY(CELL(cellX, cellY, shot)): - // ToDo: redraw only cell? - var brick = game.engine.map.getBrick(new Point(cellX, cellY)); - var item:BrickRenderItem = cast items[brick.id]; - item.redraw(brick); + case DESTROY(CELL(id, x, y, shot)): + var item:BrickRenderItem = cast items.get(id); + item.destroyCell(x, y); + case DESTROY(BRICK(id, shot)): + var item:BrickRenderItem = cast items.get(id); + item.destroy(); case _: } } diff --git a/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx index d86b465..d4b26f5 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx @@ -1,27 +1,50 @@ package ru.m.tankz.render.item; +import ru.m.geom.Point; import flash.display.BitmapData; import flash.display.Shape; import openfl.Assets; import openfl.display.DisplayObject; -import ru.m.tankz.map.Brick; +import ru.m.geom.Rectangle; import ru.m.tankz.Type.BrickType; +enum BrickState { + UNBROKEN; + BROKEN; + DESTROYED; +} + class BrickRenderItem extends RenderItem { public var type(default, set):BrickType; + public var state(get, never):BrickState; private var image:BitmapData; private var shape:Shape; + private var cells:Array; - public function new(brick:Brick) { - super(brick.rect); + public function new(rect:Rectangle, type:BrickType) { + super(rect); this.shape = new Shape(); - this.type = brick.config.type; - redraw(brick); + this.type = type; + cells = [ + new Point(0, 0), + new Point(0, 1), + new Point(1, 0), + new Point(1, 1), + ]; + redraw(); move(rect.position); } + private function get_state():BrickState { + return switch cells.length { + case 0: DESTROYED; + case 4: UNBROKEN; + case _: BROKEN; + } + } + override private function get_view():DisplayObject { return shape; } @@ -34,21 +57,34 @@ class BrickRenderItem extends RenderItem { return type; } - public function redraw(brick:Brick):Void { + public function destroyCell(x:Int, y:Int):Void { + cells = cells.filter(function(point) return !(point.x == x && point.y == y)); + redraw(); + } + + public function destroy():Void { + cells = []; + redraw(); + } + + public function redraw():Void { shape.graphics.clear(); - if (brick.destroyed) return; - if (brick.config.index > 0) { - shape.graphics.beginBitmapFill(image); - if (brick.broken == 0) { - shape.graphics.drawRect(0, 0, brick.rect.width, brick.rect.height); - } else { - for (c in brick.cells) { - if (!c.destroyed) { - shape.graphics.drawRect(c.rect.x - brick.rect.x, c.rect.y - brick.rect.y, c.rect.width, c.rect.height); - } + switch state { + case UNBROKEN: + shape.graphics.beginBitmapFill(image); + shape.graphics.drawRect(0, 0, rect.width, rect.height); + shape.graphics.endFill(); + case BROKEN: + shape.graphics.beginBitmapFill(image); + for (point in cells) { + var x = point.x * (rect.width / 2); + var y = point.y * (rect.width / 2); + var width = rect.width / 2; + var height = rect.height / 2; + shape.graphics.drawRect(x, y, width, height); } - } - shape.graphics.endFill(); + shape.graphics.endFill(); + case DESTROYED: } } } diff --git a/src/common/haxe/ru/m/tankz/bot/BotControl.hx b/src/common/haxe/ru/m/tankz/bot/BotControl.hx index 3ffffa0..8d5f3ca 100644 --- a/src/common/haxe/ru/m/tankz/bot/BotControl.hx +++ b/src/common/haxe/ru/m/tankz/bot/BotControl.hx @@ -32,7 +32,7 @@ class BotControl extends Control { shotTimer.stop(); shotTimer = null; } - //action(SHOT); + action(SHOT); } public function shot(delay:Int = 100):Void { diff --git a/src/common/haxe/ru/m/tankz/game/GameEvent.hx b/src/common/haxe/ru/m/tankz/game/GameEvent.hx index 181ab07..b1fac54 100644 --- a/src/common/haxe/ru/m/tankz/game/GameEvent.hx +++ b/src/common/haxe/ru/m/tankz/game/GameEvent.hx @@ -11,7 +11,16 @@ typedef TankInfo = { var bonus:Bool; } +typedef BrickInfo = { + var id:Int; + var x:Int; + var y:Int; + var rect:Rectangle; + var type:BrickType; +} + enum SpawnEvent { + BRICK(bricks:Array); EAGLE(id:Int, rect:Rectangle, teamId:TeamId); TANK(id:Int, rect:Rectangle, playerId:PlayerId, info:TankInfo); BULLET(id:Int, rect:Rectangle, playerId:PlayerId, piercing:Int); @@ -34,7 +43,8 @@ enum DestroyEvent { TANK(id:Int, shot:Shot); BONUS(id:Int, shot:Shot); BULLET(id:Int); - CELL(cellX:Int, cellY:Int, shot:Shot); + CELL(id:Int, x:Int, y:Int, shot:Shot); + BRICK(id:Int, shot:Shot); } enum MoveEvent { diff --git a/src/common/haxe/ru/m/tankz/game/GameRunner.hx b/src/common/haxe/ru/m/tankz/game/GameRunner.hx index 65048bf..aafaa12 100644 --- a/src/common/haxe/ru/m/tankz/game/GameRunner.hx +++ b/src/common/haxe/ru/m/tankz/game/GameRunner.hx @@ -1,5 +1,7 @@ package ru.m.tankz.game; +import ru.m.tankz.map.Grid.GridCell; +import ru.m.tankz.map.Brick; import haxe.ds.Option; import haxe.Timer; import haxework.signal.Signal; @@ -85,6 +87,16 @@ class GameRunner implements EngineListener implements GameListener { gameEventSignal.emit(GameEvent.SPAWN(EAGLE(eagle.id, eagle.rect, eagle.team))); } } + var bricks = game.engine.map.bricks.map(function(item:Brick):BrickInfo { + return { + id: item.id, + x: item.cellY, + y: item.cellY, + rect: item.rect, + type: item.config.type, + } + }); + gameEventSignal.emit(GameEvent.SPAWN(BRICK(bricks))); gameEventSignal.emit(GameEvent.START(state)); } @@ -102,7 +114,7 @@ class GameRunner implements EngineListener implements GameListener { private function spawn(task:SpawnTask):Void { var tank = builder.buildTank(++entityId, task.point, task.playerId, task.tankType); game.engine.spawn(tank); - gameEventSignal.emit(GameEvent.SPAWN(TANK(tank.id, tank.rect, tank.playerId, {type:tank.config.type, hits:tank.hits, bonus:tank.bonus}))); + gameEventSignal.emit(GameEvent.SPAWN(TANK(tank.id, tank.rect.clone(), tank.playerId, {type:tank.config.type, hits:tank.hits, bonus:tank.bonus}))); } private function checkComplete():Void { @@ -241,7 +253,7 @@ class GameRunner implements EngineListener implements GameListener { } var bonus = builder.buildBonus(++entityId, point, type); game.engine.spawn(bonus); - gameEventSignal.emit(GameEvent.SPAWN(BONUS(bonus.id, bonus.rect, bonus.config.type))); + gameEventSignal.emit(GameEvent.SPAWN(BONUS(bonus.id, bonus.rect.clone(), bonus.config.type))); } private inline function alienTank(team:TeamId):Tank->Bool { @@ -331,7 +343,7 @@ class GameRunner implements EngineListener implements GameListener { bullet.tank = tank; bullet.move(bullet.rect.direction); game.engine.spawn(bullet); - gameEventSignal.emit(GameEvent.SPAWN(BULLET(bullet.id, bullet.rect, bullet.playerId, bullet.config.piercing))); + gameEventSignal.emit(GameEvent.SPAWN(BULLET(bullet.id, bullet.rect.clone(), bullet.playerId, bullet.config.piercing))); } case GameEvent.ACTION(tankId, MOVE(direction)): game.engine.move(tankId, direction); @@ -396,15 +408,17 @@ class GameRunner implements EngineListener implements GameListener { var cells = game.engine.map.grid.getCells(side.setLength(game.engine.map.grid.cellWidth * 3)); for (cell in cells) { if (cell.armor > 0) { + var shot = buildShot(bullet); if (cell.armor == bullet.config.piercing) { game.engine.destroyCell(cell.cellX, cell.cellY); - gameEventSignal.emit(GameEvent.DESTROY(CELL(cell.cellX, cell.cellY, buildShot(bullet)))); + var brick = game.engine.map.getBrick(cell.position); + gameEventSignal.emit(GameEvent.DESTROY(CELL(brick.id, cell.cellX - brick.cellX * 2, cell.cellY - brick.cellY * 2, shot))); } else if (cell.armor < bullet.config.piercing) { var brick = game.engine.map.getBrick(cell.position); for (cell in brick.cells) { game.engine.destroyCell(cell.cellX, cell.cellY); - gameEventSignal.emit(GameEvent.DESTROY(CELL(cell.cellX, cell.cellY, buildShot(bullet)))); } + gameEventSignal.emit(GameEvent.DESTROY(BRICK(brick.id, shot))); } } }