[improve] ClassicMaskBuilder
This commit is contained in:
@@ -20,9 +20,17 @@ class Game implements IGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function start():Void {
|
public function start():Void {
|
||||||
|
shuffle();
|
||||||
signal.emit(GameEvent.START(state));
|
signal.emit(GameEvent.START(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shuffle():Void {
|
||||||
|
for (part in state.parts) {
|
||||||
|
part.rect.x = Math.random() * (state.preset.tableRect.width - part.rect.width);
|
||||||
|
part.rect.y = Math.random() * (state.preset.tableRect.height - part.rect.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static function distance(a:Point, b:Point):Float {
|
private static function distance(a:Point, b:Point):Float {
|
||||||
var diff = a.subtract(b);
|
var diff = a.subtract(b);
|
||||||
return Math.abs(diff.x) + Math.abs(diff.y);
|
return Math.abs(diff.x) + Math.abs(diff.y);
|
||||||
|
|||||||
@@ -2,18 +2,76 @@ package ru.m.puzzlez.core;
|
|||||||
|
|
||||||
import flash.geom.Point;
|
import flash.geom.Point;
|
||||||
import flash.geom.Rectangle;
|
import flash.geom.Rectangle;
|
||||||
import ru.m.puzzlez.core.Part.Bounds;
|
import ru.m.puzzlez.core.Part;
|
||||||
import ru.m.puzzlez.core.Part.BoundType;
|
|
||||||
|
class BoundsMap {
|
||||||
|
|
||||||
|
private var grid:Grid;
|
||||||
|
private var bounds:Array<PartBound>;
|
||||||
|
|
||||||
|
public function new(grid:Grid) {
|
||||||
|
this.grid = grid;
|
||||||
|
bounds = [];
|
||||||
|
for (x in 0...grid.width + 1) {
|
||||||
|
for (y in 0...grid.height + 1) {
|
||||||
|
bounds.push(buildPartBound());
|
||||||
|
bounds.push(buildPartBound());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildBound():BoundType {
|
||||||
|
return Math.random() > 0.5 ? BoundType.OUT : BoundType.IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildPartBound():PartBound {
|
||||||
|
return {
|
||||||
|
spike: buildBound(),
|
||||||
|
side: buildBound(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildNonePartBound():PartBound {
|
||||||
|
return {
|
||||||
|
spike: NONE,
|
||||||
|
side: NONE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function revert(type:BoundType):BoundType {
|
||||||
|
return switch type {
|
||||||
|
case IN: OUT;
|
||||||
|
case OUT: IN;
|
||||||
|
case NONE: NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBound(x:Int, y:Int, side:Side):PartBound {
|
||||||
|
var index = switch side {
|
||||||
|
case TOP: x + (grid.width + 1) * (y * 2);
|
||||||
|
case LEFT: x + (grid.width + 1) * (y + 1);
|
||||||
|
case RIGHT: x + (grid.width + 1) * (y + 1) + 1;
|
||||||
|
case BOTTOM: x + (grid.width + 1) * (y * 2) + (grid.width + 1) * 2;
|
||||||
|
}
|
||||||
|
return switch side {
|
||||||
|
case TOP | LEFT: {spike: revert(bounds[index].spike), side: revert(bounds[index].side)};
|
||||||
|
case _: bounds[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class GameUtil {
|
class GameUtil {
|
||||||
|
|
||||||
public static function buildPreset(image:ImageSource):GamePreset {
|
public static function buildPreset(image:ImageSource):GamePreset {
|
||||||
|
var size = 8;
|
||||||
|
var offset = 100;
|
||||||
|
var imageRect = new Rectangle(offset, offset, 1024, 1024);
|
||||||
|
var tableRect = new Rectangle(0, 0, imageRect.width + offset * 2, imageRect.height + offset * 2);
|
||||||
return {
|
return {
|
||||||
image:image,
|
image:image,
|
||||||
grid: {width: 8, height: 8},
|
grid: {width: size, height: size},
|
||||||
tableRect: new Rectangle(0, 0, 1128, 1128),
|
tableRect: tableRect,
|
||||||
//imageRect: new Rectangle(0, 0, 2304, 2304),
|
imageRect: imageRect,
|
||||||
imageRect: new Rectangle(0, 0, 1024, 1024),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,29 +79,27 @@ class GameUtil {
|
|||||||
var parts:Array<Part> = [];
|
var parts:Array<Part> = [];
|
||||||
var partWidth = preset.imageRect.width / preset.grid.width;
|
var partWidth = preset.imageRect.width / preset.grid.width;
|
||||||
var partHeight = preset.imageRect.height / preset.grid.height;
|
var partHeight = preset.imageRect.height / preset.grid.height;
|
||||||
var topLeft = new Point(
|
var topLeft = preset.imageRect.topLeft;
|
||||||
(preset.tableRect.width - preset.imageRect.width) / 2,
|
var boundsMap = new BoundsMap(preset.grid);
|
||||||
(preset.tableRect.height - preset.imageRect.height) / 2
|
|
||||||
);
|
|
||||||
for (x in 0...preset.grid.width) {
|
|
||||||
for (y in 0...preset.grid.height) {
|
for (y in 0...preset.grid.height) {
|
||||||
|
for (x in 0...preset.grid.width) {
|
||||||
var bounds:Bounds = {
|
var bounds:Bounds = {
|
||||||
left: BoundType.IN,
|
left: boundsMap.getBound(x, y, LEFT),
|
||||||
right: BoundType.OUT,
|
right: boundsMap.getBound(x, y, RIGHT),
|
||||||
top: BoundType.IN,
|
top: boundsMap.getBound(x, y, TOP),
|
||||||
bottom: BoundType.OUT,
|
bottom: boundsMap.getBound(x, y, BOTTOM),
|
||||||
}
|
}
|
||||||
if (x == 0) {
|
if (x == 0) {
|
||||||
bounds.left = BoundType.NONE;
|
bounds.left = boundsMap.buildNonePartBound();
|
||||||
}
|
}
|
||||||
if (y == 0) {
|
if (y == 0) {
|
||||||
bounds.top = BoundType.NONE;
|
bounds.top = boundsMap.buildNonePartBound();
|
||||||
}
|
}
|
||||||
if (x == preset.grid.width - 1) {
|
if (x == preset.grid.width - 1) {
|
||||||
bounds.right = BoundType.NONE;
|
bounds.right = boundsMap.buildNonePartBound();
|
||||||
}
|
}
|
||||||
if (y == preset.grid.height - 1) {
|
if (y == preset.grid.height - 1) {
|
||||||
bounds.bottom = BoundType.NONE;
|
bounds.bottom = boundsMap.buildNonePartBound();
|
||||||
}
|
}
|
||||||
var id = (x << 16) + y;
|
var id = (x << 16) + y;
|
||||||
var position = new Point(topLeft.x + x * partWidth, topLeft.y + y * partHeight);
|
var position = new Point(topLeft.x + x * partWidth, topLeft.y + y * partHeight);
|
||||||
|
|||||||
@@ -3,17 +3,29 @@ package ru.m.puzzlez.core;
|
|||||||
import flash.geom.Point;
|
import flash.geom.Point;
|
||||||
import flash.geom.Rectangle;
|
import flash.geom.Rectangle;
|
||||||
|
|
||||||
|
enum Side {
|
||||||
|
TOP;
|
||||||
|
LEFT;
|
||||||
|
RIGHT;
|
||||||
|
BOTTOM;
|
||||||
|
}
|
||||||
|
|
||||||
enum BoundType {
|
enum BoundType {
|
||||||
NONE;
|
NONE;
|
||||||
OUT;
|
OUT;
|
||||||
IN;
|
IN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef PartBound = {
|
||||||
|
var spike: BoundType;
|
||||||
|
var side: BoundType;
|
||||||
|
}
|
||||||
|
|
||||||
typedef Bounds = {
|
typedef Bounds = {
|
||||||
var left:BoundType;
|
var left:PartBound;
|
||||||
var right:BoundType;
|
var right:PartBound;
|
||||||
var top:BoundType;
|
var top:PartBound;
|
||||||
var bottom:BoundType;
|
var bottom:PartBound;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Part = {
|
typedef Part = {
|
||||||
|
|||||||
@@ -76,6 +76,13 @@ class Render extends SpriteView implements IRender {
|
|||||||
table.graphics.drawRect(state.preset.tableRect.x, state.preset.tableRect.y, state.preset.tableRect.width, state.preset.tableRect.height);
|
table.graphics.drawRect(state.preset.tableRect.x, state.preset.tableRect.y, state.preset.tableRect.width, state.preset.tableRect.height);
|
||||||
table.graphics.endFill();
|
table.graphics.endFill();
|
||||||
table.graphics.lineStyle();
|
table.graphics.lineStyle();
|
||||||
|
|
||||||
|
table.graphics.lineStyle(2, 0xCCCCCC);
|
||||||
|
table.graphics.beginFill(0x777777);
|
||||||
|
table.graphics.drawRect(state.preset.imageRect.x, state.preset.imageRect.y, state.preset.imageRect.width, state.preset.imageRect.height);
|
||||||
|
table.graphics.endFill();
|
||||||
|
table.graphics.lineStyle();
|
||||||
|
|
||||||
toUpdate();
|
toUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ class RenderUtil {
|
|||||||
public static function resolveImage(source:ImageSource):Promise<BitmapData> {
|
public static function resolveImage(source:ImageSource):Promise<BitmapData> {
|
||||||
return switch source {
|
return switch source {
|
||||||
case ASSET(name):
|
case ASSET(name):
|
||||||
return Promise.promise(Assets.getBitmapData(name));
|
Promise.promise(Assets.getBitmapData(name));
|
||||||
case URL(url):
|
case URL(url):
|
||||||
return new ImageLoader().GET(url);
|
new ImageLoader().GET(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,13 @@ class BaseMaskBuilder implements IPartMaskBuilder {
|
|||||||
public function new() {
|
public function new() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, type:BoundType):Void {
|
private function createAngle(path:DrawPath, x:Float, y:Float):Void {
|
||||||
path.commands.push(GraphicsPathCommand.LINE_TO);
|
path.commands.push(GraphicsPathCommand.LINE_TO);
|
||||||
path.data.push(toX);
|
path.data.push(x);
|
||||||
path.data.push(toY);
|
path.data.push(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
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:Bounds):DrawPath {
|
||||||
@@ -22,13 +25,15 @@ class BaseMaskBuilder implements IPartMaskBuilder {
|
|||||||
commands: new Vector<GraphicsPathCommand>(),
|
commands: new Vector<GraphicsPathCommand>(),
|
||||||
data: new Vector<Float>(),
|
data: new Vector<Float>(),
|
||||||
}
|
}
|
||||||
path.commands.push(GraphicsPathCommand.MOVE_TO);
|
createAngle(path, rect.left, rect.top);
|
||||||
path.data.push(rect.left);
|
|
||||||
path.data.push(rect.top);
|
|
||||||
createBound(path, rect.left, rect.top, rect.right, rect.top, bounds.top);
|
createBound(path, rect.left, rect.top, rect.right, rect.top, bounds.top);
|
||||||
|
createAngle(path, rect.right, rect.top);
|
||||||
createBound(path, rect.right, rect.top, rect.right, rect.bottom, bounds.right);
|
createBound(path, rect.right, rect.top, rect.right, rect.bottom, bounds.right);
|
||||||
|
createAngle(path, rect.right, rect.bottom);
|
||||||
createBound(path, rect.right, rect.bottom, rect.left, rect.bottom, bounds.bottom);
|
createBound(path, rect.right, rect.bottom, rect.left, rect.bottom, bounds.bottom);
|
||||||
|
createAngle(path, rect.left, rect.bottom);
|
||||||
createBound(path, rect.left, rect.bottom, rect.left, rect.top, bounds.left);
|
createBound(path, rect.left, rect.bottom, rect.left, rect.top, bounds.left);
|
||||||
|
createAngle(path, rect.left, rect.top);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,34 +6,38 @@ import ru.m.puzzlez.render.mask.IPartMaskBuilder;
|
|||||||
|
|
||||||
class ClassicMaskBuilder extends BaseMaskBuilder {
|
class ClassicMaskBuilder extends BaseMaskBuilder {
|
||||||
|
|
||||||
override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, type:BoundType):Void {
|
override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, bound:PartBound):Void {
|
||||||
var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX);
|
var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX);
|
||||||
var dy = toY == fromY ? 0 : (toY - fromY) / Math.abs(toY - fromY);
|
var dy = toY == fromY ? 0 : (toY - fromY) / Math.abs(toY - fromY);
|
||||||
var boundLength = Math.max(Math.abs(toX - fromX), Math.abs(toY - fromY));
|
var boundLength = Math.max(Math.abs(toX - fromX), Math.abs(toY - fromY));
|
||||||
var spikeWidth = boundLength * 0.2;
|
var spikeWidth = boundLength * 0.2;
|
||||||
var spikeOffset = (boundLength - spikeWidth) / 2;
|
var spikeOffset = (boundLength - spikeWidth) / 2;
|
||||||
var spikeDepth = switch type {
|
var spikeDepth = switch bound.spike {
|
||||||
case NONE: 0;
|
case NONE: 0;
|
||||||
case IN: spikeWidth;
|
case IN: spikeWidth;
|
||||||
case OUT: -spikeWidth;
|
case OUT: -spikeWidth;
|
||||||
};
|
};
|
||||||
switch type {
|
var spikeSideOffset = switch bound.side {
|
||||||
|
case NONE: 0;
|
||||||
|
case IN: boundLength * -0.04;
|
||||||
|
case OUT: boundLength * 0.04;
|
||||||
|
}
|
||||||
|
switch bound.spike {
|
||||||
case NONE:
|
case NONE:
|
||||||
case IN | OUT:
|
case IN | OUT:
|
||||||
path.commands.push(GraphicsPathCommand.LINE_TO);
|
path.commands.push(GraphicsPathCommand.LINE_TO);
|
||||||
path.data.push(fromX + spikeOffset * dx);
|
path.data.push(fromX + spikeOffset * dx + spikeSideOffset * dy);
|
||||||
path.data.push(fromY + spikeOffset * dy);
|
path.data.push(fromY + spikeOffset * dy + spikeSideOffset * dx);
|
||||||
path.commands.push(GraphicsPathCommand.CURVE_TO);
|
path.commands.push(GraphicsPathCommand.CURVE_TO);
|
||||||
path.data.push(fromX + (spikeOffset * 0.8) * dx - spikeDepth * dy);
|
path.data.push(fromX + (spikeOffset * 0.8) * dx - spikeDepth * dy + spikeSideOffset * dy);
|
||||||
path.data.push(fromY + spikeDepth * dx + (spikeOffset * 0.8) * dy);
|
path.data.push(fromY + spikeDepth * dx + (spikeOffset * 0.8) * dy + spikeSideOffset * dx);
|
||||||
path.data.push(fromX + (spikeOffset + spikeWidth / 2) * dx - (spikeDepth * 1.1) * dy);
|
path.data.push(fromX + (spikeOffset + spikeWidth / 2) * dx - (spikeDepth * 1.1) * dy + spikeSideOffset * dy);
|
||||||
path.data.push(fromY + (spikeDepth * 1.1) * dx + (spikeOffset + spikeWidth / 2) * dy);
|
path.data.push(fromY + (spikeDepth * 1.1) * dx + (spikeOffset + spikeWidth / 2) * dy + spikeSideOffset * dx);
|
||||||
path.commands.push(GraphicsPathCommand.CURVE_TO);
|
path.commands.push(GraphicsPathCommand.CURVE_TO);
|
||||||
path.data.push(fromX + (spikeOffset + spikeWidth + spikeOffset * 0.2) * dx - spikeDepth * dy);
|
path.data.push(fromX + (spikeOffset + spikeWidth + spikeOffset * 0.2) * dx - spikeDepth * dy + spikeSideOffset * dy);
|
||||||
path.data.push(fromY + spikeDepth * dx + (spikeOffset + spikeWidth + spikeOffset * 0.2) * dy);
|
path.data.push(fromY + spikeDepth * dx + (spikeOffset + spikeWidth + spikeOffset * 0.2) * dy + spikeSideOffset * dx);
|
||||||
path.data.push(fromX + (spikeOffset + spikeWidth) * dx);
|
path.data.push(fromX + (spikeOffset + spikeWidth) * dx + spikeSideOffset * dy);
|
||||||
path.data.push(fromY + (spikeOffset + spikeWidth) * dy);
|
path.data.push(fromY + (spikeOffset + spikeWidth) * dy + spikeSideOffset * dx);
|
||||||
}
|
}
|
||||||
super.createBound(path, fromY, fromY, toX, toY, type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import flash.display.Shape;
|
|||||||
import flash.geom.Rectangle;
|
import flash.geom.Rectangle;
|
||||||
import ru.m.puzzlez.core.Part;
|
import ru.m.puzzlez.core.Part;
|
||||||
|
|
||||||
|
|
||||||
class PartMask extends Shape {
|
class PartMask extends Shape {
|
||||||
|
|
||||||
public var rect(default, null):Rectangle;
|
public var rect(default, null):Rectangle;
|
||||||
|
|||||||
@@ -6,18 +6,18 @@ import ru.m.puzzlez.render.mask.IPartMaskBuilder;
|
|||||||
|
|
||||||
class SquareMaskBuilder extends BaseMaskBuilder {
|
class SquareMaskBuilder extends BaseMaskBuilder {
|
||||||
|
|
||||||
override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, type:BoundType):Void {
|
override private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, bound:PartBound):Void {
|
||||||
var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX);
|
var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX);
|
||||||
var dy = toY == fromY ? 0 : (toY - fromY) / Math.abs(toY - fromY);
|
var dy = toY == fromY ? 0 : (toY - fromY) / Math.abs(toY - fromY);
|
||||||
var boundLength = Math.max(Math.abs(toX - fromX), Math.abs(toY - fromY));
|
var boundLength = Math.max(Math.abs(toX - fromX), Math.abs(toY - fromY));
|
||||||
var spikeWidth = boundLength * 0.2;
|
var spikeWidth = boundLength * 0.2;
|
||||||
var spikeOffset = (boundLength - spikeWidth) / 2;
|
var spikeOffset = (boundLength - spikeWidth) / 2;
|
||||||
var spikeDepth = switch type {
|
var spikeDepth = switch bound.spike {
|
||||||
case NONE: 0;
|
case NONE: 0;
|
||||||
case IN: spikeWidth;
|
case IN: spikeWidth;
|
||||||
case OUT: -spikeWidth;
|
case OUT: -spikeWidth;
|
||||||
}
|
}
|
||||||
switch type {
|
switch bound.spike {
|
||||||
case NONE:
|
case NONE:
|
||||||
case IN | OUT:
|
case IN | OUT:
|
||||||
path.commands.push(GraphicsPathCommand.LINE_TO);
|
path.commands.push(GraphicsPathCommand.LINE_TO);
|
||||||
@@ -33,6 +33,5 @@ class SquareMaskBuilder extends BaseMaskBuilder {
|
|||||||
path.data.push(fromX + (spikeOffset + spikeWidth) * dx);
|
path.data.push(fromX + (spikeOffset + spikeWidth) * dx);
|
||||||
path.data.push(fromY + (spikeOffset + spikeWidth) * dy);
|
path.data.push(fromY + (spikeOffset + spikeWidth) * dy);
|
||||||
}
|
}
|
||||||
super.createBound(path, fromY, fromY, toX, toY, type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user