[render] use only GameEvent for redraw

This commit is contained in:
2019-05-16 23:27:27 +03:00
parent efe826110c
commit 3c116db135
14 changed files with 128 additions and 136 deletions

View File

@@ -1,6 +1,5 @@
package ru.m.tankz.render;
import ru.m.geom.Rectangle;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.Sprite;
@@ -55,7 +54,6 @@ class Render extends SpriteView implements IRender implements GameListener {
private function set_game(value:IGame):IGame {
game = value;
game.connect(this);
game.engine.spawnSignal.connect(onSpawn);
return game;
}
@@ -101,33 +99,6 @@ class Render extends SpriteView implements IRender implements GameListener {
clearLayer(upperLayer);
}
public function onSpawn(entity:EntityType):Void {
switch entity {
/*case EAGLE(eagle):
var item = new EagleRenderItem(eagle);
items.set(eagle.id, item);
entryLayer.addChild(item.view);
item.update();*/
case TANK(tank):
var item = new TankRenderItem(tank);
items.set(tank.id, item);
entryLayer.addChild(item.view);
item.update();
playAnimate(item.rect.center, AnimateBundle.tankSpawn());
case BULLET(bullet):
var item = new BulletRenderItem(bullet);
items.set(bullet.id, item);
entryLayer.addChild(item.view);
item.update();
case BONUS(bonus):
var item = new BonusRenderItem(bonus);
items.set(bonus.id, item);
upperLayer.addChild(item.view);
item.update();
case _:
}
}
public function onGameEvent(event:GameEvent):Void {
switch event {
case START(_):
@@ -148,6 +119,27 @@ class Render extends SpriteView implements IRender implements GameListener {
items.set(id, item);
entryLayer.addChild(item.view);
item.update();
case SPAWN(TANK(id, rect, playerId, info)):
var item = new TankRenderItem(rect);
var config = game.config.getTank(info.type);
item.color = game.config.getColor(playerId);
item.skin = config.skin;
item.hits = info.hits;
item.bonus = info.bonus;
items.set(id, item);
entryLayer.addChild(item.view);
item.update();
playAnimate(item.rect.center, AnimateBundle.tankSpawn());
case SPAWN(BULLET(id, rect, playerId, piercing)):
var item = new BulletRenderItem(rect, piercing);
items.set(id, item);
entryLayer.addChild(item.view);
item.update();
case SPAWN(BONUS(id, rect, type)):
var item = new BonusRenderItem(rect, type);
items.set(id, item);
upperLayer.addChild(item.view);
item.update();
case MOVE(BULLET(id, position)):
if (items.exists(id)) {
var item = items[id];

View File

@@ -1,15 +1,15 @@
package ru.m.tankz.render.item;
import ru.m.tankz.core.Bonus;
import ru.m.tankz.Type.BonusType;
import ru.m.geom.Rectangle;
import ru.m.tankz.Type;
class BonusRenderItem extends BitmapRenderItem {
public var type(default, set):BonusType;
public function new(bonus:Bonus) {
super(bonus.rect);
type = bonus.config.type;
public function new(rect:Rectangle, type:BonusType) {
super(rect);
this.type = type;
}
private function set_type(value:BonusType):BonusType {

View File

@@ -1,13 +1,13 @@
package ru.m.tankz.render.item;
import ru.m.tankz.core.Bullet;
import ru.m.geom.Rectangle;
class BulletRenderItem extends BitmapRenderItem {
public var piercing(default, set):Int = -1;
public function new(bullet:Bullet) {
super(bullet.rect);
piercing = bullet.config.piercing;
public function new(rect:Rectangle, piercing:Int) {
super(rect);
this.piercing = piercing;
}
private function set_piercing(value:Int):Int {

View File

@@ -4,7 +4,7 @@ import flash.display.BitmapData;
import haxework.color.Color;
import haxework.view.utils.BitmapUtil;
import openfl.Assets;
import ru.m.tankz.core.Tank;
import ru.m.geom.Rectangle;
class TankRenderItem extends BitmapRenderItem {
public var color(default, default):Color;
@@ -16,12 +16,8 @@ class TankRenderItem extends BitmapRenderItem {
private var images:Array<BitmapData>;
private var frame:Int;
public function new(tank:Tank) {
super(tank.rect);
color = tank.color;
skin = tank.config.skin;
hits = tank.hits;
bonus = tank.bonus;
public function new(rect:Rectangle) {
super(rect);
move(rect.position);
}

View File

@@ -32,7 +32,7 @@ class BotControl extends Control {
shotTimer.stop();
shotTimer = null;
}
action(SHOT);
//action(SHOT);
}
public function shot(delay:Int = 100):Void {

View File

@@ -1,15 +1,14 @@
package ru.m.tankz.core;
import ru.m.tankz.config.Config;
import ru.m.geom.Rectangle;
import ru.m.tankz.config.Config;
class Bonus extends Entity {
public var config(default, null):BonusConfig;
public function new(id:Int, config:BonusConfig) {
super(id, new Rectangle(0, 0, 44, 44));
public function new(id:Int, rect:Rectangle, config:BonusConfig) {
super(id, rect);
this.config = config;
}
}

View File

@@ -11,10 +11,10 @@ class Bullet extends MobileEntity {
public var tank(default, default):Tank;
public var config(default, null):BulletConfig;
public function new(id:Int, playerId:PlayerId, config:BulletConfig) {
public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:BulletConfig) {
super(id, rect, config.speed, Direction.RIGHT);
this.playerId = playerId;
this.config = config;
super(id, new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT);
this.layer = 2;
}

View File

@@ -15,8 +15,8 @@ class Tank extends MobileEntity {
public var protect(default, null):Modificator;
public var freezing(default, null):Modificator;
public function new(id:Int, playerId:PlayerId, config:TankConfig) {
super(id, new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT);
public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:TankConfig) {
super(id, rect, config.speed, Direction.RIGHT);
this.protect = new Modificator();
this.freezing = new Modificator();
this.playerId = playerId;

View File

@@ -91,7 +91,7 @@ import ru.m.tankz.map.LevelMap;
var end:Point = side.center.add(new Point(entity.mx * (d / 30), entity.my * (d / 30)));
var c:Int = Math.floor(Math.abs(((end.x - side.center.x) / (map.cellWidth / 4) + (end.y - side.center.y) / (map.cellHeight / 4))));
var isStop:Bool = false;
var withCollision:EntityType = null;
while (c-- >= 0) {
side = side.move(step);
@@ -101,9 +101,7 @@ import ru.m.tankz.map.LevelMap;
for (cell in cells) {
if (cell.getCollision(entity.layer)) {
collision = true;
var with = EntityTypeResolver.of(cell);
collisionSignal.emit(entityType, with);
isStop = true;
withCollision = EntityTypeResolver.of(cell);
// fix position
if (cells.filter(function(c:GridCell) return c.getCollision(entity.layer)).length == 1) {
if (entity.mx != 0) {
@@ -122,20 +120,20 @@ import ru.m.tankz.map.LevelMap;
for (other in entities.iterator()) {
if (other != ent && other != null) {
if (other.rect.intersection2(side)) {
var with = EntityTypeResolver.of(other);
collisionSignal.emit(entityType, with);
isStop = true;
withCollision = EntityTypeResolver.of(other);
}
}
}
if (isStop) break;
if (withCollision != null) break;
}
if (!isStop || Std.is(entity, Bullet)) {
entity.rect.x += entity.mx * (d / 30);
entity.rect.y += entity.my * (d / 30);
moveSignal.emit(entityType);
entity.rect.x += entity.mx * (d / 30);
entity.rect.y += entity.my * (d / 30);
moveSignal.emit(entityType);
if (withCollision != null) {
collisionSignal.emit(entityType, withCollision);
}
}
}

View File

@@ -1,5 +1,7 @@
package ru.m.tankz.game;
import ru.m.geom.Direction;
import ru.m.geom.Point;
import ru.m.geom.Rectangle;
import ru.m.tankz.config.Config;
import ru.m.tankz.core.Bonus;
@@ -8,6 +10,12 @@ import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.Tank;
import ru.m.tankz.Type;
typedef EntityPoint = {
var x:Int;
var y:Int;
var direction:String;
}
class EntityBuilder {
private var config:Config;
@@ -16,30 +24,45 @@ class EntityBuilder {
this.config = config;
}
public function buildEagle(id:Int, rect:Rectangle, teamId:TeamId):Eagle {
private function buildRect(point:EntityPoint, width:Float, height:Float):Rectangle {
return new Rectangle(
(point.x + 1) * config.map.cellWidth - width / 2,
(point.y + 1) * config.map.cellHeight - height / 2,
width,
height,
Direction.fromString(point.direction)
);
}
public function buildEagle(id:Int, point:EntityPoint, teamId:TeamId):Eagle {
var eageleConfig = config.getTeam(teamId).eagle;
var eagle = new Eagle(id, rect, teamId, eageleConfig);
var eagle = new Eagle(id, buildRect(point, config.map.cellWidth * 2, config.map.cellHeight * 2), teamId, eageleConfig);
eagle.color = config.getColor(new PlayerId(teamId, -1));
return eagle;
}
public function buildTank(id:Int, playerId:PlayerId, type:TankType):Tank {
public function buildTank(id:Int, point:EntityPoint, playerId:PlayerId, type:TankType):Tank {
var playerConfig = config.getPlayer(playerId);
var tankConfig = config.getTank(type);
var tank = new Tank(id, playerId, tankConfig);
var tank = new Tank(id, buildRect(point, tankConfig.width, tankConfig.height), playerId, tankConfig);
tank.color = config.getColor(playerId);
tank.bonus = Math.random() < playerConfig.bonus;
if (playerConfig.protect > 0) {
tank.protect.on(playerConfig.protect);
}
return tank;
}
public function buildBullet(id:Int, playerId:PlayerId, type:TankType):Bullet {
public function buildBullet(id:Int, point:Point, direction:Direction, playerId:PlayerId, type:TankType):Bullet {
var tankConfig = config.getTank(type);
var bullet = new Bullet(id, playerId, tankConfig.bullet);
var bulletConfig = tankConfig.bullet;
var bullet = new Bullet(id, new Rectangle(point.x - bulletConfig.width / 2, point.y - bulletConfig.height / 2, bulletConfig.width, bulletConfig.height, direction), playerId, bulletConfig);
return bullet;
}
public function buildBonus(id:Int, type:BonusType):Bonus {
public function buildBonus(id:Int, point:EntityPoint, type:BonusType):Bonus {
var bonusConfig = config.getBonus(type);
var bonus = new Bonus(id, bonusConfig);
var bonus = new Bonus(id, buildRect(point, config.map.cellWidth * 2, config.map.cellHeight * 2), bonusConfig);
return bonus;
}
}

View File

@@ -4,10 +4,8 @@ import ru.m.geom.Point;
import ru.m.geom.Position;
import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.config.Config;
import ru.m.tankz.control.Control;
import ru.m.tankz.core.Entity;
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.GameEvent;
@@ -75,47 +73,12 @@ import ru.m.tankz.Type;
this.state = state;
this.winner = winnerId;
case GameEvent.SPAWN(EAGLE(id, rect, teamId)):
var eagle = builder.buildEagle(id, rect, teamId);
var team = getTeam(teamId);
team.eagleId = eagle.id;
engine.spawn(eagle);
case GameEvent.SPAWN(TANK(id, position, playerId, type)):
var tank = builder.buildTank(id, playerId, type);
applyPosition(tank, position);
team.eagleId = id;
case GameEvent.SPAWN(TANK(id, rect, playerId, info)):
var player = getPlayer(playerId);
player.tankId = tank.id;
player.state.tank = tank.config.type;
// ToDo: in GameRunner?
if (player.config.protect > 0) {
tank.protect.on(player.config.protect);
}
tank.bonus = Math.random() < player.config.bonus;
//
engine.spawn(tank);
case GameEvent.SPAWN(BULLET(id, position, playerId)):
var player = getPlayer(playerId);
var tank:Tank = cast engine.entities.get(player.tankId);
var bullet = builder.buildBullet(id, playerId, tank.config.type);
applyPosition(bullet, position);
bullet.tank = tank;
bullet.move(bullet.rect.direction);
engine.spawn(bullet);
case GameEvent.SPAWN(BONUS(id, position, type)):
var bonus = builder.buildBonus(id, type);
applyPosition(bonus, position);
engine.spawn(bonus);
case GameEvent.DESTROY(TANK(id, _)):
engine.destroy(id);
case GameEvent.DESTROY(BONUS(id, _)):
engine.destroy(id);
case GameEvent.DESTROY(BULLET(id)):
engine.destroy(id);
case GameEvent.DESTROY(CELL(cellX, cellY, _)):
engine.destroyCell(cellX, cellY);
case GameEvent.ACTION(tankId, MOVE(direction)):
engine.move(tankId, direction);
case GameEvent.ACTION(tankId, STOP):
engine.stop(tankId);
player.tankId = id;
player.state.tank = info.type;
case _:
}
}

View File

@@ -5,11 +5,17 @@ import ru.m.geom.Rectangle;
import ru.m.tankz.control.Control;
import ru.m.tankz.Type;
typedef TankInfo = {
var type:TankType;
var hits:Int;
var bonus:Bool;
}
enum SpawnEvent {
EAGLE(id:Int, rect:Rectangle, teamId:TeamId);
TANK(id:Int, position:Position, playerId:PlayerId, type:TankType);
BULLET(id:Int, position:Position, playerId:PlayerId);
BONUS(id:Int, position:Position, type:BonusType);
TANK(id:Int, rect:Rectangle, playerId:PlayerId, info:TankInfo);
BULLET(id:Int, rect:Rectangle, playerId:PlayerId, piercing:Int);
BONUS(id:Int, rect:Rectangle, type:BonusType);
}
typedef Shot = {

View File

@@ -1,10 +1,9 @@
package ru.m.tankz.game;
import ru.m.geom.Rectangle;
import ru.m.geom.Direction;
import haxe.ds.Option;
import haxe.Timer;
import haxework.signal.Signal;
import ru.m.geom.Direction;
import ru.m.geom.Line;
import ru.m.geom.Point;
import ru.m.geom.Position;
@@ -29,9 +28,11 @@ class GameRunner implements EngineListener implements GameListener {
private var gameEventSignal(get, null):Signal<GameEvent>;
private var entityId:Int;
private var timer:Timer;
private var builder:EntityBuilder;
public function new(game:IGame) {
this.game = game;
this.builder = new EntityBuilder(this.game.config);
this.game.connect(this);
this.game.engine.connect(this);
this.entityId = 0;
@@ -79,10 +80,9 @@ class GameRunner implements EngineListener implements GameListener {
}
if (team.config.eagle != null) {
var point = game.config.getPoint(team.id, "eagle");
var position = pointToPosition(point);
var rect = new Rectangle(0, 0, 44, 44);
rect.center = new Point(position.x, position.y);
gameEventSignal.emit(GameEvent.SPAWN(EAGLE(++entityId, rect, team.id)));
var eagle = builder.buildEagle(++entityId, point, team.id);
game.engine.spawn(eagle);
gameEventSignal.emit(GameEvent.SPAWN(EAGLE(eagle.id, eagle.rect, eagle.team)));
}
}
gameEventSignal.emit(GameEvent.START(state));
@@ -100,7 +100,9 @@ class GameRunner implements EngineListener implements GameListener {
}
private function spawn(task:SpawnTask):Void {
gameEventSignal.emit(GameEvent.SPAWN(TANK(++entityId, pointToPosition(task.point), task.playerId, task.tankType)));
var tank = builder.buildTank(++entityId, task.point, task.playerId, task.tankType);
game.engine.spawn(tank);
gameEventSignal.emit(GameEvent.SPAWN(TANK(tank.id, tank.rect, tank.playerId, {type:tank.config.type, hits:tank.hits, bonus:tank.bonus})));
}
private function checkComplete():Void {
@@ -176,6 +178,7 @@ class GameRunner implements EngineListener implements GameListener {
gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet.id)));
gameEventSignal.emit(GameEvent.DESTROY(BULLET(other_bullet.id)));
case [BULLET(bullet), CELL(cell)]:
bullet.rect.lean(cell.rect);
gameEventSignal.emit(GameEvent.HIT(CELL(cell.cellX, cell.cellY, buildShot(bullet))));
gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet.id)));
case [TANK(tank), BONUS(bonus)]:
@@ -236,7 +239,9 @@ class GameRunner implements EngineListener implements GameListener {
y: Math.floor(Math.random() * (game.engine.map.gridHeight - 1)),
direction: "right",
}
gameEventSignal.emit(GameEvent.SPAWN(BONUS(++entityId, pointToPosition(point), type)));
var bonus = builder.buildBonus(++entityId, point, type);
game.engine.spawn(bonus);
gameEventSignal.emit(GameEvent.SPAWN(BONUS(bonus.id, bonus.rect, bonus.config.type)));
}
private inline function alienTank(team:TeamId):Tank->Bool {
@@ -322,18 +327,20 @@ class GameRunner implements EngineListener implements GameListener {
if (!tank.freezing.active && player.bullets < tank.config.bullets) {
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,
}
gameEventSignal.emit(GameEvent.SPAWN(BULLET(++entityId, position, tank.playerId)));
var bullet = builder.buildBullet(++entityId, point, rect.direction, player.id, tank.config.type);
bullet.tank = tank;
bullet.move(bullet.rect.direction);
game.engine.spawn(bullet);
gameEventSignal.emit(GameEvent.SPAWN(BULLET(bullet.id, bullet.rect, bullet.playerId, bullet.config.piercing)));
}
case GameEvent.ACTION(tankId, MOVE(direction)):
game.engine.move(tankId, direction);
case GameEvent.ACTION(tankId, STOP):
gameEventSignal.emit(GameEvent.STOP(TANK(tankId)));
game.engine.stop(tankId);
case GameEvent.SPAWN(TANK(_, _, playerId, _)):
game.getPlayer(playerId).control.start();
case GameEvent.SPAWN(BULLET(_, _, playerId)):
case GameEvent.SPAWN(BULLET(_, _, playerId, _)):
game.getPlayer(playerId).bullets++;
case GameEvent.DESTROY(EAGLE(id, shot)):
var eagle:Eagle = game.engine.getEntity(id);
@@ -369,6 +376,7 @@ class GameRunner implements EngineListener implements GameListener {
var shooterTank:Tank = game.engine.getEntity(shot.tankId);
changeScore(shooterTank.playerId, shot.score);
}
game.engine.destroy(id);
case GameEvent.DESTROY(BONUS(id, shot)):
var bonus:Bonus = game.engine.getEntity(id);
var tank:Tank = game.engine.getEntity(shot.tankId);
@@ -376,24 +384,31 @@ class GameRunner implements EngineListener implements GameListener {
if (shot.score != 0) {
changeScore(tank.playerId, shot.score);
}
game.engine.destroy(id);
case GameEvent.DESTROY(BULLET(id)):
var bullet:Bullet = game.engine.getEntity(id);
var player = game.getPlayer(bullet.playerId);
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(
// ToDo: move
new Point(bullet.rect.direction.x * 5, bullet.rect.direction.y * 5)
);
var cells = game.engine.map.grid.getCells(side.setLength(game.engine.map.grid.cellWidth * 3));
for (cell in cells) {
if (cell.armor > 0) {
if (cell.armor == bullet.config.piercing) {
game.engine.destroyCell(cell.cellX, cell.cellY);
gameEventSignal.emit(GameEvent.DESTROY(CELL(cell.cellX, cell.cellY, buildShot(bullet))));
} else if (cell.armor < bullet.config.piercing) {
var brick = game.engine.map.getBrick(cell.position);
for (cell in brick.cells) {
game.engine.destroyCell(cell.cellX, cell.cellY);
gameEventSignal.emit(GameEvent.DESTROY(CELL(cell.cellX, cell.cellY, buildShot(bullet))));
}
}
}
}
game.engine.destroy(id);
case _:
}
}

View File

@@ -1,10 +1,10 @@
package ru.m.tankz.map;
import ru.m.tankz.map.Grid.GridCell;
import ru.m.geom.Rectangle;
import haxe.ds.HashMap;
import ru.m.geom.Point;
import ru.m.geom.Rectangle;
import ru.m.tankz.config.Config;
import ru.m.tankz.map.Grid.GridCell;
class Brick {
public var id(get, null):Int;