[common] multiple weapon support

This commit is contained in:
2019-08-13 16:41:57 +03:00
parent 314f5a480c
commit 48f9c433e2
19 changed files with 120 additions and 86 deletions

View File

@@ -2,6 +2,7 @@
------ ------
* Improved `ResultFrame` * Improved `ResultFrame`
* Improved bonuses * Improved bonuses
* Set `DeviceType.SCREEN` as default on mobile devices
0.16.0 0.16.0
------ ------

View File

@@ -5,3 +5,4 @@
* improve bots * improve bots
* save human state in classic game * save human state in classic game
* game config macro * game config macro
* additional weapon (rockets)

View File

@@ -1,7 +1,5 @@
package ru.m.tankz; package ru.m.tankz;
import haxework.color.Color;
import haxework.view.utils.DrawUtil.FillType;
import flash.text.TextFormatAlign; import flash.text.TextFormatAlign;
import haxework.color.Color; import haxework.color.Color;
import haxework.view.geometry.Box; import haxework.view.geometry.Box;
@@ -10,6 +8,7 @@ import haxework.view.geometry.SizeValue;
import haxework.view.geometry.VAlign; import haxework.view.geometry.VAlign;
import haxework.view.theme.ITheme; import haxework.view.theme.ITheme;
import haxework.view.theme.Theme; import haxework.view.theme.Theme;
import haxework.view.utils.DrawUtil;
import openfl.Assets; import openfl.Assets;
import ru.m.skin.ButtonSVGSkin; import ru.m.skin.ButtonSVGSkin;

View File

@@ -20,7 +20,7 @@ class HumanControl extends Control {
private var binding:Map<DeviceType, Map<DeviceAction, TankAction>>; private var binding:Map<DeviceType, Map<DeviceAction, TankAction>>;
private var moveQueue:Array<Direction>; private var moveQueue:Array<Direction>;
private var shotTimer:Timer; private var shotTimers:Map<Int, Timer>;
public function new(playerId:PlayerId, controlIndex:Int) { public function new(playerId:PlayerId, controlIndex:Int) {
super(playerId); super(playerId);
@@ -34,6 +34,7 @@ class HumanControl extends Control {
binding.get(bind.device).set(bind.action, action); binding.get(bind.device).set(bind.action, action);
} }
moveQueue = []; moveQueue = [];
shotTimers = new Map();
} }
public function hasDevice(device:DeviceType):Bool { public function hasDevice(device:DeviceType):Bool {
@@ -60,10 +61,10 @@ class HumanControl extends Control {
super.stop(); super.stop();
bus.signal.disconnect(onDeviceAction); bus.signal.disconnect(onDeviceAction);
moveQueue = []; moveQueue = [];
if (shotTimer != null) { for (timer in shotTimers) {
shotTimer.stop(); timer.stop();
shotTimer = null;
} }
shotTimers = new Map();
} }
public function toggleAction(action:TankAction, on:Bool):Void { public function toggleAction(action:TankAction, on:Bool):Void {
@@ -77,17 +78,18 @@ class HumanControl extends Control {
moveQueue.remove(direction); moveQueue.remove(direction);
} }
updateMove(); updateMove();
case TankAction.SHOT: case TankAction.SHOT(weapon):
if (on) { if (on) {
if (shotTimer == null) { if (!shotTimers.exists(weapon)) {
shotTimer = new Timer(300); var timer = new Timer(300);
shotTimer.run = shot; timer.run = shooter(weapon);
shot(); timer.run();
shotTimers.set(weapon, timer);
} }
} else { } else {
if (shotTimer != null) { if (shotTimers.exists(weapon)) {
shotTimer.stop(); shotTimers.get(weapon).stop();
shotTimer = null; shotTimers.remove(weapon);
} }
} }
case TankAction.STOP: case TankAction.STOP:
@@ -107,7 +109,9 @@ class HumanControl extends Control {
} }
} }
private function shot():Void { private function shooter(weapon:Int):Void -> Void {
action(SHOT); return function():Void {
action(SHOT(weapon));
}
} }
} }

View File

@@ -20,7 +20,7 @@ class RenderUtil {
} }
public static function bulletImage(piercing:Int = 0):BitmapData { 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'); return Assets.getBitmapData('resources/image/bullet/${type}.png');
} }
} }

View File

@@ -24,6 +24,8 @@ class BitmapRenderItem extends RenderItem {
if (image != value) { if (image != value) {
image = value; image = value;
bitmap.bitmapData = image; bitmap.bitmapData = image;
bitmap.width = rect.width;
bitmap.height = rect.height;
} }
return image; return image;
} }

View File

@@ -11,7 +11,7 @@ import ru.m.tankz.control.Control;
class SettingsStorage extends SharedObjectStorage { class SettingsStorage extends SharedObjectStorage {
private static inline var VERSION = 3; private static inline var VERSION = 4;
public function new() { public function new() {
super('settings_${VERSION}'); super('settings_${VERSION}');
@@ -36,7 +36,8 @@ class SettingsStorage extends SharedObjectStorage {
MOVE(Direction.LEFT) => {device: device, action: DIRECTION(Direction.LEFT)}, MOVE(Direction.LEFT) => {device: device, action: DIRECTION(Direction.LEFT)},
MOVE(Direction.BOTTOM) => {device: device, action: DIRECTION(Direction.BOTTOM)}, MOVE(Direction.BOTTOM) => {device: device, action: DIRECTION(Direction.BOTTOM)},
MOVE(Direction.RIGHT) => {device: device, action: DIRECTION(Direction.RIGHT)}, 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.LEFT) => null,
MOVE(Direction.BOTTOM) => null, MOVE(Direction.BOTTOM) => null,
MOVE(Direction.RIGHT) => 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.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.A)},
MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.S)}, MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.S)},
MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.D)}, 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 => [ 1 => [
MOVE(Direction.TOP) => {device: KEYBOARD, action: KEY(Keyboard.UP)}, MOVE(Direction.TOP) => {device: KEYBOARD, action: KEY(Keyboard.UP)},
MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.LEFT)}, MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.LEFT)},
MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.DOWN)}, MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.DOWN)},
MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.RIGHT)}, 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)},
], ],
]; ];
} }

View File

@@ -2,8 +2,11 @@
views: views:
- $type: haxework.view.group.VGroupView - $type: haxework.view.group.VGroupView
style: container style: container
layout.margin: 10
overflow.y: scroll overflow.y: scroll
views:
- $type: haxework.view.group.VGroupView
layout.margin: 10
layout.hAlign: center
views: views:
- $type: haxework.view.form.LabelView - $type: haxework.view.form.LabelView
text: Tank'z text: Tank'z
@@ -22,10 +25,13 @@ views:
style: button.menu style: button.menu
+onPress: ~startGame('death') +onPress: ~startGame('death')
text: DeathMatch text: DeathMatch
- $type: haxework.view.SpriteView
style: line
- $type: haxework.view.form.ButtonView - $type: haxework.view.form.ButtonView
style: button.menu style: button.menu
+onPress: ~switcher.change('record') +onPress: ~switcher.change('record')
text: Records text: Records
visible: false
- id: network - id: network
$type: haxework.view.form.ButtonView $type: haxework.view.form.ButtonView
style: button.menu style: button.menu

View File

@@ -43,6 +43,7 @@ class ViewUtil {
public static function toActionLabel(action:TankAction):String { public static function toActionLabel(action:TankAction):String {
return switch (action) { return switch (action) {
case MOVE(d): 'MOVE_$d'; case MOVE(d): 'MOVE_$d';
case SHOT(w): 'SHOT_$w';
case x: '$x'; case x: '$x';
} }
} }

View File

@@ -33,9 +33,15 @@ class SmartActionAreaBuilder implements IActionAreaBuilder {
DIRECTION(Direction.RIGHT), DIRECTION(Direction.RIGHT),
new Rectangle(padding + size, height - size * 1.5 - padding, size, size) new Rectangle(padding + size, height - size * 1.5 - padding, size, size)
)); ));
// key 0
areas.push(new CircleActionArea( areas.push(new CircleActionArea(
KEY(0), 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; return areas;
} }

View File

@@ -13,6 +13,10 @@ class Point {
return new Point(x + point.x, y + point.y); return new Point(x + point.x, y + point.y);
} }
public function clone():Point {
return new Point(x, y);
}
public function hashCode():Int { public function hashCode():Int {
return Std.int(x + 1000 * y); return Std.int(x + 1000 * y);
} }

View File

@@ -32,7 +32,7 @@ class BotControl extends Control {
shotTimer.stop(); shotTimer.stop();
shotTimer = null; shotTimer = null;
} }
action(SHOT); action(SHOT(0));
} }
public function shot(delay:Int = 100):Void { public function shot(delay:Int = 100):Void {

View File

@@ -10,7 +10,7 @@ import ru.m.tankz.Type;
enum TankAction { enum TankAction {
MOVE(direction:Direction); MOVE(direction:Direction);
STOP; STOP;
SHOT; SHOT(weapon:Int);
} }
class Control { class Control {

View File

@@ -9,6 +9,7 @@ class Bullet extends MobileEntity {
public var playerId(default, null):PlayerId; public var playerId(default, null):PlayerId;
public var tankId(get, null):Int; public var tankId(get, null):Int;
public var tank(default, default):Tank; public var tank(default, default):Tank;
public var weapon(default, default):Weapon;
public var config(default, null):BulletConfig; public var config(default, null):BulletConfig;
public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:BulletConfig) { public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:BulletConfig) {

View File

@@ -5,8 +5,10 @@ import ru.m.tankz.config.Config;
class Weapon { class Weapon {
public var config(default, null):WeaponConfig; public var config(default, null):WeaponConfig;
public var count(default, default):Int;
public function new(config:WeaponConfig) { public function new(config:WeaponConfig) {
this.config = config; this.config = config;
this.count = 0;
} }
} }

View File

@@ -56,9 +56,7 @@ class EntityBuilder {
return tank; return tank;
} }
public function buildBullet(point:Point, direction:Direction, playerId:PlayerId, type:TankType):Bullet { public function buildBullet(point:Point, direction:Direction, playerId:PlayerId, bulletConfig:BulletConfig):Bullet {
var tankConfig = config.getTank(type);
var bulletConfig = tankConfig.weapons[0].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); 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; return bullet;
} }

View File

@@ -1,5 +1,6 @@
package ru.m.tankz.game; package ru.m.tankz.game;
import ru.m.tankz.core.Weapon;
import ru.m.geom.Line; import ru.m.geom.Line;
import ru.m.geom.Point; import ru.m.geom.Point;
import ru.m.tankz.bonus.BonusFactory; import ru.m.tankz.bonus.BonusFactory;
@@ -155,8 +156,10 @@ class GameRunner extends Game implements EngineListener {
tank.rect.lean(cell.rect); tank.rect.lean(cell.rect);
emitTankMove(tank); emitTankMove(tank);
case [BULLET(bullet), BULLET(other_bullet)]: case [BULLET(bullet), BULLET(other_bullet)]:
if (bullet.playerId != other_bullet.playerId) {
gameEventSignal.emit(DESTROY(BULLET(bullet.id))); gameEventSignal.emit(DESTROY(BULLET(bullet.id)));
gameEventSignal.emit(DESTROY(BULLET(other_bullet.id))); gameEventSignal.emit(DESTROY(BULLET(other_bullet.id)));
}
case [BULLET(bullet), CELL(cell)]: case [BULLET(bullet), CELL(cell)]:
bullet.rect.lean(cell.rect); bullet.rect.lean(cell.rect);
gameEventSignal.emit(HIT(CELL(cell.cellX, cell.cellY, buildShot(bullet)))); gameEventSignal.emit(HIT(CELL(cell.cellX, cell.cellY, buildShot(bullet))));
@@ -256,14 +259,16 @@ class GameRunner extends Game implements EngineListener {
timer.stop(); timer.stop();
timer = null; timer = null;
} }
case ACTION(tankId, SHOT): case ACTION(tankId, SHOT(index)):
var tank:Tank = cast engine.entities.get(tankId); var tank:Tank = cast engine.entities.get(tankId);
var player = getPlayer(tank.playerId); 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 rect = tank.rect;
var point = rect.center.add(new Point(rect.width / 4 * rect.direction.x, rect.height / 4 * rect.direction.y)); 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.tank = tank;
bullet.weapon = weapon;
bullet.move(bullet.rect.direction); bullet.move(bullet.rect.direction);
engine.spawn(bullet); engine.spawn(bullet);
gameEventSignal.emit(EventUtil.buildBulletSpawn(bullet)); gameEventSignal.emit(EventUtil.buildBulletSpawn(bullet));
@@ -279,8 +284,9 @@ class GameRunner extends Game implements EngineListener {
var player = getPlayer(playerId); var player = getPlayer(playerId);
player.tankId = id; player.tankId = id;
player.state.tank = info; player.state.tank = info;
case SPAWN(BULLET(_, _, playerId, _)): case SPAWN(BULLET(id, _, _, _)):
getPlayer(playerId).bullets++; var bullet:Bullet = engine.getEntity(id);
bullet.weapon.count++;
case CHANGE(BRICK(id, type)): case CHANGE(BRICK(id, type)):
engine.map.bricksById[id].config = config.getBrick(type); engine.map.bricksById[id].config = config.getBrick(type);
case DESTROY(EAGLE(id, shot)): case DESTROY(EAGLE(id, shot)):
@@ -344,8 +350,7 @@ class GameRunner extends Game implements EngineListener {
engine.destroy(id); engine.destroy(id);
case DESTROY(BULLET(id)): case DESTROY(BULLET(id)):
var bullet:Bullet = engine.getEntity(id); var bullet:Bullet = engine.getEntity(id);
var player = getPlayer(bullet.playerId); bullet.weapon.count--;
player.bullets--;
var side:Line = bullet.rect.getSide(bullet.rect.direction.reverse()).move( var side:Line = bullet.rect.getSide(bullet.rect.direction.reverse()).move(
// ToDo: move // ToDo: move
new Point(bullet.rect.direction.x * 5, bullet.rect.direction.y * 5) new Point(bullet.rect.direction.x * 5, bullet.rect.direction.y * 5)

View File

@@ -10,7 +10,6 @@ class Player {
public var tankId(default, set):Int; public var tankId(default, set):Int;
public var isAlive(get, null):Bool; public var isAlive(get, null):Bool;
public var state(default, default):PlayerState; public var state(default, default):PlayerState;
public var bullets(default, default):Int;
public function new(teamId:TeamId, config:PlayerConfig, state:PlayerState = null) { public function new(teamId:TeamId, config:PlayerConfig, state:PlayerState = null) {
this.config = config; this.config = config;
@@ -18,7 +17,6 @@ class Player {
this.state = state == null ? new PlayerState(id) : state; this.state = state == null ? new PlayerState(id) : state;
this.state.reset(); this.state.reset();
this.state.life = Math.isNaN(config.life) ? 0 : config.life; this.state.life = Math.isNaN(config.life) ? 0 : config.life;
this.bullets = 0;
this.tankId = -1; this.tankId = -1;
} }

View File

@@ -86,5 +86,7 @@ tanks:
weapons: weapons:
- bullet: {<<: *bullet, speed: 12.0} - bullet: {<<: *bullet, speed: 12.0}
count: 2 count: 2
- bullet: {<<: *bullet, speed: 4.0, width: 16, height: 16, piercing: 4}
count: 1
bonuses: [] bonuses: []