diff --git a/package.json b/package.json index 4f699d8..48da6f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "puzzlez", - "version": "0.0.2", + "version": "0.0.3", "private": true, "devDependencies": { "dateformat": "^3.0.3", diff --git a/src/haxe/ru/m/puzzlez/PuzzlezTheme.hx b/src/haxe/ru/m/puzzlez/PuzzlezTheme.hx index 89a282b..3289a7f 100644 --- a/src/haxe/ru/m/puzzlez/PuzzlezTheme.hx +++ b/src/haxe/ru/m/puzzlez/PuzzlezTheme.hx @@ -1,10 +1,16 @@ package ru.m.puzzlez; +import haxework.view.geometry.Box; import haxework.view.theme.Theme; class PuzzlezTheme extends Theme { public function new() { - super({name: 'Georgia'}, {light: 'gray'}); + super({name: "Georgia"}, {light: "gray"}); + register(new Style("view", [ + "skin.background.color" => colors.light, + "skin.border.color" => colors.border, + "geometry.padding" => Box.fromFloat(3), + ])); } } diff --git a/src/haxe/ru/m/puzzlez/core/Game.hx b/src/haxe/ru/m/puzzlez/core/Game.hx index 32b22f2..ec5f16c 100644 --- a/src/haxe/ru/m/puzzlez/core/Game.hx +++ b/src/haxe/ru/m/puzzlez/core/Game.hx @@ -26,18 +26,12 @@ class Game implements IGame { public function shuffle():Void { for (part in state.parts) { - var bound = part.rect.width * 0.25; - part.rect.x = bound + Math.random() * (state.preset.tableRect.width - part.rect.width - bound * 2); - part.rect.y = bound + Math.random() * (state.preset.tableRect.height - part.rect.height - bound * 2); - signal.emit(GameEvent.PART_MOVED(part.id, part.rect.topLeft)); - } - } - - public function collect():Void { - for (part in state.parts) { - part.rect.x = part.position.x; - part.rect.y = part.position.y; - signal.emit(GameEvent.PART_MOVED(part.id, part.rect.topLeft)); + if (!part.completed) { + var bound = part.rect.width * 0.25; + part.rect.x = bound + Math.random() * (state.preset.tableRect.width - part.rect.width - bound * 2); + part.rect.y = bound + Math.random() * (state.preset.tableRect.height - part.rect.height - bound * 2); + signal.emit(GameEvent.PART_MOVED(part.id, part.rect.topLeft)); + } } } @@ -49,12 +43,16 @@ class Game implements IGame { private function onGameEvent(event:GameEvent):Void { switch event { case GameEvent.PART_MOVE(id, position): + var part = partsById[id]; + part.rect.topLeft = position; signal.emit(GameEvent.PART_MOVED(id, position)); case GameEvent.PART_PUT(id, position): var part = partsById[id]; var d = distance(part.position, position); - if (d < 50) { - signal.emit(GameEvent.PART_MOVED(id, part.position)); + if (d < 70) { + part.completed = true; + part.rect.topLeft = part.position; + signal.emit(GameEvent.PART_COMPLETED(id, part.position)); } else { signal.emit(GameEvent.PART_MOVED(id, position)); } diff --git a/src/haxe/ru/m/puzzlez/core/GameEvent.hx b/src/haxe/ru/m/puzzlez/core/GameEvent.hx index 2e389ae..1cb6440 100644 --- a/src/haxe/ru/m/puzzlez/core/GameEvent.hx +++ b/src/haxe/ru/m/puzzlez/core/GameEvent.hx @@ -7,4 +7,5 @@ enum GameEvent { PART_MOVE(id:Int, position:Point); PART_PUT(id:Int, position:Point); PART_MOVED(id:Int, position:Point); + PART_COMPLETED(id:Int, position:Point); } diff --git a/src/haxe/ru/m/puzzlez/core/GameUtil.hx b/src/haxe/ru/m/puzzlez/core/GameUtil.hx index 20b030d..09a3bbe 100644 --- a/src/haxe/ru/m/puzzlez/core/GameUtil.hx +++ b/src/haxe/ru/m/puzzlez/core/GameUtil.hx @@ -110,7 +110,8 @@ class GameUtil { gridY: y, position: position, rect: new Rectangle(position.x, position.y, partWidth, partHeight), - bounds: bounds + bounds: bounds, + completed: false, }); } } diff --git a/src/haxe/ru/m/puzzlez/core/IGame.hx b/src/haxe/ru/m/puzzlez/core/IGame.hx index 6815d44..3d2d68e 100644 --- a/src/haxe/ru/m/puzzlez/core/IGame.hx +++ b/src/haxe/ru/m/puzzlez/core/IGame.hx @@ -9,6 +9,5 @@ interface IGame { public function start():Void; public function stop():Void; public function shuffle():Void; - public function collect():Void; public function dispose():Void; } diff --git a/src/haxe/ru/m/puzzlez/core/Part.hx b/src/haxe/ru/m/puzzlez/core/Part.hx index 8432668..6e666bb 100644 --- a/src/haxe/ru/m/puzzlez/core/Part.hx +++ b/src/haxe/ru/m/puzzlez/core/Part.hx @@ -35,4 +35,5 @@ typedef Part = { var position:Point; var rect:Rectangle; var bounds:Bounds; + var completed:Bool; } diff --git a/src/haxe/ru/m/puzzlez/render/PartView.hx b/src/haxe/ru/m/puzzlez/render/PartView.hx index 7f6ba66..b687860 100644 --- a/src/haxe/ru/m/puzzlez/render/PartView.hx +++ b/src/haxe/ru/m/puzzlez/render/PartView.hx @@ -10,6 +10,7 @@ class PartView extends Sprite { public var id(default, null):Int; public var position(default, set):Point; + public var completed(default, default):Bool; private function set_position(value:Point):Point { position = value.clone(); diff --git a/src/haxe/ru/m/puzzlez/render/ProgressView.hx b/src/haxe/ru/m/puzzlez/render/ProgressView.hx new file mode 100644 index 0000000..b170807 --- /dev/null +++ b/src/haxe/ru/m/puzzlez/render/ProgressView.hx @@ -0,0 +1,17 @@ +package ru.m.puzzlez.render; + +import haxework.view.form.LabelView; + +class ProgressView extends LabelView { + + public function new() { + super(); + text = 'Loading 0/0'; + update(); + } + + public function setProgress(current:Int, total:Int):Void { + text = 'Loading ${current}/${total}'; + update(); + } +} diff --git a/src/haxe/ru/m/puzzlez/render/Render.hx b/src/haxe/ru/m/puzzlez/render/Render.hx index a23fd2b..b40c4e4 100644 --- a/src/haxe/ru/m/puzzlez/render/Render.hx +++ b/src/haxe/ru/m/puzzlez/render/Render.hx @@ -1,5 +1,6 @@ package ru.m.puzzlez.render; +import haxe.Timer; import flash.display.BitmapData; import flash.display.PNGEncoderOptions; import flash.display.Sprite; @@ -24,6 +25,8 @@ class Render extends SpriteView implements IRender { private function set_scale(value:Float):Float { var result = table.scaleX = table.scaleY = value; + table.x = (width - state.preset.tableRect.width * value) / 2; + table.y = (height - state.preset.tableRect.height * value) / 2; //setSize(table.width, table.height, 'table'); return result; } @@ -31,6 +34,7 @@ class Render extends SpriteView implements IRender { private var state:GameState; private var image:BitmapData; + private var progress:ProgressView; private var table:Sprite; private var parts:Map; private var activePart:PartView; @@ -38,6 +42,7 @@ class Render extends SpriteView implements IRender { public function new() { super(); + progress = new ProgressView(); signal = new Signal(); table = new Sprite(); table.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); @@ -52,6 +57,11 @@ class Render extends SpriteView implements IRender { case PART_MOVED(id, point): var part:PartView = parts[id]; part.position = point; + case PART_COMPLETED(id, point): + var part:PartView = parts[id]; + part.position = point; + part.completed = true; + table.setChildIndex(part, 0); case _: } } @@ -68,30 +78,40 @@ class Render extends SpriteView implements IRender { table.graphics.lineStyle(2, 0xCCCCCC); table.graphics.beginFill(0x555555); - table.graphics.drawRect(state.preset.tableRect.x, state.preset.tableRect.y, state.preset.tableRect.width, state.preset.tableRect.height); - table.graphics.endFill(); - 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(); + progress.setProgress(0, state.parts.length); + content.addChild(progress.content); RenderUtil.resolveImage(state.preset.image).then(onImageResolved); toUpdate(); } private function onImageResolved(image:BitmapData):Void { this.image = RenderUtil.cropImage(image, state.preset.imageRect); - for (part in state.parts) { + var i = 0; + var loadNext = null; + loadNext = function():Void { + var part = state.parts[i]; var partImage = RenderUtil.cropImagePart(this.image, part); var partView = parts[part.id]; partView.image = partImage; + progress.setProgress(++i, state.parts.length); + if (i < state.parts.length - 1) { + i++; + Timer.delay(loadNext, 0); + } else { + content.removeChild(progress.content); + } } + Timer.delay(loadNext, 0); } override public function update():Void { super.update(); + progress.x = (width - progress.width) / 2; + progress.y = (height - progress.height) / 2; + progress.update(); if (state != null) { scale = Math.min(width / state.preset.tableRect.width, height / state.preset.tableRect.height); } @@ -99,7 +119,11 @@ class Render extends SpriteView implements IRender { private function onMouseDown(event:MouseEvent):Void { if (Std.is(event.target, PartView)) { - activePart = event.target; + var part:PartView = event.target; + if (part.completed) { + return; + } + activePart = part; table.setChildIndex(activePart, table.numChildren - 1); activePoint = table.globalToLocal(new Point(event.stageX, event.stageY)); table.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); diff --git a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx index 0d8cc01..9fb5455 100644 --- a/src/haxe/ru/m/puzzlez/render/RenderUtil.hx +++ b/src/haxe/ru/m/puzzlez/render/RenderUtil.hx @@ -2,7 +2,8 @@ package ru.m.puzzlez.render; import flash.display.BitmapData; import flash.display.Shape; -import flash.filters.GlowFilter; +import flash.filters.BitmapFilterQuality; +import flash.filters.DropShadowFilter; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; @@ -47,14 +48,15 @@ class RenderUtil { var matrix = new Matrix(); matrix.translate(-mask.rect.x, -mask.rect.y); image.draw(canvas, matrix, null, null, null, true); - var borderWidth = image.width * 0.02; - var borderAlpha = 1.0; + var alpha = 1.0; + var blur = 2; + var strength = 255; #if flash - borderWidth /= 3; - //borderAlpha = 0.5; + alpha = 0.5; + strength = 8; #end - image.applyFilter(image, image.rect, new Point(), new GlowFilter(0xffffff, 0.3, borderWidth, borderWidth, 8, 1, true)); - image.applyFilter(image, image.rect, new Point(), new GlowFilter(0x555555, 0.3, borderWidth / 2, borderWidth / 2, 16, 1, true)); + image.applyFilter(image, image.rect, new Point(), new DropShadowFilter(0, 0, 0x000000, alpha, blur, blur, strength, BitmapFilterQuality.HIGH, true)); + image.applyFilter(image, image.rect, new Point(), new DropShadowFilter(0, 0, 0xffffff, alpha, blur / 2, blur / 2, strength / 2, BitmapFilterQuality.HIGH, true)); return image; } diff --git a/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx b/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx index 5e42575..25c1a70 100644 --- a/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx +++ b/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.hx @@ -34,9 +34,11 @@ typedef PixabayResponse = { private function imageViewFactory(index:Int, image:ImageSource):ImageView { var result = new ImageView(); + result.style = "view"; result.stretch = false; result.fillType = FillType.COVER; result.setSize(192, 128); + result.image = Assets.getBitmapData("resources/icon.png"); RenderUtil.resolveImage(image).then(function(image) result.image = image); return result; } diff --git a/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.yaml b/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.yaml index bd641cf..3be1156 100644 --- a/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.yaml +++ b/src/haxe/ru/m/puzzlez/view/PuzzlezAppView.yaml @@ -8,6 +8,7 @@ views: views: - $type: haxework.view.group.VGroupView geometry.height: 100% + layout.hAlign: center views: - $type: haxework.view.form.LabelView text: Puzzle'z @@ -15,9 +16,6 @@ views: - $type: haxework.view.form.ButtonView text: Shuffle +onPress: ~game.shuffle() - - $type: haxework.view.form.ButtonView - text: Collect - +onPress: ~game.collect() - id: images $type: haxework.view.data.DataView layout: