[update] (render) add PartView
This commit is contained in:
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@@ -0,0 +1,13 @@
|
||||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1,5 +1,8 @@
|
||||
package ru.m.puzzlez.core;
|
||||
|
||||
import flash.geom.Point;
|
||||
|
||||
enum GameEvent {
|
||||
START(state:GameState);
|
||||
PART_MOVE(id:Int, position:Point);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package ru.m.puzzlez.core;
|
||||
|
||||
import flash.geom.Rectangle;
|
||||
|
||||
typedef GamePreset = {
|
||||
var image:String;
|
||||
var grid:Grid;
|
||||
var tableRect:Rectangle;
|
||||
var imageRect:Rectangle;
|
||||
}
|
||||
|
||||
@@ -2,4 +2,5 @@ package ru.m.puzzlez.core;
|
||||
|
||||
typedef GameState = {
|
||||
var preset:GamePreset;
|
||||
var parts:Array<Part>;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,37 @@
|
||||
package ru.m.puzzlez.core;
|
||||
|
||||
import flash.geom.Rectangle;
|
||||
|
||||
class GameUtil {
|
||||
|
||||
public static function buildPreset(image:String):GamePreset {
|
||||
return {
|
||||
image:image,
|
||||
grid: {width: 8, height: 8},
|
||||
tableRect: new Rectangle(0, 0, 0, 0),
|
||||
imageRect: new Rectangle(0, 0, 2304, 2304),
|
||||
}
|
||||
}
|
||||
|
||||
public static function buildState(preset:GamePreset):GameState {
|
||||
var parts:Array<Part> = [];
|
||||
var partWidth = preset.imageRect.width / preset.grid.width;
|
||||
var partHeight = preset.imageRect.height / preset.grid.height;
|
||||
var offset = 5;
|
||||
for (x in 0...preset.grid.width) {
|
||||
for (y in 0...preset.grid.height) {
|
||||
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),
|
||||
});
|
||||
}
|
||||
}
|
||||
return {
|
||||
preset: preset,
|
||||
parts: parts,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package ru.m.puzzlez.core;
|
||||
|
||||
import flash.geom.Rectangle;
|
||||
|
||||
typedef Part = {
|
||||
var x:Int;
|
||||
var y:Int;
|
||||
var id:Int;
|
||||
var gridX:Int;
|
||||
var gridY:Int;
|
||||
var rect:Rectangle;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package ru.m.puzzlez.render;
|
||||
|
||||
import haxework.signal.Signal;
|
||||
import haxework.view.IView;
|
||||
import ru.m.puzzlez.core.GameEvent;
|
||||
|
||||
interface IRender extends IView<Dynamic> {
|
||||
public var signal(default, null):Signal<GameEvent>;
|
||||
public function onGameEvent(event:GameEvent):Void;
|
||||
}
|
||||
|
||||
20
src/haxe/ru/m/puzzlez/render/PartView.hx
Normal file
20
src/haxe/ru/m/puzzlez/render/PartView.hx
Normal file
@@ -0,0 +1,20 @@
|
||||
package ru.m.puzzlez.render;
|
||||
|
||||
import flash.display.Bitmap;
|
||||
import flash.display.BitmapData;
|
||||
import flash.display.Sprite;
|
||||
|
||||
class PartView extends Sprite {
|
||||
|
||||
public var id(default, null):Int;
|
||||
|
||||
private var bitmap:Bitmap;
|
||||
|
||||
public function new(id:Int, image:BitmapData) {
|
||||
super();
|
||||
this.id = id;
|
||||
bitmap = new Bitmap();
|
||||
bitmap.bitmapData = image;
|
||||
addChild(bitmap);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package ru.m.puzzlez.render;
|
||||
|
||||
import flash.display.Bitmap;
|
||||
import haxework.signal.Signal;
|
||||
import flash.display.BitmapData;
|
||||
import flash.display.Sprite;
|
||||
import flash.events.MouseEvent;
|
||||
@@ -12,67 +12,69 @@ import ru.m.puzzlez.core.GameState;
|
||||
|
||||
class Render extends SpriteView implements IRender {
|
||||
|
||||
public var signal(default, null):Signal<GameEvent>;
|
||||
|
||||
private var state:GameState;
|
||||
private var image:BitmapData;
|
||||
|
||||
private var table:Sprite;
|
||||
private var parts:Array<Bitmap>;
|
||||
private var activePart:Bitmap;
|
||||
private var parts:Map<Int, PartView>;
|
||||
private var activePart:PartView;
|
||||
private var activePoint:Point;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
signal = new Signal();
|
||||
table = new Sprite();
|
||||
table.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
|
||||
content.addChild(table);
|
||||
parts = [];
|
||||
parts = new Map();
|
||||
}
|
||||
|
||||
public function onGameEvent(event:GameEvent):Void {
|
||||
switch event {
|
||||
case START(state): onStart(state);
|
||||
case START(state):
|
||||
onStart(state);
|
||||
case PART_MOVE(id, point):
|
||||
var part = parts[id];
|
||||
part.x = point.x;
|
||||
part.y = point.y;
|
||||
}
|
||||
}
|
||||
|
||||
private function onStart(state:GameState):Void {
|
||||
clean();
|
||||
image = Assets.getBitmapData(state.preset.image);
|
||||
image = RenderUtil.cropImage(image, state.preset.grid);
|
||||
var partWidth = image.width / state.preset.grid.width + 2;
|
||||
var partHeight = image.height / state.preset.grid.height + 2;
|
||||
for (x in 0...state.preset.grid.width) {
|
||||
for (y in 0...state.preset.grid.height) {
|
||||
var partImage = RenderUtil.cropImagePart(image, state.preset.grid, x, y);
|
||||
var bitmap = new Bitmap(partImage);
|
||||
bitmap.x = 5 + partWidth * x;
|
||||
bitmap.y = 5 + partHeight * y;
|
||||
parts.push(bitmap);
|
||||
table.addChild(bitmap);
|
||||
image = RenderUtil.cropImage(image, state.preset.imageRect);
|
||||
for (part in state.parts) {
|
||||
var partImage = RenderUtil.cropImagePart(image, part.gridX, part.gridY, part.rect);
|
||||
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.graphics.clear();
|
||||
table.graphics.beginFill(0xffff00, 1);
|
||||
table.graphics.drawRect(0, 0, image.width, image.height);
|
||||
table.graphics.endFill();
|
||||
table.scaleX = table.scaleY = 0.25;
|
||||
}
|
||||
|
||||
private function onMouseDown(event:MouseEvent):Void {
|
||||
for (part in parts) {
|
||||
if (part.x < event.localX && part.x + part.width > event.localX && part.y < event.localY && part.y + width > event.localY) {
|
||||
activePart = part;
|
||||
if (Std.is(event.target, PartView)) {
|
||||
activePart = event.target;
|
||||
table.setChildIndex(activePart, table.numChildren - 1);
|
||||
activePoint = new Point(event.localX - part.x, event.localY - part.y);
|
||||
activePoint = table.globalToLocal(new Point(event.stageX, event.stageY));
|
||||
table.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
|
||||
table.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function onMouseMove(event:MouseEvent):Void {
|
||||
activePart.x = event.localX - activePoint.x;
|
||||
activePart.y = event.localY - activePoint.y;
|
||||
var newPoint = table.globalToLocal(new Point(event.stageX, event.stageY));
|
||||
var partPosition = new Point(
|
||||
activePart.x + newPoint.x - activePoint.x,
|
||||
activePart.y + newPoint.y - activePoint.y
|
||||
);
|
||||
signal.emit(GameEvent.PART_MOVE(activePart.id, partPosition));
|
||||
activePoint = newPoint;
|
||||
}
|
||||
|
||||
private function onMouseUp(event:MouseEvent):Void {
|
||||
@@ -83,9 +85,9 @@ class Render extends SpriteView implements IRender {
|
||||
}
|
||||
|
||||
private function clean() {
|
||||
for (bitmap in parts) {
|
||||
table.removeChild(bitmap);
|
||||
for (partView in parts) {
|
||||
table.removeChild(partView);
|
||||
}
|
||||
parts = [];
|
||||
parts = new Map();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,27 @@
|
||||
package ru.m.puzzlez.render;
|
||||
|
||||
import flash.geom.Matrix;
|
||||
import flash.display.BitmapData;
|
||||
import ru.m.puzzlez.core.Grid;
|
||||
import flash.geom.Matrix;
|
||||
import flash.geom.Rectangle;
|
||||
|
||||
class RenderUtil {
|
||||
|
||||
public static function buildRectangle(source:Rectangle, grid:Grid):Rectangle {
|
||||
var r1 = grid.width / grid.height;
|
||||
var r2 = source.width / source.height;
|
||||
if (r1 > r2) {
|
||||
var height = source.width * r1;
|
||||
return new Rectangle(0, (source.height - height) / 2, source.width, height);
|
||||
} else {
|
||||
var width = source.height * r1;
|
||||
return new Rectangle((source.width - width) / 2, 0, width, source.height);
|
||||
}
|
||||
}
|
||||
|
||||
public static function cropImage(source:BitmapData, grid:Grid):BitmapData {
|
||||
var rect = buildRectangle(new Rectangle(0, 0, source.width, source.height), grid);
|
||||
public static function cropImage(source:BitmapData, rect:Rectangle):BitmapData {
|
||||
var image = new BitmapData(Std.int(rect.width), Std.int(rect.height));
|
||||
var matrix = new Matrix();
|
||||
matrix.translate(-rect.x, -rect.y);
|
||||
var scale = Math.max(rect.width / source.width, rect.height / source.height);
|
||||
matrix.scale(scale, scale);
|
||||
matrix.translate((rect.width - source.width * scale) / 2, (rect.height - source.height * scale) / 2);
|
||||
image.draw(source, matrix);
|
||||
return image;
|
||||
}
|
||||
|
||||
public static function cropImagePart(source:BitmapData, grid:Grid, x:Int, y:Int):BitmapData {
|
||||
var partWidth = source.width / grid.width;
|
||||
var partHeight = source.height / grid.height;
|
||||
var rect = new Rectangle(partWidth * x, partHeight * y, partWidth, partHeight);
|
||||
var image = new BitmapData(Std.int(partWidth), Std.int(partHeight));
|
||||
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));
|
||||
var matrix = new Matrix();
|
||||
matrix.translate(-rect.x, -rect.y);
|
||||
image.draw(source, matrix);
|
||||
image.draw(source, matrix, null, null, null, true);
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package ru.m.puzzlez.view;
|
||||
|
||||
import haxework.view.utils.DrawUtil.FillType;
|
||||
import haxework.view.data.DataView;
|
||||
import haxework.view.group.VGroupView;
|
||||
import haxework.view.ImageView;
|
||||
import haxework.view.utils.DrawUtil;
|
||||
import openfl.utils.Assets;
|
||||
import openfl.utils.AssetType;
|
||||
import ru.m.puzzlez.core.Game;
|
||||
import ru.m.puzzlez.core.GameUtil;
|
||||
import ru.m.puzzlez.core.IGame;
|
||||
import ru.m.puzzlez.render.IRender;
|
||||
|
||||
@@ -33,13 +34,15 @@ import ru.m.puzzlez.render.IRender;
|
||||
|
||||
public function start(image:String):Void {
|
||||
stop();
|
||||
game = new Game({image:image, grid: {width: 7, height: 5}});
|
||||
game = new Game(GameUtil.buildPreset(image));
|
||||
game.signal.connect(render.onGameEvent);
|
||||
render.signal.connect(game.signal.emit);
|
||||
game.start();
|
||||
}
|
||||
|
||||
public function stop():Void {
|
||||
if (game != null) {
|
||||
render.signal.disconnect(game.signal.emit);
|
||||
game.stop();
|
||||
game.dispose();
|
||||
game = null;
|
||||
|
||||
@@ -5,11 +5,14 @@ views:
|
||||
- $type: haxework.view.form.LabelView
|
||||
text: Puzzle'z
|
||||
font.size: 42
|
||||
- $type: haxework.view.group.HGroupView
|
||||
geometry.stretch: true
|
||||
views:
|
||||
- id: images
|
||||
$type: haxework.view.data.DataView
|
||||
layout:
|
||||
$type: haxework.view.layout.HorizontalLayout
|
||||
geometry.width: 100%
|
||||
$type: haxework.view.layout.VerticalLayout
|
||||
geometry.height: 100%
|
||||
# geometry.height: 100
|
||||
factory: ~imageViewFactory
|
||||
+onDataSelect: ~start
|
||||
|
||||
BIN
src/resources/avatar_2019.jpg
Normal file
BIN
src/resources/avatar_2019.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 160 KiB |
Reference in New Issue
Block a user