diff --git a/package.json b/package.json index 01f5cbc..88f8964 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tankz", - "version": "0.2.3", + "version": "0.3.0", "private": true, "devDependencies": { "ansi-colors": "^1.0.1", diff --git a/src/client/haxe/ru/m/animate/Animate.hx b/src/client/haxe/ru/m/animate/Animate.hx index 7dc5bf4..3db9430 100644 --- a/src/client/haxe/ru/m/animate/Animate.hx +++ b/src/client/haxe/ru/m/animate/Animate.hx @@ -26,17 +26,28 @@ class Animate extends Bitmap { } } + private static var a = new BitmapData(1, 1); + public var playing(default, set):Bool; - private var frames:Array; + public var frames(default, set):Array; private var index:Int; - public function new(frames:Array) { - super(frames[0], PixelSnapping.AUTO, true); - this.frames = frames; + public function new(?frames:Array) { + super(null, PixelSnapping.AUTO, true); + this.frames = frames == null ? [] : frames; init(); instances.push(this); } + public function set_frames(value:Array):Array { + if (value != null) { + frames = value; + bitmapData = frames[0]; + index = 0; + } + return frames; + } + public function set_playing(value:Bool):Bool { if (playing != value) { playing = value; diff --git a/src/client/haxe/ru/m/tankz/render/RenderItem.hx b/src/client/haxe/ru/m/tankz/render/RenderItem.hx index de4b3ca..b023598 100644 --- a/src/client/haxe/ru/m/tankz/render/RenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/RenderItem.hx @@ -117,25 +117,34 @@ class BrickItem extends RenderItem { class TankItem extends RenderItem { private var type:String; + private var hits:Int; public function new(value:Tank) { super(value); - this.view = new Animate(getFrames().map(function(s) return Assets.getBitmapData(s))); + view = new Animate(); + redraw(); + } + + override public function redraw():Void { + view.frames = getFrames().map(function(s) return Assets.getBitmapData(s)); } private function getFrames():Array { + var team = value.playerId.team; var group = value.config.group; var index = value.playerId.index; - if (group == 'human') group = 'player'; - if (group == 'radiant') { - group = 'player'; + if (team == 'radiant') { index = 0; } - if (group == 'dire') { - group = 'player'; + if (team == 'dire') { index = 1; } - if (group == 'bot') index = 0; + if (team == 'human' || team == 'radiant' || team == 'dire') { + group = 'player'; + } + if (team == 'bot') { + index = value.hits; + } return [ 'resources/images/tank/${group}/tank_${group.charAt(0)}${value.config.type}_${index}-0.png', 'resources/images/tank/${group}/tank_${group.charAt(0)}${value.config.type}_${index}-1.png', @@ -145,8 +154,10 @@ class TankItem extends RenderItem { override public function update():Void { super.update(); var t = value.config.type; - if (t != this.type) { + var h = value.hits; + if (t != this.type || h != this.hits) { this.type = t; + this.hits = h; redraw(); } view.playing = (value.mx !=0 || value.my != 0); diff --git a/src/client/haxe/ru/m/tankz/view/frames/LevelFrame.hx b/src/client/haxe/ru/m/tankz/view/frames/LevelFrame.hx index a379872..4e238f3 100644 --- a/src/client/haxe/ru/m/tankz/view/frames/LevelFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/LevelFrame.hx @@ -24,7 +24,7 @@ class LevelFrame extends VGroupView implements ViewBuilder implements LevelFrame public function onShow():Void { var state = Provider.get(GameState); - var c = ConfigBundle.get(state.type).levels; + var c = ConfigBundle.get(state.type).game.levels; levels.data = [for (i in 0...c) i]; } diff --git a/src/client/resources/classic/config.yaml b/src/client/resources/classic/config.yaml index 64254a8..5f69e96 100644 --- a/src/client/resources/classic/config.yaml +++ b/src/client/resources/classic/config.yaml @@ -1,4 +1,6 @@ -levels: 36 +game: + levels: 36 + friendlyFire: false map: cellWidth: 22 @@ -39,6 +41,10 @@ bricks: teams: - id: human spawnInterval: 0 + tanks: + - group: human + type: 0 + rate: 1 points: - type: eagle index: -1 @@ -57,6 +63,19 @@ teams: direction: top - id: bot spawnInterval: 3000 + tanks: + - group: bot + type: 0 + rate: 0.5 + - group: bot + type: 1 + rate: 0.5 + - group: bot + type: 2 + rate: 0.5 + - group: bot + type: 3 + rate: 0.5 points: - type: tank index: -1 @@ -107,7 +126,7 @@ tanks: bullet: <<: *bullet speed: 9.0 - bullets: 3 + bullets: 2 - type: 3 width: 42 @@ -159,4 +178,4 @@ tanks: speed: 8.0 bullets: 1 score: 400 - hits: 4 + hits: 3 diff --git a/src/client/resources/dota/config.yaml b/src/client/resources/dota/config.yaml index 5d8c19a..85fba11 100644 --- a/src/client/resources/dota/config.yaml +++ b/src/client/resources/dota/config.yaml @@ -1,4 +1,6 @@ -levels: 36 +game: + levels: 2 + friendlyFire: true map: cellWidth: 22 @@ -36,8 +38,24 @@ bricks: layer: 2 armor: 1 +team_tanks: &team_tanks + tanks: + - group: any + type: 0 + rate: 0.25 + - group: any + type: 1 + rate: 0.25 + - group: any + type: 2 + rate: 0.25 + # - group: any + # type: 3 + # rate: 0.25 + teams: - - id: radiant + - <<: *team_tanks + id: radiant spawnInterval: 0 points: - type: eagle @@ -49,28 +67,29 @@ teams: index: 0 x: 0 y: 0 - direction: top + direction: right - type: tank index: 1 x: 6 y: 10 - direction: top + direction: right - type: tank index: 2 x: 6 y: 16 - direction: top + direction: right - type: tank index: 3 x: 6 y: 22 - direction: top + direction: right - type: tank index: 4 x: 10 y: 28 - direction: top - - id: dire + direction: right + - <<: *team_tanks + id: dire spawnInterval: 0 points: - type: eagle @@ -82,27 +101,27 @@ teams: index: 0 x: 38 y: 28 - direction: bottom + direction: left - type: tank index: 1 x: 32 y: 18 - direction: bottom + direction: left - type: tank index: 2 x: 32 y: 12 - direction: bottom + direction: left - type: tank index: 3 x: 32 y: 6 - direction: bottom + direction: left - type: tank index: 4 x: 28 y: 0 - direction: bottom + direction: left bullet: &bullet @@ -112,7 +131,7 @@ bullet: &bullet piercing: 1 tanks: - radiant: &tanks + any: - type: 0 width: 36 height: 36 @@ -130,5 +149,22 @@ tanks: <<: *bullet speed: 8.5 bullets: 1 - dire: - - <<: *tanks + + - type: 2 + width: 40 + height: 36 + speed: 3.0 + bullet: + <<: *bullet + speed: 9.0 + bullets: 2 + + - type: 3 + width: 42 + height: 38 + speed: 2.9 + bullet: + <<: *bullet + speed: 9.0 + piercing: 3 + bullets: 2 \ No newline at end of file diff --git a/src/client/resources/dota/levels/level001.txt b/src/client/resources/dota/levels/level001.txt new file mode 100644 index 0000000..4335f93 --- /dev/null +++ b/src/client/resources/dota/levels/level001.txt @@ -0,0 +1,30 @@ +0000000000000000000000000000000000004400 +0000000000000000000000000000000000004400 +0000000000000000000000000000000000004444 +0000000000000000000000000000000000004444 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +0000000000000000000000000000000000000000 +4444000000000000000000000000000000000000 +4444000000000000000000000000000000000000 +0044000000000000000000000000000000000000 +0044000000000000000000000000000000000000 diff --git a/src/common/haxe/ru/m/tankz/bot/BotControl.hx b/src/common/haxe/ru/m/tankz/bot/BotControl.hx index 1ad360a..1f592ab 100644 --- a/src/common/haxe/ru/m/tankz/bot/BotControl.hx +++ b/src/common/haxe/ru/m/tankz/bot/BotControl.hx @@ -11,6 +11,7 @@ class BotControl extends Control { private var shotTimer:Timer; private var turnTimer:Timer; + private var turnDelayTimer:Timer; public function new(index:Int) { super({type:TYPE, index:index}); @@ -18,22 +19,22 @@ class BotControl extends Control { override public function onCollision(with:EntityType):Void { switch (with) { - case EntityType.TANK(_): turn(); - case EntityType.CELL(_): turn(); + case EntityType.TANK(_): turnAfter(300); + case EntityType.CELL(_): turnAfter(300); case _: } } override public function start():Void { - //var tank = handler.entities.get(tankId); - //action(TankAction.MOVE(tank.rect.direction)); - action(TankAction.MOVE(Direction.BOTTOM)); // ToDo: hardcode bot start direction + if (handler == null) return; + var tank = handler.entities.get(tankId); + action(TankAction.MOVE(tank.rect.direction)); if (shotTimer == null) { shotTimer = new Timer(1000); shotTimer.run = shot; } if (turnTimer == null) { - turnTimer = new Timer(3000); + turnTimer = new Timer(2000); turnTimer.run = turn; } } @@ -53,6 +54,17 @@ class BotControl extends Control { action(TankAction.SHOT); } + public function turnAfter(delay:Int):Void { + if (turnDelayTimer == null) { + turnDelayTimer = new Timer(delay); + turnDelayTimer.run = function() { + turnDelayTimer.stop(); + turnDelayTimer = null; + turn(); + } + } + } + public function turn():Void { action(TankAction.MOVE(randomDirection())); } diff --git a/src/common/haxe/ru/m/tankz/config/Config.hx b/src/common/haxe/ru/m/tankz/config/Config.hx index 0d5536b..d7e965d 100644 --- a/src/common/haxe/ru/m/tankz/config/Config.hx +++ b/src/common/haxe/ru/m/tankz/config/Config.hx @@ -1,6 +1,11 @@ package ru.m.tankz.config; +typedef GameConfig = { + var levels: Int; + var friendlyFire:Bool; +} + typedef SpawnPoint = { var type:String; var index:Int; @@ -41,6 +46,11 @@ typedef TankConfig = { > TankType, var speed:Float; var bullet:BulletConfig; var bullets:Int; + var hits:Int; +} + +typedef TankSpawn = { > TankType, + var rate: Float; } @@ -48,13 +58,14 @@ typedef TeamConfig = { var id:String; var size:Int; var spawnInterval:Int; + var tanks:Array; var points:Array; } class Config { public var type(default, null):String; - public var levels(default, null):Int; + public var game(default, null):GameConfig; public var map(default, null):MapConfig; public var bricks(default, null):Array; public var tanks(default, null):Array; @@ -64,9 +75,9 @@ class Config { private var tankMap:Map>; private var teamMap:Map; - public function new(type:String, levels:Int, map:MapConfig, bricks:Array, teams:Array, tanks:Array) { + public function new(type:String, game:GameConfig, map:MapConfig, bricks:Array, teams:Array, tanks:Array) { this.type = type; - this.levels = levels; + this.game = game; 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 e37fba7..fd8911d 100644 --- a/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx +++ b/src/common/haxe/ru/m/tankz/config/ConfigBundle.hx @@ -1,6 +1,5 @@ package ru.m.tankz.config; -import ru.m.tankz.game.ClassicGame; import yaml.Parser; import openfl.Assets; import yaml.Yaml; @@ -8,7 +7,7 @@ import ru.m.tankz.config.Config; typedef ConfigSource = { - var levels:Int; + var game:GameConfig; var map: MapConfig; var bricks: Array; var teams: Array; @@ -31,6 +30,6 @@ class ConfigBundle { tanks.push(item); } } - return new Config(type, source.levels, source.map, source.bricks, source.teams, tanks); + return new Config(type, source.game, source.map, source.bricks, source.teams, tanks); } } diff --git a/src/common/haxe/ru/m/tankz/core/Tank.hx b/src/common/haxe/ru/m/tankz/core/Tank.hx index 8e9bc16..5e4740b 100755 --- a/src/common/haxe/ru/m/tankz/core/Tank.hx +++ b/src/common/haxe/ru/m/tankz/core/Tank.hx @@ -11,6 +11,7 @@ import ru.m.geom.Direction; class Tank extends MobileEntity { public var playerId(default, null):PlayerId; public var config(default, set):TankConfig; + public var hits(default, default):Int; private var bulletsCounter:Int = 0; @@ -18,6 +19,7 @@ class Tank extends MobileEntity { super(new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT); this.playerId = playerId; this.config = config; + this.hits = config.hits; 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 84d9f4a..a87c245 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -31,7 +31,16 @@ class CollisionProcessor implements EngineListener { public function onSpawn(entity:EntityType):Void {} private function checkTankBullet(tank:Tank, bullet:Bullet):Bool { - return tank.playerId.team != bullet.playerId.team; + if (bullet.tankId == tank.id) return false; + return engine.config.game.friendlyFire || tank.playerId.team != bullet.playerId.team; + } + + private function hitTank(tank:Tank):Void { + if (tank.hits > 0) { + tank.hits--; + } else { + engine.destroy(tank); + } } public function onCollision(entity:EntityType, with:EntityType):Void { @@ -42,7 +51,7 @@ class CollisionProcessor implements EngineListener { tank1.rect.lean(tank2.rect); case EntityType.BULLET(bullet2): if (checkTankBullet(tank1, bullet2)) { - engine.destroy(tank1); + hitTank(tank1); engine.destroy(bullet2); } case EntityType.EAGLE(eagle): @@ -55,7 +64,7 @@ class CollisionProcessor implements EngineListener { case EntityType.TANK(tank2): if (checkTankBullet(tank2, bullet1)) { engine.destroy(bullet1); - engine.destroy(tank2); + hitTank(tank2); } case EntityType.BULLET(bullet2): engine.destroy(bullet1); diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index 976df36..29ba2ea 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -59,7 +59,7 @@ class ClassicGame extends Game { override public function next():Option { if (!state.teams[HUMAN].lose) { state.level++; - if (state.level >= config.levels) state.level = 0; + if (state.level >= config.game.levels) state.level = 0; state.teams[BOT].lose = false; state.teams[BOT].life = BOT_LIFE; for (ps in state.teams[HUMAN].players) { diff --git a/src/common/haxe/ru/m/tankz/game/DotaGame.hx b/src/common/haxe/ru/m/tankz/game/DotaGame.hx index 723163b..3f8071c 100644 --- a/src/common/haxe/ru/m/tankz/game/DotaGame.hx +++ b/src/common/haxe/ru/m/tankz/game/DotaGame.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import haxe.ds.Option; import ru.m.tankz.game.Game; import ru.m.tankz.game.GameState; @@ -53,4 +54,10 @@ class DotaGame extends Game { } return state; } + + override public function next():Option { + state.level++; + if (state.level >= config.game.levels) state.level = 0; + return Option.Some(buildState(state.level, 0)); + } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 07c0684..bbe7229 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -54,8 +54,11 @@ class Game implements EngineListener { return teams.get(playerId.team).players[playerId.index]; } - private function buildTank(playerId:PlayerId, config:TankConfig, point:SpawnPoint):Tank { - var tank = new Tank(playerId, config); + private function buildTank(playerId:PlayerId, point:SpawnPoint):Tank { + var types:Array = teams[playerId.team].config.tanks; + var type:TankSpawn = types[Math.floor(Math.random() * types.length)]; + var tankConfig:TankConfig = config.getTank(type.group, type.type); + var tank = new Tank(playerId, tankConfig); applyPoint(tank, point); return tank; } @@ -114,7 +117,7 @@ class Game implements EngineListener { private function spawn(task:SpawnTask):Void { getPlayer(task.playerId).tankId = 0; if (trySpawn(task.playerId, true)) { - var tank = buildTank(task.playerId, config.getTank(task.playerId.team, '0'), task.point); + var tank = buildTank(task.playerId, task.point); var player:Player = getPlayer(task.playerId); engine.spawn(tank); player.tankId = tank.id;