[refactor] GameEvent

This commit is contained in:
2020-02-03 22:44:52 +03:00
parent 05d02b44c7
commit 71d765c231
16 changed files with 136 additions and 90 deletions

View File

@@ -0,0 +1,7 @@
package ru.m.puzzlez.core;
enum BoundType {
NONE;
OUT;
IN;
}

View File

@@ -2,6 +2,8 @@ package ru.m.puzzlez.core;
import flash.geom.Point; import flash.geom.Point;
import haxework.signal.Signal; import haxework.signal.Signal;
import ru.m.puzzlez.core.GameEvent;
import ru.m.puzzlez.core.PartLocation;
class Game implements IGame { class Game implements IGame {
public var state(default, null):GameState; public var state(default, null):GameState;
@@ -26,11 +28,14 @@ class Game implements IGame {
public function shuffle():Void { public function shuffle():Void {
for (part in state.parts) { for (part in state.parts) {
if (!part.completed) { switch part.location {
var bound = part.rect.width * 0.25; case TABLE(_):
part.rect.x = bound + Math.random() * (state.preset.tableRect.width - part.rect.width - bound * 2); var bound = part.rect.width * 0.25;
part.rect.y = bound + Math.random() * (state.preset.tableRect.height - part.rect.height - bound * 2); var x = bound + Math.random() * (state.preset.tableRect.width - part.rect.width - bound * 2);
signal.emit(GameEvent.PART_MOVED(part.id, part.rect.topLeft)); var y = bound + Math.random() * (state.preset.tableRect.height - part.rect.height - bound * 2);
part.location = TABLE(new Point(x, y));
signal.emit(CHANGE(PART_UPDATE(part.id, part.location)));
case _:
} }
} }
} }
@@ -42,19 +47,21 @@ class Game implements IGame {
private function onGameEvent(event:GameEvent):Void { private function onGameEvent(event:GameEvent):Void {
switch event { switch event {
case GameEvent.PART_MOVE(id, position): case ACTION(PART_MOVE(id, point)):
var part = partsById[id]; var part = partsById[id];
part.rect.topLeft = position; part.location = TABLE(point);
signal.emit(GameEvent.PART_MOVED(id, position)); signal.emit(CHANGE(PART_UPDATE(id, part.location)));
case GameEvent.PART_PUT(id, position): case ACTION(PART_PUT(id, point)):
var part = partsById[id]; var part:Part = partsById[id];
var d = distance(part.position, position); var target:Point = state.preset.imageRect.topLeft.clone();
target = target.add(new Point(part.gridX * part.rect.width, part.gridY * part.rect.height));
var d = distance(target, point);
if (d < 70) { if (d < 70) {
part.completed = true; part.location = IMAGE;
part.rect.topLeft = part.position; signal.emit(CHANGE(PART_UPDATE(id, part.location)));
signal.emit(GameEvent.PART_COMPLETED(id, part.position));
} else { } else {
signal.emit(GameEvent.PART_MOVED(id, position)); part.location = TABLE(point);
signal.emit(CHANGE(PART_UPDATE(id, part.location)));
} }
case _: case _:
} }

View File

@@ -2,10 +2,19 @@ package ru.m.puzzlez.core;
import flash.geom.Point; import flash.geom.Point;
enum GameAction {
PART_TAKE(id:Int);
PART_MOVE(id:Int, point:Point);
PART_PUT(id:Int, point:Point);
}
enum GameChange {
PART_UPDATE(id:Int, location:PartLocation);
}
enum GameEvent { enum GameEvent {
START(state:GameState); START(state:GameState);
PART_MOVE(id:Int, position:Point); ACTION(action:GameAction);
PART_PUT(id:Int, position:Point); CHANGE(change:GameChange);
PART_MOVED(id:Int, position:Point); COMPLETE;
PART_COMPLETED(id:Int, position:Point);
} }

View File

@@ -1,9 +1,11 @@
package ru.m.puzzlez.core; package ru.m.puzzlez.core;
import ru.m.puzzlez.core.Id.ImageId;
import flash.geom.Point; import flash.geom.Point;
import flash.geom.Rectangle; import flash.geom.Rectangle;
import ru.m.puzzlez.core.BoundType;
import ru.m.puzzlez.core.Id;
import ru.m.puzzlez.core.Part; import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.core.Side;
class BoundsMap { class BoundsMap {
@@ -92,7 +94,7 @@ class GameUtil {
var boundsMap = new BoundsMap(preset.grid); var boundsMap = new BoundsMap(preset.grid);
for (y in 0...preset.grid.height) { for (y in 0...preset.grid.height) {
for (x in 0...preset.grid.width) { for (x in 0...preset.grid.width) {
var bounds:Bounds = { var bounds:PartBounds = {
left: boundsMap.getBound(x, y, LEFT), left: boundsMap.getBound(x, y, LEFT),
right: boundsMap.getBound(x, y, RIGHT), right: boundsMap.getBound(x, y, RIGHT),
top: boundsMap.getBound(x, y, TOP), top: boundsMap.getBound(x, y, TOP),
@@ -116,10 +118,9 @@ class GameUtil {
id: id, id: id,
gridX: x, gridX: x,
gridY: y, gridY: y,
position: position, location: PartLocation.TABLE(position),
rect: new Rectangle(position.x, position.y, partWidth, partHeight),
bounds: bounds, bounds: bounds,
completed: false, rect: new Rectangle(0, 0, partWidth, partHeight),
}); });
} }
} }

View File

@@ -7,7 +7,10 @@ interface IGame {
public var signal(default, null):Signal<GameEvent>; public var signal(default, null):Signal<GameEvent>;
public function start():Void; public function start():Void;
public function stop():Void; public function stop():Void;
public function shuffle():Void; public function shuffle():Void;
public function dispose():Void; public function dispose():Void;
} }

View File

@@ -4,9 +4,11 @@ typedef SourceId = String;
abstract ImageId({source:SourceId, id:String}) { abstract ImageId({source:SourceId, id:String}) {
public var source(get, never):SourceId; public var source(get, never):SourceId;
private inline function get_source():SourceId return this.source; private inline function get_source():SourceId return this.source;
public var id(get, never):String; public var id(get, never):String;
private inline function get_id():String return this.id; private inline function get_id():String return this.id;
public function new(source:SourceId, id:String) { public function new(source:SourceId, id:String) {

View File

@@ -1,27 +1,13 @@
package ru.m.puzzlez.core; package ru.m.puzzlez.core;
import flash.geom.Point;
import flash.geom.Rectangle; import flash.geom.Rectangle;
enum Side {
TOP;
LEFT;
RIGHT;
BOTTOM;
}
enum BoundType {
NONE;
OUT;
IN;
}
typedef PartBound = { typedef PartBound = {
var spike: BoundType; var spike:BoundType;
var side: BoundType; var side:BoundType;
} }
typedef Bounds = { typedef PartBounds = {
var left:PartBound; var left:PartBound;
var right:PartBound; var right:PartBound;
var top:PartBound; var top:PartBound;
@@ -32,8 +18,7 @@ typedef Part = {
var id:Int; var id:Int;
var gridX:Int; var gridX:Int;
var gridY:Int; var gridY:Int;
var position:Point; var location:PartLocation;
var bounds:PartBounds;
var rect:Rectangle; var rect:Rectangle;
var bounds:Bounds;
var completed:Bool;
} }

View File

@@ -0,0 +1,9 @@
package ru.m.puzzlez.core;
import flash.geom.Point;
enum PartLocation {
//PANEL(index:Int);
TABLE(point:Point);
IMAGE;
}

View File

@@ -0,0 +1,8 @@
package ru.m.puzzlez.core;
enum Side {
TOP;
LEFT;
RIGHT;
BOTTOM;
}

View File

@@ -5,12 +5,14 @@ import flash.display.BitmapData;
import flash.display.PixelSnapping; import flash.display.PixelSnapping;
import flash.display.Sprite; import flash.display.Sprite;
import flash.geom.Point; import flash.geom.Point;
import ru.m.puzzlez.core.Part;
class PartView extends Sprite { class PartView extends Sprite {
public var id(default, null):Int; public var id(default, null):Int;
public var position(default, set):Point; public var position(default, set):Point;
public var completed(default, default):Bool; public var completed(default, default):Bool;
public var target(default, null):Point;
private function set_position(value:Point):Point { private function set_position(value:Point):Point {
position = value.clone(); position = value.clone();
@@ -29,16 +31,14 @@ class PartView extends Sprite {
private var size:Point; private var size:Point;
public function new(id:Int, image:BitmapData, size:Point) { public function new(part:Part) {
super(); super();
#if !android #if !android
filters = RenderUtil.buildFilters(); filters = RenderUtil.buildFilters();
#end #end
this.id = id; this.id = part.id;
this.size = size; this.size = part.rect.size.clone();
if (image != null) { this.target = new Point(part.gridX * size.x, part.gridY * size.y);
this.image = image;
}
} }
private function redraw():Void { private function redraw():Void {
@@ -52,8 +52,13 @@ class PartView extends Sprite {
} }
} }
public static function factory(id:Int, image:BitmapData, size:Point):PartView { public function complete():Void {
return new SpritePartView(id, image, size); position = target;
completed = true;
}
public static function factory(part:Part):PartView {
return new SpritePartView(part);
} }
} }
@@ -70,9 +75,9 @@ class SpritePartView extends PartView {
class BitmapPartView extends PartView { class BitmapPartView extends PartView {
private var bitmap:Bitmap; private var bitmap:Bitmap;
public function new(id:Int, image:BitmapData, size:Point) { public function new(part) {
super(id, image, size); super(part);
bitmap = new Bitmap(image, PixelSnapping.AUTO, true); bitmap = new Bitmap(null, PixelSnapping.AUTO, true);
addChild(bitmap); addChild(bitmap);
} }

View File

@@ -12,6 +12,7 @@ import haxework.signal.Signal;
import haxework.view.SpriteView; import haxework.view.SpriteView;
import ru.m.puzzlez.core.GameEvent; import ru.m.puzzlez.core.GameEvent;
import ru.m.puzzlez.core.GameState; import ru.m.puzzlez.core.GameState;
import ru.m.puzzlez.core.PartLocation;
import ru.m.puzzlez.storage.ImageStorage; import ru.m.puzzlez.storage.ImageStorage;
class Render extends SpriteView implements IRender { class Render extends SpriteView implements IRender {
@@ -20,13 +21,13 @@ class Render extends SpriteView implements IRender {
public var scale(get, set):Float; public var scale(get, set):Float;
private function get_scale():Float { private function get_scale():Float {
return table.scaleX; return tableView.scaleX;
} }
private function set_scale(value:Float):Float { private function set_scale(value:Float):Float {
var result = table.scaleX = table.scaleY = value; var result = tableView.scaleX = tableView.scaleY = value;
table.x = (width - state.preset.tableRect.width * value) / 2; tableView.x = (width - state.preset.tableRect.width * value) / 2;
table.y = (height - state.preset.tableRect.height * value) / 2; tableView.y = (height - state.preset.tableRect.height * value) / 2;
//setSize(table.width, table.height, 'table'); //setSize(table.width, table.height, 'table');
return result; return result;
} }
@@ -35,7 +36,8 @@ class Render extends SpriteView implements IRender {
private var image:BitmapData; private var image:BitmapData;
private var progress:ProgressView; private var progress:ProgressView;
private var table:Sprite; private var tableView:Sprite;
private var imageView:Sprite;
private var parts:Map<Int, PartView>; private var parts:Map<Int, PartView>;
private var activePart:PartView; private var activePart:PartView;
private var activePoint:Point; private var activePoint:Point;
@@ -46,9 +48,11 @@ class Render extends SpriteView implements IRender {
super(); super();
progress = new ProgressView(); progress = new ProgressView();
signal = new Signal(); signal = new Signal();
table = new Sprite(); tableView = new Sprite();
table.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); tableView.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
content.addChild(table); imageView = new Sprite();
tableView.addChild(imageView);
content.addChild(tableView);
parts = new Map(); parts = new Map();
} }
@@ -56,14 +60,13 @@ class Render extends SpriteView implements IRender {
switch event { switch event {
case START(state): case START(state):
onStart(state); onStart(state);
case PART_MOVED(id, point): case CHANGE(PART_UPDATE(id, TABLE(point))):
var part:PartView = parts[id]; var part:PartView = parts[id];
part.position = point; part.position = point;
case PART_COMPLETED(id, point): case CHANGE(PART_UPDATE(id, IMAGE)):
var part:PartView = parts[id]; var part:PartView = parts[id];
part.position = point; part.complete();
part.completed = true; imageView.addChild(part);
table.setChildIndex(part, 0);
case _: case _:
} }
} }
@@ -72,18 +75,20 @@ class Render extends SpriteView implements IRender {
clean(); clean();
this.state = state; this.state = state;
for (part in state.parts) { for (part in state.parts) {
var partView = PartView.factory(part.id, null, part.rect.size); var partView = PartView.factory(part);
partView.position = part.rect.topLeft; partView.position = part.rect.topLeft;
parts.set(part.id, partView); parts.set(part.id, partView);
table.addChild(partView); tableView.addChild(partView);
} }
table.graphics.clear(); imageView.x = state.preset.imageRect.x;
table.graphics.lineStyle(2, 0xCCCCCC); imageView.y = state.preset.imageRect.y;
table.graphics.beginFill(0x555555); imageView.graphics.clear();
table.graphics.drawRect(state.preset.imageRect.x, state.preset.imageRect.y, state.preset.imageRect.width, state.preset.imageRect.height); imageView.graphics.lineStyle(2, 0xCCCCCC);
table.graphics.endFill(); imageView.graphics.beginFill(0x555555);
table.graphics.lineStyle(); imageView.graphics.drawRect(0, 0, state.preset.imageRect.width, state.preset.imageRect.height);
imageView.graphics.endFill();
imageView.graphics.lineStyle();
progress.text = "Loading image"; progress.text = "Loading image";
content.addChild(progress.content); content.addChild(progress.content);
imageStorage.resolve(state.preset.image).then(onImageResolved); imageStorage.resolve(state.preset.image).then(onImageResolved);
@@ -119,26 +124,27 @@ class Render extends SpriteView implements IRender {
return; return;
} }
activePart = part; activePart = part;
table.setChildIndex(activePart, table.numChildren - 1); tableView.setChildIndex(activePart, tableView.numChildren - 1);
activePoint = table.globalToLocal(new Point(event.stageX, event.stageY)); activePoint = tableView.globalToLocal(new Point(event.stageX, event.stageY));
table.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); tableView.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
table.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); tableView.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
signal.emit(ACTION(PART_TAKE(activePart.id)));
} }
} }
private function onMouseMove(event:MouseEvent):Void { private function onMouseMove(event:MouseEvent):Void {
var newPoint = table.globalToLocal(new Point(event.stageX, event.stageY)); var newPoint = tableView.globalToLocal(new Point(event.stageX, event.stageY));
var partPosition = activePart.position.add(newPoint).subtract(activePoint); var partPosition = activePart.position.add(newPoint).subtract(activePoint);
signal.emit(GameEvent.PART_MOVE(activePart.id, partPosition.clone())); signal.emit(ACTION(PART_MOVE(activePart.id, partPosition.clone())));
activePoint = newPoint; activePoint = newPoint;
} }
private function onMouseUp(event:MouseEvent):Void { private function onMouseUp(event:MouseEvent):Void {
var newPoint = table.globalToLocal(new Point(event.stageX, event.stageY)); var newPoint = tableView.globalToLocal(new Point(event.stageX, event.stageY));
var partPosition = activePart.position.add(newPoint).subtract(activePoint); var partPosition = activePart.position.add(newPoint).subtract(activePoint);
signal.emit(GameEvent.PART_PUT(activePart.id, partPosition.clone())); signal.emit(ACTION(PART_PUT(activePart.id, partPosition.clone())));
table.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); tableView.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
table.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); tableView.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
//save(activePart); //save(activePart);
activePart = null; activePart = null;
activePoint = null; activePoint = null;
@@ -154,7 +160,9 @@ class Render extends SpriteView implements IRender {
private function clean() { private function clean() {
for (partView in parts) { for (partView in parts) {
table.removeChild(partView); if (partView.parent != null) {
partView.parent.removeChild(partView);
}
} }
parts = new Map(); parts = new Map();
} }

View File

@@ -20,7 +20,7 @@ class BaseMaskBuilder implements IPartMaskBuilder {
private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, bound:PartBound):Void { private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, bound:PartBound):Void {
} }
public function build(rect:Rectangle, bounds:Bounds):DrawPath { public function build(rect:Rectangle, bounds:PartBounds):DrawPath {
var path:DrawPath = { var path:DrawPath = {
commands: new Vector<GraphicsPathCommand>(), commands: new Vector<GraphicsPathCommand>(),
data: new Vector<Float>(), data: new Vector<Float>(),

View File

@@ -1,6 +1,7 @@
package ru.m.puzzlez.render.mask; package ru.m.puzzlez.render.mask;
import flash.display.GraphicsPathCommand; import flash.display.GraphicsPathCommand;
import ru.m.puzzlez.core.BoundType;
import ru.m.puzzlez.core.Part; import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.IPartMaskBuilder; import ru.m.puzzlez.render.mask.IPartMaskBuilder;

View File

@@ -11,5 +11,5 @@ typedef DrawPath = {
} }
interface IPartMaskBuilder { interface IPartMaskBuilder {
public function build(rect:Rectangle, bound:Bounds):DrawPath; public function build(rect:Rectangle, bound:PartBounds):DrawPath;
} }

View File

@@ -11,7 +11,7 @@ class PartMask extends Shape {
private static var builder:IPartMaskBuilder = new ClassicMaskBuilder(); private static var builder:IPartMaskBuilder = new ClassicMaskBuilder();
public function new(rect:Rectangle, bounds:Bounds) { public function new(rect:Rectangle, bounds:PartBounds) {
super(); super();
this.rect = rect.clone(); this.rect = rect.clone();
var offset = rect.width / 4 + rect.width * 0.05; var offset = rect.width / 4 + rect.width * 0.05;

View File

@@ -1,6 +1,7 @@
package ru.m.puzzlez.render.mask; package ru.m.puzzlez.render.mask;
import flash.display.GraphicsPathCommand; import flash.display.GraphicsPathCommand;
import ru.m.puzzlez.core.BoundType;
import ru.m.puzzlez.core.Part; import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.mask.IPartMaskBuilder; import ru.m.puzzlez.render.mask.IPartMaskBuilder;