[add] GameStorage

This commit is contained in:
2020-02-04 21:34:18 +03:00
parent a3fef53956
commit 8f934ba365
21 changed files with 181 additions and 66 deletions

View File

@@ -11,8 +11,8 @@ class Game implements IGame {
private var partsById:Map<Int, Part>; private var partsById:Map<Int, Part>;
public function new(preset:GamePreset) { public function new(state:GameState) {
state = GameUtil.buildState(preset); this.state = state;
partsById = new Map(); partsById = new Map();
for (part in state.parts) { for (part in state.parts) {
partsById[part.id] = part; partsById[part.id] = part;
@@ -23,7 +23,10 @@ class Game implements IGame {
public function start():Void { public function start():Void {
signal.emit(GameEvent.START(state)); signal.emit(GameEvent.START(state));
shuffle(); if (!state.started) {
shuffle();
state.started = true;
}
} }
public function shuffle():Void { public function shuffle():Void {

View File

@@ -1,6 +1,7 @@
package ru.m.puzzlez.core; package ru.m.puzzlez.core;
typedef GameState = { typedef GameState = {
var started:Bool;
var preset:GamePreset; var preset:GamePreset;
var parts:Array<Part>; var parts:Array<Part>;
} }

View File

@@ -125,6 +125,7 @@ class GameUtil {
} }
} }
return { return {
started: false,
preset: preset, preset: preset,
parts: parts, parts: parts,
} }

View File

@@ -78,9 +78,16 @@ class Render extends SpriteView implements IRender {
this.state = state; this.state = state;
for (part in state.parts) { for (part in state.parts) {
var partView = PartView.factory(part); var partView = PartView.factory(part);
partView.position = part.rect.topLeft;
parts.set(part.id, partView); parts.set(part.id, partView);
tableView.addChild(partView); switch part.location {
case TABLE(point):
partView.position = point;
tableView.addChild(partView);
case IMAGE:
partView.complete();
imageView.addChild(partView);
case _:
}
} }
imageView.x = state.preset.imageRect.x; imageView.x = state.preset.imageRect.x;
@@ -105,7 +112,9 @@ class Render extends SpriteView implements IRender {
parts[result.part.id].image = result.image; parts[result.part.id].image = result.image;
progress.setProgress(++i, state.parts.length); progress.setProgress(++i, state.parts.length);
}).endThen(function(_) { }).endThen(function(_) {
content.removeChild(progress.content); if (progress.content.parent != null) {
progress.content.parent.removeChild(progress.content);
}
}); });
} }

View File

@@ -1,4 +1,4 @@
package ru.m.puzzlez.storage; package ru.m.puzzlez.source;
import flash.display.BitmapData; import flash.display.BitmapData;
import openfl.Assets; import openfl.Assets;

View File

@@ -1,4 +1,4 @@
package ru.m.puzzlez.storage; package ru.m.puzzlez.source;
import flash.display.BitmapData; import flash.display.BitmapData;
import flash.net.SharedObject; import flash.net.SharedObject;

View File

@@ -0,0 +1,24 @@
package ru.m.puzzlez.source;
import haxework.storage.SharedObjectStorage;
import ru.m.puzzlez.core.GameState;
import ru.m.puzzlez.core.Id.ImageId;
@:provide class GameStorage extends SharedObjectStorage {
public function new() {
super('game_1');
}
public function save(state:GameState):Void {
write(state.preset.image, state);
}
public function load(imageId:ImageId):Null<GameState> {
return read(imageId);
}
public function list():Array<ImageId> {
return [for (key in Reflect.fields(so.data)) ImageId.fromString(key)];
}
}

View File

@@ -1,4 +1,4 @@
package ru.m.puzzlez.storage; package ru.m.puzzlez.source;
import flash.display.BitmapData; import flash.display.BitmapData;
import promhx.Promise; import promhx.Promise;

View File

@@ -1,4 +1,4 @@
package ru.m.puzzlez.storage; package ru.m.puzzlez.source;
import flash.display.BitmapData; import flash.display.BitmapData;
import haxework.net.ImageLoader; import haxework.net.ImageLoader;

View File

@@ -13,6 +13,10 @@ import promhx.Deferred;
import promhx.Promise; import promhx.Promise;
import Reflect; import Reflect;
import ru.m.puzzlez.core.Id; import ru.m.puzzlez.core.Id;
import ru.m.puzzlez.source.AssetSource;
import ru.m.puzzlez.source.FileSource;
import ru.m.puzzlez.source.IImageSource;
import ru.m.puzzlez.source.PixabaySource;
@:provide class ImageStorage { @:provide class ImageStorage {

View File

@@ -3,25 +3,30 @@ package ru.m.puzzlez.view;
import haxework.view.frame.FrameSwitcher; import haxework.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView; import haxework.view.frame.FrameView;
import ru.m.puzzlez.core.Game; import ru.m.puzzlez.core.Game;
import ru.m.puzzlez.core.GamePreset; import ru.m.puzzlez.core.GameEvent;
import ru.m.puzzlez.core.GameState;
import ru.m.puzzlez.core.IGame; import ru.m.puzzlez.core.IGame;
import ru.m.puzzlez.core.PartLocation;
import ru.m.puzzlez.render.IRender; import ru.m.puzzlez.render.IRender;
import ru.m.puzzlez.source.GameStorage;
@:template class GameFrame extends FrameView<GamePreset> { @:template class GameFrame extends FrameView<GameState> {
public static var ID = "game"; public static var ID = "game";
@:view private var render:IRender; @:view private var render:IRender;
private var game:IGame; private var game:IGame;
@:provide var switcher:FrameSwitcher; @:provide var switcher:FrameSwitcher;
@:provide var storage:GameStorage;
public function new() { public function new() {
super(ID); super(ID);
} }
override public function onShow(preset:GamePreset):Void { override public function onShow(state:GameState):Void {
onHide(); onHide();
game = new Game(preset); game = new Game(state);
game.signal.connect(render.onGameEvent); game.signal.connect(render.onGameEvent);
game.signal.connect(onGameEvent);
render.signal.connect(game.signal.emit); render.signal.connect(game.signal.emit);
game.start(); game.start();
} }
@@ -35,7 +40,15 @@ import ru.m.puzzlez.render.IRender;
} }
} }
private function onGameEvent(event:GameEvent):Void {
switch event {
case CHANGE(PART_UPDATE(_, IMAGE)):
storage.save(game.state);
case _:
}
}
private function back():Void { private function back():Void {
switcher.change(ImagesFrame.ID); switcher.change(ImageListFrame.ID);
} }
} }

View File

@@ -0,0 +1,34 @@
package ru.m.puzzlez.view;
import haxework.view.data.DataView;
import haxework.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView;
import ru.m.puzzlez.core.Id;
import ru.m.puzzlez.source.GameStorage;
@:template class GameListFrame extends FrameView<Dynamic> {
public static var ID(default, never) = "game_list";
@:view var images:DataView<ImageId, PuzzleImageView>;
@:provide var switcher:FrameSwitcher;
@:provide var storage:GameStorage;
public function new() {
super(ID);
}
override public function onShow(data:Dynamic):Void {
images.data = storage.list();
}
private function start(image:ImageId):Void {
var state = storage.load(image);
switcher.change(GameFrame.ID, state);
}
private function back():Void {
switcher.change(StartFrame.ID);
}
}

View File

@@ -0,0 +1,20 @@
---
style: frame
views:
- id: images
$type: haxework.view.data.DataView
layout:
$type: haxework.view.layout.TailLayout
margin: 5
vAlign: middle
geometry.stretch: true
factory: ~ru.m.puzzlez.view.PuzzleImageView.factory
+onDataSelect: ~start
geometry.margin: 5
overflow.y: scroll
- $type: haxework.view.form.ButtonView
text: Back
geometry.position: absolute
geometry.hAlign: right
geometry.vAlign: top
+onPress: ~back()

View File

@@ -1,49 +1,16 @@
package ru.m.puzzlez.view; package ru.m.puzzlez.view;
import haxework.view.group.GroupView;
import haxework.view.data.DataView; import haxework.view.data.DataView;
import haxework.view.form.ButtonView; import haxework.view.form.ButtonView;
import haxework.view.frame.FrameSwitcher; import haxework.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView; import haxework.view.frame.FrameView;
import haxework.view.ImageView;
import haxework.view.utils.DrawUtil;
import ru.m.puzzlez.core.Id; import ru.m.puzzlez.core.Id;
import ru.m.puzzlez.FileUtil; import ru.m.puzzlez.FileUtil;
import ru.m.puzzlez.storage.FileSource; import ru.m.puzzlez.source.FileSource;
import ru.m.puzzlez.storage.ImageStorage; import ru.m.puzzlez.storage.ImageStorage;
@:template class ImageListFrame extends FrameView<ImageListSource<Dynamic>> {
class PuzzleImageView extends GroupView { public static var ID = "image_list";
public var imageId(null, set):ImageId;
private function set_imageId(value:ImageId):ImageId {
if (imageId != value) {
imageId = value;
loading.promise = imageStorage.resolve(imageId, true).then(function(data) image.image = data);
}
return imageId;
}
private var image:ImageView;
private var loading:LoadingWrapper;
@:provide var imageStorage:ImageStorage;
public function new() {
super();
style = "view";
image = new ImageView();
image.geometry.stretch = true;
image.stretch = false;
image.fillType = COVER;
addView(image);
loading = new LoadingWrapper(this);
}
}
@:template class ImagesFrame extends FrameView<ImageListSource<Dynamic>> {
public static var ID = "images";
@:view var images:DataView<ImageId, PuzzleImageView>; @:view var images:DataView<ImageId, PuzzleImageView>;
@:view var select:ButtonView; @:view var select:ButtonView;
@@ -71,12 +38,6 @@ class PuzzleImageView extends GroupView {
//images.data = []; //images.data = [];
} }
private function imageViewFactory(index:Int, imageId:ImageId):PuzzleImageView {
var result = new PuzzleImageView();
result.imageId = imageId;
return result;
}
private function selectFile():Void { private function selectFile():Void {
FileUtil.browse().then(function(data:FileContent) { FileUtil.browse().then(function(data:FileContent) {
var fileSource:FileSource = cast source.source; var fileSource:FileSource = cast source.source;

View File

@@ -8,7 +8,7 @@ views:
margin: 5 margin: 5
vAlign: middle vAlign: middle
geometry.stretch: true geometry.stretch: true
factory: ~imageViewFactory factory: ~ru.m.puzzlez.view.PuzzleImageView.factory
+onDataSelect: ~start +onDataSelect: ~start
geometry.margin: 5 geometry.margin: 5
overflow.y: scroll overflow.y: scroll

View File

@@ -1,6 +1,6 @@
package ru.m.puzzlez.view; package ru.m.puzzlez.view;
import ru.m.puzzlez.storage.IImageSource; import ru.m.puzzlez.source.IImageSource;
typedef ImageListSource<T> = { typedef ImageListSource<T> = {
var source:IImageSource<T>; var source:IImageSource<T>;

View File

@@ -47,10 +47,10 @@ import ru.m.puzzlez.storage.ImageStorage;
} }
private function start():Void { private function start():Void {
switcher.change(GameFrame.ID, imageView.preset); switcher.change(GameFrame.ID, GameUtil.buildState(imageView.preset));
} }
private function back():Void { private function back():Void {
switcher.change(ImagesFrame.ID); switcher.change(ImageListFrame.ID);
} }
} }

View File

@@ -0,0 +1,41 @@
package ru.m.puzzlez.view;
import haxework.view.group.GroupView;
import haxework.view.ImageView;
import haxework.view.utils.DrawUtil;
import ru.m.puzzlez.core.Id;
import ru.m.puzzlez.storage.ImageStorage;
class PuzzleImageView extends GroupView {
public var imageId(null, set):ImageId;
private function set_imageId(value:ImageId):ImageId {
if (imageId != value) {
imageId = value;
loading.promise = imageStorage.resolve(imageId, true).then(function(data) image.image = data);
}
return imageId;
}
private var image:ImageView;
private var loading:LoadingWrapper;
@:provide var imageStorage:ImageStorage;
public function new() {
super();
style = "view";
image = new ImageView();
image.geometry.stretch = true;
image.stretch = false;
image.fillType = COVER;
addView(image);
loading = new LoadingWrapper(this);
}
public static function factory(index:Int, imageId:ImageId):PuzzleImageView {
var result = new PuzzleImageView();
result.imageId = imageId;
return result;
}
}

View File

@@ -6,6 +6,7 @@ views:
style: dark style: dark
factory: factory:
_start_: {$class: ru.m.puzzlez.view.StartFrame} _start_: {$class: ru.m.puzzlez.view.StartFrame}
_images_: {$class: ru.m.puzzlez.view.ImagesFrame} _game_list_: {$class: ru.m.puzzlez.view.GameListFrame}
_image_list_: {$class: ru.m.puzzlez.view.ImageListFrame}
_preset_: {$class: ru.m.puzzlez.view.PresetFrame} _preset_: {$class: ru.m.puzzlez.view.PresetFrame}
_game_: {$class: ru.m.puzzlez.view.GameFrame} _game_: {$class: ru.m.puzzlez.view.GameFrame}

View File

@@ -4,10 +4,10 @@ import haxework.view.data.DataView;
import haxework.view.form.ButtonView; import haxework.view.form.ButtonView;
import haxework.view.frame.FrameSwitcher; import haxework.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView; import haxework.view.frame.FrameView;
import ru.m.puzzlez.storage.AssetSource; import ru.m.puzzlez.source.AssetSource;
import ru.m.puzzlez.storage.FileSource; import ru.m.puzzlez.source.FileSource;
import ru.m.puzzlez.storage.ImageStorage; import ru.m.puzzlez.storage.ImageStorage;
import ru.m.puzzlez.storage.PixabaySource; import ru.m.puzzlez.source.PixabaySource;
@:template class StartFrame extends FrameView<Dynamic> { @:template class StartFrame extends FrameView<Dynamic> {
public static var ID = "start"; public static var ID = "start";
@@ -34,6 +34,6 @@ import ru.m.puzzlez.storage.PixabaySource;
} }
private function load(source:ImageListSource<Dynamic>):Void { private function load(source:ImageListSource<Dynamic>):Void {
switcher.change(ImagesFrame.ID, source); switcher.change(ImageListFrame.ID, source);
} }
} }

View File

@@ -18,3 +18,6 @@ views:
+onDataSelect: ~load +onDataSelect: ~load
geometry.margin: 5 geometry.margin: 5
overflow.y: scroll overflow.y: scroll
- $type: haxework.view.form.ButtonView
text: Load
+onPress: ~switcher.change('game_list')