diff --git a/src/haxe/ru/m/puzzlez/core/GameUtil.hx b/src/haxe/ru/m/puzzlez/core/GameUtil.hx index eac84a1..4fd85fb 100644 --- a/src/haxe/ru/m/puzzlez/core/GameUtil.hx +++ b/src/haxe/ru/m/puzzlez/core/GameUtil.hx @@ -1,5 +1,7 @@ package ru.m.puzzlez.core; +import ru.m.puzzlez.core.Part.Bounds; +import ru.m.puzzlez.core.Part.BoundType; import flash.geom.Rectangle; class GameUtil { @@ -9,7 +11,8 @@ class GameUtil { image:image, grid: {width: 8, height: 8}, tableRect: new Rectangle(0, 0, 0, 0), - imageRect: new Rectangle(0, 0, 2304, 2304), + //imageRect: new Rectangle(0, 0, 2304, 2304), + imageRect: new Rectangle(0, 0, 1024, 1024), } } @@ -17,15 +20,34 @@ class GameUtil { var parts:Array = []; var partWidth = preset.imageRect.width / preset.grid.width; var partHeight = preset.imageRect.height / preset.grid.height; - var offset = 5; + var offset = 0; for (x in 0...preset.grid.width) { for (y in 0...preset.grid.height) { + var bounds:Bounds = { + left: BoundType.IN, + right: BoundType.OUT, + top: BoundType.IN, + bottom: BoundType.OUT, + } + if (x == 0) { + bounds.left = BoundType.NONE; + } + if (y == 0) { + bounds.top = BoundType.NONE; + } + if (x == preset.grid.width - 1) { + bounds.right = BoundType.NONE; + } + if (y == preset.grid.height - 1) { + bounds.bottom = BoundType.NONE; + } var id = (x << 16) + y; parts.push({ id: id, gridX: x, gridY: y, rect: new Rectangle(offset + x * (partWidth + offset), offset + y * (partHeight + offset), partWidth, partHeight), + bounds: bounds }); } } diff --git a/src/haxe/ru/m/puzzlez/core/Part.hx b/src/haxe/ru/m/puzzlez/core/Part.hx index d525821..aff47f4 100644 --- a/src/haxe/ru/m/puzzlez/core/Part.hx +++ b/src/haxe/ru/m/puzzlez/core/Part.hx @@ -2,9 +2,23 @@ package ru.m.puzzlez.core; import flash.geom.Rectangle; +enum BoundType { + NONE; + OUT; + IN; +} + +typedef Bounds = { + var left:BoundType; + var right:BoundType; + var top:BoundType; + var bottom:BoundType; +} + typedef Part = { var id:Int; var gridX:Int; var gridY:Int; var rect:Rectangle; + var bounds:Bounds; } diff --git a/src/haxe/ru/m/puzzlez/render/PartMask.hx b/src/haxe/ru/m/puzzlez/render/PartMask.hx new file mode 100644 index 0000000..15437c4 --- /dev/null +++ b/src/haxe/ru/m/puzzlez/render/PartMask.hx @@ -0,0 +1,67 @@ +package ru.m.puzzlez.render; + +import flash.display.GraphicsPathCommand; +import flash.display.Shape; +import flash.geom.Rectangle; +import flash.Vector; +import ru.m.puzzlez.core.Part; + + +class PartMask extends Shape { + + private static function createBound(commands:Vector, data:Vector, fromX:Float, fromY:Float, toX:Float, toY:Float, type:BoundType) { + var dx = toX == fromX ? 0 : (toX - fromX) / Math.abs(toX - fromX); + var dy = toY == fromY ? 0 : (toY - fromY) / Math.abs(toY - fromY); + var boundLength = Math.max(Math.abs(toX - fromX), Math.abs(toY - fromY)); + var spikeWidth = boundLength * 0.2; + var spikeOffset = (boundLength - spikeWidth) / 2; + var spikeDepth = switch type { + case NONE: 0; + case IN: spikeWidth; + case OUT: -spikeWidth; + } + switch type { + case NONE: + case IN | OUT: + commands.push(GraphicsPathCommand.LINE_TO); + data.push(fromX + spikeOffset * dx); + data.push(fromY + spikeOffset * dy); + commands.push(GraphicsPathCommand.LINE_TO); + data.push(fromX + spikeOffset * dx - spikeDepth * dy); + data.push(fromY + spikeDepth * dx + spikeOffset * dy); + commands.push(GraphicsPathCommand.LINE_TO); + data.push(fromX + (spikeOffset + spikeWidth) * dx - spikeDepth * dy); + data.push(fromY + spikeDepth * dx + (spikeOffset + spikeWidth) * dy); + commands.push(GraphicsPathCommand.LINE_TO); + data.push(fromX + (spikeOffset + spikeWidth) * dx); + data.push(fromY + (spikeOffset + spikeWidth) * dy); + } + commands.push(GraphicsPathCommand.LINE_TO); + data.push(toX); + data.push(toY); + } + + public var rect(default, null):Rectangle; + + public function new(rect:Rectangle, bound:Bounds) { + super(); + graphics.beginFill(0xff00ff, 1); + var commands = new Vector(); + var data = new Vector(); + commands.push(GraphicsPathCommand.MOVE_TO); + data.push(rect.left); + data.push(rect.top); + createBound(commands, data, rect.left, rect.top, rect.right, rect.top, bound.top); + createBound(commands, data, rect.right, rect.top, rect.right, rect.bottom, bound.right); + createBound(commands, data, rect.right, rect.bottom, rect.left, rect.bottom, bound.bottom); + createBound(commands, data, rect.left, rect.bottom, rect.left, rect.top, bound.left); + graphics.drawPath(commands, data); + graphics.endFill(); + this.rect = rect.clone(); + var offset = rect.width / 4 + rect.width * 0.05; + this.rect.x -= offset; + this.rect.y -= offset; + this.rect.width += offset * 2; + this.rect.height += offset * 2; + } +} diff --git a/src/haxe/ru/m/puzzlez/render/Render.hx b/src/haxe/ru/m/puzzlez/render/Render.hx index f80c0f0..4dfd796 100644 --- a/src/haxe/ru/m/puzzlez/render/Render.hx +++ b/src/haxe/ru/m/puzzlez/render/Render.hx @@ -47,14 +47,14 @@ class Render extends SpriteView implements IRender { image = Assets.getBitmapData(state.preset.image); image = RenderUtil.cropImage(image, state.preset.imageRect); for (part in state.parts) { - var partImage = RenderUtil.cropImagePart(image, part.gridX, part.gridY, part.rect); + var partImage = RenderUtil.cropImagePart(image, part); var partView = new PartView(part.id, partImage); partView.x = part.rect.x; partView.y = part.rect.y; parts.set(part.id, partView); table.addChild(partView); } - table.scaleX = table.scaleY = 0.25; + table.scaleX = table.scaleY = 0.5; } private function onMouseDown(event:MouseEvent):Void { diff --git a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx index 8ce1152..ea6004d 100644 --- a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx +++ b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx @@ -1,5 +1,9 @@ package ru.m.puzzlez.render; +import flash.filters.GlowFilter; +import flash.geom.Point; +import ru.m.puzzlez.core.Part; +import flash.display.Shape; import flash.display.BitmapData; import flash.geom.Matrix; import flash.geom.Rectangle; @@ -16,12 +20,26 @@ class RenderUtil { return image; } - public static function cropImagePart(source:BitmapData, gridX:Int, gridY:Int, rect:Rectangle):BitmapData { - var rect = new Rectangle(rect.width * gridX, rect.height * gridY, rect.width, rect.width); - var image = new BitmapData(Std.int(rect.width), Std.int(rect.width)); + public static function cropImagePart(source:BitmapData, part:Part):BitmapData { + var rect = new Rectangle(part.rect.width * part.gridX, part.rect.height * part.gridY, part.rect.width, part.rect.width); + var mask = new PartMask(rect, part.bounds); + var canvas:Shape = new Shape(); + canvas.cacheAsBitmap = true; + canvas.mask = mask; + canvas.graphics.beginBitmapFill(source); + canvas.graphics.drawRect(0, 0, source.width, source.height); + canvas.graphics.endFill(); + var image = new BitmapData(Std.int(mask.rect.width), Std.int(mask.rect.height), true, 0x00000000); var matrix = new Matrix(); - matrix.translate(-rect.x, -rect.y); - image.draw(source, matrix, null, null, null, true); + matrix.translate(-mask.rect.x, -mask.rect.y); + image.draw(canvas, matrix); + var borderWidth = image.width * 0.05; + var borderAlpha = 1.0; + #if flash + borderWidth /= 3; + borderAlpha = 0.5; + #end + image.applyFilter(image, image.rect, new Point(), new GlowFilter(0xffffff, borderAlpha, borderWidth, borderWidth, 8, 1, true)); return image; }