Tetris example: add controls

This commit is contained in:
Vadim Lopatin 2014-12-26 15:08:17 +03:00
parent a77a20e6e7
commit 981f53b825
11 changed files with 95 additions and 46 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -14,14 +14,15 @@ enum TetrisAction : int {
LevelUp, LevelUp,
} }
const Action ACTION_MOVE_LEFT = (new Action(TetrisAction.MoveLeft, KeyCode.LEFT)).addAccelerator(KeyCode.KEY_A); const Action ACTION_MOVE_LEFT = (new Action(TetrisAction.MoveLeft, KeyCode.LEFT)).addAccelerator(KeyCode.KEY_A).iconId("arrow-left");
const Action ACTION_MOVE_RIGHT = (new Action(TetrisAction.MoveRight, KeyCode.RIGHT)).addAccelerator(KeyCode.KEY_D); const Action ACTION_MOVE_RIGHT = (new Action(TetrisAction.MoveRight, KeyCode.RIGHT)).addAccelerator(KeyCode.KEY_D).iconId("arrow-right");
const Action ACTION_ROTATE = (new Action(TetrisAction.RotateCCW, KeyCode.UP)).addAccelerator(KeyCode.KEY_W); const Action ACTION_ROTATE = (new Action(TetrisAction.RotateCCW, KeyCode.UP)).addAccelerator(KeyCode.KEY_W).iconId("rotate");
const Action ACTION_FAST_DOWN = (new Action(TetrisAction.FastDown, KeyCode.SPACE)).addAccelerator(KeyCode.KEY_S); const Action ACTION_FAST_DOWN = (new Action(TetrisAction.FastDown, KeyCode.SPACE)).addAccelerator(KeyCode.KEY_S).iconId("arrow-down");
const Action ACTION_PAUSE = (new Action(TetrisAction.Pause, KeyCode.ESCAPE)).addAccelerator(KeyCode.PAUSE); const Action ACTION_PAUSE = (new Action(TetrisAction.Pause, KeyCode.ESCAPE)).addAccelerator(KeyCode.PAUSE).iconId("pause");
const Action ACTION_LEVEL_UP = (new Action(TetrisAction.LevelUp, KeyCode.ADD)).addAccelerator(KeyCode.INS); const Action ACTION_LEVEL_UP = (new Action(TetrisAction.LevelUp, KeyCode.ADD)).addAccelerator(KeyCode.INS).iconId("levelup");
const Action[] CUP_ACTIONS = [ACTION_MOVE_LEFT, ACTION_MOVE_RIGHT, ACTION_ROTATE, ACTION_FAST_DOWN, ACTION_PAUSE, ACTION_LEVEL_UP]; const Action[] CUP_ACTIONS = [ACTION_PAUSE, ACTION_ROTATE, ACTION_LEVEL_UP,
ACTION_MOVE_LEFT, ACTION_FAST_DOWN, ACTION_MOVE_RIGHT];
/// about dialog /// about dialog
Widget createAboutWidget() Widget createAboutWidget()
@ -88,12 +89,14 @@ class CupWidget : Widget {
protected int _totalRowsDestroyed; protected int _totalRowsDestroyed;
static const int[10] LEVEL_SPEED = [15000000, 10000000, 7000000, 6000000, 5000000, 4000000, 3500000, 3000000, 2500000, 2000000]; static const int[10] LEVEL_SPEED = [15000000, 10000000, 7000000, 6000000, 5000000, 4000000, 300000, 2000000, 1500000, 1000000];
static const int RESERVED_ROWS = 5; // reserved for next figure static const int RESERVED_ROWS = 5; // reserved for next figure
/// set difficulty level 1..10 /// set difficulty level 1..10
void setLevel(int level) { void setLevel(int level) {
if (level > 10)
return;
_level = level; _level = level;
_movementDuration = LEVEL_SPEED[level - 1]; _movementDuration = LEVEL_SPEED[level - 1];
_status.setLevel(_level); _status.setLevel(_level);
@ -455,9 +458,7 @@ class CupWidget : Widget {
// TODO: implement pause // TODO: implement pause
return true; return true;
case TetrisAction.LevelUp: case TetrisAction.LevelUp:
if (_level < 10) setLevel(_level + 1);
_level++;
// TODO: update state
return true; return true;
default: default:
if (parent) // by default, pass to parent widget if (parent) // by default, pass to parent widget
@ -474,7 +475,7 @@ class CupWidget : Widget {
this(StatusWidget status) { this(StatusWidget status) {
super("CUP"); super("CUP");
this._status = status; this._status = status;
layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT).layoutWeight(3).setState(State.Default).focusable(true).padding(Rect(20, 20, 20, 20)); layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT).layoutWeight(2).setState(State.Default).focusable(true).padding(Rect(20, 20, 20, 20));
_cols = 10; _cols = 10;
_rows = 18; _rows = 18;
@ -500,11 +501,36 @@ class StatusWidget : VerticalLayout {
res.layoutWidth(FILL_PARENT).alignment(Align.Center).fontSize(25).textColor(color); res.layoutWidth(FILL_PARENT).alignment(Align.Center).fontSize(25).textColor(color);
return res; return res;
} }
Widget createControls() {
TableLayout res = new TableLayout();
res.colCount = 3;
foreach(const Action a; CUP_ACTIONS) {
ImageButton btn = new ImageButton(a);
btn.focusable = false;
res.addChild(btn);
}
res.layoutWidth(WRAP_CONTENT).layoutHeight(WRAP_CONTENT).margins(Rect(10, 10, 10, 10)).alignment(Align.Center);
return res;
}
this() { this() {
super("CUP_STATUS"); super("CUP_STATUS");
addChild(new VSpacer()); addChild(new VSpacer());
addChild((new ImageWidget(null, "tetris_logo_big")).layoutWidth(FILL_PARENT).alignment(Align.Center));
ImageWidget image = new ImageWidget(null, "tetris_logo_big");
image.layoutWidth(FILL_PARENT).alignment(Align.Center).clickable(true);
image.onClickListener = delegate(Widget src) {
_cup.handleAction(ACTION_PAUSE);
// about dialog when clicking on image
Window wnd = Platform.instance.createWindow("About...", window, WindowFlag.Modal);
wnd.mainWidget = createAboutWidget();
wnd.show();
return true;
};
addChild(image);
addChild(new VSpacer()); addChild(new VSpacer());
addChild(createTextWidget("Level:"d, 0x008000)); addChild(createTextWidget("Level:"d, 0x008000));
addChild((_level = createTextWidget(""d, 0x008000))); addChild((_level = createTextWidget(""d, 0x008000)));
@ -515,9 +541,10 @@ class StatusWidget : VerticalLayout {
addChild(createTextWidget("Score:"d, 0x800000)); addChild(createTextWidget("Score:"d, 0x800000));
addChild((_score = createTextWidget(""d, 0x800000))); addChild((_score = createTextWidget(""d, 0x800000)));
addChild(new VSpacer()); addChild(new VSpacer());
addChild(createControls());
addChild(new VSpacer()); addChild(new VSpacer());
layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT).layoutWeight(2).padding(Rect(20, 20, 20, 20)); layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT).layoutWeight(2).padding(Rect(10, 10, 10, 10));
} }
void setLevel(int level) { void setLevel(int level) {
@ -554,7 +581,7 @@ class CupPage : HorizontalLayout {
override void measure(int parentWidth, int parentHeight) { override void measure(int parentWidth, int parentHeight) {
super.measure(parentWidth, parentHeight); super.measure(parentWidth, parentHeight);
/// fixed size /// fixed size
measuredContent(parentWidth, parentHeight, 550, 550); measuredContent(parentWidth, parentHeight, 600, 550);
} }
} }

View File

@ -74,59 +74,59 @@ const Figure[7] FIGURES = [
// ## #### // ## ####
// 00## 00## // 00## 00##
// ## // ##
Figure([FigureShape([1, 0], [1, 1], [0, -1]), Figure([FigureShape([1, 0], [ 1, 1], [0,-1]),
FigureShape([0, 1], [-1, 1], [1, 0]), FigureShape([0, 1], [-1, 1], [1, 0]),
FigureShape([1, 0], [1, 1], [0, -1]), FigureShape([1, 0], [ 1, 1], [0,-1]),
FigureShape([0, 1], [-1, 1], [1, 0])]), FigureShape([0, 1], [-1, 1], [1, 0])]),
// FIGURE2 =========================================== // FIGURE2 ===========================================
// ## #### // ## ####
// 00## ##00 // 00## ##00
// ## // ##
Figure([FigureShape([1, 0], [0, 1], [1, 1]), Figure([FigureShape([1, 0], [0, 1], [ 1,-1]),
FigureShape([0, 1], [1, 1], [-1, 0]), FigureShape([0, 1], [1, 1], [-1, 0]),
FigureShape([1, 0], [0, 1], [1, 1]), FigureShape([1, 0], [0, 1], [ 1,-1]),
FigureShape([0, 1], [1, 1], [-1, 0])]), FigureShape([0, 1], [1, 1], [-1, 0])]),
// FIGURE3 =========================================== // FIGURE3 ===========================================
// ## ## #### // ## ## ####
// ##00## 00 ##00## 00 // ##00## 00 ##00## 00
// ## #### ## // ## #### ##
Figure([FigureShape([1, 0], [-1,0], [-1,-1]), Figure([FigureShape([1, 0], [-1, 0], [-1,-1]),
FigureShape([0, 1], [0,-1], [ 1,-1]), FigureShape([0, 1], [ 0,-1], [ 1,-1]),
FigureShape([1, 0], [-1,0], [1, 1]), FigureShape([1, 0], [-1, 0], [ 1, 1]),
FigureShape([0, 1], [-1,1], [0,-1])]), FigureShape([0, 1], [-1, 1], [ 0,-1])]),
// FIGURE4 =========================================== // FIGURE4 ===========================================
// #### ## ## // #### ## ##
// ##00## 00 ##00## 00 // ##00## 00 ##00## 00
// ## ## #### // ## ## ####
Figure([FigureShape([1, 0], [-1,0], [ 1,-1]), Figure([FigureShape([1, 0], [-1, 0], [ 1,-1]),
FigureShape([0, 1], [0,-1], [ 1, 1]), FigureShape([0, 1], [ 0,-1], [ 1, 1]),
FigureShape([1, 0], [-1,0], [-1, 1]), FigureShape([1, 0], [-1, 0], [-1, 1]),
FigureShape([0, 1], [-1,-1], [0, -1])]), FigureShape([0, 1], [-1,-1], [ 0,-1])]),
// FIGURE5 =========================================== // FIGURE5 ===========================================
// #### // ####
// 00## // 00##
// //
Figure([FigureShape([1, 0], [0, 1], [ 1, 1]), Figure([FigureShape([1, 0], [0, 1], [ 1, 1]),
FigureShape([1, 0], [0, 1], [ 1, 1]), FigureShape([1, 0], [0, 1], [ 1, 1]),
FigureShape([1, 0], [0, 1], [ 1, 1]), FigureShape([1, 0], [0, 1], [ 1, 1]),
FigureShape([1, 0], [0, 1], [ 1, 1])]), FigureShape([1, 0], [0, 1], [ 1, 1])]),
// FIGURE6 =========================================== // FIGURE6 ===========================================
// ## // ##
// ## // ##
// 00 ##00#### // 00 ##00####
// ## // ##
Figure([FigureShape([0, 1], [0, 2], [ 0,-1]), Figure([FigureShape([0, 1], [0, 2], [ 0,-1]),
FigureShape([1, 0], [2, 0], [-1, 0]), FigureShape([1, 0], [2, 0], [-1, 0]),
FigureShape([0, 1], [0, 2], [ 0,-1]), FigureShape([0, 1], [0, 2], [ 0,-1]),
FigureShape([1, 0], [2, 0], [-1, 0])]), FigureShape([1, 0], [2, 0], [-1, 0])]),
// FIGURE7 =========================================== // FIGURE7 ===========================================
// ## ## ## // ## ## ##
// ##00## 00## ##00## ##00 // ##00## 00## ##00## ##00
// ## ## ## // ## ## ##
Figure([FigureShape([1, 0], [-1,0], [ 0,-1]), Figure([FigureShape([1, 0], [-1,0], [ 0,-1]),
FigureShape([0, 1], [0,-1], [ 1, 0]), FigureShape([0, 1], [0,-1], [ 1, 0]),
FigureShape([1, 0], [-1,0], [ 0, 1]), FigureShape([1, 0], [-1,0], [ 0, 1]),
FigureShape([0, 1], [0,-1], [-1, 0])]), FigureShape([0, 1], [0,-1], [-1, 0])]),
]; ];
/// colors for different figure types /// colors for different figure types

View File

@ -30,7 +30,8 @@ module dlangui.widgets.controls;
import dlangui.widgets.widget; import dlangui.widgets.widget;
import dlangui.widgets.layouts; import dlangui.widgets.layouts;
import std.algorithm; private import std.algorithm;
private import std.conv : to;
/// vertical spacer to fill empty space in vertical layouts /// vertical spacer to fill empty space in vertical layouts
class VSpacer : Widget { class VSpacer : Widget {
@ -171,6 +172,7 @@ class ImageWidget : Widget {
} }
measuredContent(parentWidth, parentHeight, w, h); measuredContent(parentWidth, parentHeight, w, h);
} }
override void onDraw(DrawBuf buf) { override void onDraw(DrawBuf buf) {
if (visibility != Visibility.Visible) if (visibility != Visibility.Visible)
return; return;
@ -194,6 +196,7 @@ class ImageWidget : Widget {
/// button with image only /// button with image only
class ImageButton : ImageWidget { class ImageButton : ImageWidget {
/// constructor by id and icon resource id
this(string ID = null, string drawableId = null) { this(string ID = null, string drawableId = null) {
super(ID, drawableId); super(ID, drawableId);
styleId = "BUTTON"; styleId = "BUTTON";
@ -202,8 +205,11 @@ class ImageButton : ImageWidget {
focusable = true; focusable = true;
trackHover = true; trackHover = true;
} }
/// constructor from action
this(const Action a) {
this("imagebutton-action" ~ to!string(a.id), a.iconId);
action = a;
}
} }
/// button with image and text /// button with image and text
@ -265,6 +271,14 @@ class ImageTextButton : HorizontalLayout {
UIString caption = rawText; UIString caption = rawText;
init(drawableId, caption); init(drawableId, caption);
} }
/// constructor from action
this(const Action a) {
super("imagetextbutton-action" ~ to!string(a.id));
init(a.iconId, a.labelValue);
action = a;
}
} }
/// checkbox /// checkbox
@ -353,6 +367,12 @@ class Button : Widget {
focusable = true; focusable = true;
trackHover = true; trackHover = true;
} }
/// constructor from action
this(const Action a) {
this("button-action" ~ to!string(a.id));
_text = a.labelValue;
action = a;
}
override void measure(int parentWidth, int parentHeight) { override void measure(int parentWidth, int parentHeight) {
FontRef font = font(); FontRef font = font();

View File

@ -625,7 +625,7 @@ class FrameLayout : WidgetGroup {
/// layout children as table with rows and columns /// layout children as table with rows and columns
class TableLayout : WidgetGroup { class TableLayout : WidgetGroup {
this(string ID) { this(string ID = null) {
super(ID); super(ID);
} }

View File

@ -598,7 +598,9 @@ class Widget {
protected Action _action; protected Action _action;
/// action to emit on click /// action to emit on click
@property Action action() { return _action; } @property const(Action) action() { return _action; }
/// action to emit on click
@property void action(const Action action) { _action = action.clone; }
/// action to emit on click /// action to emit on click
@property void action(Action action) { _action = action; } @property void action(Action action) { _action = action; }