[common] add EntityBuilder

This commit is contained in:
2019-05-06 16:21:45 +03:00
parent d11d0ac53f
commit d6b572aead
17 changed files with 205 additions and 66 deletions

View File

@@ -213,4 +213,13 @@ class Config {
}
return -1;
}
public function getPoint(teamId:TeamId, type:String, index:Int = -1):SpawnPoint {
for (point in points) {
if (point.team == teamId && point.type == type && point.index == index) {
return point;
}
}
return null;
}
}

View File

@@ -1,5 +1,6 @@
package ru.m.tankz.engine;
import ru.m.geom.Direction;
import ru.m.geom.Line;
import ru.m.geom.Point;
import ru.m.tankz.config.Config;
@@ -30,11 +31,24 @@ import ru.m.tankz.map.LevelMap;
public function spawn(entity:Entity):Void {
entities.set(entity.id, entity);
spawnSignal.emit(EntityTypeResolver.of(entity));
}
public function destroy(entity:Entity):Void {
if (entities.exists(entity.id)) {
entities.remove(entity.id);
public function destroy(entityId:Int):Void {
if (entities.exists(entityId)) {
entities.remove(entityId);
}
}
public function move(entityId:Int, direction:Direction):Void {
if (entities.exists(entityId)) {
cast(entities.get(entityId), MobileEntity).move(direction);
}
}
public function stop(entityId:Int):Void {
if (entities.exists(entityId)) {
cast(entities.get(entityId), MobileEntity).stop();
}
}

View File

@@ -1,6 +1,7 @@
package ru.m.tankz.engine;
import haxework.signal.Signal;
import ru.m.geom.Direction;
import ru.m.tankz.config.Config;
import ru.m.tankz.core.Entity;
import ru.m.tankz.core.EntityType;
@@ -12,12 +13,17 @@ interface IEngine {
public var config(default, default):Config;
public var map(default, null):LevelMap;
public var spawnSignal(default, null):Signal1<EntityType>;
public var collisionSignal(default, null):Signal2<EntityType, EntityType>;
public var moveSignal(default, null):Signal1<EntityType>;
public function spawn(entity:Entity):Void;
public function destroy(entity:Entity):Void;
public function move(entityId:Int, direction:Direction):Void;
public function stop(entityId:Int):Void;
public function destroy(entityId:Int):Void;
public function update():Void;
@@ -31,6 +37,7 @@ interface IEngine {
}
interface EngineListener {
public function onSpawn(entity:EntityType):Void;
public function onCollision(entity:EntityType, with:EntityType):Void;
public function onMove(entity:EntityType):Void;
}
}

View File

@@ -0,0 +1,31 @@
package ru.m.tankz.game;
import ru.m.geom.Point;
import ru.m.tankz.config.Config;
import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.Entity;
import ru.m.tankz.Type;
class EntityBuilder {
private var config:Config;
public function new(config:Config) {
this.config = config;
}
private function applyPoint(entity:Entity, point:SpawnPoint):Void {
entity.rect.center = new Point((point.x + 1) * config.map.cellWidth, (point.y + 1) * config.map.cellHeight);
entity.rect.direction = point.direction;
}
public function buildEagle(teamId:TeamId):Eagle {
var eageleConfig = config.getTeam(teamId).eagle;
var eaglePoint = config.getPoint(teamId, "eagle");
var eagle = new Eagle(teamId, eageleConfig);
eagle.color = config.getColor(new PlayerId(teamId, -1));
applyPoint(eagle, eaglePoint);
return eagle;
}
}

View File

@@ -2,7 +2,9 @@ package ru.m.tankz.game;
import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.config.Config;
import ru.m.tankz.control.Control;
import ru.m.tankz.core.EntityType;
import ru.m.tankz.core.Tank;
import ru.m.tankz.engine.Engine;
import ru.m.tankz.engine.IEngine;
import ru.m.tankz.game.GameState;
@@ -21,6 +23,8 @@ import ru.m.tankz.Type;
public var state(default, null):GameState;
private var builder:EntityBuilder;
@:provide var configBundle:IConfigBundle;
public function new(type:GameType) {
@@ -28,6 +32,7 @@ import ru.m.tankz.Type;
this.teams = new Map();
this.config = configBundle.get(type);
this.engine = new Engine(config);
this.builder = new EntityBuilder(config);
connect(this);
}
@@ -46,7 +51,9 @@ import ru.m.tankz.Type;
case GameEvent.COMPLETE(state, team):
this.state = state;
this.winner = team.id;
case GameEvent.SPAWN(EAGLE(eagle)):
case GameEvent.SPAWN(EAGLE(teamId)):
var eagle = builder.buildEagle(teamId);
getTeam(teamId).eagleId = eagle.id;
engine.spawn(eagle);
case GameEvent.SPAWN(TANK(tank)):
engine.spawn(tank);
@@ -55,11 +62,15 @@ import ru.m.tankz.Type;
case GameEvent.SPAWN(BONUS(bonus)):
engine.spawn(bonus);
case GameEvent.DESTROY(TANK(tank, who, wherewith, score)):
engine.destroy(tank);
engine.destroy(tank.id);
case GameEvent.DESTROY(BONUS(bonus, who, score)):
engine.destroy(bonus);
engine.destroy(bonus.id);
case GameEvent.DESTROY(BULLET(bullet)):
engine.destroy(bullet);
engine.destroy(bullet.id);
case GameEvent.ACTION(tankId, MOVE(direction)):
engine.move(tankId, direction);
case GameEvent.ACTION(tankId, STOP):
engine.stop(tankId);
case _:
}
}

View File

@@ -1,14 +1,15 @@
package ru.m.tankz.game;
import ru.m.tankz.control.Control.TankAction;
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.core.Bullet;
import ru.m.tankz.map.Grid;
import ru.m.tankz.Type.TeamId;
enum SpawnEvent {
EAGLE(eagle:Eagle);
EAGLE(teamId:TeamId);
TANK(tank:Tank);
BULLET(bullet:Bullet);
BONUS(bonus:Bonus);

View File

@@ -46,22 +46,6 @@ class GameRunner implements EngineListener implements GameListener {
game.engine.update();
}
private function applyAction(tankId:Int, action:TankAction):Void {
if (!game.engine.entities.exists(tankId)) return;
var tank:Tank = cast game.engine.entities.get(tankId);
switch (action) {
case MOVE(direction):
tank.move(direction);
case STOP:
tank.stop();
case SHOT:
var bullet = tank.shot();
if (bullet != null) {
gameEventSignal.emit(GameEvent.SPAWN(BULLET(bullet)));
}
}
}
private function buildTank(task:SpawnTask):Tank {
var player = game.getPlayer(task.playerId);
var tankType:TankType = if (task.tankType != null) {
@@ -110,13 +94,8 @@ class GameRunner implements EngineListener implements GameListener {
team.spawner.push(player.id, player.state.tank);
}
}
var eaglePoint = team.spawner.getPoint("eagle");
if (eaglePoint != null) {
var eagle = new Eagle(team.id, team.config.eagle);
eagle.color = game.config.getColor(new PlayerId(eagle.team, -1));
team.eagleId = eagle.id;
applyPoint(eagle, eaglePoint);
gameEventSignal.emit(GameEvent.SPAWN(EAGLE(eagle)));
if (team.config.eagle != null) {
gameEventSignal.emit(GameEvent.SPAWN(EAGLE(team.id)));
}
}
gameEventSignal.emit(GameEvent.START(state));
@@ -178,6 +157,9 @@ class GameRunner implements EngineListener implements GameListener {
}, 5000);
}
public function onSpawn(entity:EntityType):Void {
}
public function onCollision(entity:EntityType, with:EntityType):Void {
switch entity {
case EntityType.TANK(tank):
@@ -317,8 +299,12 @@ class GameRunner implements EngineListener implements GameListener {
timer.stop();
timer = null;
}
case GameEvent.ACTION(tankId, action):
applyAction(tankId, action);
case GameEvent.ACTION(tankId, SHOT):
var tank:Tank = cast game.engine.entities.get(tankId);
var bullet = tank.shot();
if (bullet != null) {
gameEventSignal.emit(GameEvent.SPAWN(BULLET(bullet)));
}
case GameEvent.SPAWN(TANK(tank)):
game.getPlayer(tank.playerId).control.start();
case GameEvent.DESTROY(EAGLE(eagle, who, wherewith, score)):

View File

@@ -1,8 +1,9 @@
package ru.m.tankz.game;
import ru.m.tankz.game.Game;
import ru.m.tankz.game.IGame;
class GameTracer implements GameListener {
public function new() {
}

View File

@@ -1,6 +0,0 @@
package ru.m.tankz.game.record;
typedef EventItem = {
frame:Int,
event:GameEvent
}

View File

@@ -2,17 +2,20 @@ package ru.m.tankz.game.record;
import flash.events.Event;
import flash.Lib;
import ru.m.tankz.game.record.GameRecord;
class GamePlayer {
private var frame:Int;
private var game:IGame;
private var record:GameRecord;
private var data:Array<EventItem>;
public function new(game:IGame, data:Array<EventItem>) {
public function new(game:IGame, record:GameRecord) {
frame = 0;
this.game = game;
this.data = data;
this.record = record;
this.data = null;
}
public function onGameEvent(event:GameEvent):Void {
@@ -24,6 +27,7 @@ class GamePlayer {
public function start():Void {
frame = 0;
data = record.events.slice(0);
Lib.current.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

View File

@@ -0,0 +1,21 @@
package ru.m.tankz.game.record;
import com.hurlant.crypto.extra.UUID;
import com.hurlant.crypto.prng.Random;
typedef EventItem = {
frame:Int,
event:GameEvent
}
class GameRecord {
public var id(default, default):String;
public var date(default, default):Date;
public var events(default, default):Array<EventItem>;
public function new() {
this.id = UUID.generateRandom(new Random()).toString();
this.date = null;
this.events = [];
}
}

View File

@@ -7,11 +7,11 @@ import ru.m.tankz.game.IGame;
class GameRecorder implements GameListener {
private var frame:Int;
public var data(default, null):Array<EventItem>;
public var record(default, null):GameRecord;
public function new() {
frame = 0;
data = [];
record = new GameRecord();
}
public function onGameEvent(event:GameEvent):Void {
@@ -22,11 +22,12 @@ class GameRecorder implements GameListener {
stop();
case _:
}
data.push({frame: frame, event: event});
record.events.push({frame: frame, event: event});
}
public function start():Void {
frame = 0;
record.date = Date.now();
Lib.current.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}