[common] add ArmorEagleBonus
This commit is contained in:
43
src/common/haxe/ru/m/tankz/bonus/ArmorEagleBonus.hx
Normal file
43
src/common/haxe/ru/m/tankz/bonus/ArmorEagleBonus.hx
Normal file
@@ -0,0 +1,43 @@
|
||||
package ru.m.tankz.bonus;
|
||||
|
||||
import ru.m.geom.Point;
|
||||
import ru.m.tankz.core.Eagle;
|
||||
import ru.m.tankz.engine.IEngine;
|
||||
import ru.m.tankz.game.GameEvent;
|
||||
import ru.m.tankz.game.IGame;
|
||||
import ru.m.tankz.game.Team;
|
||||
import ru.m.tankz.Type;
|
||||
|
||||
using ru.m.tankz.game.GameUtil;
|
||||
|
||||
class ArmorEagleBonus extends BaseBonus {
|
||||
|
||||
public static inline var CLASS = "armor.eagle";
|
||||
|
||||
override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void {
|
||||
var team:Team = game.getTeam(playerId.team);
|
||||
if (team.eagleId > 0) {
|
||||
var eagle:Eagle = cast(engine.entities[team.eagleId], Eagle);
|
||||
var center = eagle.rect.center;
|
||||
var cx:Int = Math.round(center.x / engine.map.cellWidth);
|
||||
var cy:Int = Math.round(center.y / engine.map.cellHeight);
|
||||
var bricks:Array<Int> = [];
|
||||
for (x in cx - 2...cx + 2) {
|
||||
for (y in cy - 2...cy + 2) {
|
||||
var brick = engine.map.getBrick(new Point(x, y));
|
||||
if (brick != null && brick.config.type != "none") {
|
||||
bricks.push(brick.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (brickId in bricks) {
|
||||
game.gameEventSignal.emit(CHANGE(BRICK(brickId, "armor")));
|
||||
}
|
||||
game.ticker.emit(function() {
|
||||
for (brickId in bricks) {
|
||||
game.gameEventSignal.emit(CHANGE(BRICK(brickId, "brick")));
|
||||
}
|
||||
}, Std.int(config.duration * 1000), '$CLASS.${eagle.id}');
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/common/haxe/ru/m/tankz/bonus/BonusFactory.hx
Normal file
26
src/common/haxe/ru/m/tankz/bonus/BonusFactory.hx
Normal file
@@ -0,0 +1,26 @@
|
||||
package ru.m.tankz.bonus;
|
||||
|
||||
import ru.m.tankz.config.Config.BonusConfig;
|
||||
|
||||
class BonusFactory {
|
||||
|
||||
private var classes:Map<String, Class<IBonus>>;
|
||||
|
||||
public function new() {
|
||||
classes = [
|
||||
DestroyTeamBonus.CLASS => DestroyTeamBonus,
|
||||
FreezeTeamBonus.CLASS => FreezeTeamBonus,
|
||||
LifeBonus.CLASS => LifeBonus,
|
||||
ArmorEagleBonus.CLASS => ArmorEagleBonus,
|
||||
ProtectEagleBonus.CLASS => ProtectEagleBonus,
|
||||
ProtectTankBonus.CLASS => ProtectTankBonus,
|
||||
UpgradeTankBonus.CLASS => UpgradeTankBonus,
|
||||
SuicideTankBonus.CLASS => SuicideTankBonus,
|
||||
];
|
||||
}
|
||||
|
||||
public function build(config:BonusConfig):IBonus {
|
||||
var bonusClass = classes.exists(config.factory) ? classes[config.factory] : classes[SuicideTankBonus.CLASS];
|
||||
return Type.createInstance(bonusClass, [config]);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ using ru.m.tankz.game.GameUtil;
|
||||
|
||||
class DestroyTeamBonus extends BaseBonus {
|
||||
|
||||
public static inline var CLASS = "destroy.team";
|
||||
|
||||
override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void {
|
||||
var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId);
|
||||
if (tank != null) {
|
||||
|
||||
@@ -8,6 +8,8 @@ using ru.m.tankz.game.GameUtil;
|
||||
|
||||
class FreezeTeamBonus extends BaseBonus {
|
||||
|
||||
public static inline var CLASS = "freeze.team";
|
||||
|
||||
override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void {
|
||||
for (team in game.teams) {
|
||||
if (team.id != playerId.team) {
|
||||
|
||||
@@ -8,6 +8,8 @@ using ru.m.tankz.game.GameUtil;
|
||||
|
||||
class LifeBonus extends BaseBonus {
|
||||
|
||||
public static inline var CLASS = "life";
|
||||
|
||||
override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void {
|
||||
game.changeLife(playerId, 1);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ using ru.m.tankz.game.GameUtil;
|
||||
|
||||
class ProtectEagleBonus extends BaseBonus {
|
||||
|
||||
public static inline var CLASS = "protect.eagle";
|
||||
|
||||
override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void {
|
||||
var team:Team = game.getTeam(playerId.team);
|
||||
if (team.eagleId > 0) {
|
||||
|
||||
@@ -9,6 +9,8 @@ using ru.m.tankz.game.GameUtil;
|
||||
|
||||
class ProtectTankBonus extends BaseBonus {
|
||||
|
||||
public static inline var CLASS = "protect.tank";
|
||||
|
||||
override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void {
|
||||
var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId);
|
||||
if (tank != null) {
|
||||
|
||||
21
src/common/haxe/ru/m/tankz/bonus/SuicideTankBonus.hx
Normal file
21
src/common/haxe/ru/m/tankz/bonus/SuicideTankBonus.hx
Normal file
@@ -0,0 +1,21 @@
|
||||
package ru.m.tankz.bonus;
|
||||
|
||||
import ru.m.tankz.core.Tank;
|
||||
import ru.m.tankz.engine.IEngine;
|
||||
import ru.m.tankz.game.GameEvent;
|
||||
import ru.m.tankz.game.IGame;
|
||||
import ru.m.tankz.Type;
|
||||
|
||||
using ru.m.tankz.game.GameUtil;
|
||||
|
||||
class SuicideTankBonus extends BaseBonus {
|
||||
|
||||
public static inline var CLASS = "suicide.tank";
|
||||
|
||||
override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void {
|
||||
var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId);
|
||||
if (tank != null) {
|
||||
game.gameEventSignal.emit(DESTROY(TANK(tank.id, {tankId: tank.id})));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ using ru.m.tankz.game.GameUtil;
|
||||
|
||||
class UpgradeTankBonus extends BaseBonus {
|
||||
|
||||
public static inline var CLASS = "upgrade.tank";
|
||||
|
||||
override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void {
|
||||
var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId);
|
||||
if (tank != null) {
|
||||
|
||||
@@ -63,6 +63,7 @@ typedef TankConfig = {
|
||||
|
||||
typedef BonusConfig = {
|
||||
var type:BonusType;
|
||||
var factory:String;
|
||||
@:optional var duration:Null<Int>;
|
||||
@:optional var value:Null<Int>;
|
||||
@:optinal var score:Null<Int>;
|
||||
|
||||
@@ -7,5 +7,6 @@ interface ITicker {
|
||||
public function start():Void;
|
||||
public function stop():Void;
|
||||
public function tick():Int;
|
||||
public function emit(f:Void->Void, delay:Int):Void;
|
||||
public function emit(f:Void->Void, delay:Int, ?key:String):Void;
|
||||
public function cancel(key:String):Void;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ class Ticker implements ITicker {
|
||||
private var passed:Int;
|
||||
private var last_tick:Int;
|
||||
private var actions:Array<Action>;
|
||||
private var actionsByKey:Map<String, Action>;
|
||||
private var actionId = 0;
|
||||
|
||||
private static var TIME = Timer.stamp();
|
||||
@@ -26,6 +27,7 @@ class Ticker implements ITicker {
|
||||
last_tick = 0;
|
||||
running = false;
|
||||
actions = [];
|
||||
actionsByKey = new Map();
|
||||
}
|
||||
|
||||
private function get_time():Int {
|
||||
@@ -73,10 +75,21 @@ class Ticker implements ITicker {
|
||||
}
|
||||
}
|
||||
|
||||
public function emit(fun:Void->Void, delay:Int):Void {
|
||||
public function emit(fun:Void->Void, delay:Int, ?key:String):Void {
|
||||
var action:Action = {action:fun, time:time+delay, id:++actionId};
|
||||
//L.d("Ticker", 'emit: ${action.id} ${action.time}');
|
||||
if (key != null) {
|
||||
cancel(key);
|
||||
actionsByKey[key] = action;
|
||||
}
|
||||
actions.push(action);
|
||||
actions.sort(function(a, b) return a.time - b.time);
|
||||
}
|
||||
|
||||
public function cancel(key:String):Void {
|
||||
if (actionsByKey.exists(key)) {
|
||||
actions.remove(actionsByKey[key]);
|
||||
actionsByKey.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,7 @@ package ru.m.tankz.game;
|
||||
|
||||
import ru.m.geom.Line;
|
||||
import ru.m.geom.Point;
|
||||
import ru.m.tankz.bonus.DestroyTeamBonus;
|
||||
import ru.m.tankz.bonus.FreezeTeamBonus;
|
||||
import ru.m.tankz.bonus.IBonus;
|
||||
import ru.m.tankz.bonus.LifeBonus;
|
||||
import ru.m.tankz.bonus.ProtectEagleBonus;
|
||||
import ru.m.tankz.bonus.ProtectTankBonus;
|
||||
import ru.m.tankz.bonus.UpgradeTankBonus;
|
||||
import ru.m.tankz.bonus.BonusFactory;
|
||||
import ru.m.tankz.control.Control;
|
||||
import ru.m.tankz.core.Bonus;
|
||||
import ru.m.tankz.core.Bullet;
|
||||
@@ -18,7 +12,7 @@ import ru.m.tankz.core.Tank;
|
||||
import ru.m.tankz.engine.Engine;
|
||||
import ru.m.tankz.engine.IEngine;
|
||||
import ru.m.tankz.game.GameEvent;
|
||||
import ru.m.tankz.game.GameState.FragTarget;
|
||||
import ru.m.tankz.game.GameState;
|
||||
import ru.m.tankz.game.Spawner;
|
||||
import ru.m.tankz.Type;
|
||||
import ru.m.Timer;
|
||||
@@ -28,34 +22,19 @@ using ru.m.tankz.game.GameUtil;
|
||||
class GameRunner extends Game implements EngineListener {
|
||||
private var timer:Timer;
|
||||
private var builder:EntityBuilder;
|
||||
private var bonuses:Map<String, IBonus>;
|
||||
private var bonuses:BonusFactory;
|
||||
|
||||
public function new(start:Start) {
|
||||
super(start.state.type);
|
||||
this.level = start.level;
|
||||
this.state = start.state;
|
||||
builder = new EntityBuilder(config);
|
||||
bonuses = new Map();
|
||||
for (bonus in buildBonuses()) {
|
||||
bonuses[bonus.type] = bonus;
|
||||
}
|
||||
bonuses = new BonusFactory();
|
||||
engine = new Engine(config, level.size);
|
||||
ticker = engine.ticker;
|
||||
engine.connect(this);
|
||||
}
|
||||
|
||||
private function buildBonuses():Array<IBonus> {
|
||||
return [
|
||||
new ProtectEagleBonus(config.getBonus("shovel")),
|
||||
new ProtectTankBonus(config.getBonus("helmet")),
|
||||
new LifeBonus(config.getBonus("life")),
|
||||
new UpgradeTankBonus(config.getBonus("star")),
|
||||
new UpgradeTankBonus(config.getBonus("gun")),
|
||||
new DestroyTeamBonus(config.getBonus("grenade")),
|
||||
new FreezeTeamBonus(config.getBonus("clock")),
|
||||
];
|
||||
}
|
||||
|
||||
override function changePause(value:Bool):Void {
|
||||
if (engine != null) {
|
||||
if (value) {
|
||||
@@ -254,11 +233,8 @@ class GameRunner extends Game implements EngineListener {
|
||||
}
|
||||
|
||||
private function applyBonus(tank:Tank, bonus:Bonus):Void {
|
||||
if (bonuses.exists(bonus.config.type)) {
|
||||
bonuses[bonus.config.type].apply(tank.playerId, this, engine);
|
||||
} else {
|
||||
gameEventSignal.emit(DESTROY(TANK(tank.id, {tankId: tank.id}))); // :-D
|
||||
}
|
||||
var bonus = bonuses.build(bonus.config);
|
||||
bonus.apply(tank.playerId, this, engine);
|
||||
}
|
||||
|
||||
override public function onGameEvent(event:GameEvent):Void {
|
||||
@@ -306,6 +282,8 @@ class GameRunner extends Game implements EngineListener {
|
||||
player.state.tank = info;
|
||||
case SPAWN(BULLET(_, _, playerId, _)):
|
||||
getPlayer(playerId).bullets++;
|
||||
case CHANGE(BRICK(id, type)):
|
||||
engine.map.bricksById[id].config = config.getBrick(type);
|
||||
case DESTROY(EAGLE(id, shot)):
|
||||
var eagle:Eagle = engine.getEntity(id);
|
||||
eagle.death = true;
|
||||
@@ -355,6 +333,12 @@ class GameRunner extends Game implements EngineListener {
|
||||
var bonus:Bonus = engine.getEntity(id);
|
||||
var tank:Tank = engine.getEntity(shot.tankId);
|
||||
applyBonus(tank, bonus);
|
||||
var shooter = getPlayer(tank.playerId);
|
||||
shooter.state.frags.push({
|
||||
playerId: shooter.id,
|
||||
target: BONUS(bonus.config.type),
|
||||
score: shot.score,
|
||||
});
|
||||
if (shot.score != null) {
|
||||
changeScore(tank.playerId, shot.score);
|
||||
}
|
||||
@@ -373,10 +357,10 @@ class GameRunner extends Game implements EngineListener {
|
||||
var shot = buildShot(bullet);
|
||||
if (cell.armor == bullet.config.piercing) {
|
||||
engine.destroyCell(cell.cellX, cell.cellY);
|
||||
var brick = engine.map.getBrick(cell.position);
|
||||
var brick = engine.map.getCellBrick(cell.position);
|
||||
gameEventSignal.emit(DESTROY(CELL(brick.id, cell.cellX - brick.cellX * 2, cell.cellY - brick.cellY * 2, shot)));
|
||||
} else if (cell.armor < bullet.config.piercing) {
|
||||
var brick = engine.map.getBrick(cell.position);
|
||||
var brick = engine.map.getCellBrick(cell.position);
|
||||
for (cell in brick.cells) {
|
||||
engine.destroyCell(cell.cellX, cell.cellY);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import ru.m.tankz.Type;
|
||||
enum FragTarget {
|
||||
TANK(tank:TankInfo);
|
||||
EAGLE(color:Color);
|
||||
BONUS(type:BonusType);
|
||||
}
|
||||
|
||||
typedef Frag = {
|
||||
|
||||
@@ -33,7 +33,7 @@ class GameUtil {
|
||||
game.ticker.emit(function() {
|
||||
tank.protect = false;
|
||||
game.gameEventSignal.emit(CHANGE(TANK_PROTECT(tank.id, tank.protect)));
|
||||
}, Std.int(duration * 1000));
|
||||
}, Std.int(duration * 1000), 'protect.tank.${tank.id}');
|
||||
}
|
||||
|
||||
public static function protectEagle(game:IGame, eagle:Eagle, duration:Float):Void {
|
||||
@@ -42,7 +42,7 @@ class GameUtil {
|
||||
game.ticker.emit(function() {
|
||||
eagle.protect = false;
|
||||
game.gameEventSignal.emit(CHANGE(EAGLE_PROTECT(eagle.id, eagle.protect)));
|
||||
}, Std.int(duration * 1000));
|
||||
}, Std.int(duration * 1000), 'protect.eagle.${eagle.id}');
|
||||
}
|
||||
|
||||
public static function freezeTank(game:IGame, tank:Tank, duration:Float):Void {
|
||||
@@ -53,7 +53,7 @@ class GameUtil {
|
||||
game.ticker.emit(function() {
|
||||
tank.freezing = false;
|
||||
game.gameEventSignal.emit(CHANGE(TANK_FREEZE(tank.id, tank.freezing)));
|
||||
}, Std.int(duration * 1000));
|
||||
}, Std.int(duration * 1000), 'freeze.tank.${tank.id}');
|
||||
}
|
||||
|
||||
public static function freezeTeam(game:IGame, engine:IEngine, teamId:TeamId, duration:Float):Void {
|
||||
@@ -70,7 +70,7 @@ class GameUtil {
|
||||
tank.freezing = false;
|
||||
game.gameEventSignal.emit(CHANGE(TANK_FREEZE(tank.id, tank.freezing)));
|
||||
}
|
||||
}, Std.int(duration * 1000));
|
||||
}, Std.int(duration * 1000), 'freeze.team.${teamId}');
|
||||
}
|
||||
|
||||
public static function changeLife(game:IGame, playerId:PlayerId, life:Int):Void {
|
||||
|
||||
@@ -13,7 +13,7 @@ class Brick {
|
||||
public var cellY(default, null):Int;
|
||||
|
||||
public var mapConfig(default, null):MapConfig;
|
||||
public var config(default, default):BrickConfig;
|
||||
public var config(default, set):BrickConfig;
|
||||
|
||||
public var rect(default, null):Rectangle;
|
||||
public var cells(default, null):HashMap<Point, GridCell>;
|
||||
@@ -34,7 +34,17 @@ class Brick {
|
||||
);
|
||||
}
|
||||
|
||||
public function get_broken():Int {
|
||||
private function set_config(value:BrickConfig):BrickConfig {
|
||||
config = value;
|
||||
for (cell in cells) {
|
||||
cell.layer = config.layer;
|
||||
cell.armor = config.armor;
|
||||
cell.destroyed = false;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private function get_broken():Int {
|
||||
var i:Int = 0;
|
||||
for (c in cells.iterator()) {
|
||||
if (c.destroyed) {
|
||||
@@ -44,7 +54,7 @@ class Brick {
|
||||
return i;
|
||||
}
|
||||
|
||||
public function get_destroyed():Bool {
|
||||
private function get_destroyed():Bool {
|
||||
var i = 0;
|
||||
var result:Bool = false;
|
||||
for (c in cells.iterator()) {
|
||||
@@ -57,7 +67,7 @@ class Brick {
|
||||
return result;
|
||||
}
|
||||
|
||||
public function set_destroyed(value:Bool):Bool {
|
||||
private function set_destroyed(value:Bool):Bool {
|
||||
if (value) {
|
||||
for (c in cells.iterator()) {
|
||||
c.destroyed = true;
|
||||
@@ -66,7 +76,7 @@ class Brick {
|
||||
return value;
|
||||
}
|
||||
|
||||
public function get_id():Int {
|
||||
private function get_id():Int {
|
||||
return -((cellX * 1000) + cellY);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class LevelMap {
|
||||
public var height(get, null):Float;
|
||||
|
||||
public var bricks(default, null):Array<Brick>;
|
||||
public var bricksById(default, null):Map<Int, Brick>;
|
||||
|
||||
public var grid(default, null):Grid;
|
||||
|
||||
@@ -31,6 +32,7 @@ class LevelMap {
|
||||
gridHeight = size != null ? size.height : config.grid.height;
|
||||
bricksMap = new HashMap();
|
||||
bricks = [];
|
||||
bricksById = new Map();
|
||||
grid = new Grid(
|
||||
Std.int(cellWidth / 2),
|
||||
Std.int(cellHeight / 2),
|
||||
@@ -57,11 +59,16 @@ class LevelMap {
|
||||
for (cell in brick.cells.iterator()) {
|
||||
bricksMap.set(cell.position, brick);
|
||||
}
|
||||
bricksById.set(brick.id, brick);
|
||||
return brick;
|
||||
}));
|
||||
}
|
||||
|
||||
public function getBrick(position:Point):Brick {
|
||||
return bricks[Std.int(position.x + position.y * gridWidth)];
|
||||
}
|
||||
|
||||
public function getCellBrick(position:Point):Brick {
|
||||
return bricksMap.get(position);
|
||||
}
|
||||
|
||||
|
||||
@@ -147,13 +147,13 @@ tanks:
|
||||
skin: bd
|
||||
|
||||
bonuses:
|
||||
- {score: 500, type: clock, duration: 10}
|
||||
- {score: 500, type: grenade}
|
||||
- {score: 500, type: helmet, duration: 20}
|
||||
- {score: 500, type: life}
|
||||
- {score: 500, type: shovel, duration: 10}
|
||||
- {score: 500, type: star, value: 1}
|
||||
- {score: 500, type: gun, value: 5}
|
||||
- {score: 500, factory: freeze.team, type: clock, duration: 10}
|
||||
- {score: 500, factory: destroy.team, type: grenade}
|
||||
- {score: 500, factory: protect.tank, type: helmet, duration: 15}
|
||||
- {score: 500, factory: life, type: life}
|
||||
- {score: 500, factory: armor.eagle, type: shovel, duration: 10}
|
||||
- {score: 500, factory: upgrade.tank, type: star, value: 1}
|
||||
- {score: 500, factory: upgrade.tank, type: gun, value: 5}
|
||||
|
||||
presets:
|
||||
- id: 0
|
||||
|
||||
@@ -107,9 +107,8 @@ tanks:
|
||||
skin: bb
|
||||
|
||||
bonuses:
|
||||
- {type: clock, duration: 10}
|
||||
- {type: grenade}
|
||||
- {type: helmet, duration: 20}
|
||||
- {type: life}
|
||||
- {type: shovel, duration: 10}
|
||||
- {type: star}
|
||||
- {score: 100, factory: freeze.team, type: clock, duration: 10}
|
||||
- {score: 100, factory: destroy.team, type: grenade}
|
||||
- {score: 100, factory: protect.tank, type: helmet, duration: 15}
|
||||
- {score: 100, factory: life, type: life}
|
||||
- {score: 100, factory: protect.eagle, type: shovel, duration: 10}
|
||||
|
||||
Reference in New Issue
Block a user