From 48f9c433e28acb41f0d7c6c836d1f8b3e9672805 Mon Sep 17 00:00:00 2001 From: shmyga Date: Tue, 13 Aug 2019 16:41:57 +0300 Subject: [PATCH] [common] multiple weapon support --- CHANGELOG.md | 1 + WORK.md | 1 + src/client/haxe/ru/m/tankz/AppTheme.hx | 3 +- .../haxe/ru/m/tankz/control/HumanControl.hx | 32 +++--- .../haxe/ru/m/tankz/render/RenderUtil.hx | 2 +- .../m/tankz/render/item/BitmapRenderItem.hx | 2 + .../ru/m/tankz/storage/SettingsStorage.hx | 14 ++- .../haxe/ru/m/tankz/view/MenuFrame.yaml | 100 ++++++++++-------- src/client/haxe/ru/m/tankz/view/ViewUtil.hx | 1 + .../view/gamepad/SmartActionAreaBuilder.hx | 8 +- src/common/haxe/ru/m/geom/Point.hx | 4 + src/common/haxe/ru/m/tankz/bot/BotControl.hx | 2 +- src/common/haxe/ru/m/tankz/control/Control.hx | 2 +- src/common/haxe/ru/m/tankz/core/Bullet.hx | 1 + src/common/haxe/ru/m/tankz/core/Weapon.hx | 2 + .../haxe/ru/m/tankz/game/EntityBuilder.hx | 4 +- src/common/haxe/ru/m/tankz/game/GameRunner.hx | 23 ++-- src/common/haxe/ru/m/tankz/game/Player.hx | 2 - src/common/resources/config/death.yaml | 2 + 19 files changed, 120 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6c5e06..6f382f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ------ * Improved `ResultFrame` * Improved bonuses +* Set `DeviceType.SCREEN` as default on mobile devices 0.16.0 ------ diff --git a/WORK.md b/WORK.md index a1a7049..8c7e999 100644 --- a/WORK.md +++ b/WORK.md @@ -5,3 +5,4 @@ * improve bots * save human state in classic game * game config macro +* additional weapon (rockets) diff --git a/src/client/haxe/ru/m/tankz/AppTheme.hx b/src/client/haxe/ru/m/tankz/AppTheme.hx index 7254c27..95d37b5 100644 --- a/src/client/haxe/ru/m/tankz/AppTheme.hx +++ b/src/client/haxe/ru/m/tankz/AppTheme.hx @@ -1,7 +1,5 @@ package ru.m.tankz; -import haxework.color.Color; -import haxework.view.utils.DrawUtil.FillType; import flash.text.TextFormatAlign; import haxework.color.Color; import haxework.view.geometry.Box; @@ -10,6 +8,7 @@ import haxework.view.geometry.SizeValue; import haxework.view.geometry.VAlign; import haxework.view.theme.ITheme; import haxework.view.theme.Theme; +import haxework.view.utils.DrawUtil; import openfl.Assets; import ru.m.skin.ButtonSVGSkin; diff --git a/src/client/haxe/ru/m/tankz/control/HumanControl.hx b/src/client/haxe/ru/m/tankz/control/HumanControl.hx index 617eb64..ca99dbd 100644 --- a/src/client/haxe/ru/m/tankz/control/HumanControl.hx +++ b/src/client/haxe/ru/m/tankz/control/HumanControl.hx @@ -20,7 +20,7 @@ class HumanControl extends Control { private var binding:Map>; private var moveQueue:Array; - private var shotTimer:Timer; + private var shotTimers:Map; public function new(playerId:PlayerId, controlIndex:Int) { super(playerId); @@ -34,6 +34,7 @@ class HumanControl extends Control { binding.get(bind.device).set(bind.action, action); } moveQueue = []; + shotTimers = new Map(); } public function hasDevice(device:DeviceType):Bool { @@ -60,10 +61,10 @@ class HumanControl extends Control { super.stop(); bus.signal.disconnect(onDeviceAction); moveQueue = []; - if (shotTimer != null) { - shotTimer.stop(); - shotTimer = null; + for (timer in shotTimers) { + timer.stop(); } + shotTimers = new Map(); } public function toggleAction(action:TankAction, on:Bool):Void { @@ -77,17 +78,18 @@ class HumanControl extends Control { moveQueue.remove(direction); } updateMove(); - case TankAction.SHOT: + case TankAction.SHOT(weapon): if (on) { - if (shotTimer == null) { - shotTimer = new Timer(300); - shotTimer.run = shot; - shot(); + if (!shotTimers.exists(weapon)) { + var timer = new Timer(300); + timer.run = shooter(weapon); + timer.run(); + shotTimers.set(weapon, timer); } } else { - if (shotTimer != null) { - shotTimer.stop(); - shotTimer = null; + if (shotTimers.exists(weapon)) { + shotTimers.get(weapon).stop(); + shotTimers.remove(weapon); } } case TankAction.STOP: @@ -107,7 +109,9 @@ class HumanControl extends Control { } } - private function shot():Void { - action(SHOT); + private function shooter(weapon:Int):Void -> Void { + return function():Void { + action(SHOT(weapon)); + } } } diff --git a/src/client/haxe/ru/m/tankz/render/RenderUtil.hx b/src/client/haxe/ru/m/tankz/render/RenderUtil.hx index 8966fbb..818a918 100644 --- a/src/client/haxe/ru/m/tankz/render/RenderUtil.hx +++ b/src/client/haxe/ru/m/tankz/render/RenderUtil.hx @@ -20,7 +20,7 @@ class RenderUtil { } public static function bulletImage(piercing:Int = 0):BitmapData { - var type = piercing > 0 ? 'piercing' : 'normal'; + var type = piercing > 1 ? 'piercing' : 'normal'; return Assets.getBitmapData('resources/image/bullet/${type}.png'); } } 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 fc69e40..af8d72d 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx @@ -24,6 +24,8 @@ class BitmapRenderItem extends RenderItem { if (image != value) { image = value; bitmap.bitmapData = image; + bitmap.width = rect.width; + bitmap.height = rect.height; } return image; } diff --git a/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx index 3a6eba4..8130b49 100644 --- a/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx +++ b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx @@ -11,7 +11,7 @@ import ru.m.tankz.control.Control; class SettingsStorage extends SharedObjectStorage { - private static inline var VERSION = 3; + private static inline var VERSION = 4; public function new() { super('settings_${VERSION}'); @@ -36,7 +36,8 @@ class SettingsStorage extends SharedObjectStorage { MOVE(Direction.LEFT) => {device: device, action: DIRECTION(Direction.LEFT)}, MOVE(Direction.BOTTOM) => {device: device, action: DIRECTION(Direction.BOTTOM)}, MOVE(Direction.RIGHT) => {device: device, action: DIRECTION(Direction.RIGHT)}, - SHOT => {device: device, action: KEY(0)}, + SHOT(0) => {device: device, action: KEY(0)}, + SHOT(1) => {device: device, action: KEY(1)}, ]; } @@ -46,7 +47,8 @@ class SettingsStorage extends SharedObjectStorage { MOVE(Direction.LEFT) => null, MOVE(Direction.BOTTOM) => null, MOVE(Direction.RIGHT) => null, - SHOT => null, + SHOT(0) => null, + SHOT(1) => null, ]; } @@ -60,14 +62,16 @@ class SettingsStorage extends SharedObjectStorage { MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.A)}, MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.S)}, MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.D)}, - SHOT => {device: KEYBOARD, action: KEY(Keyboard.SPACE)}, + SHOT(0) => {device: KEYBOARD, action: KEY(Keyboard.SPACE)}, + SHOT(1) => {device: KEYBOARD, action: KEY(Keyboard.Q)}, ], 1 => [ MOVE(Direction.TOP) => {device: KEYBOARD, action: KEY(Keyboard.UP)}, MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.LEFT)}, MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.DOWN)}, MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.RIGHT)}, - SHOT => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_0)}, + SHOT(0) => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_0)}, + SHOT(1) => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_DECIMAL)}, ], ]; } diff --git a/src/client/haxe/ru/m/tankz/view/MenuFrame.yaml b/src/client/haxe/ru/m/tankz/view/MenuFrame.yaml index 12d7870..04ac771 100644 --- a/src/client/haxe/ru/m/tankz/view/MenuFrame.yaml +++ b/src/client/haxe/ru/m/tankz/view/MenuFrame.yaml @@ -2,35 +2,41 @@ views: - $type: haxework.view.group.VGroupView style: container - layout.margin: 10 overflow.y: scroll views: - - $type: haxework.view.form.LabelView - text: Tank'z - style: font - font.size: 100 - geometry.margin.bottom: 30 - - $type: haxework.view.form.ButtonView - style: button.menu - +onPress: ~startGame('classic') - text: Classic - - $type: haxework.view.form.ButtonView - style: button.menu - +onPress: ~startGame('dota') - text: DotA - - $type: haxework.view.form.ButtonView - style: button.menu - +onPress: ~startGame('death') - text: DeathMatch - - $type: haxework.view.form.ButtonView - style: button.menu - +onPress: ~switcher.change('record') - text: Records - - id: network - $type: haxework.view.form.ButtonView - style: button.menu - +onPress: ~startNetwork() - text: Network + - $type: haxework.view.group.VGroupView + layout.margin: 10 + layout.hAlign: center + views: + - $type: haxework.view.form.LabelView + text: Tank'z + style: font + font.size: 100 + geometry.margin.bottom: 30 + - $type: haxework.view.form.ButtonView + style: button.menu + +onPress: ~startGame('classic') + text: Classic + - $type: haxework.view.form.ButtonView + style: button.menu + +onPress: ~startGame('dota') + text: DotA + - $type: haxework.view.form.ButtonView + style: button.menu + +onPress: ~startGame('death') + text: DeathMatch + - $type: haxework.view.SpriteView + style: line + - $type: haxework.view.form.ButtonView + style: button.menu + +onPress: ~switcher.change('record') + text: Records + visible: false + - id: network + $type: haxework.view.form.ButtonView + style: button.menu + +onPress: ~startNetwork() + text: Network - $type: haxework.view.form.LabelView geometry.hAlign: right geometry.vAlign: top @@ -42,23 +48,23 @@ views: style: panel layout.margin: 10 views: - - id: settings - $type: haxework.view.form.ButtonView - style: button.settings - +onPress: ~switcher.change('settings') - - $type: haxework.view.SpriteView - geometry.width: 50% - - id: username - $type: haxework.view.form.LabelView - style: text - - id: login - $type: haxework.view.form.ButtonView - style: button.login - +onPress: ~login() - - id: logout - $type: haxework.view.form.ButtonView - style: button.logout - +onPress: ~logout() - visible: false - - $type: haxework.view.SpriteView - geometry.width: 50% + - id: settings + $type: haxework.view.form.ButtonView + style: button.settings + +onPress: ~switcher.change('settings') + - $type: haxework.view.SpriteView + geometry.width: 50% + - id: username + $type: haxework.view.form.LabelView + style: text + - id: login + $type: haxework.view.form.ButtonView + style: button.login + +onPress: ~login() + - id: logout + $type: haxework.view.form.ButtonView + style: button.logout + +onPress: ~logout() + visible: false + - $type: haxework.view.SpriteView + geometry.width: 50% diff --git a/src/client/haxe/ru/m/tankz/view/ViewUtil.hx b/src/client/haxe/ru/m/tankz/view/ViewUtil.hx index a52ac32..ba61851 100644 --- a/src/client/haxe/ru/m/tankz/view/ViewUtil.hx +++ b/src/client/haxe/ru/m/tankz/view/ViewUtil.hx @@ -43,6 +43,7 @@ class ViewUtil { public static function toActionLabel(action:TankAction):String { return switch (action) { case MOVE(d): 'MOVE_$d'; + case SHOT(w): 'SHOT_$w'; case x: '$x'; } } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/SmartActionAreaBuilder.hx b/src/client/haxe/ru/m/tankz/view/gamepad/SmartActionAreaBuilder.hx index 2c2f7f1..02574d9 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/SmartActionAreaBuilder.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/SmartActionAreaBuilder.hx @@ -33,9 +33,15 @@ class SmartActionAreaBuilder implements IActionAreaBuilder { DIRECTION(Direction.RIGHT), new Rectangle(padding + size, height - size * 1.5 - padding, size, size) )); + // key 0 areas.push(new CircleActionArea( KEY(0), - new Circle(width - size * 1 - padding, height - size * 1 - padding, size / 2) + new Circle(width - size * 1 - padding, height - size * 0.5 - padding, size / 2) + )); + // key 1 + areas.push(new CircleActionArea( + KEY(1), + new Circle(width - size * 1 - padding, height - size * 1.5 - padding, size / 2) )); return areas; } diff --git a/src/common/haxe/ru/m/geom/Point.hx b/src/common/haxe/ru/m/geom/Point.hx index 289e5ee..20de2fc 100644 --- a/src/common/haxe/ru/m/geom/Point.hx +++ b/src/common/haxe/ru/m/geom/Point.hx @@ -13,6 +13,10 @@ class Point { return new Point(x + point.x, y + point.y); } + public function clone():Point { + return new Point(x, y); + } + public function hashCode():Int { return Std.int(x + 1000 * y); } diff --git a/src/common/haxe/ru/m/tankz/bot/BotControl.hx b/src/common/haxe/ru/m/tankz/bot/BotControl.hx index 6e4ac40..41837f7 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(0)); } public function shot(delay:Int = 100):Void { diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx index 78e0a17..60cc5e3 100644 --- a/src/common/haxe/ru/m/tankz/control/Control.hx +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -10,7 +10,7 @@ import ru.m.tankz.Type; enum TankAction { MOVE(direction:Direction); STOP; - SHOT; + SHOT(weapon:Int); } class Control { diff --git a/src/common/haxe/ru/m/tankz/core/Bullet.hx b/src/common/haxe/ru/m/tankz/core/Bullet.hx index 0c328dc..cdb9d23 100644 --- a/src/common/haxe/ru/m/tankz/core/Bullet.hx +++ b/src/common/haxe/ru/m/tankz/core/Bullet.hx @@ -9,6 +9,7 @@ class Bullet extends MobileEntity { public var playerId(default, null):PlayerId; public var tankId(get, null):Int; public var tank(default, default):Tank; + public var weapon(default, default):Weapon; public var config(default, null):BulletConfig; public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:BulletConfig) { diff --git a/src/common/haxe/ru/m/tankz/core/Weapon.hx b/src/common/haxe/ru/m/tankz/core/Weapon.hx index 59b7dee..54ee78d 100644 --- a/src/common/haxe/ru/m/tankz/core/Weapon.hx +++ b/src/common/haxe/ru/m/tankz/core/Weapon.hx @@ -5,8 +5,10 @@ import ru.m.tankz.config.Config; class Weapon { public var config(default, null):WeaponConfig; + public var count(default, default):Int; public function new(config:WeaponConfig) { this.config = config; + this.count = 0; } } diff --git a/src/common/haxe/ru/m/tankz/game/EntityBuilder.hx b/src/common/haxe/ru/m/tankz/game/EntityBuilder.hx index 973b18f..f9f6795 100644 --- a/src/common/haxe/ru/m/tankz/game/EntityBuilder.hx +++ b/src/common/haxe/ru/m/tankz/game/EntityBuilder.hx @@ -56,9 +56,7 @@ class EntityBuilder { return tank; } - public function buildBullet(point:Point, direction:Direction, playerId:PlayerId, type:TankType):Bullet { - var tankConfig = config.getTank(type); - var bulletConfig = tankConfig.weapons[0].bullet; + public function buildBullet(point:Point, direction:Direction, playerId:PlayerId, bulletConfig:BulletConfig):Bullet { var bullet = new Bullet(++entityId, new Rectangle(point.x - bulletConfig.width / 2, point.y - bulletConfig.height / 2, bulletConfig.width, bulletConfig.height, direction), playerId, bulletConfig); return bullet; } diff --git a/src/common/haxe/ru/m/tankz/game/GameRunner.hx b/src/common/haxe/ru/m/tankz/game/GameRunner.hx index e819d94..61dc2f4 100644 --- a/src/common/haxe/ru/m/tankz/game/GameRunner.hx +++ b/src/common/haxe/ru/m/tankz/game/GameRunner.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import ru.m.tankz.core.Weapon; import ru.m.geom.Line; import ru.m.geom.Point; import ru.m.tankz.bonus.BonusFactory; @@ -155,8 +156,10 @@ class GameRunner extends Game implements EngineListener { tank.rect.lean(cell.rect); emitTankMove(tank); case [BULLET(bullet), BULLET(other_bullet)]: - gameEventSignal.emit(DESTROY(BULLET(bullet.id))); - gameEventSignal.emit(DESTROY(BULLET(other_bullet.id))); + if (bullet.playerId != other_bullet.playerId) { + gameEventSignal.emit(DESTROY(BULLET(bullet.id))); + gameEventSignal.emit(DESTROY(BULLET(other_bullet.id))); + } case [BULLET(bullet), CELL(cell)]: bullet.rect.lean(cell.rect); gameEventSignal.emit(HIT(CELL(cell.cellX, cell.cellY, buildShot(bullet)))); @@ -256,14 +259,16 @@ class GameRunner extends Game implements EngineListener { timer.stop(); timer = null; } - case ACTION(tankId, SHOT): + case ACTION(tankId, SHOT(index)): var tank:Tank = cast engine.entities.get(tankId); var player = getPlayer(tank.playerId); - if (!tank.freezing && player.bullets < tank.weapon.config.count) { + var weapon:Weapon = tank.weapons.length > index - 1 ? tank.weapons[index] : null; + if (weapon != null && !tank.freezing && weapon.count < weapon.config.count) { var rect = tank.rect; var point = rect.center.add(new Point(rect.width / 4 * rect.direction.x, rect.height / 4 * rect.direction.y)); - var bullet = builder.buildBullet(point, rect.direction, player.id, tank.config.type); + var bullet = builder.buildBullet(point, rect.direction, player.id, weapon.config.bullet); bullet.tank = tank; + bullet.weapon = weapon; bullet.move(bullet.rect.direction); engine.spawn(bullet); gameEventSignal.emit(EventUtil.buildBulletSpawn(bullet)); @@ -279,8 +284,9 @@ class GameRunner extends Game implements EngineListener { var player = getPlayer(playerId); player.tankId = id; player.state.tank = info; - case SPAWN(BULLET(_, _, playerId, _)): - getPlayer(playerId).bullets++; + case SPAWN(BULLET(id, _, _, _)): + var bullet:Bullet = engine.getEntity(id); + bullet.weapon.count++; case CHANGE(BRICK(id, type)): engine.map.bricksById[id].config = config.getBrick(type); case DESTROY(EAGLE(id, shot)): @@ -344,8 +350,7 @@ class GameRunner extends Game implements EngineListener { engine.destroy(id); case DESTROY(BULLET(id)): var bullet:Bullet = engine.getEntity(id); - var player = getPlayer(bullet.playerId); - player.bullets--; + bullet.weapon.count--; var side:Line = bullet.rect.getSide(bullet.rect.direction.reverse()).move( // ToDo: move new Point(bullet.rect.direction.x * 5, bullet.rect.direction.y * 5) diff --git a/src/common/haxe/ru/m/tankz/game/Player.hx b/src/common/haxe/ru/m/tankz/game/Player.hx index 7ba8616..8b7e4ef 100644 --- a/src/common/haxe/ru/m/tankz/game/Player.hx +++ b/src/common/haxe/ru/m/tankz/game/Player.hx @@ -10,7 +10,6 @@ class Player { public var tankId(default, set):Int; public var isAlive(get, null):Bool; public var state(default, default):PlayerState; - public var bullets(default, default):Int; public function new(teamId:TeamId, config:PlayerConfig, state:PlayerState = null) { this.config = config; @@ -18,7 +17,6 @@ class Player { this.state = state == null ? new PlayerState(id) : state; this.state.reset(); this.state.life = Math.isNaN(config.life) ? 0 : config.life; - this.bullets = 0; this.tankId = -1; } diff --git a/src/common/resources/config/death.yaml b/src/common/resources/config/death.yaml index c83c45d..487792a 100644 --- a/src/common/resources/config/death.yaml +++ b/src/common/resources/config/death.yaml @@ -86,5 +86,7 @@ tanks: weapons: - bullet: {<<: *bullet, speed: 12.0} count: 2 + - bullet: {<<: *bullet, speed: 4.0, width: 16, height: 16, piercing: 4} + count: 1 bonuses: []