[common] spawn system
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
package ru.m.tankz.bot;
|
||||
|
||||
import ru.m.tankz.core.EntityType;
|
||||
import ru.m.tankz.control.Control;
|
||||
import ru.m.geom.Direction;
|
||||
import haxe.Timer;
|
||||
import ru.m.tankz.map.Grid.GridCell;
|
||||
import ru.m.tankz.core.Tank;
|
||||
import Type.ValueType;
|
||||
|
||||
|
||||
class Bot extends Control {
|
||||
@@ -17,10 +15,10 @@ class Bot extends Control {
|
||||
super();
|
||||
}
|
||||
|
||||
override public function onCollision(with:Dynamic):Void {
|
||||
switch (Type.typeof(with)) {
|
||||
case ValueType.TClass(Tank): turn();
|
||||
case ValueType.TClass(GridCell): turn();
|
||||
override public function onCollision(with:EntityType):Void {
|
||||
switch (with) {
|
||||
case EntityType.TANK(_): turn();
|
||||
case EntityType.CELL(_): turn();
|
||||
case _:
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,7 @@ typedef MapConfig = {
|
||||
var cellHeight:Float;
|
||||
var gridWidth:Int;
|
||||
var gridHeight:Int;
|
||||
|
||||
var bricks:Array<BrickConfig>;
|
||||
var points:Array<SpawnPoint>;
|
||||
}
|
||||
|
||||
typedef BrickConfig = {
|
||||
@@ -35,7 +33,7 @@ typedef BulletConfig = {
|
||||
|
||||
typedef TankConfig = {
|
||||
var group:String;
|
||||
var type:Int;
|
||||
var type:String;
|
||||
var width:Float;
|
||||
var height:Float;
|
||||
var speed:Float;
|
||||
@@ -44,48 +42,57 @@ typedef TankConfig = {
|
||||
}
|
||||
|
||||
|
||||
typedef TeamConfig = {
|
||||
var id:String;
|
||||
var size:Int;
|
||||
var spawnInterval:Int;
|
||||
var points:Array<SpawnPoint>;
|
||||
}
|
||||
|
||||
|
||||
class Config {
|
||||
public var map(default, null):MapConfig;
|
||||
public var bricks(default, null):Array<BrickConfig>;
|
||||
public var tanks(default, null):Array<TankConfig>;
|
||||
public var teams(default, null):Array<TeamConfig>;
|
||||
|
||||
private var pointMap:Map<String, Map<Int, SpawnPoint>>;
|
||||
private var brickMap:Map<Int, BrickConfig>;
|
||||
private var tankMap:Map<String, Map<Int, TankConfig>>;
|
||||
private var tankMap:Map<String, Map<String, TankConfig>>;
|
||||
private var teamMap:Map<String, TeamConfig>;
|
||||
|
||||
public function new(map:MapConfig, bricks:Array<BrickConfig>, tanks:Array<TankConfig>) {
|
||||
public function new(map:MapConfig, bricks:Array<BrickConfig>, teams:Array<TeamConfig>, tanks:Array<TankConfig>) {
|
||||
this.map = map;
|
||||
this.bricks = bricks;
|
||||
this.teams = teams;
|
||||
this.tanks = tanks;
|
||||
init();
|
||||
}
|
||||
|
||||
private function init() {
|
||||
pointMap = new Map();
|
||||
for (item in map.points) {
|
||||
if (!pointMap.exists(item.type)) pointMap.set(item.type, new Map<Int, SpawnPoint>());
|
||||
pointMap.get(item.type).set(item.index, item);
|
||||
}
|
||||
brickMap = new Map();
|
||||
for (item in bricks) {
|
||||
brickMap.set(item.type, item);
|
||||
}
|
||||
teamMap = new Map();
|
||||
for (team in teams) {
|
||||
teamMap.set(team.id, team);
|
||||
}
|
||||
tankMap = new Map();
|
||||
for (item in tanks) {
|
||||
if (!tankMap.exists(item.group)) tankMap.set(item.group, new Map<Int, TankConfig>());
|
||||
if (!tankMap.exists(item.group)) tankMap.set(item.group, new Map<String, TankConfig>());
|
||||
tankMap.get(item.group).set(item.type, item);
|
||||
}
|
||||
}
|
||||
|
||||
public function getSpawnPoint(type:String, index:Int):SpawnPoint {
|
||||
return pointMap.get(type).get(index);
|
||||
}
|
||||
|
||||
public function getBrick(type:Int):BrickConfig {
|
||||
return brickMap.get(type);
|
||||
}
|
||||
|
||||
public function getTank(group:String, type:Int):TankConfig {
|
||||
public function getTeam(id:String):TeamConfig {
|
||||
return teamMap.get(id);
|
||||
}
|
||||
|
||||
public function getTank(group:String, type:String):TankConfig {
|
||||
return tankMap.get(group).get(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import ru.m.tankz.config.Config;
|
||||
typedef ConfigSource = {
|
||||
var map: MapConfig;
|
||||
var bricks: Array<BrickConfig>;
|
||||
var teams: Array<TeamConfig>;
|
||||
var tanks: Dynamic<Array<TankConfig>>;
|
||||
}
|
||||
|
||||
@@ -41,7 +42,7 @@ class ConfigBundle {
|
||||
tanks.push(item);
|
||||
}
|
||||
}
|
||||
return new Config(source.map, source.bricks, tanks);
|
||||
return new Config(source.map, source.bricks, source.teams, tanks);
|
||||
case _:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ru.m.tankz.control;
|
||||
|
||||
import ru.m.tankz.core.EntityType;
|
||||
import ru.m.geom.Direction;
|
||||
|
||||
|
||||
@@ -27,7 +28,7 @@ class Control {
|
||||
}
|
||||
}
|
||||
|
||||
public function onCollision(with:Dynamic):Void {
|
||||
public function onCollision(with:EntityType):Void {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ import ru.m.geom.Direction;
|
||||
|
||||
|
||||
class Bullet extends MobileEntity {
|
||||
public var team(default, null):TeamId;
|
||||
public var playerId(default, null):PlayerId;
|
||||
public var tankId(default, null):Int;
|
||||
public var config(default, null):BulletConfig;
|
||||
|
||||
public function new(tank:Tank) {
|
||||
this.team = tank.team;
|
||||
this.playerId = tank.playerId;
|
||||
this.config = tank.config.bullet;
|
||||
super(new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT);
|
||||
this.tankId = tank.id;
|
||||
|
||||
@@ -9,16 +9,14 @@ import ru.m.geom.Direction;
|
||||
|
||||
|
||||
class Tank extends MobileEntity {
|
||||
public var team(default, null):TeamId;
|
||||
public var index(default, null):Int;
|
||||
public var playerId(default, null):PlayerId;
|
||||
public var config(default, set):TankConfig;
|
||||
|
||||
private var bulletsCounter:Int = 0;
|
||||
|
||||
public function new(index:Int, team:TeamId, config:TankConfig) {
|
||||
public function new(playerId:PlayerId, config:TankConfig) {
|
||||
super(new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT);
|
||||
this.index = index;
|
||||
this.team = team;
|
||||
this.playerId = playerId;
|
||||
this.config = config;
|
||||
this.layer = 1;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class CollisionProcessor implements EngineListener {
|
||||
public function onSpawn(entity:EntityType):Void {}
|
||||
|
||||
private function checkTankBullet(tank:Tank, bullet:Bullet):Bool {
|
||||
return tank.team != bullet.team;
|
||||
return tank.playerId.team != bullet.playerId.team;
|
||||
}
|
||||
|
||||
public function onCollision(entity:EntityType, with:EntityType):Void {
|
||||
@@ -116,7 +116,7 @@ class Engine {
|
||||
case TankAction.MOVE(direction):
|
||||
tank.move(direction);
|
||||
case TankAction.LEVEL_UP(level):
|
||||
tank.config = config.getTank('player', Std.int(Math.min(tank.config.type + level, 3)));
|
||||
tank.config = config.getTank('player', Std.string(Std.int(Math.min(Std.parseInt(tank.config.type) + level, 3))));
|
||||
case TankAction.STOP:
|
||||
tank.stop();
|
||||
case TankAction.SHOT:
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
package ru.m.tankz.game;
|
||||
|
||||
import ru.m.tankz.control.Control;
|
||||
import ru.m.tankz.bot.Bot;
|
||||
import ru.m.tankz.game.Game;
|
||||
import ru.m.tankz.config.Config;
|
||||
|
||||
|
||||
typedef ClassicGameSettings = { > GameSettings,
|
||||
var humans:Int;
|
||||
var bots:Int;
|
||||
}
|
||||
|
||||
|
||||
class ClassicGame extends Game<ClassicGameSettings> {
|
||||
class ClassicGame extends Game {
|
||||
|
||||
public static var TYPE(default, never):GameType = Type.getClassName(ClassicGame);
|
||||
|
||||
@@ -20,36 +13,10 @@ class ClassicGame extends Game<ClassicGameSettings> {
|
||||
super(TYPE, config);
|
||||
}
|
||||
|
||||
override public function start(settings:ClassicGameSettings):Void {
|
||||
super.start(settings);
|
||||
var humans = new Team('player', settings.humans, 3);
|
||||
for (index in 0...humans.size) {
|
||||
var player = new Player(humans.id, index);
|
||||
humans.players.push(player);
|
||||
}
|
||||
var bots = new Team('bot', settings.bots, 20);
|
||||
for (index in 0...bots.size) {
|
||||
var bot = new Player(bots.id, 0, new Bot());
|
||||
bot.control.bind(this);
|
||||
bots.players.push(bot);
|
||||
}
|
||||
teams = new Map<TeamId, Team>();
|
||||
teams.set(humans.id, humans);
|
||||
teams.set(bots.id, bots);
|
||||
|
||||
for (player in humans.players) {
|
||||
var point:SpawnPoint = config.getSpawnPoint(humans.type, 0);
|
||||
var tank = buildTank(0, humans.id, config.getTank(humans.type, 0), point);
|
||||
engine.spawn(tank);
|
||||
player.tankId = tank.id;
|
||||
}
|
||||
|
||||
for (player in bots.players) {
|
||||
var index = bots.players.indexOf(player);
|
||||
var point:SpawnPoint = config.getSpawnPoint(bots.type, index);
|
||||
var tank = buildTank(0, bots.id, config.getTank(bots.type, 0), point);
|
||||
engine.spawn(tank);
|
||||
player.tankId = tank.id;
|
||||
override public function start():Void {
|
||||
super.start();
|
||||
for (player in teams.get('bot').players) {
|
||||
setControl(player.id, new Bot());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ru.m.tankz.game;
|
||||
|
||||
import haxe.Timer;
|
||||
import ru.m.tankz.core.EntityType;
|
||||
import ru.m.geom.Direction;
|
||||
import ru.m.geom.Point;
|
||||
@@ -9,43 +10,142 @@ import ru.m.tankz.core.Tank;
|
||||
import ru.m.tankz.engine.Engine;
|
||||
|
||||
typedef GameType = String;
|
||||
typedef TeamId = Int;
|
||||
|
||||
typedef TeamId = String;
|
||||
|
||||
typedef PlayerId = {
|
||||
var team:TeamId;
|
||||
var index:Int;
|
||||
}
|
||||
|
||||
|
||||
typedef GameSettings = {}
|
||||
typedef SpawnTask = {
|
||||
var point:SpawnPoint;
|
||||
var playerId:PlayerId;
|
||||
}
|
||||
|
||||
|
||||
class Game<S:GameSettings> implements EngineListener implements ControlListener {
|
||||
class Spawner {
|
||||
|
||||
private var config:TeamConfig;
|
||||
private var runner:SpawnTask -> Void;
|
||||
private var queue:Array<SpawnTask>;
|
||||
private var timer:Timer;
|
||||
|
||||
private var indexedPoints:Map<Int, SpawnPoint>;
|
||||
private var anyPoints:Array<SpawnPoint>;
|
||||
private var index:Int;
|
||||
|
||||
public function new(config:TeamConfig, runner:SpawnTask -> Void) {
|
||||
this.config = config;
|
||||
this.runner = runner;
|
||||
queue = [];
|
||||
indexedPoints = new Map();
|
||||
anyPoints = [];
|
||||
for (point in config.points) {
|
||||
if (point.type == 'tank') {
|
||||
if (point.index > -1) {
|
||||
indexedPoints.set(point.index, point);
|
||||
} else {
|
||||
anyPoints.push(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function push(playerId:PlayerId):Void {
|
||||
var point:SpawnPoint = null;
|
||||
if (indexedPoints.exists(playerId.index)) {
|
||||
point = indexedPoints.get(playerId.index);
|
||||
} else {
|
||||
point = anyPoints[index++];
|
||||
if (index >= anyPoints.length) index = 0;
|
||||
}
|
||||
if (point != null) {
|
||||
queue.push({playerId:playerId, point:point});
|
||||
run();
|
||||
}
|
||||
}
|
||||
|
||||
private function run():Void {
|
||||
if (timer == null) {
|
||||
timer = new Timer(config.spawnInterval);
|
||||
timer.run = spawn;
|
||||
}
|
||||
}
|
||||
|
||||
private function spawn():Void {
|
||||
if (queue.length == 0) {
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
timer = null;
|
||||
}
|
||||
} else {
|
||||
runner(queue.shift());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Game implements EngineListener implements ControlListener {
|
||||
|
||||
public var type(default, null):GameType;
|
||||
public var teams(default, null):Map<TeamId, Team>;
|
||||
public var config(default, null):Config;
|
||||
public var engine(default, null):Engine;
|
||||
public var settings(default, null):S;
|
||||
|
||||
private var spawners:Map<TeamId, Spawner>;
|
||||
|
||||
public function new(type:GameType, config:Config) {
|
||||
this.type = type;
|
||||
this.config = config;
|
||||
this.engine = new Engine(config);
|
||||
engine.listeners.push(this);
|
||||
}
|
||||
|
||||
private function buildTank(index:Int, teamId:TeamId, config:TankConfig, point:SpawnPoint):Tank {
|
||||
var tank = new Tank(index, teamId, config);
|
||||
public function getPlayer(playerId:PlayerId):Player {
|
||||
return teams.get(playerId.team).players[playerId.index];
|
||||
}
|
||||
|
||||
private function buildTank(playerId:PlayerId, config:TankConfig, point:SpawnPoint):Tank {
|
||||
var tank = new Tank(playerId, config);
|
||||
tank.rect.center = new Point((point.x + 1) * engine.map.cellWidth, (point.y + 1) * engine.map.cellHeight);
|
||||
tank.rect.direction = Direction.fromString(point.direction);
|
||||
return tank;
|
||||
}
|
||||
|
||||
public function start(settings:S):Void {
|
||||
this.settings = settings;
|
||||
public function start():Void {
|
||||
teams = new Map<TeamId, Team>();
|
||||
spawners = new Map<TeamId, Spawner>();
|
||||
for (teamConfig in config.teams) {
|
||||
var team = new Team(teamConfig);
|
||||
for (index in 0...team.config.size) {
|
||||
var player = new Player({team:team.id, index:index});
|
||||
team.players.push(player);
|
||||
teams.set(team.id, team);
|
||||
}
|
||||
spawners.set(team.id, new Spawner(team.config, spawn));
|
||||
}
|
||||
|
||||
for (team in teams) {
|
||||
for (player in team.players) {
|
||||
var point = team.config.points[0];
|
||||
spawners.get(team.id).push(player.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setControl(teamType:String, index:Int, control:Control):Void {
|
||||
private function spawn(task:SpawnTask):Void {
|
||||
var tank = buildTank(task.playerId, config.getTank(task.playerId.team, '0'), task.point);
|
||||
var player:Player = teams.get(task.playerId.team).players[task.playerId.index];
|
||||
player.tankId = tank.id;
|
||||
engine.spawn(tank);
|
||||
}
|
||||
|
||||
public function setControl(playerId:PlayerId, control:Control):Void {
|
||||
for (team in teams.iterator()) {
|
||||
if (team.type == teamType) {
|
||||
L.w('XXX', 'players: ${team.players}');
|
||||
var player = team.players[index];
|
||||
if (team.id == playerId.team) {
|
||||
var player = team.players[playerId.index];
|
||||
if (player.control != null) {
|
||||
player.control.dispose();
|
||||
}
|
||||
@@ -62,11 +162,20 @@ class Game<S:GameSettings> implements EngineListener implements ControlListener
|
||||
}
|
||||
|
||||
public function onCollision(entity:EntityType, with:EntityType):Void {
|
||||
|
||||
switch (entity) {
|
||||
case EntityType.TANK(tank):
|
||||
var control = getPlayer(tank.playerId).control;
|
||||
if (control != null) control.onCollision(with);
|
||||
case x:
|
||||
}
|
||||
}
|
||||
|
||||
public function onDestroy(entity:EntityType):Void {
|
||||
|
||||
switch (entity) {
|
||||
case EntityType.TANK(tank):
|
||||
spawners.get(tank.playerId.team).push(tank.playerId);
|
||||
case x:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,14 +6,12 @@ import ru.m.tankz.game.Game;
|
||||
|
||||
class Player {
|
||||
|
||||
public var index(default, null):Int;
|
||||
public var team(default, null):TeamId;
|
||||
public var id(default, null):PlayerId;
|
||||
public var tankId(default, set):Int;
|
||||
public var control(default, set):Control;
|
||||
|
||||
public function new(team:TeamId, index:Int, control:Control=null) {
|
||||
this.team = team;
|
||||
this.index = index;
|
||||
public function new(id:PlayerId, control:Control=null) {
|
||||
this.id = id;
|
||||
this.control = control;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ru.m.tankz.game;
|
||||
|
||||
import ru.m.tankz.config.Config.TeamConfig;
|
||||
import ru.m.tankz.game.Player;
|
||||
import ru.m.tankz.game.Game;
|
||||
|
||||
@@ -7,18 +8,14 @@ import ru.m.tankz.game.Game;
|
||||
class Team {
|
||||
|
||||
public var id(default, null):TeamId;
|
||||
public var type(default, null):String;
|
||||
public var size(default, null):Int;
|
||||
public var life(default, default):Int;
|
||||
public var config(default, null):TeamConfig;
|
||||
public var players(default, null):Array<Player>;
|
||||
|
||||
private static var i:Int = 0;
|
||||
|
||||
public function new(type:String, size:Int, life:Int) {
|
||||
this.id = ++i;
|
||||
this.type = type;
|
||||
this.size = size;
|
||||
this.life = life;
|
||||
public function new(config:TeamConfig) {
|
||||
this.id = config.id;
|
||||
this.config = config;
|
||||
this.players = [];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user