[render] bricks and cells from GameEvent

This commit is contained in:
2019-05-17 12:55:32 +03:00
parent 3c116db135
commit 96e608c36f
5 changed files with 106 additions and 41 deletions

View File

@@ -11,8 +11,8 @@ import promhx.Promise;
import ru.m.animate.Animate; import ru.m.animate.Animate;
import ru.m.animate.OnceAnimate; import ru.m.animate.OnceAnimate;
import ru.m.geom.Point; import ru.m.geom.Point;
import ru.m.tankz.config.Config;
import ru.m.tankz.core.EntityType; import ru.m.tankz.core.EntityType;
import ru.m.tankz.engine.IEngine;
import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.IGame; import ru.m.tankz.game.IGame;
import ru.m.tankz.render.item.BonusRenderItem; import ru.m.tankz.render.item.BonusRenderItem;
@@ -57,13 +57,15 @@ class Render extends SpriteView implements IRender implements GameListener {
return game; return game;
} }
private function drawBackground(engine:IEngine):Void { private function drawBackground(config:Config):Void {
var width = config.map.cellWidth * config.map.gridWidth;
var height = config.map.cellHeight * config.map.gridHeight;
var g:Graphics = backgroundLayer.graphics; var g:Graphics = backgroundLayer.graphics;
g.clear(); g.clear();
g.beginFill(0x000000); g.beginFill(0x000000);
g.drawRect(0, 0, engine.map.width, engine.map.height); g.drawRect(0, 0, width, height);
g.endFill(); g.endFill();
setContentSize(engine.map.width, engine.map.height); setContentSize(width, height);
} }
public function draw():Void { public function draw():Void {
@@ -71,7 +73,7 @@ class Render extends SpriteView implements IRender implements GameListener {
item.update(); item.update();
} }
if (background == null) { if (background == null) {
drawBackground(game.engine); drawBackground(game.config);
} }
} }
@@ -102,18 +104,20 @@ class Render extends SpriteView implements IRender implements GameListener {
public function onGameEvent(event:GameEvent):Void { public function onGameEvent(event:GameEvent):Void {
switch event { switch event {
case START(_): case START(_):
for (brick in game.engine.map.bricks) { content.addEventListener(Event.ENTER_FRAME, onEnterFrame);
var item:IRenderItem = new BrickRenderItem(brick); case COMPLETE(_, _):
content.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
case SPAWN(BRICK(bricks)):
for (brick in bricks) {
var item:IRenderItem = new BrickRenderItem(brick.rect, brick.type);
var config = game.config.getBrick(brick.type);
items[brick.id] = item; items[brick.id] = item;
if (brick.config.layer > 2) { if (config.layer > 2) {
upLayer.addChild(item.view); upLayer.addChild(item.view);
} else { } else {
groundLayer.addChild(item.view); groundLayer.addChild(item.view);
} }
} }
content.addEventListener(Event.ENTER_FRAME, onEnterFrame);
case COMPLETE(_, _):
content.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
case SPAWN(EAGLE(id, rect, teamId)): case SPAWN(EAGLE(id, rect, teamId)):
var item = new EagleRenderItem(rect); var item = new EagleRenderItem(rect);
items.set(id, item); items.set(id, item);
@@ -201,11 +205,12 @@ class Render extends SpriteView implements IRender implements GameListener {
} }
items.remove(id); items.remove(id);
} }
case DESTROY(CELL(cellX, cellY, shot)): case DESTROY(CELL(id, x, y, shot)):
// ToDo: redraw only cell? var item:BrickRenderItem = cast items.get(id);
var brick = game.engine.map.getBrick(new Point(cellX, cellY)); item.destroyCell(x, y);
var item:BrickRenderItem = cast items[brick.id]; case DESTROY(BRICK(id, shot)):
item.redraw(brick); var item:BrickRenderItem = cast items.get(id);
item.destroy();
case _: case _:
} }
} }

View File

@@ -1,27 +1,50 @@
package ru.m.tankz.render.item; package ru.m.tankz.render.item;
import ru.m.geom.Point;
import flash.display.BitmapData; import flash.display.BitmapData;
import flash.display.Shape; import flash.display.Shape;
import openfl.Assets; import openfl.Assets;
import openfl.display.DisplayObject; import openfl.display.DisplayObject;
import ru.m.tankz.map.Brick; import ru.m.geom.Rectangle;
import ru.m.tankz.Type.BrickType; import ru.m.tankz.Type.BrickType;
enum BrickState {
UNBROKEN;
BROKEN;
DESTROYED;
}
class BrickRenderItem extends RenderItem { class BrickRenderItem extends RenderItem {
public var type(default, set):BrickType; public var type(default, set):BrickType;
public var state(get, never):BrickState;
private var image:BitmapData; private var image:BitmapData;
private var shape:Shape; private var shape:Shape;
private var cells:Array<Point>;
public function new(brick:Brick) { public function new(rect:Rectangle, type:BrickType) {
super(brick.rect); super(rect);
this.shape = new Shape(); this.shape = new Shape();
this.type = brick.config.type; this.type = type;
redraw(brick); cells = [
new Point(0, 0),
new Point(0, 1),
new Point(1, 0),
new Point(1, 1),
];
redraw();
move(rect.position); move(rect.position);
} }
private function get_state():BrickState {
return switch cells.length {
case 0: DESTROYED;
case 4: UNBROKEN;
case _: BROKEN;
}
}
override private function get_view():DisplayObject { override private function get_view():DisplayObject {
return shape; return shape;
} }
@@ -34,21 +57,34 @@ class BrickRenderItem extends RenderItem {
return type; return type;
} }
public function redraw(brick:Brick):Void { public function destroyCell(x:Int, y:Int):Void {
cells = cells.filter(function(point) return !(point.x == x && point.y == y));
redraw();
}
public function destroy():Void {
cells = [];
redraw();
}
public function redraw():Void {
shape.graphics.clear(); shape.graphics.clear();
if (brick.destroyed) return; switch state {
if (brick.config.index > 0) { case UNBROKEN:
shape.graphics.beginBitmapFill(image); shape.graphics.beginBitmapFill(image);
if (brick.broken == 0) { shape.graphics.drawRect(0, 0, rect.width, rect.height);
shape.graphics.drawRect(0, 0, brick.rect.width, brick.rect.height); shape.graphics.endFill();
} else { case BROKEN:
for (c in brick.cells) { shape.graphics.beginBitmapFill(image);
if (!c.destroyed) { for (point in cells) {
shape.graphics.drawRect(c.rect.x - brick.rect.x, c.rect.y - brick.rect.y, c.rect.width, c.rect.height); var x = point.x * (rect.width / 2);
} var y = point.y * (rect.width / 2);
var width = rect.width / 2;
var height = rect.height / 2;
shape.graphics.drawRect(x, y, width, height);
} }
} shape.graphics.endFill();
shape.graphics.endFill(); case DESTROYED:
} }
} }
} }

View File

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

View File

@@ -11,7 +11,16 @@ typedef TankInfo = {
var bonus:Bool; var bonus:Bool;
} }
typedef BrickInfo = {
var id:Int;
var x:Int;
var y:Int;
var rect:Rectangle;
var type:BrickType;
}
enum SpawnEvent { enum SpawnEvent {
BRICK(bricks:Array<BrickInfo>);
EAGLE(id:Int, rect:Rectangle, teamId:TeamId); EAGLE(id:Int, rect:Rectangle, teamId:TeamId);
TANK(id:Int, rect:Rectangle, playerId:PlayerId, info:TankInfo); TANK(id:Int, rect:Rectangle, playerId:PlayerId, info:TankInfo);
BULLET(id:Int, rect:Rectangle, playerId:PlayerId, piercing:Int); BULLET(id:Int, rect:Rectangle, playerId:PlayerId, piercing:Int);
@@ -34,7 +43,8 @@ enum DestroyEvent {
TANK(id:Int, shot:Shot); TANK(id:Int, shot:Shot);
BONUS(id:Int, shot:Shot); BONUS(id:Int, shot:Shot);
BULLET(id:Int); BULLET(id:Int);
CELL(cellX:Int, cellY:Int, shot:Shot); CELL(id:Int, x:Int, y:Int, shot:Shot);
BRICK(id:Int, shot:Shot);
} }
enum MoveEvent { enum MoveEvent {

View File

@@ -1,5 +1,7 @@
package ru.m.tankz.game; package ru.m.tankz.game;
import ru.m.tankz.map.Grid.GridCell;
import ru.m.tankz.map.Brick;
import haxe.ds.Option; import haxe.ds.Option;
import haxe.Timer; import haxe.Timer;
import haxework.signal.Signal; import haxework.signal.Signal;
@@ -85,6 +87,16 @@ class GameRunner implements EngineListener implements GameListener {
gameEventSignal.emit(GameEvent.SPAWN(EAGLE(eagle.id, eagle.rect, eagle.team))); gameEventSignal.emit(GameEvent.SPAWN(EAGLE(eagle.id, eagle.rect, eagle.team)));
} }
} }
var bricks = game.engine.map.bricks.map(function(item:Brick):BrickInfo {
return {
id: item.id,
x: item.cellY,
y: item.cellY,
rect: item.rect,
type: item.config.type,
}
});
gameEventSignal.emit(GameEvent.SPAWN(BRICK(bricks)));
gameEventSignal.emit(GameEvent.START(state)); gameEventSignal.emit(GameEvent.START(state));
} }
@@ -102,7 +114,7 @@ class GameRunner implements EngineListener implements GameListener {
private function spawn(task:SpawnTask):Void { private function spawn(task:SpawnTask):Void {
var tank = builder.buildTank(++entityId, task.point, task.playerId, task.tankType); var tank = builder.buildTank(++entityId, task.point, task.playerId, task.tankType);
game.engine.spawn(tank); 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}))); gameEventSignal.emit(GameEvent.SPAWN(TANK(tank.id, tank.rect.clone(), tank.playerId, {type:tank.config.type, hits:tank.hits, bonus:tank.bonus})));
} }
private function checkComplete():Void { private function checkComplete():Void {
@@ -241,7 +253,7 @@ class GameRunner implements EngineListener implements GameListener {
} }
var bonus = builder.buildBonus(++entityId, point, type); var bonus = builder.buildBonus(++entityId, point, type);
game.engine.spawn(bonus); game.engine.spawn(bonus);
gameEventSignal.emit(GameEvent.SPAWN(BONUS(bonus.id, bonus.rect, bonus.config.type))); gameEventSignal.emit(GameEvent.SPAWN(BONUS(bonus.id, bonus.rect.clone(), bonus.config.type)));
} }
private inline function alienTank(team:TeamId):Tank->Bool { private inline function alienTank(team:TeamId):Tank->Bool {
@@ -331,7 +343,7 @@ class GameRunner implements EngineListener implements GameListener {
bullet.tank = tank; bullet.tank = tank;
bullet.move(bullet.rect.direction); bullet.move(bullet.rect.direction);
game.engine.spawn(bullet); game.engine.spawn(bullet);
gameEventSignal.emit(GameEvent.SPAWN(BULLET(bullet.id, bullet.rect, bullet.playerId, bullet.config.piercing))); gameEventSignal.emit(GameEvent.SPAWN(BULLET(bullet.id, bullet.rect.clone(), bullet.playerId, bullet.config.piercing)));
} }
case GameEvent.ACTION(tankId, MOVE(direction)): case GameEvent.ACTION(tankId, MOVE(direction)):
game.engine.move(tankId, direction); game.engine.move(tankId, direction);
@@ -396,15 +408,17 @@ class GameRunner implements EngineListener implements GameListener {
var cells = game.engine.map.grid.getCells(side.setLength(game.engine.map.grid.cellWidth * 3)); var cells = game.engine.map.grid.getCells(side.setLength(game.engine.map.grid.cellWidth * 3));
for (cell in cells) { for (cell in cells) {
if (cell.armor > 0) { if (cell.armor > 0) {
var shot = buildShot(bullet);
if (cell.armor == bullet.config.piercing) { if (cell.armor == bullet.config.piercing) {
game.engine.destroyCell(cell.cellX, cell.cellY); game.engine.destroyCell(cell.cellX, cell.cellY);
gameEventSignal.emit(GameEvent.DESTROY(CELL(cell.cellX, cell.cellY, buildShot(bullet)))); var brick = game.engine.map.getBrick(cell.position);
gameEventSignal.emit(GameEvent.DESTROY(CELL(brick.id, cell.cellX - brick.cellX * 2, cell.cellY - brick.cellY * 2, shot)));
} else if (cell.armor < bullet.config.piercing) { } else if (cell.armor < bullet.config.piercing) {
var brick = game.engine.map.getBrick(cell.position); var brick = game.engine.map.getBrick(cell.position);
for (cell in brick.cells) { for (cell in brick.cells) {
game.engine.destroyCell(cell.cellX, cell.cellY); game.engine.destroyCell(cell.cellX, cell.cellY);
gameEventSignal.emit(GameEvent.DESTROY(CELL(cell.cellX, cell.cellY, buildShot(bullet))));
} }
gameEventSignal.emit(GameEvent.DESTROY(BRICK(brick.id, shot)));
} }
} }
} }