[common] update GameEvent

This commit is contained in:
2019-05-14 12:24:29 +03:00
parent 608ed3acc4
commit aa10825b12
14 changed files with 194 additions and 151 deletions

View File

@@ -1,5 +1,6 @@
package ru.m.tankz.render; package ru.m.tankz.render;
import ru.m.geom.Rectangle;
import flash.display.DisplayObjectContainer; import flash.display.DisplayObjectContainer;
import flash.display.Graphics; import flash.display.Graphics;
import flash.display.Sprite; import flash.display.Sprite;
@@ -24,7 +25,7 @@ class Render extends SpriteView implements IRender {
private var upperLayer:Sprite; private var upperLayer:Sprite;
private var background:Sprite; private var background:Sprite;
private var items:Map<String, RenderItem<Dynamic, Dynamic>>; private var items:Map<Int, RenderItem<Dynamic, Dynamic>>;
public function new() { public function new() {
super(); super();
@@ -53,7 +54,7 @@ class Render extends SpriteView implements IRender {
public function draw(game:IEngine):Void { public function draw(game:IEngine):Void {
for (brick in game.map.bricks) if (brick.config.index > 0) { for (brick in game.map.bricks) if (brick.config.index > 0) {
if (!items.exists(brick.key)) { if (!items.exists(brick.id)) {
var item:RenderItem<Dynamic, Dynamic> = switch(brick.config.type) { var item:RenderItem<Dynamic, Dynamic> = switch(brick.config.type) {
case 'ace' | 'bush': new BrickItem(brick); case 'ace' | 'bush': new BrickItem(brick);
case 'water': new BrickAnimateItem(brick); case 'water': new BrickAnimateItem(brick);
@@ -61,7 +62,7 @@ class Render extends SpriteView implements IRender {
case x: null; case x: null;
}; };
if (item != null) { if (item != null) {
items[brick.key] = item; items[brick.id] = item;
if (brick.config.layer > 2) { if (brick.config.layer > 2) {
upLayer.addChild(item.view); upLayer.addChild(item.view);
} else { } else {
@@ -101,23 +102,23 @@ class Render extends SpriteView implements IRender {
switch entity { switch entity {
case EAGLE(eagle): case EAGLE(eagle):
var item = new EagleItem(eagle); var item = new EagleItem(eagle);
items.set(eagle.key, item); items.set(eagle.id, item);
entryLayer.addChild(item.view); entryLayer.addChild(item.view);
item.update(); item.update();
case TANK(tank): case TANK(tank):
var item = new TankItem(tank); var item = new TankItem(tank);
items.set(tank.key, item); items.set(tank.id, item);
entryLayer.addChild(item.view); entryLayer.addChild(item.view);
item.update(); item.update();
playAnimate(tank.rect.center, AnimateBundle.tankSpawn()); playAnimate(tank.rect.center, AnimateBundle.tankSpawn());
case BULLET(bullet): case BULLET(bullet):
var item = new BulletItem(bullet); var item = new BulletItem(bullet);
items.set(bullet.key, item); items.set(bullet.id, item);
entryLayer.addChild(item.view); entryLayer.addChild(item.view);
item.update(); item.update();
case BONUS(bonus): case BONUS(bonus):
var item = new BonusItem(bonus); var item = new BonusItem(bonus);
items.set(bonus.key, item); items.set(bonus.id, item);
upperLayer.addChild(item.view); upperLayer.addChild(item.view);
item.update(); item.update();
case _: case _:
@@ -135,34 +136,44 @@ class Render extends SpriteView implements IRender {
public function onGameEvent(event:GameEvent):Void { public function onGameEvent(event:GameEvent):Void {
switch event { switch event {
case DESTROY(TANK(tank, who, wherewith, score)): case DESTROY(TANK(id, shot)):
if (items.exists(tank.key)) { if (items.exists(id)) {
entryLayer.removeChild(items.get(tank.key).view); var item = items[id];
items.remove(tank.key); entryLayer.removeChild(item.view);
playAnimate(tank.rect.center, AnimateBundle.tankBoom()); var rect:Rectangle = item.value.rect;
if (score != 0) { playAnimate(rect.center, AnimateBundle.tankBoom());
showScore(tank.rect.center, score); if (shot.score != 0) {
showScore(rect.center, shot.score);
} }
items.remove(id);
} }
case DESTROY(BULLET(bullet)): case DESTROY(BULLET(id)):
if (items.exists(bullet.key)) { if (items.exists(id)) {
entryLayer.removeChild(items.get(bullet.key).view); var item = items[id];
items.remove(bullet.key); entryLayer.removeChild(item.view);
var point = bullet.rect.center.add(new Point(bullet.rect.width * bullet.rect.direction.x, bullet.rect.height * bullet.rect.direction.y)); var rect:Rectangle = item.value.rect;
var point = rect.center.add(new Point(rect.width * rect.direction.x, rect.height * rect.direction.y));
playAnimate(point, AnimateBundle.bulletBoom()); playAnimate(point, AnimateBundle.bulletBoom());
items.remove(id);
} }
case DESTROY(BONUS(bonus, who, score)): case DESTROY(BONUS(id, shot)):
if (items.exists(bonus.key)) { if (items.exists(id)) {
upperLayer.removeChild(items.get(bonus.key).view); var item = items[id];
items.remove(bonus.key); upperLayer.removeChild(item.view);
if (score != 0) { var rect:Rectangle = item.value.rect;
showScore(bonus.rect.center, score); if (shot.score != 0) {
showScore(rect.center, shot.score);
} }
items.remove(id);
}
case DESTROY(EAGLE(id, shot)):
if (items.exists(id)) {
var item = items[id];
var rect:Rectangle = item.value.rect;
playAnimate(rect.center, AnimateBundle.tankBoom());
if (shot.score != 0) {
showScore(rect.center, shot.score);
} }
case DESTROY(EAGLE(eagle, who, wherewith, score)):
playAnimate(eagle.rect.center, AnimateBundle.tankBoom());
if (score != 0) {
showScore(eagle.rect.center, score);
} }
case _: case _:
} }

View File

@@ -76,26 +76,28 @@ class SoundManager implements GameListener {
public function onGameEvent(event:GameEvent):Void { public function onGameEvent(event:GameEvent):Void {
switch event { switch event {
case START(state): case START(_):
play('start'); play('start');
case SPAWN(_, BULLET(_)): case SPAWN(BULLET(_)):
if (false /* ToDo: human tank */) { if (false /*ToDo: human tank*/) {
play('shot'); play('shot');
} }
case SPAWN(_, BONUS(_, _)): case SPAWN(BONUS(_, _)):
play('bonus_add'); play('bonus_add');
case HIT(TANK(tank, who, wherewith)): case HIT(TANK(_, _)):
play('bullet_hit'); play('bullet_hit');
case DESTROY(TANK(tank, who, wherewith, score)): case DESTROY(TANK(_, _)):
if (true /* ToDo: human tank */) { if (true /*ToDo: human tank*/) {
play('boom_player'); play('boom_player');
} else { } else {
play('boom_bot'); play('boom_bot');
} }
case DESTROY(EAGLE(eagle, who, wherewith, score)): case DESTROY(EAGLE(_, _)):
play('boom_player'); play('boom_player');
case DESTROY(BONUS(bonus, who, score)): case DESTROY(BONUS(_, _)):
if (bonus.type == 'life') { // ToDo: bonus type
play('bonus_get');
if (false /*ToDo: bonus.type == 'life'*/) {
play('live'); play('live');
} else { } else {
play('bonus_get'); play('bonus_get');

View File

@@ -13,9 +13,6 @@ import ru.m.tankz.game.record.GameRecord;
} }
public function save(record:GameRecord):Void { public function save(record:GameRecord):Void {
trace(record.id);
trace(record.date);
trace(record.events);
write(record.id, record); write(record.id, record);
} }

View File

@@ -98,7 +98,7 @@ import ru.m.tankz.view.game.GameView;
public function onGameEvent(event:GameEvent):Void { public function onGameEvent(event:GameEvent):Void {
switch event { switch event {
case GameEvent.COMPLETE(state, winner): case GameEvent.COMPLETE(state, _):
// ToDo: // ToDo:
recordStorage.save(recorder.record); recordStorage.save(recorder.record);
result = state; result = state;

View File

@@ -12,7 +12,7 @@ class BotControl extends Control {
private var tank(get, null):Tank; private var tank(get, null):Tank;
private inline function get_tank():Tank { private inline function get_tank():Tank {
return handler == null ? null : cast handler.engine.entities[tankId]; return handler == null ? null : handler.engine.getEntity(tankId);
} }
override public function stop():Void { override public function stop():Void {

View File

@@ -3,12 +3,10 @@ package ru.m.tankz.core;
import ru.m.geom.Rectangle; import ru.m.geom.Rectangle;
import Type; import Type;
class Entity {
class Entity implements IKey {
public var id(default, null):Int; public var id(default, null):Int;
public var type(default, null):String; public var type(default, null):String;
public var key(get, null):String;
public var rect(default, null):Rectangle; public var rect(default, null):Rectangle;
public function new(id:Int, rect:Rectangle) { public function new(id:Int, rect:Rectangle) {
@@ -17,11 +15,7 @@ class Entity implements IKey {
this.rect = rect; this.rect = rect;
} }
private function get_key():String {
return '$type:$id';
}
public function toString():String { public function toString():String {
return key; return '$type($id)';
} }
} }

View File

@@ -1,5 +0,0 @@
package ru.m.tankz.core;
interface IKey {
public var key(get, null):String;
}

View File

@@ -18,6 +18,7 @@ import ru.m.tankz.map.LevelMap;
public var config(default, default):Config; public var config(default, default):Config;
public var map(default, null):LevelMap; public var map(default, null):LevelMap;
public var allEntities(default, null):Map<Int, Entity>;
public var entities(default, null):Map<Int, Entity>; public var entities(default, null):Map<Int, Entity>;
private var time:Float; private var time:Float;
@@ -25,19 +26,26 @@ import ru.m.tankz.map.LevelMap;
public function new(config:Config) { public function new(config:Config) {
this.config = config; this.config = config;
map = new LevelMap(config.map); map = new LevelMap(config.map);
allEntities = new Map();
entities = new Map(); entities = new Map();
time = Date.now().getTime(); time = Date.now().getTime();
} }
public function getEntity<T:Entity>(entityId:Int):T {
return cast allEntities.get(entityId);
}
public function spawn(entity:Entity):Void { public function spawn(entity:Entity):Void {
allEntities.set(entity.id, entity);
entities.set(entity.id, entity); entities.set(entity.id, entity);
spawnSignal.emit(EntityTypeResolver.of(entity)); spawnSignal.emit(EntityTypeResolver.of(entity));
} }
public function destroy(entityId:Int):Void { public function destroy(entityId:Int):Void {
if (entities.exists(entityId)) { if (entities.exists(entityId)) {
var entity = entities.remove(entityId); var entity = entities[entityId];
destroySignal.emit(EntityTypeResolver.of(entity)); destroySignal.emit(EntityTypeResolver.of(entity));
entities.remove(entityId);
} }
} }

View File

@@ -18,6 +18,8 @@ interface IEngine {
public var moveSignal(default, null):Signal1<EntityType>; public var moveSignal(default, null):Signal1<EntityType>;
public var destroySignal(default, null):Signal1<EntityType>; public var destroySignal(default, null):Signal1<EntityType>;
public function getEntity<T:Entity>(entityId:Int):T;
public function spawn(entity:Entity):Void; public function spawn(entity:Entity):Void;
public function move(entityId:Int, direction:Direction):Void; public function move(entityId:Int, direction:Direction):Void;

View File

@@ -10,6 +10,7 @@ import ru.m.tankz.core.EntityType;
import ru.m.tankz.core.Tank; import ru.m.tankz.core.Tank;
import ru.m.tankz.engine.Engine; import ru.m.tankz.engine.Engine;
import ru.m.tankz.engine.IEngine; import ru.m.tankz.engine.IEngine;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameState;
import ru.m.tankz.game.IGame; import ru.m.tankz.game.IGame;
import ru.m.tankz.Type; import ru.m.tankz.Type;
@@ -56,9 +57,11 @@ import ru.m.tankz.Type;
engine.update(); engine.update();
} }
private function applyPoint(entity:Entity, point:SpawnPoint):Void { private function applyPosition(entity:Entity, position:Position):Void {
entity.rect.center = new Point((point.x + 1) * config.map.cellWidth, (point.y + 1) * config.map.cellHeight); entity.rect.center = new Point(position.x, position.y);
entity.rect.direction = point.direction; if (position.direction != null) {
entity.rect.direction = position.direction;
}
} }
public inline function getTeam(teamId:TeamId):Team { public inline function getTeam(teamId:TeamId):Team {
@@ -75,22 +78,22 @@ import ru.m.tankz.Type;
this.state = state; this.state = state;
timer = new Timer(10); timer = new Timer(10);
timer.run = update; timer.run = update;
case GameEvent.COMPLETE(state, team): case GameEvent.COMPLETE(state, winnerId):
this.state = state; this.state = state;
this.winner = team.id; this.winner = winnerId;
if (timer != null) { if (timer != null) {
timer.stop(); timer.stop();
timer = null; timer = null;
} }
case GameEvent.SPAWN(entityId, EAGLE(teamId, point)): case GameEvent.SPAWN(EAGLE(id, position, teamId)):
var eagle = builder.buildEagle(entityId, teamId); var eagle = builder.buildEagle(id, teamId);
applyPoint(eagle, point); applyPosition(eagle, position);
var team = getTeam(teamId); var team = getTeam(teamId);
team.eagleId = eagle.id; team.eagleId = eagle.id;
engine.spawn(eagle); engine.spawn(eagle);
case GameEvent.SPAWN(entityId, TANK(playerId, type, point)): case GameEvent.SPAWN(TANK(id, position, playerId, type)):
var tank = builder.buildTank(entityId, playerId, type); var tank = builder.buildTank(id, playerId, type);
applyPoint(tank, point); applyPosition(tank, position);
var player = getPlayer(playerId); var player = getPlayer(playerId);
player.tankId = tank.id; player.tankId = tank.id;
player.state.tank = tank.config.type; player.state.tank = tank.config.type;
@@ -101,28 +104,26 @@ import ru.m.tankz.Type;
tank.bonus = Math.random() < player.config.bonus; tank.bonus = Math.random() < player.config.bonus;
// //
engine.spawn(tank); engine.spawn(tank);
case GameEvent.SPAWN(entityId, BULLET(playerId)): case GameEvent.SPAWN(BULLET(id, position, playerId)):
var player = getPlayer(playerId); var player = getPlayer(playerId);
var tank:Tank = cast engine.entities.get(player.tankId); var tank:Tank = cast engine.entities.get(player.tankId);
var bullet = builder.buildBullet(entityId, playerId, tank.config.type); var bullet = builder.buildBullet(id, playerId, tank.config.type);
applyPosition(bullet, position);
bullet.tank = tank; bullet.tank = tank;
var rect = tank.rect; bullet.move(bullet.rect.direction);
bullet.rect.center = rect.center.add(new Point(rect.width / 4 * rect.direction.x, rect.height / 4 * rect.direction.y));
bullet.move(rect.direction);
engine.spawn(bullet); engine.spawn(bullet);
case GameEvent.SPAWN(entityId, BONUS(type, point)): case GameEvent.SPAWN(BONUS(id, position, type)):
var bonus = builder.buildBonus(entityId, type); var bonus = builder.buildBonus(id, type);
bonus.rect.x = point.x * config.map.cellWidth; applyPosition(bonus, position);
bonus.rect.y = point.y * config.map.cellHeight;
engine.spawn(bonus); engine.spawn(bonus);
case GameEvent.DESTROY(TANK(tank, who, wherewith, score)): case GameEvent.DESTROY(TANK(id, _)):
engine.destroy(tank.id); engine.destroy(id);
case GameEvent.DESTROY(BONUS(bonus, who, score)): case GameEvent.DESTROY(BONUS(id, _)):
engine.destroy(bonus.id); engine.destroy(id);
case GameEvent.DESTROY(BULLET(bullet)): case GameEvent.DESTROY(BULLET(id)):
engine.destroy(bullet.id); engine.destroy(id);
case GameEvent.DESTROY(CELL(cell, tank, bullet)): case GameEvent.DESTROY(CELL(cellX, cellY, _)):
engine.destroyCell(cell.cellX, cell.cellY); engine.destroyCell(cellX, cellY);
case GameEvent.ACTION(tankId, MOVE(direction)): case GameEvent.ACTION(tankId, MOVE(direction)):
engine.move(tankId, direction); engine.move(tankId, direction);
case GameEvent.ACTION(tankId, STOP): case GameEvent.ACTION(tankId, STOP):

View File

@@ -1,32 +1,39 @@
package ru.m.tankz.game; package ru.m.tankz.game;
import ru.m.tankz.config.Config; import ru.m.geom.Direction;
import ru.m.tankz.control.Control; import ru.m.tankz.control.Control;
import ru.m.tankz.core.Bonus;
import ru.m.tankz.core.Bullet;
import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.Tank;
import ru.m.tankz.map.Grid;
import ru.m.tankz.Type; import ru.m.tankz.Type;
typedef Position = {
var x:Float;
var y:Float;
@:optional var direction:Direction;
}
enum SpawnEvent { enum SpawnEvent {
EAGLE(teamId:TeamId, point:SpawnPoint); EAGLE(id:Int, position:Position, teamId:TeamId);
TANK(playerId:PlayerId, type:TankType, point:SpawnPoint); TANK(id:Int, position:Position, playerId:PlayerId, type:TankType);
BULLET(playerId:PlayerId); BULLET(id:Int, position:Position, playerId:PlayerId);
BONUS(type:BonusType, point:{x:Int, y:Int}); BONUS(id:Int, position:Position, type:BonusType);
}
typedef Shot = {
var tankId:Int;
@:optional var bulletId:Int;
@:optional var score:Int;
} }
enum HitEvent { enum HitEvent {
TANK(tank:Tank, who:Tank, wherewith:Bullet); TANK(id:Int, shot:Shot);
CELL(cell:GridCell, who:Tank, wherewith:Bullet); CELL(cellX:Int, cellY:Int, shot:Shot);
} }
enum DestroyEvent { enum DestroyEvent {
EAGLE(eagle:Eagle, who:Tank, wherewith:Bullet, score:Int); EAGLE(id:Int, shot:Shot);
TANK(tank:Tank, who:Tank, wherewith:Bullet, score:Int); TANK(id:Int, shot:Shot);
CELL(cell:GridCell, who:Tank, wherewith:Bullet); BONUS(id:Int, shot:Shot);
BONUS(bonus:Bonus, who:Tank, score:Int); BULLET(id:Int);
BULLET(bullet:Bullet); CELL(cellX:Int, cellY:Int, shot:Shot);
} }
enum ChangeEvent { enum ChangeEvent {
@@ -38,10 +45,10 @@ enum ChangeEvent {
enum GameEvent { enum GameEvent {
START(state:GameState); START(state:GameState);
SPAWN(entityId:Int, event:SpawnEvent); SPAWN(event:SpawnEvent);
HIT(event:HitEvent); HIT(event:HitEvent);
DESTROY(event:DestroyEvent); DESTROY(event:DestroyEvent);
CHANGE(event:ChangeEvent); CHANGE(event:ChangeEvent);
COMPLETE(state:GameState, winner:Team); COMPLETE(state:GameState, winnerId:TeamId);
ACTION(tankId:Int, action:TankAction); ACTION(tankId:Int, action:TankAction);
} }

View File

@@ -1,7 +1,7 @@
package ru.m.tankz.game; package ru.m.tankz.game;
import haxe.Timer;
import haxe.ds.Option; import haxe.ds.Option;
import haxe.Timer;
import haxework.signal.Signal; import haxework.signal.Signal;
import ru.m.geom.Line; import ru.m.geom.Line;
import ru.m.geom.Point; import ru.m.geom.Point;
@@ -10,11 +10,12 @@ import ru.m.tankz.control.Control;
import ru.m.tankz.control.Controller; import ru.m.tankz.control.Controller;
import ru.m.tankz.control.IControlFactory; import ru.m.tankz.control.IControlFactory;
import ru.m.tankz.core.Bonus; import ru.m.tankz.core.Bonus;
import ru.m.tankz.core.Bullet;
import ru.m.tankz.core.Eagle; import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.Entity;
import ru.m.tankz.core.EntityType; import ru.m.tankz.core.EntityType;
import ru.m.tankz.core.Tank; import ru.m.tankz.core.Tank;
import ru.m.tankz.engine.IEngine; import ru.m.tankz.engine.IEngine;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.IGame; import ru.m.tankz.game.IGame;
import ru.m.tankz.game.Spawner; import ru.m.tankz.game.Spawner;
import ru.m.tankz.Type; import ru.m.tankz.Type;
@@ -42,9 +43,12 @@ class GameRunner implements EngineListener implements GameListener {
game.engine.disconnect(this); game.engine.disconnect(this);
} }
private function applyPoint(entity:Entity, point:SpawnPoint):Void { private function pointToPosition(point:{x:Int, y:Int, direction:String}):Position {
entity.rect.center = new Point((point.x + 1) * game.engine.map.cellWidth, (point.y + 1) * game.engine.map.cellHeight); return {
entity.rect.direction = point.direction; x: (point.x + 1) * game.config.map.cellWidth,
y: (point.y + 1) * game.config.map.cellHeight,
direction: point.direction,
}
} }
public function start(state:GameState):Void { public function start(state:GameState):Void {
@@ -64,7 +68,7 @@ class GameRunner implements EngineListener implements GameListener {
} }
if (team.config.eagle != null) { if (team.config.eagle != null) {
var point = game.config.getPoint(team.id, "eagle"); var point = game.config.getPoint(team.id, "eagle");
gameEventSignal.emit(GameEvent.SPAWN(++entityId, EAGLE(team.id, point))); gameEventSignal.emit(GameEvent.SPAWN(EAGLE(++entityId, pointToPosition(point), team.id)));
} }
} }
gameEventSignal.emit(GameEvent.START(state)); gameEventSignal.emit(GameEvent.START(state));
@@ -82,7 +86,7 @@ class GameRunner implements EngineListener implements GameListener {
} }
private function spawn(task:SpawnTask):Void { private function spawn(task:SpawnTask):Void {
gameEventSignal.emit(GameEvent.SPAWN(++entityId, TANK(task.playerId, task.tankType, task.point))); gameEventSignal.emit(GameEvent.SPAWN(TANK(++entityId, pointToPosition(task.point), task.playerId, task.tankType)));
} }
private function checkComplete():Void { private function checkComplete():Void {
@@ -114,13 +118,21 @@ class GameRunner implements EngineListener implements GameListener {
} }
} }
Timer.delay(function() { Timer.delay(function() {
gameEventSignal.emit(GameEvent.COMPLETE(game.state, game.getTeam(winner))); gameEventSignal.emit(GameEvent.COMPLETE(game.state, winner));
}, 5000); }, 5000);
} }
public function onSpawn(entity:EntityType):Void { public function onSpawn(entity:EntityType):Void {
} }
private static function buildShot(bullet:Bullet, score:Int = 0):Shot {
return {
tankId: bullet.tank.id,
bulletId: bullet.id,
score: score,
}
}
public function onCollision(entity:EntityType, with:EntityType):Void { public function onCollision(entity:EntityType, with:EntityType):Void {
switch entity { switch entity {
case EntityType.TANK(tank): case EntityType.TANK(tank):
@@ -134,13 +146,13 @@ class GameRunner implements EngineListener implements GameListener {
case [TANK(tank), EAGLE(eagle)]: case [TANK(tank), EAGLE(eagle)]:
tank.rect.lean(eagle.rect); tank.rect.lean(eagle.rect);
case [BULLET(bullet), BULLET(other_bullet)]: case [BULLET(bullet), BULLET(other_bullet)]:
gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet))); gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet.id)));
gameEventSignal.emit(GameEvent.DESTROY(BULLET(other_bullet))); gameEventSignal.emit(GameEvent.DESTROY(BULLET(other_bullet.id)));
case [BULLET(bullet), CELL(cell)]: case [BULLET(bullet), CELL(cell)]:
gameEventSignal.emit(GameEvent.HIT(CELL(cell, bullet.tank, bullet))); gameEventSignal.emit(GameEvent.HIT(CELL(cell.cellX, cell.cellY, buildShot(bullet))));
gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet))); gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet.id)));
case [TANK(tank), BONUS(bonus)]: case [TANK(tank), BONUS(bonus)]:
gameEventSignal.emit(GameEvent.DESTROY(BONUS(bonus, tank, bonus.config.score))); gameEventSignal.emit(GameEvent.DESTROY(BONUS(bonus.id, {tankId: tank.id, score: bonus.config.score})));
case [BULLET(bullet), TANK(tank)]/* | [TANK(tank), BULLET(bullet)]*/: case [BULLET(bullet), TANK(tank)]/* | [TANK(tank), BULLET(bullet)]*/:
if (bullet.tankId == tank.id || (!game.config.game.friendlyFire && tank.playerId.team == bullet.playerId.team)) { if (bullet.tankId == tank.id || (!game.config.game.friendlyFire && tank.playerId.team == bullet.playerId.team)) {
// Nothing // Nothing
@@ -152,25 +164,25 @@ class GameRunner implements EngineListener implements GameListener {
tank.bonus = false; tank.bonus = false;
spawnBonus(); spawnBonus();
} }
gameEventSignal.emit(GameEvent.HIT(TANK(tank, bullet.tank, bullet))); gameEventSignal.emit(GameEvent.HIT(TANK(tank.id, buildShot(bullet))));
} else if (tank.config.downgrade != null) { } else if (tank.config.downgrade != null) {
tank.config = game.config.getTank(tank.config.downgrade); tank.config = game.config.getTank(tank.config.downgrade);
gameEventSignal.emit(GameEvent.HIT(TANK(tank, bullet.tank, bullet))); gameEventSignal.emit(GameEvent.HIT(TANK(tank.id, buildShot(bullet))));
} else { } else {
var score = tank.config.score; var score = tank.config.score;
if (tank.playerId.team == bullet.playerId.team) { if (tank.playerId.team == bullet.playerId.team) {
score = Math.round(score * -0.5); score = Math.round(score * -0.5);
} }
gameEventSignal.emit(GameEvent.DESTROY(TANK(tank, bullet.tank, bullet, score))); gameEventSignal.emit(GameEvent.DESTROY(TANK(tank.id, buildShot(bullet, score))));
} }
} }
gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet))); gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet.id)));
} }
case [BULLET(bullet), EAGLE(eagle)]: case [BULLET(bullet), EAGLE(eagle)]:
if (!eagle.protect.active) { if (!eagle.protect.active) {
gameEventSignal.emit(GameEvent.DESTROY(EAGLE(eagle, bullet.tank, bullet, eagle.score))); gameEventSignal.emit(GameEvent.DESTROY(EAGLE(eagle.id, buildShot(bullet, eagle.score))));
} }
gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet))); gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet.id)));
case _: case _:
} }
} }
@@ -186,8 +198,9 @@ class GameRunner implements EngineListener implements GameListener {
var point = { var point = {
x: Math.floor(Math.random() * (game.engine.map.gridWidth - 1)), x: Math.floor(Math.random() * (game.engine.map.gridWidth - 1)),
y: Math.floor(Math.random() * (game.engine.map.gridHeight - 1)), y: Math.floor(Math.random() * (game.engine.map.gridHeight - 1)),
direction: "right",
} }
gameEventSignal.emit(GameEvent.SPAWN(++entityId, BONUS(type, point))); gameEventSignal.emit(GameEvent.SPAWN(BONUS(++entityId, pointToPosition(point), type)));
} }
private inline function alienTank(team:TeamId):Tank->Bool { private inline function alienTank(team:TeamId):Tank->Bool {
@@ -202,7 +215,7 @@ class GameRunner implements EngineListener implements GameListener {
upgradeTank(tank); upgradeTank(tank);
case "grenade": case "grenade":
for (t in game.engine.iterTanks(alienTank(tank.playerId.team))) { for (t in game.engine.iterTanks(alienTank(tank.playerId.team))) {
gameEventSignal.emit(GameEvent.DESTROY(TANK(t, tank, null, 0))); gameEventSignal.emit(GameEvent.DESTROY(TANK(t.id, {tankId: tank.id})));
} }
case "helmet": case "helmet":
tank.protect.on(bonus.config.duration); tank.protect.on(bonus.config.duration);
@@ -220,7 +233,7 @@ class GameRunner implements EngineListener implements GameListener {
case "gun": case "gun":
upgradeTank(tank, 5); upgradeTank(tank, 5);
case _: case _:
gameEventSignal.emit(GameEvent.DESTROY(TANK(tank, null, null, 0))); // :-D gameEventSignal.emit(GameEvent.DESTROY(TANK(tank.id, {tankId: tank.id}))); // :-D
} }
} }
@@ -264,19 +277,29 @@ class GameRunner implements EngineListener implements GameListener {
var tank:Tank = cast game.engine.entities.get(tankId); var tank:Tank = cast game.engine.entities.get(tankId);
var player = game.getPlayer(tank.playerId); var player = game.getPlayer(tank.playerId);
if (!tank.freezing.active && player.bullets < tank.config.bullets) { if (!tank.freezing.active && player.bullets < tank.config.bullets) {
gameEventSignal.emit(GameEvent.SPAWN(++entityId, BULLET(tank.playerId))); var rect = tank.rect;
var point = rect.center.add(new Point(rect.width / 4 * rect.direction.x, rect.height / 4 * rect.direction.y));
var position = {
x: point.x,
y: point.y,
direction: rect.direction,
} }
case GameEvent.SPAWN(entityId, TANK(playerId, _)): gameEventSignal.emit(GameEvent.SPAWN(BULLET(++entityId, position, tank.playerId)));
}
case GameEvent.SPAWN(TANK(_, _, playerId, _)):
game.getPlayer(playerId).control.start(); game.getPlayer(playerId).control.start();
case GameEvent.SPAWN(entityId, BULLET(playerId)): case GameEvent.SPAWN(BULLET(_, _, playerId)):
game.getPlayer(playerId).bullets++; game.getPlayer(playerId).bullets++;
case GameEvent.DESTROY(EAGLE(eagle, who, wherewith, score)): case GameEvent.DESTROY(EAGLE(id, shot)):
var eagle:Eagle = game.engine.getEntity(id);
eagle.death = true; eagle.death = true;
if (score != 0) { if (shot.score != 0) {
changeScore(who.playerId, score); var tank:Tank = game.engine.getEntity(shot.tankId);
changeScore(tank.playerId, shot.score);
} }
checkComplete(); checkComplete();
case GameEvent.DESTROY(TANK(tank, who, wherewith, score)): case GameEvent.DESTROY(TANK(id, shot)):
var tank:Tank = game.engine.getEntity(id);
var team = game.getTeam(tank.playerId.team); var team = game.getTeam(tank.playerId.team);
var player = game.getPlayer(tank.playerId); var player = game.getPlayer(tank.playerId);
player.control.stop(); player.control.stop();
@@ -294,18 +317,22 @@ class GameRunner implements EngineListener implements GameListener {
if (!team.isAlive) { if (!team.isAlive) {
checkComplete(); checkComplete();
} }
if (tank.bonus && wherewith != null) { if (tank.bonus && shot.bulletId != null) {
spawnBonus(); spawnBonus();
} }
if (score != 0) { if (shot.score != 0) {
changeScore(who.playerId, score); var shooterTank:Tank = game.engine.getEntity(shot.tankId);
changeScore(shooterTank.playerId, shot.score);
} }
case GameEvent.DESTROY(BONUS(bonus, who, score)): case GameEvent.DESTROY(BONUS(id, shot)):
applyBonus(who, bonus); var bonus:Bonus = game.engine.getEntity(id);
if (score != 0) { var tank:Tank = game.engine.getEntity(shot.tankId);
changeScore(who.playerId, score); applyBonus(tank, bonus);
if (shot.score != 0) {
changeScore(tank.playerId, shot.score);
} }
case GameEvent.DESTROY(BULLET(bullet)): case GameEvent.DESTROY(BULLET(id)):
var bullet:Bullet = game.engine.getEntity(id);
var player = game.getPlayer(bullet.playerId); var player = game.getPlayer(bullet.playerId);
player.bullets--; player.bullets--;
var side:Line = bullet.rect.getSide(bullet.rect.direction.reverse()).move(new Point(bullet.mx, bullet.my)); var side:Line = bullet.rect.getSide(bullet.rect.direction.reverse()).move(new Point(bullet.mx, bullet.my));
@@ -313,11 +340,11 @@ class GameRunner implements EngineListener implements GameListener {
for (cell in cells) { for (cell in cells) {
if (cell.armor > 0) { if (cell.armor > 0) {
if (cell.armor == bullet.config.piercing) { if (cell.armor == bullet.config.piercing) {
gameEventSignal.emit(GameEvent.DESTROY(CELL(cell, bullet.tank, bullet))); gameEventSignal.emit(GameEvent.DESTROY(CELL(cell.cellX, cell.cellY, buildShot(bullet))));
} else if (cell.armor < bullet.config.piercing) { } else if (cell.armor < bullet.config.piercing) {
var brick = game.engine.map.getBrick(cell); var brick = game.engine.map.getBrick(cell);
for (cell in brick.cells) { for (cell in brick.cells) {
gameEventSignal.emit(GameEvent.DESTROY(CELL(cell, bullet.tank, bullet))); gameEventSignal.emit(GameEvent.DESTROY(CELL(cell.cellX, cell.cellY, buildShot(bullet))));
} }
} }
} }

View File

@@ -5,7 +5,7 @@ import ru.m.tankz.config.Config;
import ru.m.tankz.engine.IEngine; import ru.m.tankz.engine.IEngine;
import ru.m.tankz.Type; import ru.m.tankz.Type;
interface IGame { interface IGame extends GameListener {
public var type(default, null):GameType; public var type(default, null):GameType;
public var teams(default, null):Map<TeamId, Team>; public var teams(default, null):Map<TeamId, Team>;
public var config(default, null):Config; public var config(default, null):Config;

View File

@@ -5,13 +5,12 @@ import ru.m.geom.Rectangle;
import haxe.ds.HashMap; import haxe.ds.HashMap;
import ru.m.geom.Point; import ru.m.geom.Point;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;
import ru.m.tankz.core.IKey;
class Brick {
public var id(get, null):Int;
class Brick implements IKey {
public var cellX(default, null):Int; public var cellX(default, null):Int;
public var cellY(default, null):Int; public var cellY(default, null):Int;
public var key(get, null):String;
public var mapConfig(default, null):MapConfig; public var mapConfig(default, null):MapConfig;
public var config(default, default):BrickConfig; public var config(default, default):BrickConfig;
@@ -67,11 +66,11 @@ class Brick implements IKey {
return value; return value;
} }
public function get_key():String { public function get_id():Int {
return 'brick:$cellX:$cellY'; return -((cellX * 1000) + cellY);
} }
public function toString() { public function toString() {
return 'Brick{${config.type},$cellX:$cellY}'; return 'Brick(${config.type},$cellX:$cellY)';
} }
} }