diff --git a/package.json b/package.json index 9e91ca8..c1c0626 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tankz", - "version": "0.10.0", + "version": "0.11.0", "private": true, "devDependencies": { "dateformat": "^3.0.3", diff --git a/src/client/haxe/ru/m/tankz/render/AnimateBundle.hx b/src/client/haxe/ru/m/tankz/render/AnimateBundle.hx index 3a670e7..724b773 100644 --- a/src/client/haxe/ru/m/tankz/render/AnimateBundle.hx +++ b/src/client/haxe/ru/m/tankz/render/AnimateBundle.hx @@ -1,13 +1,8 @@ package ru.m.tankz.render; -import haxework.view.utils.BitmapUtil; -import haxework.color.Color; -import flash.display.BitmapData; import openfl.Assets; import ru.m.animate.Animate; import ru.m.animate.OnceAnimate; -import ru.m.tankz.core.Tank; -import ru.m.tankz.Type; class AnimateBundle { @@ -44,27 +39,4 @@ class AnimateBundle { length: 5 })]); } - - public static function tankFrames(tank:Tank):Array { - var color:Color = switch (tank.hits) { - case 1: 0x869C43; - case 2: 0xDEAF80; - case 3: 0x5EA67A; - case _: tank.color; - } - var colors:Array = [color, color]; - if (tank.bonus) { - colors[1] = 0xff00aa; - } - return [for (i in 0...2) ({ - image: BitmapUtil.colorize(Assets.getBitmapData('resources/image/tank/${tank.config.skin}-${i}.png'), colors[i]), - length: 3 - })]; - } - - public static function bonusFrames(type:BonusType):Array { - var image = Assets.getBitmapData('resources/image/bonus/${type}.png'); - var empty = new BitmapData(image.width, image.height, true, 0x00000000); - return [{image: image, length: 15}, {image: empty, length: 15}]; - } } diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index 3596b10..4d42d5c 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -167,6 +167,16 @@ class Render extends SpriteView implements IRender implements GameListener { item.hits = hits; item.bonus = bonus; } + case CHANGE(TANK_PROTECT(id, state)): + if (items.exists(id)) { + var item:TankRenderItem = cast items[id]; + item.protect = state; + } + case CHANGE(EAGLE_PROTECT(id, state)): + if (items.exists(id)) { + var item:EagleRenderItem = cast items[id]; + item.protect = state; + } case DESTROY(TANK(id, shot)): if (items.exists(id)) { var item = items[id]; diff --git a/src/client/haxe/ru/m/tankz/render/RenderItem.hx b/src/client/haxe/ru/m/tankz/render/RenderItem.hx deleted file mode 100644 index aaf5229..0000000 --- a/src/client/haxe/ru/m/tankz/render/RenderItem.hx +++ /dev/null @@ -1,301 +0,0 @@ -package ru.m.tankz.render; - -import haxework.view.utils.BitmapUtil; -import flash.display.Bitmap; -import flash.display.DisplayObject; -import flash.display.Shape; -import flash.display.Sprite; -import openfl.Assets; -import ru.m.animate.Animate; -import ru.m.geom.Rectangle; -import ru.m.tankz.core.Bonus; -import ru.m.tankz.core.Bullet; -import ru.m.tankz.core.Eagle; -import ru.m.tankz.core.Tank; -import ru.m.tankz.map.Brick; -import ru.m.tankz.Type.BrickType; - -typedef TRectangle = { - var rect(default, null):Rectangle; -} - -class RenderItem { - - public var value(default, null):T; - public var view(default, null):D; - - public function new(value:T) { - this.value = value; - this.view = null; - } - - public function redraw():Void {} - - public function update():Void { - var rect = value.rect; - view.rotation = rect.direction.angle; - 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; - } - - public function dispose():Void {} -} - - -class BitmapItem extends RenderItem { - - public function new(value:T) { - super(value); - this.view = new Bitmap(); - redraw(); - } - - override public function redraw():Void { - view.bitmapData = Assets.getBitmapData(getImage()); - } - - private function getImage():String { - return 'ERROR'; - } -} - - -class BrickItem extends BitmapItem { - private var type:BrickType; - - public function new(value:Brick) { - super(value); - redraw(); - } - - override public function update():Void { - super.update(); - var t = value.config.type; - if (t != type) { - type = t; - view.visible = t != 'none'; - redraw(); - } - } - - override private function getImage():String { - return 'resources/image/map/${value.config.type}.png'; - } -} - - -class BrickAnimateItem extends AnimateItem { - - public function new(value:Brick) { - super(value); - redraw(); - } - - override public function redraw():Void { - view.frames = [for (i in 0...2) ({ - image: Assets.getBitmapData('resources/image/map/${value.config.type}-${i}.png'), - length: 15 - })]; - view.playing = true; - } -} - - -class BrickBreakingItem extends RenderItem { - private var broken:Int; - private var type:BrickType; - - public function new(value:Brick) { - super(value); - this.view = new Shape(); - redraw(); - } - - override public function redraw():Void { - var image = Assets.getBitmapData(getImage()); - var g = view.graphics; - g.clear(); - if (value.destroyed) return; - if (value.config.index > 0) { - g.beginBitmapFill(image); - //g.drawRect(0, 0, value.rect.width, value.rect.height); - for (c in value.cells) { - if (!c.destroyed) { - 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; - var t = value.config.type; - if (b != broken || t != type) { - broken = b; - type = t; - redraw(); - } - } - - private function getImage():String { - return 'resources/image/map/${value.config.type}.png'; - } -} - - -class AnimateItem extends RenderItem { - - public function new(value:T) { - super(value); - view = new Animate(); - } - - override public function dispose():Void { - view.dispose(); - } -} - - -class TankItem extends RenderItem { - - private var type:String; - private var hits:Int; - private var protected:Bool; - private var frozen:Bool; - - private var tankView:Animate; - private var protectView:Animate; - - public function new(value:Tank) { - super(value); - view = new Sprite(); - tankView = new Animate(); - view.addChild(tankView); - protectView = AnimateBundle.tankProtect(); - protectView.visible = false; - view.addChild(protectView); - redraw(); - } - - override public function redraw():Void { - tankView.frames = AnimateBundle.tankFrames(value); - if (value.protect.active) { - protectView.x = (tankView.frames[0].image.width - protectView.frames[0].image.width) / 2; - protectView.y = (tankView.frames[0].image.height - protectView.frames[0].image.height) / 2; - protectView.playing = true; - protectView.visible = true; - } else { - protectView.playing = false; - protectView.visible = false; - } - } - - private function getFrames():Array { - var frame0 = 'resources/image/tank/${value.config.skin}-0.png'; - var frame1 = 'resources/image/tank/${value.config.skin}-1.png'; - return [frame1, frame0]; - } - - override public function update():Void { - super.update(); - var t = value.config.type; - var h = value.hits; - var p = value.protect.active; - var f = value.freezing.active; - if (t != type || h != hits || p != protected || f != frozen) { - this.type = t; - this.hits = h; - this.protected = p; - this.frozen = f; - redraw(); - } - tankView.playing = !value.freezing.active && (value.mx !=0 || value.my != 0); - } - - override public function dispose():Void { - if (tankView != null) { - tankView.dispose(); - tankView = null; - } - } -} - - -class BulletItem extends BitmapItem { - - override private function getImage():String { - var type:String = 'normal'; - if (value.config.piercing > 0) type = 'piercing'; - return 'resources/image/bullet/${type}.png'; - } -} - - -class EagleItem extends RenderItem { - - private var eagleView:Bitmap; - private var protectView:Animate; - private var death:Bool; - private var protected:Bool; - - public function new(value:Eagle) { - super(value); - view = new Sprite(); - eagleView = new Bitmap(); - view.addChild(eagleView); - protectView = AnimateBundle.tankProtect(); - protectView.visible = false; - view.addChild(protectView); - redraw(); - } - - override public function update():Void { - super.update(); - var d = value.death; - var p = value.protect.active; - if (d != death || p != protected) { - death = d; - protected = p; - redraw(); - } - } - - private function getImage():String { - var suffix = value.death ? '-death' : ''; - return 'resources/image/eagle/eagle${suffix}.png'; - } - - override public function redraw():Void { - var image = Assets.getBitmapData(getImage()); - if (!value.color.zero) { - image = BitmapUtil.colorize(image, value.color); - } - eagleView.bitmapData = image; - if (value.protect.active) { - protectView.x = (image.width - protectView.frames[0].image.width) / 2; - protectView.y = (image.height - protectView.frames[0].image.height) / 2; - protectView.playing = true; - protectView.visible = true; - } else { - protectView.playing = false; - protectView.visible = false; - } - } -} - - -class BonusItem extends AnimateItem { - - public function new(value:Bonus) { - super(value); - redraw(); - } - - override public function redraw():Void { - var image = Assets.getBitmapData('resources/image/bonus/${value.config.type}.png'); - view.frames = AnimateBundle.bonusFrames(value.config.type); - view.playing = true; - } -} diff --git a/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx index d029894..ce990f8 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx @@ -16,7 +16,6 @@ class BitmapRenderItem extends RenderItem { public function new(rect:Rectangle) { super(rect); this.bitmap = new Bitmap(null, PixelSnapping.AUTO, true); - move(rect.position); } override private function get_view():DisplayObject { diff --git a/src/client/haxe/ru/m/tankz/render/item/BonusRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/BonusRenderItem.hx index 3c682a0..109ee67 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BonusRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BonusRenderItem.hx @@ -6,10 +6,12 @@ import ru.m.tankz.Type; class BonusRenderItem extends BitmapRenderItem { public var type(default, set):BonusType; + private var d = 0.1; public function new(rect:Rectangle, type:BonusType) { super(rect); this.type = type; + move(rect.position); } private function set_type(value:BonusType):BonusType { @@ -19,4 +21,12 @@ class BonusRenderItem extends BitmapRenderItem { } return type; } + + override public function update():Void { + super.update(); + view.alpha += d; + if (view.alpha < 0 || view.alpha > 1.5) { + d = -d; + } + } } 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 d4b26f5..8dc78ad 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx @@ -1,10 +1,10 @@ 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.geom.Point; import ru.m.geom.Rectangle; import ru.m.tankz.Type.BrickType; diff --git a/src/client/haxe/ru/m/tankz/render/item/BulletRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/BulletRenderItem.hx index 2588e51..de47df1 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BulletRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BulletRenderItem.hx @@ -8,6 +8,7 @@ class BulletRenderItem extends BitmapRenderItem { public function new(rect:Rectangle, piercing:Int) { super(rect); this.piercing = piercing; + move(rect.position); } private function set_piercing(value:Int):Int { diff --git a/src/client/haxe/ru/m/tankz/render/item/EagleRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/EagleRenderItem.hx index a2c2e7b..5df43bf 100644 --- a/src/client/haxe/ru/m/tankz/render/item/EagleRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/EagleRenderItem.hx @@ -1,13 +1,43 @@ package ru.m.tankz.render.item; +import flash.display.DisplayObject; +import flash.display.Sprite; +import ru.m.animate.Animate; import ru.m.geom.Rectangle; class EagleRenderItem extends BitmapRenderItem { public var death(default, set):Bool = true; + public var protect(default, set):Bool; + + private var container:Sprite; + private var protectView:Animate; public function new(rect:Rectangle) { super(rect); + container = new Sprite(); + container.addChild(bitmap); + protectView = AnimateBundle.tankProtect(); + protectView.visible = false; + container.addChild(protectView); death = false; + move(rect.position); + } + + override private function get_view():DisplayObject { + return container; + } + + private function set_protect(value:Bool):Bool { + if (protect != value) { + protect = value; + if (protect) { + protectView.x = (bitmapData.width - protectView.frames[0].image.width) / 2; + protectView.y = (bitmapData.height - protectView.frames[0].image.height) / 2; + } + protectView.visible = protect; + protectView.playing = protect; + } + return protect; } private function set_death(value:Bool):Bool { diff --git a/src/client/haxe/ru/m/tankz/render/item/TankRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/TankRenderItem.hx index e470fcc..f3dc08c 100644 --- a/src/client/haxe/ru/m/tankz/render/item/TankRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/TankRenderItem.hx @@ -1,9 +1,12 @@ package ru.m.tankz.render.item; +import flash.display.DisplayObject; +import flash.display.Sprite; import flash.display.BitmapData; import haxework.color.Color; import haxework.view.utils.BitmapUtil; import openfl.Assets; +import ru.m.animate.Animate; import ru.m.geom.Rectangle; class TankRenderItem extends BitmapRenderItem { @@ -12,15 +15,27 @@ class TankRenderItem extends BitmapRenderItem { public var hits(default, set):Int; public var bonus(default, set):Bool; public var moves(default, set):Bool; + public var protect(default, set):Bool; + private var container:Sprite; private var images:Array; private var frame:Int; + private var protectView:Animate; public function new(rect:Rectangle) { super(rect); + container = new Sprite(); + container.addChild(bitmap); + protectView = AnimateBundle.tankProtect(); + protectView.visible = false; + container.addChild(protectView); move(rect.position); } + override private function get_view():DisplayObject { + return container; + } + private function redraw():Void { var image1 = Assets.getBitmapData('resources/image/tank/${skin}-0.png'); var image2 = Assets.getBitmapData('resources/image/tank/${skin}-1.png'); @@ -72,6 +87,19 @@ class TankRenderItem extends BitmapRenderItem { return bonus; } + private function set_protect(value:Bool):Bool { + if (protect != value) { + protect = value; + if (protect) { + protectView.x = (images[0].width - protectView.frames[0].image.width) / 2; + protectView.y = (images[0].height - protectView.frames[0].image.height) / 2; + } + protectView.visible = protect; + protectView.playing = protect; + } + return protect; + } + private function set_moves(value:Bool):Bool { if (moves != value) { moves = value; diff --git a/src/common/haxe/ru/m/tankz/core/Eagle.hx b/src/common/haxe/ru/m/tankz/core/Eagle.hx index 6c5553f..93bd51a 100644 --- a/src/common/haxe/ru/m/tankz/core/Eagle.hx +++ b/src/common/haxe/ru/m/tankz/core/Eagle.hx @@ -20,10 +20,15 @@ class Eagle extends Entity { this.team = team; this.config = config; this.death = false; - this.protect = new Modificator(); + this.protect = new Modificator(id); } private inline function get_score():Int { return config != null ? config.score : 0; } + + override public function dispose() { + super.dispose(); + protect.dispose(); + } } diff --git a/src/common/haxe/ru/m/tankz/core/Entity.hx b/src/common/haxe/ru/m/tankz/core/Entity.hx index 172591d..570a7ab 100755 --- a/src/common/haxe/ru/m/tankz/core/Entity.hx +++ b/src/common/haxe/ru/m/tankz/core/Entity.hx @@ -18,4 +18,6 @@ class Entity { public function toString():String { return '$type($id)'; } + + public function dispose() {} } diff --git a/src/common/haxe/ru/m/tankz/core/Modificator.hx b/src/common/haxe/ru/m/tankz/core/Modificator.hx index 01f05f5..d53b14c 100644 --- a/src/common/haxe/ru/m/tankz/core/Modificator.hx +++ b/src/common/haxe/ru/m/tankz/core/Modificator.hx @@ -1,26 +1,37 @@ package ru.m.tankz.core; import haxe.Timer; +import haxework.signal.Signal; -class Modificator { +class Modificator extends Signal2 { + public var id(default, default):Int; public var active(default, default):Bool; private var timer:Timer; - public function new() { + public function new(id) { + super(); + this.id = id; active = false; } + override public function connect(receiver:Int->Bool->Void):Void { + super.connect(receiver); + receiver(id, active); + } + public function on(seconds:Float):Void { off(); active = true; timer = Timer.delay(off, Std.int(seconds * 1000)); + emit(id, true); } public function off():Void { if (timer != null) { timer.stop(); timer = null; + emit(id, false); } active = false; } diff --git a/src/common/haxe/ru/m/tankz/core/Tank.hx b/src/common/haxe/ru/m/tankz/core/Tank.hx index df54772..efe564f 100755 --- a/src/common/haxe/ru/m/tankz/core/Tank.hx +++ b/src/common/haxe/ru/m/tankz/core/Tank.hx @@ -17,8 +17,8 @@ class Tank extends MobileEntity { public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:TankConfig) { super(id, rect, config.speed, Direction.RIGHT); - this.protect = new Modificator(); - this.freezing = new Modificator(); + this.protect = new Modificator(id); + this.freezing = new Modificator(id); this.playerId = playerId; this.config = config; this.layer = 1; @@ -39,4 +39,10 @@ class Tank extends MobileEntity { super.move(direction); } } + + override public function dispose() { + super.dispose(); + protect.dispose(); + freezing.dispose(); + } } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 265ea89..4fef152 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -140,7 +140,10 @@ import ru.m.tankz.map.LevelMap; } public function dispose():Void { - // ToDo: set to null + for (entity in allEntities) { + entity.dispose(); + } + allEntities = new Map(); entities = new Map(); //map = null; spawnSignal.dispose(); diff --git a/src/common/haxe/ru/m/tankz/game/GameEvent.hx b/src/common/haxe/ru/m/tankz/game/GameEvent.hx index b1fac54..6a87fc5 100644 --- a/src/common/haxe/ru/m/tankz/game/GameEvent.hx +++ b/src/common/haxe/ru/m/tankz/game/GameEvent.hx @@ -58,6 +58,9 @@ enum StopEvent { enum ChangeEvent { TANK(id:Int, type:TankType, hits:Int, bonus:Bool); + TANK_PROTECT(id:Int, state:Bool); + TANK_FREEZE(id:Int, state:Bool); + EAGLE_PROTECT(id:Int, state:Bool); PLAYER_SCORE(playerId:PlayerId, value:Int); PLAYER_LIFE(playerId:PlayerId, value:Int); TEAM_SCORE(teamId:TeamId, value:Int); diff --git a/src/common/haxe/ru/m/tankz/game/GameRunner.hx b/src/common/haxe/ru/m/tankz/game/GameRunner.hx index aafaa12..79e4088 100644 --- a/src/common/haxe/ru/m/tankz/game/GameRunner.hx +++ b/src/common/haxe/ru/m/tankz/game/GameRunner.hx @@ -1,7 +1,5 @@ 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; @@ -21,6 +19,7 @@ import ru.m.tankz.engine.IEngine; import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.IGame; import ru.m.tankz.game.Spawner; +import ru.m.tankz.map.Brick; import ru.m.tankz.Type; class GameRunner implements EngineListener implements GameListener { @@ -85,6 +84,7 @@ class GameRunner implements EngineListener implements GameListener { var eagle = builder.buildEagle(++entityId, point, team.id); game.engine.spawn(eagle); gameEventSignal.emit(GameEvent.SPAWN(EAGLE(eagle.id, eagle.rect, eagle.team))); + eagle.protect.connect(onEagleProtectChange); } } var bricks = game.engine.map.bricks.map(function(item:Brick):BrickInfo { @@ -115,6 +115,20 @@ class GameRunner implements EngineListener implements GameListener { var tank = builder.buildTank(++entityId, task.point, task.playerId, task.tankType); game.engine.spawn(tank); gameEventSignal.emit(GameEvent.SPAWN(TANK(tank.id, tank.rect.clone(), tank.playerId, {type:tank.config.type, hits:tank.hits, bonus:tank.bonus}))); + tank.protect.connect(onTankProtectChange); + tank.freezing.connect(onTankFreezingChange); + } + + private function onEagleProtectChange(id:Int, state:Bool):Void { + gameEventSignal.emit(GameEvent.CHANGE(EAGLE_PROTECT(id, state))); + } + + private function onTankProtectChange(id:Int, state:Bool):Void { + gameEventSignal.emit(GameEvent.CHANGE(TANK_PROTECT(id, state))); + } + + private function onTankFreezingChange(id:Int, state:Bool):Void { + gameEventSignal.emit(GameEvent.CHANGE(TANK_FREEZE(id, state))); } private function checkComplete():Void {