[common] add ICaller; [client] rework BrickRenderItem
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
package ru.m.tankz.local;
|
||||
|
||||
import flash.events.Event;
|
||||
import flash.Lib;
|
||||
import ru.m.tankz.control.HumanControl;
|
||||
import ru.m.tankz.game.GameEvent;
|
||||
import ru.m.tankz.game.GameRunner;
|
||||
@@ -13,25 +11,15 @@ class LocalGame extends GameRunner {
|
||||
|
||||
@:provide static var gameStorage:GameStorage;
|
||||
|
||||
private var updateEvent:String;
|
||||
|
||||
public function new(start:Start) {
|
||||
super(start);
|
||||
controlFactory = new LocalControlFactory();
|
||||
updateEvent = Event.ENTER_FRAME;
|
||||
}
|
||||
|
||||
private function onUpdateEvent(_):Void {
|
||||
update();
|
||||
}
|
||||
|
||||
override public function onGameEvent(event:GameEvent):Void {
|
||||
super.onGameEvent(event);
|
||||
switch event {
|
||||
case START(_):
|
||||
Lib.current.stage.addEventListener(updateEvent, onUpdateEvent);
|
||||
case COMPLETE(result):
|
||||
Lib.current.stage.removeEventListener(updateEvent, onUpdateEvent);
|
||||
updateProgress(result);
|
||||
case _:
|
||||
}
|
||||
@@ -51,9 +39,4 @@ class LocalGame extends GameRunner {
|
||||
gameStorage.set(progress);
|
||||
}
|
||||
}
|
||||
|
||||
override public function dispose():Void {
|
||||
super.dispose();
|
||||
Lib.current.stage.removeEventListener(updateEvent, onUpdateEvent);
|
||||
}
|
||||
}
|
||||
|
||||
31
src/client/haxe/ru/m/tankz/local/StageCaller.hx
Normal file
31
src/client/haxe/ru/m/tankz/local/StageCaller.hx
Normal file
@@ -0,0 +1,31 @@
|
||||
package ru.m.tankz.local;
|
||||
|
||||
import flash.display.Stage;
|
||||
import flash.events.Event;
|
||||
import ru.m.tankz.engine.ICaller;
|
||||
|
||||
class StageCaller implements ICaller {
|
||||
|
||||
private var stage:Stage;
|
||||
private var event:String;
|
||||
private var calback:Void -> Void;
|
||||
|
||||
public function new(stage:Stage, ?event:String) {
|
||||
this.stage = stage;
|
||||
this.event = event != null ? event : Event.ENTER_FRAME;
|
||||
}
|
||||
|
||||
private function onEvent(_):Void {
|
||||
calback();
|
||||
}
|
||||
|
||||
public function start(calback:Void -> Void):Void {
|
||||
this.calback = calback;
|
||||
stage.addEventListener(event, onEvent);
|
||||
}
|
||||
|
||||
public function stop():Void {
|
||||
stage.removeEventListener(event, onEvent);
|
||||
calback = null;
|
||||
}
|
||||
}
|
||||
@@ -1,62 +1,77 @@
|
||||
package ru.m.tankz.render.item;
|
||||
|
||||
import flash.display.BitmapData;
|
||||
import flash.display.Shape;
|
||||
import openfl.Assets;
|
||||
import openfl.display.DisplayObject;
|
||||
import ru.m.geom.Point;
|
||||
import ru.m.geom.GridPoint;
|
||||
import ru.m.geom.Rectangle;
|
||||
import ru.m.tankz.Type.BrickType;
|
||||
import ru.m.tankz.Type;
|
||||
|
||||
enum BrickState {
|
||||
UNBROKEN;
|
||||
BROKEN;
|
||||
DESTROYED;
|
||||
class BrickBitmapBundle {
|
||||
|
||||
private var data:Map<String, BitmapData>;
|
||||
|
||||
public function new() {
|
||||
data = new Map();
|
||||
}
|
||||
|
||||
private function resolve(type:BrickType, cells:Array<GridPoint>):BitmapData {
|
||||
return switch cells.length {
|
||||
case 0:
|
||||
Assets.getBitmapData('resources/image/map/none.png');
|
||||
case 4:
|
||||
Assets.getBitmapData('resources/image/map/${type}.png');
|
||||
case _:
|
||||
var image = Assets.getBitmapData('resources/image/map/${type}.png');
|
||||
var result = new BitmapData(image.width, image.height, true, 0x00000000);
|
||||
for (point in cells) {
|
||||
var rect = new flash.geom.Rectangle(
|
||||
point.x * image.width / 2,
|
||||
point.y * image.height / 2,
|
||||
image.width / 2,
|
||||
image.height / 2);
|
||||
result.draw(image, null, null, null, rect);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public function get(type:BrickType, cells:Array<GridPoint>):BitmapData {
|
||||
var key:String = '${type}_${cells.map(function(point) return point.toString()).join(",")}';
|
||||
if (!data.exists(key)) {
|
||||
data.set(key, resolve(type, cells));
|
||||
}
|
||||
return data.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
class BrickRenderItem extends RenderItem {
|
||||
class BrickRenderItem extends BitmapRenderItem {
|
||||
|
||||
private static var bundle:BrickBitmapBundle = new BrickBitmapBundle();
|
||||
|
||||
public var type(default, set):BrickType;
|
||||
public var state(get, never):BrickState;
|
||||
|
||||
private var image:BitmapData;
|
||||
private var shape:Shape;
|
||||
private var cells:Array<Point>;
|
||||
private var cells:Array<GridPoint>;
|
||||
|
||||
private static function buildCells():Array<Point> {
|
||||
private static function buildCells():Array<GridPoint> {
|
||||
return [
|
||||
new Point(0, 0),
|
||||
new Point(0, 1),
|
||||
new Point(1, 0),
|
||||
new Point(1, 1),
|
||||
new GridPoint(0, 0),
|
||||
new GridPoint(0, 1),
|
||||
new GridPoint(1, 0),
|
||||
new GridPoint(1, 1),
|
||||
];
|
||||
}
|
||||
|
||||
public function new(rect:Rectangle, type:BrickType) {
|
||||
super(rect);
|
||||
this.shape = new Shape();
|
||||
cells = buildCells();
|
||||
this.type = type;
|
||||
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 {
|
||||
return shape;
|
||||
}
|
||||
|
||||
private function set_type(value:BrickType):BrickType {
|
||||
if (type != value) {
|
||||
type = value;
|
||||
cells = buildCells();
|
||||
image = Assets.getBitmapData('resources/image/map/${type}.png');
|
||||
redraw();
|
||||
}
|
||||
return type;
|
||||
@@ -73,24 +88,6 @@ class BrickRenderItem extends RenderItem {
|
||||
}
|
||||
|
||||
public function redraw():Void {
|
||||
shape.graphics.clear();
|
||||
if (type == "none") return;
|
||||
switch state {
|
||||
case UNBROKEN:
|
||||
shape.graphics.beginBitmapFill(image);
|
||||
shape.graphics.drawRect(0, 0, rect.width, rect.height);
|
||||
shape.graphics.endFill();
|
||||
case BROKEN:
|
||||
shape.graphics.beginBitmapFill(image);
|
||||
for (point in cells) {
|
||||
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();
|
||||
case DESTROYED:
|
||||
}
|
||||
image = bundle.get(type, cells);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,4 +20,8 @@ abstract GridPoint({x:Int, y:Int}) {
|
||||
@:to inline public function toPoint():Point {
|
||||
return new Point(this.x, this.y);
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
return '${this.x}:${this.y}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package ru.m.tankz.core;
|
||||
|
||||
abstract TimeInterval(Array<Int>) {
|
||||
|
||||
public function new(min:Int, ?max:Null<Int>) {
|
||||
this = [min, max != null ? max : min]
|
||||
}
|
||||
|
||||
public function resolve():Int {
|
||||
return this[0] + (this[1] - this[0]) * Math.random();
|
||||
}
|
||||
|
||||
@:from public static function fromArray(value:Array<Int>):TimeInterval {
|
||||
return new TimeInterval(value[0], value[1]);
|
||||
}
|
||||
|
||||
@:from public static function fromInt(value:Int):TimeInterval {
|
||||
return new TimeInterval(value);
|
||||
}
|
||||
|
||||
@:from public static function fromFloat(value:Float):TimeInterval {
|
||||
return new TimeInterval(value * 1000);
|
||||
}
|
||||
}
|
||||
6
src/common/haxe/ru/m/tankz/engine/ICaller.hx
Normal file
6
src/common/haxe/ru/m/tankz/engine/ICaller.hx
Normal file
@@ -0,0 +1,6 @@
|
||||
package ru.m.tankz.engine;
|
||||
|
||||
interface ICaller {
|
||||
public function start(calback:Void -> Void):Void;
|
||||
public function stop():Void;
|
||||
}
|
||||
24
src/common/haxe/ru/m/tankz/engine/TimerCaller.hx
Normal file
24
src/common/haxe/ru/m/tankz/engine/TimerCaller.hx
Normal file
@@ -0,0 +1,24 @@
|
||||
package ru.m.tankz.engine;
|
||||
|
||||
class TimerCaller implements ICaller {
|
||||
|
||||
private var interval:Int;
|
||||
private var timer:Timer;
|
||||
|
||||
public function new(interval:Int = 30) {
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
public function start(calback:Void -> Void):Void {
|
||||
stop();
|
||||
timer = new Timer(interval);
|
||||
timer.run = calback;
|
||||
}
|
||||
|
||||
public function stop():Void {
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,9 @@ import ru.m.tankz.core.EntityType;
|
||||
import ru.m.tankz.core.Tank;
|
||||
import ru.m.tankz.core.Weapon;
|
||||
import ru.m.tankz.engine.Engine;
|
||||
import ru.m.tankz.engine.ICaller;
|
||||
import ru.m.tankz.engine.IEngine;
|
||||
import ru.m.tankz.engine.TimerCaller;
|
||||
import ru.m.tankz.game.GameEvent;
|
||||
import ru.m.tankz.game.GameState;
|
||||
import ru.m.tankz.game.Spawner;
|
||||
@@ -20,11 +22,14 @@ import ru.m.tankz.Type;
|
||||
using ru.m.tankz.game.GameUtil;
|
||||
|
||||
class GameRunner extends Game implements EngineListener {
|
||||
private var updater:ICaller;
|
||||
|
||||
private var builder:EntityBuilder;
|
||||
private var bonuses:BonusFactory;
|
||||
|
||||
public function new(start:Start) {
|
||||
public function new(start:Start, ?updater:ICaller) {
|
||||
super(start.state.type);
|
||||
this.updater = updater != null ? updater : new TimerCaller();
|
||||
this.level = start.level;
|
||||
this.state = start.state;
|
||||
builder = new EntityBuilder(config);
|
||||
@@ -52,15 +57,12 @@ class GameRunner extends Game implements EngineListener {
|
||||
override public function start():Void {
|
||||
super.start();
|
||||
gameEventSignal.emit(START({level:level, state:state}));
|
||||
updater.start(update);
|
||||
}
|
||||
|
||||
override public function dispose():Void {
|
||||
super.dispose();
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
timer = null;
|
||||
}
|
||||
engine.dispose();
|
||||
updater.stop();
|
||||
}
|
||||
|
||||
public function newPlayerTank(playerId:PlayerId):TankInfo {
|
||||
@@ -277,6 +279,7 @@ class GameRunner extends Game implements EngineListener {
|
||||
engine.ticker.start();
|
||||
case COMPLETE(_):
|
||||
engine.ticker.stop();
|
||||
updater.stop();
|
||||
case ACTION(tankId, SHOT(index)):
|
||||
var tank:Tank = cast engine.entities.get(tankId);
|
||||
var player = getPlayer(tank.playerId);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package ru.m.tankz.server.game;
|
||||
|
||||
import ru.m.tankz.control.Controller;
|
||||
import ru.m.tankz.bundle.ILevelBundle;
|
||||
import ru.m.tankz.control.Controller;
|
||||
import ru.m.tankz.control.PlayerControl;
|
||||
import ru.m.tankz.core.EntityType;
|
||||
import ru.m.tankz.game.EventUtil;
|
||||
@@ -38,19 +38,6 @@ class ServerGame extends GameRunner {
|
||||
return room.game.id;
|
||||
}
|
||||
|
||||
override public function onGameEvent(event:GameEvent):Void {
|
||||
switch event {
|
||||
case START(_):
|
||||
timer = new Timer(30);
|
||||
timer.run = update;
|
||||
case COMPLETE(_):
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function contains(user:UserProto):Bool {
|
||||
for (slot in room.slots) {
|
||||
if (slot.hasUser() && slot.user.uuid == user.uuid) {
|
||||
@@ -103,14 +90,6 @@ class ServerGame extends GameRunner {
|
||||
super.start();
|
||||
}
|
||||
|
||||
override public function dispose():Void {
|
||||
super.dispose();
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public function restore():Array<GameEvent> {
|
||||
var result = [];
|
||||
result.push(EventUtil.buildBricksSpawn(engine.map));
|
||||
|
||||
Reference in New Issue
Block a user