[common] add EntityBuilder
This commit is contained in:
@@ -18,6 +18,7 @@ import ru.m.tankz.proto.pack.Response;
|
||||
import ru.m.tankz.sound.SoundManager;
|
||||
import ru.m.tankz.storage.GameStorage;
|
||||
import ru.m.tankz.storage.MultiplayerStorage;
|
||||
import ru.m.tankz.storage.RecordStorage;
|
||||
import ru.m.tankz.storage.SettingsStorage;
|
||||
#if flash
|
||||
import flash.Lib;
|
||||
@@ -33,6 +34,7 @@ class Init {
|
||||
@:provide static var settingsStorage:SettingsStorage;
|
||||
@:provide static var multiplayerStorage:MultiplayerStorage;
|
||||
@:provide static var gameStorage:GameStorage;
|
||||
@:provide static var recordStorage:RecordStorage;
|
||||
@:provide static var soundManager:SoundManager;
|
||||
@:provide static var networkManager:NetworkManager;
|
||||
@:provide static var controlFactory:IControlFactory;
|
||||
@@ -62,10 +64,15 @@ class Init {
|
||||
settingsStorage = new SettingsStorage();
|
||||
multiplayerStorage = new MultiplayerStorage();
|
||||
gameStorage = new GameStorage();
|
||||
recordStorage = new RecordStorage();
|
||||
soundManager = new SoundManager();
|
||||
controlFactory = new ClientControlFactory();
|
||||
popupManager = new PopupManager();
|
||||
|
||||
for (record in recordStorage) {
|
||||
L.w("RECORD", '${record.id}. ${record.date}');
|
||||
}
|
||||
|
||||
popupManager.showAnimateFactory = function(v) return new UnFadeAnimate(v, 100);
|
||||
popupManager.closeAnimateFactory = function(v) return new FadeAnimate(v, 100);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ru.m.tankz.render;
|
||||
|
||||
import ru.m.tankz.core.EntityType;
|
||||
import flash.display.DisplayObjectContainer;
|
||||
import flash.display.Graphics;
|
||||
import flash.display.Sprite;
|
||||
@@ -15,7 +16,7 @@ import ru.m.tankz.game.GameEvent;
|
||||
import ru.m.tankz.game.IGame;
|
||||
import ru.m.tankz.render.RenderItem;
|
||||
|
||||
class Render extends SpriteView implements GameListener {
|
||||
class Render extends SpriteView implements GameListener implements EngineListener {
|
||||
|
||||
private var backgroundLayer:Sprite;
|
||||
private var groundLayer:Sprite;
|
||||
@@ -97,6 +98,23 @@ class Render extends SpriteView implements GameListener {
|
||||
clearLayer(upperLayer);
|
||||
}
|
||||
|
||||
public function onSpawn(entity:EntityType):Void {
|
||||
switch entity {
|
||||
case EAGLE(eagle):
|
||||
var item = new EagleItem(eagle);
|
||||
items.set(eagle.key, item);
|
||||
entryLayer.addChild(item.view);
|
||||
item.update();
|
||||
case _:
|
||||
}
|
||||
}
|
||||
|
||||
public function onCollision(entity:EntityType, with:EntityType):Void {
|
||||
}
|
||||
|
||||
public function onMove(entity:EntityType):Void {
|
||||
}
|
||||
|
||||
public function onGameEvent(event:GameEvent):Void {
|
||||
switch event {
|
||||
case SPAWN(TANK(tank)):
|
||||
@@ -110,11 +128,11 @@ class Render extends SpriteView implements GameListener {
|
||||
items.set(bullet.key, item);
|
||||
entryLayer.addChild(item.view);
|
||||
item.update();
|
||||
case SPAWN(EAGLE(eagle)):
|
||||
/*case SPAWN(EAGLE(eagle)):
|
||||
var item = new EagleItem(eagle);
|
||||
items.set(eagle.key, item);
|
||||
entryLayer.addChild(item.view);
|
||||
item.update();
|
||||
item.update();*/
|
||||
case SPAWN(BONUS(bonus)):
|
||||
var item = new BonusItem(bonus);
|
||||
items.set(bonus.key, item);
|
||||
|
||||
28
src/client/haxe/ru/m/tankz/storage/RecordStorage.hx
Normal file
28
src/client/haxe/ru/m/tankz/storage/RecordStorage.hx
Normal file
@@ -0,0 +1,28 @@
|
||||
package ru.m.tankz.storage;
|
||||
|
||||
import haxe.DynamicAccess;
|
||||
import haxework.storage.SharedObjectStorage;
|
||||
import ru.m.tankz.game.record.GameRecord;
|
||||
|
||||
@:yield class RecordStorage extends SharedObjectStorage {
|
||||
|
||||
private static inline var VERSION = 1;
|
||||
|
||||
public function new() {
|
||||
super('record_${VERSION}');
|
||||
}
|
||||
|
||||
public function save(record:GameRecord):Void {
|
||||
trace(record.id);
|
||||
trace(record.date);
|
||||
trace(record.events);
|
||||
write(record.id, record);
|
||||
}
|
||||
|
||||
public function iterator():Iterator<GameRecord> {
|
||||
var data:DynamicAccess<String> = so.data;
|
||||
for (id in data.keys()) {
|
||||
@yield return read(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import ru.m.tankz.network.NetworkManager;
|
||||
import ru.m.tankz.render.Render;
|
||||
import ru.m.tankz.sound.SoundManager;
|
||||
import ru.m.tankz.storage.GameStorage;
|
||||
import ru.m.tankz.storage.RecordStorage;
|
||||
import ru.m.tankz.view.common.IGamePanel;
|
||||
|
||||
class GameFrame extends GroupView implements GameListener {
|
||||
@@ -28,7 +29,8 @@ class GameFrame extends GroupView implements GameListener {
|
||||
@:provide var state:GameState;
|
||||
@:provide("result") var result:GameState;
|
||||
@:provide var switcher:FrameSwitcher;
|
||||
@:provide var storage:GameStorage;
|
||||
@:provide var gameStorage:GameStorage;
|
||||
@:provide var recordStorage:RecordStorage;
|
||||
|
||||
private var game:IGame;
|
||||
private var runner:GameRunner;
|
||||
@@ -49,6 +51,7 @@ class GameFrame extends GroupView implements GameListener {
|
||||
private function start(state:GameState):Void {
|
||||
game = new Game(state.type);
|
||||
game.connect(render);
|
||||
game.engine.connect(render);
|
||||
game.connect(soundManager);
|
||||
game.connect(this);
|
||||
if (panel != null) {
|
||||
@@ -79,14 +82,15 @@ class GameFrame extends GroupView implements GameListener {
|
||||
public function onGameEvent(event:GameEvent):Void {
|
||||
switch event {
|
||||
case GameEvent.COMPLETE(state, winner):
|
||||
L.w("RECORD", Std.string(recorder.data));
|
||||
// ToDo:
|
||||
//recordStorage.save(recorder.record);
|
||||
result = state;
|
||||
this.state = switch runner.next() {
|
||||
case Some(s):
|
||||
// ToDo:
|
||||
var progress = storage.get(game.type);
|
||||
var progress = gameStorage.get(game.type);
|
||||
progress.completeLevel(result.levelId, result.presetId);
|
||||
storage.set(progress);
|
||||
gameStorage.set(progress);
|
||||
s;
|
||||
case None: null;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
31
src/common/haxe/ru/m/tankz/game/EntityBuilder.hx
Normal file
31
src/common/haxe/ru/m/tankz/game/EntityBuilder.hx
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 _:
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)):
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package ru.m.tankz.game.record;
|
||||
|
||||
typedef EventItem = {
|
||||
frame:Int,
|
||||
event:GameEvent
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
21
src/common/haxe/ru/m/tankz/game/record/GameRecord.hx
Normal file
21
src/common/haxe/ru/m/tankz/game/record/GameRecord.hx
Normal 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 = [];
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,14 @@ player:
|
||||
- {type: bot2, rate: 0.27}
|
||||
- {type: bot3, rate: 0.15}
|
||||
|
||||
team:
|
||||
human: &team_human
|
||||
id: human
|
||||
players:
|
||||
- {<<: *human, index: 0, color: 0xFFFF00, control: human-0}
|
||||
eagle:
|
||||
score: 0
|
||||
|
||||
points:
|
||||
- {team: human, type: eagle, index: -1, direction: right, x: 12, y: 24}
|
||||
- {team: human, type: tank, index: 0, direction: top, x: 8, y: 24}
|
||||
@@ -152,12 +160,10 @@ presets:
|
||||
- id: 0
|
||||
name: easy
|
||||
teams:
|
||||
- id: human
|
||||
players:
|
||||
- {<<: *human, index: 0, color: 0xFFFF00, control: human-0}
|
||||
- {<<: *team_human}
|
||||
- id: bot
|
||||
spawnInterval: 3000
|
||||
life: 10
|
||||
life: 1
|
||||
players:
|
||||
- {<<: *bot, index: 0, control: bot-stupid}
|
||||
- {<<: *bot, index: 1, control: bot-stupid}
|
||||
@@ -165,9 +171,7 @@ presets:
|
||||
- id: 1
|
||||
name: normal
|
||||
teams:
|
||||
- id: human
|
||||
players:
|
||||
- {<<: *human, index: 0, color: 0xFFFF00, control: human-0}
|
||||
- {<<: *team_human}
|
||||
- id: bot
|
||||
spawnInterval: 3000
|
||||
life: 20
|
||||
@@ -180,9 +184,7 @@ presets:
|
||||
- id: 2
|
||||
name: hard
|
||||
teams:
|
||||
- id: human
|
||||
players:
|
||||
- {<<: *human, index: 0, color: 0xFFFF00, control: human-0}
|
||||
- {<<: *team_human}
|
||||
- id: bot
|
||||
spawnInterval: 1000
|
||||
life: 30
|
||||
|
||||
Reference in New Issue
Block a user