diff --git a/src/client/haxe/ru/m/tankz/control/HumanControl.hx b/src/client/haxe/ru/m/tankz/control/HumanControl.hx index 5582b3d..52904e6 100644 --- a/src/client/haxe/ru/m/tankz/control/HumanControl.hx +++ b/src/client/haxe/ru/m/tankz/control/HumanControl.hx @@ -43,7 +43,7 @@ class HumanControl extends Control { case _: } if (event.keyCode == Keyboard.U) { - action(TankAction.LEVEL_UP(1)); + action(TankAction.UPGRADE); } } diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index e13468d..03b93e0 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -108,6 +108,11 @@ class Render extends SpriteView implements EngineListener { items.set(eagle.key, item); entryLayer.addChild(item.view); item.update(); + case EntityType.BONUS(bonus): + var item = new BonusItem(bonus); + items.set(bonus.key, item); + entryLayer.addChild(item.view); + item.update(); case _: } } @@ -136,6 +141,11 @@ class Render extends SpriteView implements EngineListener { items.get(eagle.key).redraw(); playTankBoom(eagle.rect.center); } + case EntityType.BONUS(bonus): + if (items.exists(bonus.key)) { + entryLayer.removeChild(items.get(bonus.key).view); + items.remove(bonus.key); + } case _: } } diff --git a/src/client/haxe/ru/m/tankz/render/RenderItem.hx b/src/client/haxe/ru/m/tankz/render/RenderItem.hx index e5a1f21..74e90e6 100644 --- a/src/client/haxe/ru/m/tankz/render/RenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/RenderItem.hx @@ -1,5 +1,8 @@ package ru.m.tankz.render; +import openfl.display.BitmapData; +import ru.m.draw.Color; +import ru.m.tankz.core.Bonus; import flash.display.Bitmap; import flash.display.DisplayObject; import flash.display.Shape; @@ -9,7 +12,6 @@ import ru.m.animate.Animate; import ru.m.draw.BitmapUtil; import ru.m.geom.Direction; import ru.m.geom.Rectangle; -import ru.m.tankz.control.Control; import ru.m.tankz.core.Bullet; import ru.m.tankz.core.Eagle; import ru.m.tankz.core.Tank; @@ -121,6 +123,19 @@ class BrickItem extends RenderItem { } +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; @@ -131,28 +146,14 @@ class TankItem extends RenderItem { public function new(value:Tank) { super(value); view = new Sprite(); - if (value.playerId.type == Control.HUMAN) { - view.addChild(buildHumanMarkView(value)); - } tankView = new Animate(); view.addChild(tankView); redraw(); } - private static function buildHumanMarkView(tank:Tank):DisplayObject { - var view = new Shape(); - view.graphics.beginFill(0x00aa00); - view.graphics.lineStyle(2, 0x00ff00); - view.graphics.drawCircle(0, 0, 23); - view.graphics.endFill(); - view.x = tank.rect.width / 2; - view.y = tank.rect.height / 2; - view.alpha = 0.2; - return view; - } - override public function redraw():Void { - tankView.frames = getFrames().map(function(src) return BitmapUtil.colorize(Assets.getBitmapData(src), value.color)); + var colors:Array = [value.color, value.bonus ? 0xff00aa : value.color]; + tankView.frames = getFrames().map(function(src) return BitmapUtil.colorize(Assets.getBitmapData(src), colors.shift())); } private function getFrames():Array { @@ -199,3 +200,21 @@ class EagleItem extends BitmapItem { return 'resources/images/eagle/eagle-${destoyed ? 1 : 0}.png'; } } + + +class BonusItem extends AnimateItem { + + public function new(value:Bonus) { + super(value); + redraw(); + } + + override public function redraw():Void { + // ToDo: 15/15 frames + view.frames = [ + Assets.getBitmapData('resources/image/bonus/${value.bonusType}.png'), + new BitmapData(1, 1), + ]; + view.playing = true; + } +} diff --git a/src/client/resources/classic/config.yaml b/src/client/resources/classic/config.yaml index 51dada7..8cdd87f 100644 --- a/src/client/resources/classic/config.yaml +++ b/src/client/resources/classic/config.yaml @@ -24,10 +24,10 @@ teams: - id: bot spawnInterval: 3000 tanks: - - {type: bot0, rate: 0.5} - - {type: bot1, rate: 0.5} - - {type: bot2, rate: 0.5} - - {type: bot3, rate: 0.5} + - {type: bot0, rate: 0.25, bonus: 1} + - {type: bot1, rate: 0.25, bonus: 1} + - {type: bot2, rate: 0.25, bonus: 1} + - {type: bot3, rate: 0.25, bonus: 1} points: - {team: human, type: eagle, index: -1, direction: right, x: 12, y: 24} @@ -45,6 +45,7 @@ bullet: &bullet tanks: - type: human0 + upgrade: human1 width: 36 height: 36 speed: 2.5 @@ -55,6 +56,7 @@ tanks: skin: pa - type: human1 + upgrade: human2 width: 40 height: 36 speed: 3.0 @@ -65,6 +67,7 @@ tanks: skin: pb - type: human2 + upgrade: human3 width: 40 height: 36 speed: 3.0 @@ -75,6 +78,7 @@ tanks: skin: pc - type: human3 + upgrade: human3 width: 42 height: 38 speed: 2.9 @@ -130,3 +134,11 @@ tanks: score: 400 hits: 3 skin: bd + +bonuses: + - {type: clock} + - {type: grenade} + - {type: helmet} + - {type: life} + - {type: shovel} + - {type: star} diff --git a/src/client/resources/dota/config.yaml b/src/client/resources/dota/config.yaml index 60b3433..f813fd4 100644 --- a/src/client/resources/dota/config.yaml +++ b/src/client/resources/dota/config.yaml @@ -70,3 +70,11 @@ tanks: speed: 7.0 bullets: 1 skin: bb + +bonuses: + - {type: clock} + - {type: grenade} + - {type: helmet} + - {type: life} + - {type: shovel} + - {type: star} diff --git a/src/client/resources/images/bonus/bonus_1-0.png b/src/client/resources/image/bonus/clock.png similarity index 100% rename from src/client/resources/images/bonus/bonus_1-0.png rename to src/client/resources/image/bonus/clock.png diff --git a/src/client/resources/images/bonus/bonus_0-0.png b/src/client/resources/image/bonus/grenade.png similarity index 100% rename from src/client/resources/images/bonus/bonus_0-0.png rename to src/client/resources/image/bonus/grenade.png diff --git a/src/client/resources/images/bonus/bonus_2-0.png b/src/client/resources/image/bonus/helmet.png similarity index 100% rename from src/client/resources/images/bonus/bonus_2-0.png rename to src/client/resources/image/bonus/helmet.png diff --git a/src/client/resources/images/bonus/bonus_5-0.png b/src/client/resources/image/bonus/life.png similarity index 100% rename from src/client/resources/images/bonus/bonus_5-0.png rename to src/client/resources/image/bonus/life.png diff --git a/src/client/resources/images/bonus/bonus_3-0.png b/src/client/resources/image/bonus/shovel.png similarity index 100% rename from src/client/resources/images/bonus/bonus_3-0.png rename to src/client/resources/image/bonus/shovel.png diff --git a/src/client/resources/images/bonus/bonus_4-0.png b/src/client/resources/image/bonus/star.png similarity index 100% rename from src/client/resources/images/bonus/bonus_4-0.png rename to src/client/resources/image/bonus/star.png diff --git a/src/client/resources/images/bonus/bonus_0-1.png b/src/client/resources/images/bonus/bonus_0-1.png deleted file mode 100644 index 2772af1..0000000 Binary files a/src/client/resources/images/bonus/bonus_0-1.png and /dev/null differ diff --git a/src/common/haxe/ru/m/tankz/Type.hx b/src/common/haxe/ru/m/tankz/Type.hx index 0d82d2f..96c76cb 100644 --- a/src/common/haxe/ru/m/tankz/Type.hx +++ b/src/common/haxe/ru/m/tankz/Type.hx @@ -10,8 +10,12 @@ typedef TeamId = String; typedef ControlType = String; +typedef BrickType = Int; + typedef TankType = String; +typedef BonusType = String; + typedef PlayerId = { var team:TeamId; var type:ControlType; diff --git a/src/common/haxe/ru/m/tankz/config/Config.hx b/src/common/haxe/ru/m/tankz/config/Config.hx index 9a29108..37c33eb 100644 --- a/src/common/haxe/ru/m/tankz/config/Config.hx +++ b/src/common/haxe/ru/m/tankz/config/Config.hx @@ -26,7 +26,7 @@ typedef MapConfig = { } typedef BrickConfig = { - var type:Int; + var type:BrickType; var layer:Int; var armor:Int; } @@ -47,11 +47,17 @@ typedef TankConfig = { var bullets:Int; var hits:Int; var skin:String; + @:optinal var upgrade:TankType; +} + +typedef BonusConfig = { + var type:BonusType; } typedef TankSpawn = { var type:TankType; - var rate: Float; + var rate:Float; + @:optional var bonus:Float; } @@ -78,10 +84,12 @@ class Config { public var tanks(default, null):Array; public var teams(default, null):Array; public var points(default, null):Array; + public var bonuses(default, null):Array; private var brickMap:Map; private var tankMap:Map; - private var teamMap:Map; + private var teamMap:Map; + private var bonusMap:Map; public function new( type:String, @@ -90,7 +98,8 @@ class Config { bricks:Array, teams:Array, points:Array, - tanks:Array + tanks:Array, + bonuses:Array ) { this.type = type; this.game = game; @@ -99,6 +108,7 @@ class Config { this.teams = teams; this.points = points; this.tanks = tanks; + this.bonuses = bonuses; init(); } @@ -115,6 +125,10 @@ class Config { for (item in tanks) { tankMap.set(item.type, item); } + bonusMap = new Map(); + for (item in bonuses) { + bonusMap.set(item.type, item); + } } public function getBrick(type:Int):BrickConfig { @@ -128,4 +142,8 @@ class Config { public function getTank(type:TankType):TankConfig { return tankMap.get(type); } + + public function getBonus(type:BonusType):BonusConfig { + return bonusMap.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 68c0fc2..bcca43a 100644 --- a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx +++ b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx @@ -13,6 +13,7 @@ typedef ConfigSource = { var teams: Array; var points: Array; var tanks: Array; + var bonuses: Array; } class ConfigBundle { @@ -23,6 +24,6 @@ class ConfigBundle { public static function get(type:String):Config { var source = convert(Yaml.parse(Assets.getText('resources/${type}/config.yaml'), Parser.options().useObjects())); - return new Config(type, source.game, source.map, source.bricks, source.teams, source.points, source.tanks); + return new Config(type, source.game, source.map, source.bricks, source.teams, source.points, source.tanks, source.bonuses); } } diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx index 0d1827b..1470f91 100644 --- a/src/common/haxe/ru/m/tankz/control/Control.hx +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -8,7 +8,7 @@ import ru.m.tankz.Type; enum TankAction { MOVE(direction:Direction); - LEVEL_UP(level:Int); + UPGRADE; STOP; SHOT; } diff --git a/src/common/haxe/ru/m/tankz/core/Bonus.hx b/src/common/haxe/ru/m/tankz/core/Bonus.hx new file mode 100644 index 0000000..d9b7740 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/core/Bonus.hx @@ -0,0 +1,15 @@ +package ru.m.tankz.core; + +import ru.m.geom.Rectangle; +import ru.m.tankz.Type; + + +class Bonus extends Entity { + + public var bonusType(default, null):BonusType; + + public function new(bonusType:BonusType) { + super(new Rectangle(0, 0, 44, 44)); + this.bonusType = bonusType; + } +} diff --git a/src/common/haxe/ru/m/tankz/core/EntityType.hx b/src/common/haxe/ru/m/tankz/core/EntityType.hx index 03a6965..ad301a0 100644 --- a/src/common/haxe/ru/m/tankz/core/EntityType.hx +++ b/src/common/haxe/ru/m/tankz/core/EntityType.hx @@ -1,7 +1,7 @@ package ru.m.tankz.core; import Type; -import ru.m.tankz.map.Grid.GridCell; +import ru.m.tankz.map.Grid; enum EntityType { @@ -9,6 +9,7 @@ enum EntityType { TANK(tank:Tank); BULLET(bullet:Bullet); CELL(cell:GridCell); + BONUS(bonus:Bonus); } @@ -20,6 +21,7 @@ class EntityTypeResolver { 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 ValueType.TClass(Bonus): EntityType.BONUS(cast entity); case x: null; } } diff --git a/src/common/haxe/ru/m/tankz/core/Tank.hx b/src/common/haxe/ru/m/tankz/core/Tank.hx index b1b87f6..7f0fd60 100755 --- a/src/common/haxe/ru/m/tankz/core/Tank.hx +++ b/src/common/haxe/ru/m/tankz/core/Tank.hx @@ -14,6 +14,7 @@ class Tank extends MobileEntity { public var config(default, set):TankConfig; public var color(default, default):Color; public var hits(default, default):Int; + public var bonus(default, default):Bool; private var bulletsCounter:Int = 0; diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 2ac4130..5de01f1 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -58,6 +58,8 @@ class CollisionProcessor implements EngineListener { tank1.rect.lean(eagle.rect); case EntityType.CELL(cell): tank1.rect.lean(cell.rect); + case EntityType.BONUS(bonus): + engine.destroy(bonus); } case EntityType.BULLET(bullet1): switch (with) { @@ -74,6 +76,7 @@ class CollisionProcessor implements EngineListener { engine.destroy(eagle); case EntityType.CELL(cell): engine.destroy(bullet1); + case EntityType.BONUS(bonus): } case _: } @@ -131,15 +134,10 @@ class Engine implements ControlHandler { switch (action) { case TankAction.MOVE(direction): tank.move(direction); - case TankAction.LEVEL_UP(level): - // ToDo: - var newType = switch(tank.config.type) { - case 'human0': 'human1'; - case 'human1': 'human2'; - case 'human2': 'human3'; - case x: 'human3'; + case TankAction.UPGRADE: + if (tank.config.upgrade != null) { + tank.config = config.getTank(tank.config.upgrade); } - tank.config = config.getTank(newType); case TankAction.STOP: tank.stop(); case TankAction.SHOT: diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 39e8c61..61659bb 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 ru.m.tankz.core.Bonus; import haxe.ds.Option; import haxe.Timer; import promhx.Deferred; @@ -54,6 +55,7 @@ class Game implements EngineListener { var tankConfig:TankConfig = config.getTank(spawn.type); var tank = new Tank(playerId, tankConfig); tank.color = playerId.color.zero ? teams[playerId.team].config.color : playerId.color; + tank.bonus = Math.random() < spawn.bonus; applyPoint(tank, point); return tank; } @@ -154,6 +156,11 @@ class Game implements EngineListener { case EntityType.TANK(tank): var control = getPlayer(tank.playerId).control; if (control != null) control.onCollision(with); + switch (with) { + case EntityType.BONUS(bonus): + applyBonus(tank, bonus); + case x: + } case x: } } @@ -207,6 +214,7 @@ class Game implements EngineListener { state.teams[tank.playerId.team].lose = true; complete(); } + if (tank.bonus) spawnBonus(); deferred.resolve(state); case EntityType.EAGLE(eagle): state.teams[eagle.team].lose = true; @@ -216,18 +224,53 @@ class Game implements EngineListener { } } - public function onAction(tankId:Int, action:TankAction):Void { engine.action(tankId, action); } - public function next():Option { return Option.None; } - public function dispose():Void { engine.dispose(); } + + + private function spawnBonus():Void { + var bonusConfig = config.bonuses[Math.floor(Math.random() * config.bonuses.length)]; + L.d(TAG, 'Spawn Bonus(${bonusConfig}'); + var bonus = new Bonus(bonusConfig.type); + bonus.rect.x = Math.random() * engine.map.width; + bonus.rect.y = Math.random() * engine.map.height; + engine.spawn(bonus); + } + + private function applyBonus(tank:Tank, bonus:Bonus):Void { + switch (bonus.bonusType) { + case 'life': + state.teams[tank.playerId.team].players[tank.playerId.index].life++; + case 'star': + if (tank.config.upgrade != null) { + tank.config = config.getTank(tank.config.upgrade); + } else { + tank.hits++; + } + case 'grenade': + for (entity in engine.entities.iterator()) { + switch (EntityTypeResolver.of(entity)) { + case EntityType.TANK(t): + if (t.playerId.team != tank.playerId.team) { + engine.destroy(t); + } + case x: + } + } + case 'helmet': + case 'clock': + case 'shovel': + case x: + engine.destroy(tank); // :-D + } + } } diff --git a/src/common/haxe/ru/m/tankz/map/LevelMap.hx b/src/common/haxe/ru/m/tankz/map/LevelMap.hx index 7a4c036..b6b321c 100755 --- a/src/common/haxe/ru/m/tankz/map/LevelMap.hx +++ b/src/common/haxe/ru/m/tankz/map/LevelMap.hx @@ -15,6 +15,9 @@ class LevelMap { public var gridWidth(default, null):Int; public var gridHeight(default, null):Int; + public var width(get, null):Float; + public var height(get, null):Float; + public var bricks(default, null):Array; public var grid(default, null):Grid; @@ -68,4 +71,12 @@ class LevelMap { var cellY:Int = Math.floor(point.y / config.cellHeight); return bricks[cellX + cellY * config.gridWidth]; } + + private inline function get_width():Float { + return config.cellWidth * config.gridWidth; + } + + private inline function get_height():Float { + return config.cellHeight * config.gridHeight; + } }