mirror of https://github.com/buggins/dlangui.git
Tetris example improvements
This commit is contained in:
parent
af5a631051
commit
a77a20e6e7
|
@ -1,14 +1,29 @@
|
|||
module gui;
|
||||
|
||||
import dlangui.all;
|
||||
import dlangui.widgets.popup;
|
||||
import dlangui.graphics.drawbuf;
|
||||
//import std.stdio;
|
||||
import std.conv;
|
||||
import std.utf;
|
||||
import model;
|
||||
|
||||
import dlangui.all;
|
||||
|
||||
/// game action codes
|
||||
enum TetrisAction : int {
|
||||
MoveLeft = 10000,
|
||||
MoveRight,
|
||||
RotateCCW,
|
||||
FastDown,
|
||||
Pause,
|
||||
LevelUp,
|
||||
}
|
||||
|
||||
const Action ACTION_MOVE_LEFT = (new Action(TetrisAction.MoveLeft, KeyCode.LEFT)).addAccelerator(KeyCode.KEY_A);
|
||||
const Action ACTION_MOVE_RIGHT = (new Action(TetrisAction.MoveRight, KeyCode.RIGHT)).addAccelerator(KeyCode.KEY_D);
|
||||
const Action ACTION_ROTATE = (new Action(TetrisAction.RotateCCW, KeyCode.UP)).addAccelerator(KeyCode.KEY_W);
|
||||
const Action ACTION_FAST_DOWN = (new Action(TetrisAction.FastDown, KeyCode.SPACE)).addAccelerator(KeyCode.KEY_S);
|
||||
const Action ACTION_PAUSE = (new Action(TetrisAction.Pause, KeyCode.ESCAPE)).addAccelerator(KeyCode.PAUSE);
|
||||
const Action ACTION_LEVEL_UP = (new Action(TetrisAction.LevelUp, KeyCode.ADD)).addAccelerator(KeyCode.INS);
|
||||
|
||||
const Action[] CUP_ACTIONS = [ACTION_MOVE_LEFT, ACTION_MOVE_RIGHT, ACTION_ROTATE, ACTION_FAST_DOWN, ACTION_PAUSE, ACTION_LEVEL_UP];
|
||||
|
||||
/// about dialog
|
||||
Widget createAboutWidget()
|
||||
{
|
||||
LinearLayout res = new VerticalLayout();
|
||||
|
@ -26,16 +41,24 @@ Widget createAboutWidget()
|
|||
return res;
|
||||
}
|
||||
|
||||
enum TetrisAction : int {
|
||||
MoveLeft = 10000,
|
||||
MoveRight,
|
||||
RotateCCW,
|
||||
FastDown,
|
||||
Pause,
|
||||
LevelUp,
|
||||
/// Cup States
|
||||
enum CupState : int {
|
||||
/// New figure appears
|
||||
NewFigure,
|
||||
/// Game is paused
|
||||
Paused,
|
||||
/// Figure is falling
|
||||
FallingFigure,
|
||||
/// Figure is hanging - pause between falling by one row
|
||||
HangingFigure,
|
||||
/// destroying complete rows
|
||||
DestroyingRows,
|
||||
/// falling after some rows were destroyed
|
||||
FallingRows,
|
||||
/// Game is over
|
||||
GameOver,
|
||||
}
|
||||
|
||||
|
||||
/// Cup widget
|
||||
class CupWidget : Widget {
|
||||
/// cup columns count
|
||||
|
@ -54,37 +77,21 @@ class CupWidget : Widget {
|
|||
long _movementDuration;
|
||||
/// When true, figure is falling down fast
|
||||
bool _fastDownFlag;
|
||||
|
||||
/// animation helper for fade and movement in different states
|
||||
AnimationHelper _animation;
|
||||
/// GameOver popup
|
||||
private PopupWidget _gameOverPopup;
|
||||
|
||||
/// Cup States
|
||||
enum CupState : int {
|
||||
/// New figure appears
|
||||
NewFigure,
|
||||
/// Game is paused
|
||||
Paused,
|
||||
/// Figure is falling
|
||||
FallingFigure,
|
||||
/// Figure is hanging - pause between falling by one row
|
||||
HangingFigure,
|
||||
/// destroying complete rows
|
||||
DestroyingRows,
|
||||
/// falling after some rows were destroyed
|
||||
FallingRows,
|
||||
/// Game is over
|
||||
GameOver,
|
||||
}
|
||||
|
||||
/// Status widget
|
||||
private StatusWidget _status;
|
||||
/// Current state
|
||||
protected CupState _state;
|
||||
|
||||
protected int _totalRowsDestroyed;
|
||||
|
||||
static const int[10] LEVEL_SPEED = [15000000, 10000000, 7000000, 6000000, 5000000, 4000000, 3500000, 3000000, 2500000, 2000000];
|
||||
|
||||
|
||||
static const int RESERVED_ROWS = 5; // reserved for next figure
|
||||
|
||||
|
||||
|
||||
/// set difficulty level 1..10
|
||||
void setLevel(int level) {
|
||||
_level = level;
|
||||
|
@ -93,8 +100,10 @@ class CupWidget : Widget {
|
|||
}
|
||||
|
||||
static const int MIN_FAST_FALLING_INTERVAL = 600000;
|
||||
static const int ROWS_FALLING_INTERVAL = 600000;
|
||||
|
||||
static const int ROWS_FALLING_INTERVAL = 1200000;
|
||||
|
||||
/// change game state, init state animation when necessary
|
||||
void setCupState(CupState state) {
|
||||
int animationIntervalPercent = 100;
|
||||
switch (state) {
|
||||
|
@ -114,6 +123,8 @@ class CupWidget : Widget {
|
|||
animationIntervalPercent = 50;
|
||||
break;
|
||||
default:
|
||||
// no animation for other states
|
||||
animationIntervalPercent = 0;
|
||||
break;
|
||||
}
|
||||
_state = state;
|
||||
|
@ -128,18 +139,14 @@ class CupWidget : Widget {
|
|||
invalidate();
|
||||
}
|
||||
|
||||
/// returns true is widget is being animated - need to call animate() and redraw
|
||||
override @property bool animating() {
|
||||
switch (_state) {
|
||||
case CupState.NewFigure:
|
||||
case CupState.FallingFigure:
|
||||
case CupState.HangingFigure:
|
||||
case CupState.DestroyingRows:
|
||||
case CupState.FallingRows:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
void addScore(int score) {
|
||||
_score += score;
|
||||
_status.setScore(_score);
|
||||
}
|
||||
|
||||
/// returns true if figure is in falling - movement state
|
||||
@property bool falling() {
|
||||
return _state == CupState.FallingFigure;
|
||||
}
|
||||
|
||||
/// Turn on / off fast falling down
|
||||
|
@ -167,6 +174,8 @@ class CupWidget : Widget {
|
|||
return true;
|
||||
}
|
||||
|
||||
static const int[] NEXT_LEVEL_SCORE = [0, 20, 50, 100, 200, 350, 500, 750, 1000, 1500, 2000];
|
||||
|
||||
/// try start next figure
|
||||
protected void nextFigure() {
|
||||
if (!_cup.dropNextFigure()) {
|
||||
|
@ -177,6 +186,8 @@ class CupWidget : Widget {
|
|||
_gameOverPopup = window.showPopup(popupWidget, this);
|
||||
} else {
|
||||
setCupState(CupState.NewFigure);
|
||||
if (_level < 10 && _totalRowsDestroyed >= NEXT_LEVEL_SCORE[_level])
|
||||
setLevel(_level + 1); // level up
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,6 +225,8 @@ class CupWidget : Widget {
|
|||
break;
|
||||
case CupState.DestroyingRows:
|
||||
int rowsDestroyed = _cup.destroyFullRows();
|
||||
_totalRowsDestroyed += rowsDestroyed;
|
||||
_status.setRowsDestroyed(_totalRowsDestroyed);
|
||||
int scorePerRow = 0;
|
||||
for (int i = 0; i < rowsDestroyed; i++) {
|
||||
scorePerRow += 10;
|
||||
|
@ -245,14 +258,23 @@ class CupWidget : Widget {
|
|||
}
|
||||
}
|
||||
|
||||
/// animates window; interval is time left from previous draw, in hnsecs (1/10000000 of second)
|
||||
override void animate(long interval) {
|
||||
_animation.animate(interval);
|
||||
if (_animation.finished) {
|
||||
onAnimationFinished();
|
||||
/// start new game
|
||||
void newGame() {
|
||||
setLevel(1);
|
||||
init(_cols, _rows);
|
||||
_cup.dropNextFigure();
|
||||
setCupState(CupState.NewFigure);
|
||||
if (window && _gameOverPopup) {
|
||||
window.removePopup(_gameOverPopup);
|
||||
_gameOverPopup = null;
|
||||
}
|
||||
_score = 0;
|
||||
_status.setScore(0);
|
||||
_totalRowsDestroyed = 0;
|
||||
_status.setRowsDestroyed(0);
|
||||
}
|
||||
|
||||
/// init cup
|
||||
void init(int cols, int rows) {
|
||||
_cup.init(cols, rows);
|
||||
_cols = cols;
|
||||
|
@ -321,6 +343,31 @@ class CupWidget : Widget {
|
|||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
// Overrides of Widget methods
|
||||
|
||||
/// returns true is widget is being animated - need to call animate() and redraw
|
||||
override @property bool animating() {
|
||||
switch (_state) {
|
||||
case CupState.NewFigure:
|
||||
case CupState.FallingFigure:
|
||||
case CupState.HangingFigure:
|
||||
case CupState.DestroyingRows:
|
||||
case CupState.FallingRows:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// animates window; interval is time left from previous draw, in hnsecs (1/10000000 of second)
|
||||
override void animate(long interval) {
|
||||
_animation.animate(interval);
|
||||
if (_animation.finished) {
|
||||
onAnimationFinished();
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw widget at its position to buffer
|
||||
override void onDraw(DrawBuf buf) {
|
||||
super.onDraw(buf);
|
||||
|
@ -387,15 +434,6 @@ class CupWidget : Widget {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
/// fixed size 350 x 550
|
||||
measuredContent(parentWidth, parentHeight, 350, 550);
|
||||
}
|
||||
|
||||
@property bool falling() {
|
||||
return _state == CupState.FallingFigure;
|
||||
}
|
||||
|
||||
/// override to handle specific actions
|
||||
|
@ -428,54 +466,30 @@ class CupWidget : Widget {
|
|||
}
|
||||
}
|
||||
|
||||
void addScore(int score) {
|
||||
_score += score;
|
||||
_status.setScore(_score);
|
||||
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
measuredContent(parentWidth, parentHeight, parentWidth * 3 / 5, parentHeight);
|
||||
}
|
||||
|
||||
/// start new game
|
||||
void newGame() {
|
||||
setLevel(1);
|
||||
_score = 0;
|
||||
init(_cols, _rows);
|
||||
_cup.dropNextFigure();
|
||||
setCupState(CupState.NewFigure);
|
||||
if (window && _gameOverPopup) {
|
||||
window.removePopup(_gameOverPopup);
|
||||
_gameOverPopup = null;
|
||||
}
|
||||
_status.setScore(_score);
|
||||
}
|
||||
|
||||
private StatusWidget _status;
|
||||
this(StatusWidget status) {
|
||||
super("CUP");
|
||||
this._status = status;
|
||||
layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT).layoutWeight(3);
|
||||
setState(State.Default);
|
||||
//backgroundColor = 0xC0808080;
|
||||
padding(Rect(20, 20, 20, 20));
|
||||
_cols = 11;
|
||||
_rows = 15;
|
||||
layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT).layoutWeight(3).setState(State.Default).focusable(true).padding(Rect(20, 20, 20, 20));
|
||||
|
||||
_cols = 10;
|
||||
_rows = 18;
|
||||
newGame();
|
||||
|
||||
focusable = true;
|
||||
|
||||
acceleratorMap.add( [
|
||||
(new Action(TetrisAction.MoveLeft, KeyCode.LEFT)).addAccelerator(KeyCode.KEY_A),
|
||||
(new Action(TetrisAction.MoveRight, KeyCode.RIGHT)).addAccelerator(KeyCode.KEY_D),
|
||||
(new Action(TetrisAction.RotateCCW, KeyCode.UP)).addAccelerator(KeyCode.KEY_W),
|
||||
(new Action(TetrisAction.FastDown, KeyCode.SPACE)).addAccelerator(KeyCode.KEY_S),
|
||||
(new Action(TetrisAction.Pause, KeyCode.ESCAPE)).addAccelerator(KeyCode.PAUSE),
|
||||
(new Action(TetrisAction.LevelUp, KeyCode.ADD)).addAccelerator(KeyCode.INS),
|
||||
]);
|
||||
|
||||
acceleratorMap.add(CUP_ACTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
/// Panel to show game status
|
||||
class StatusWidget : VerticalLayout {
|
||||
private TextWidget _level;
|
||||
private TextWidget _rowsDestroyed;
|
||||
private TextWidget _score;
|
||||
private CupWidget _cup;
|
||||
void setCup(CupWidget cup) {
|
||||
|
@ -483,26 +497,27 @@ class StatusWidget : VerticalLayout {
|
|||
}
|
||||
TextWidget createTextWidget(dstring str, uint color) {
|
||||
TextWidget res = new TextWidget(null, str);
|
||||
res.layoutWidth(FILL_PARENT).alignment(Align.Center);
|
||||
res.fontSize(30);
|
||||
res.textColor(color);
|
||||
res.layoutWidth(FILL_PARENT).alignment(Align.Center).fontSize(25).textColor(color);
|
||||
return res;
|
||||
}
|
||||
this() {
|
||||
super("CUP_STATUS");
|
||||
//backgroundColor = 0xC080FF80;
|
||||
|
||||
addChild(new VSpacer());
|
||||
addChild(new ImageWidget(null, "tetris_logo_big"));
|
||||
addChild((new ImageWidget(null, "tetris_logo_big")).layoutWidth(FILL_PARENT).alignment(Align.Center));
|
||||
addChild(new VSpacer());
|
||||
addChild(createTextWidget("Level:"d, 0x008000));
|
||||
addChild((_level = createTextWidget(""d, 0x008000)));
|
||||
addChild(new VSpacer());
|
||||
addChild(createTextWidget("Rows:"d, 0x202080));
|
||||
addChild((_rowsDestroyed = createTextWidget(""d, 0x202080)));
|
||||
addChild(new VSpacer());
|
||||
addChild(createTextWidget("Score:"d, 0x800000));
|
||||
addChild((_score = createTextWidget(""d, 0x800000)));
|
||||
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(20, 20, 20, 20));
|
||||
}
|
||||
|
||||
void setLevel(int level) {
|
||||
|
@ -513,17 +528,16 @@ class StatusWidget : VerticalLayout {
|
|||
_score.text = toUTF32(to!string(score));
|
||||
}
|
||||
|
||||
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
super.measure(parentWidth, parentHeight);
|
||||
/// fixed size 350 x 550
|
||||
measuredContent(parentWidth, parentHeight, 150, 550);
|
||||
void setRowsDestroyed(int rows) {
|
||||
_rowsDestroyed.text = toUTF32(to!string(rows));
|
||||
}
|
||||
|
||||
override bool handleAction(const Action a) {
|
||||
return _cup.handleAction(a);
|
||||
}
|
||||
}
|
||||
|
||||
/// Cup page: cup widget + status widget
|
||||
class CupPage : HorizontalLayout {
|
||||
CupWidget _cup;
|
||||
StatusWidget _status;
|
||||
|
@ -539,13 +553,13 @@ class CupPage : HorizontalLayout {
|
|||
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
super.measure(parentWidth, parentHeight);
|
||||
/// fixed size 350 x 550
|
||||
measuredContent(parentWidth, parentHeight, 500, 550);
|
||||
/// fixed size
|
||||
measuredContent(parentWidth, parentHeight, 550, 550);
|
||||
}
|
||||
}
|
||||
|
||||
//FrameLayout
|
||||
class GameWidget : HorizontalLayout {
|
||||
//
|
||||
class GameWidget : FrameLayout {
|
||||
|
||||
CupPage _cupPage;
|
||||
this() {
|
||||
|
@ -555,9 +569,4 @@ class GameWidget : HorizontalLayout {
|
|||
//showChild(_cupPage.id, Visibility.Invisible, true);
|
||||
backgroundImageId = "tx_fabric.tiled";
|
||||
}
|
||||
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
super.measure(parentWidth, parentHeight);
|
||||
measuredContent(parentWidth, parentHeight, 500, 550);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,9 @@ import dlangui.all;
|
|||
import model;
|
||||
import gui;
|
||||
|
||||
|
||||
/// Required for Windows platform: DMD cannot find WinMain if it's in library
|
||||
mixin APP_ENTRY_POINT;
|
||||
|
||||
|
||||
/// entry point for dlangui based application
|
||||
extern (C) int UIAppMain(string[] args) {
|
||||
|
||||
|
@ -50,14 +49,10 @@ extern (C) int UIAppMain(string[] args) {
|
|||
// load theme from file "theme_default.xml"
|
||||
Platform.instance.uiTheme = "theme_default";
|
||||
|
||||
//drawableCache.get("tx_fabric.tiled");
|
||||
|
||||
// create window
|
||||
Window window = Platform.instance.createWindow("DLangUI: Tetris game example", null, WindowFlag.Modal);
|
||||
Window window = Platform.instance.createWindow("DLangUI: Tetris game example"d, null, WindowFlag.Modal);
|
||||
|
||||
GameWidget game = new GameWidget();
|
||||
|
||||
window.mainWidget = game;
|
||||
window.mainWidget = new GameWidget();
|
||||
|
||||
window.windowIcon = drawableCache.getImage("dtetris-logo1");
|
||||
|
||||
|
|
|
@ -2,6 +2,28 @@ module model;
|
|||
|
||||
import std.random : uniform;
|
||||
|
||||
/// Cell codes
|
||||
enum : int {
|
||||
WALL = -1,
|
||||
EMPTY = 0,
|
||||
FIGURE1,
|
||||
FIGURE2,
|
||||
FIGURE3,
|
||||
FIGURE4,
|
||||
FIGURE5,
|
||||
FIGURE6,
|
||||
FIGURE7,
|
||||
}
|
||||
|
||||
/// Orientations
|
||||
enum : int {
|
||||
ORIENTATION0,
|
||||
ORIENTATION90,
|
||||
ORIENTATION180,
|
||||
ORIENTATION270
|
||||
}
|
||||
|
||||
|
||||
/// Cell offset
|
||||
struct FigureCell {
|
||||
// horizontal offset
|
||||
|
@ -22,8 +44,9 @@ struct FigureShape {
|
|||
int extent;
|
||||
/// upper y coordinate - initial Y offset to place figure to cup
|
||||
int y0;
|
||||
this(int[2] c1, int[2] c2, int[2] c3, int[2] c4) {
|
||||
cells[0] = FigureCell(c1);
|
||||
/// Init cells (cell 0 is [0,0])
|
||||
this(int[2] c2, int[2] c3, int[2] c4) {
|
||||
cells[0] = FigureCell([0, 0]);
|
||||
cells[1] = FigureCell(c2);
|
||||
cells[2] = FigureCell(c3);
|
||||
cells[3] = FigureCell(c4);
|
||||
|
@ -37,6 +60,7 @@ struct FigureShape {
|
|||
}
|
||||
}
|
||||
|
||||
/// Figure data - shapes for 4 orientations
|
||||
struct Figure {
|
||||
FigureShape[4] shapes; // by orientation
|
||||
this(FigureShape[4] v) {
|
||||
|
@ -44,71 +68,69 @@ struct Figure {
|
|||
}
|
||||
}
|
||||
|
||||
const Figure[6] FIGURES = [
|
||||
/// All shapes
|
||||
const Figure[7] FIGURES = [
|
||||
// FIGURE1 ===========================================
|
||||
// ## ####
|
||||
// 00## 00##
|
||||
// ##
|
||||
Figure([FigureShape([0, 0], [1, 0], [1, 1], [0, -1]),
|
||||
FigureShape([0, 0], [0, 1], [-1, 1], [1, 0]),
|
||||
FigureShape([0, 0], [1, 0], [1, 1], [0, -1]),
|
||||
FigureShape([0, 0], [0, 1], [-1, 1], [1, 0])]),
|
||||
Figure([FigureShape([1, 0], [1, 1], [0, -1]),
|
||||
FigureShape([0, 1], [-1, 1], [1, 0]),
|
||||
FigureShape([1, 0], [1, 1], [0, -1]),
|
||||
FigureShape([0, 1], [-1, 1], [1, 0])]),
|
||||
// FIGURE2 ===========================================
|
||||
// ## ####
|
||||
// 00## ##00
|
||||
// ##
|
||||
Figure([FigureShape([0, 0], [1, 0], [0, 1], [1, 1]),
|
||||
FigureShape([0, 0], [0, 1], [1, 1], [-1, 0]),
|
||||
FigureShape([0, 0], [1, 0], [0, 1], [1, 1]),
|
||||
FigureShape([0, 0], [0, 1], [1, 1], [-1, 0])]),
|
||||
Figure([FigureShape([1, 0], [0, 1], [1, 1]),
|
||||
FigureShape([0, 1], [1, 1], [-1, 0]),
|
||||
FigureShape([1, 0], [0, 1], [1, 1]),
|
||||
FigureShape([0, 1], [1, 1], [-1, 0])]),
|
||||
// FIGURE3 ===========================================
|
||||
// ## ## ####
|
||||
// ##00## 00 ##00## 00
|
||||
// ## #### ##
|
||||
Figure([FigureShape([0, 0], [1, 0], [-1,0], [-1,-1]),
|
||||
FigureShape([0, 0], [0, 1], [0,-1], [ 1,-1]),
|
||||
FigureShape([0, 0], [1, 0], [-1,0], [1, 1]),
|
||||
FigureShape([0, 0], [0, 1], [-1,1], [0,-1])]),
|
||||
Figure([FigureShape([1, 0], [-1,0], [-1,-1]),
|
||||
FigureShape([0, 1], [0,-1], [ 1,-1]),
|
||||
FigureShape([1, 0], [-1,0], [1, 1]),
|
||||
FigureShape([0, 1], [-1,1], [0,-1])]),
|
||||
// FIGURE4 ===========================================
|
||||
// #### ## ##
|
||||
// ##00## 00 ##00## 00
|
||||
// ## ## ####
|
||||
Figure([FigureShape([0, 0], [1, 0], [-1,0], [ 1, 1]),
|
||||
FigureShape([0, 0], [0, 1], [0,-1], [ 1, 1]),
|
||||
FigureShape([0, 0], [1, 0], [-1,0], [-1, 1]),
|
||||
FigureShape([0, 0], [0, 1], [-1,-1], [0, -1])]),
|
||||
Figure([FigureShape([1, 0], [-1,0], [ 1,-1]),
|
||||
FigureShape([0, 1], [0,-1], [ 1, 1]),
|
||||
FigureShape([1, 0], [-1,0], [-1, 1]),
|
||||
FigureShape([0, 1], [-1,-1], [0, -1])]),
|
||||
// FIGURE5 ===========================================
|
||||
// ####
|
||||
// 00##
|
||||
//
|
||||
Figure([FigureShape([0, 0], [1, 0], [0, 1], [ 1, 1]),
|
||||
FigureShape([0, 0], [1, 0], [0, 1], [ 1, 1]),
|
||||
FigureShape([0, 0], [1, 0], [0, 1], [ 1, 1]),
|
||||
FigureShape([0, 0], [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])]),
|
||||
// FIGURE6 ===========================================
|
||||
// ##
|
||||
// ##
|
||||
// 00 ##00####
|
||||
// ##
|
||||
Figure([FigureShape([0, 0], [0, 1], [0, 2], [ 0,-1]),
|
||||
FigureShape([0, 0], [1, 0], [2, 0], [-1, 0]),
|
||||
FigureShape([0, 0], [0, 1], [0, 2], [ 0,-1]),
|
||||
FigureShape([0, 0], [1, 0], [2, 0], [-1, 0])]),
|
||||
Figure([FigureShape([0, 1], [0, 2], [ 0,-1]),
|
||||
FigureShape([1, 0], [2, 0], [-1, 0]),
|
||||
FigureShape([0, 1], [0, 2], [ 0,-1]),
|
||||
FigureShape([1, 0], [2, 0], [-1, 0])]),
|
||||
// FIGURE7 ===========================================
|
||||
// ## ## ##
|
||||
// ##00## 00## ##00## ##00
|
||||
// ## ## ##
|
||||
Figure([FigureShape([1, 0], [-1,0], [ 0,-1]),
|
||||
FigureShape([0, 1], [0,-1], [ 1, 0]),
|
||||
FigureShape([1, 0], [-1,0], [ 0, 1]),
|
||||
FigureShape([0, 1], [0,-1], [-1, 0])]),
|
||||
];
|
||||
|
||||
enum : int {
|
||||
WALL = -1,
|
||||
EMPTY = 0,
|
||||
FIGURE1,
|
||||
FIGURE2,
|
||||
FIGURE3,
|
||||
FIGURE4,
|
||||
FIGURE5,
|
||||
FIGURE6,
|
||||
}
|
||||
|
||||
enum : int {
|
||||
ORIENTATION0,
|
||||
ORIENTATION90,
|
||||
ORIENTATION180,
|
||||
ORIENTATION270
|
||||
}
|
||||
|
||||
const uint[6] _figureColors = [0xFF0000, 0xA0A000, 0xA000A0, 0x0000FF, 0x800000, 0x408000];
|
||||
/// colors for different figure types
|
||||
const uint[7] _figureColors = [0xC00000, 0x80A000, 0xA00080, 0x0000C0, 0x800020, 0x408000, 0x204000];
|
||||
|
||||
/// Figure type, orientation and position container
|
||||
struct FigurePosition {
|
||||
|
@ -289,13 +311,15 @@ struct Cup {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// random next figure
|
||||
void genNextFigure() {
|
||||
_nextFigure.index = uniform(FIGURE1, FIGURE6 + 1);
|
||||
_nextFigure.index = uniform(FIGURE1, FIGURE7 + 1);
|
||||
_nextFigure.orientation = ORIENTATION0;
|
||||
_nextFigure.x = _cols / 2;
|
||||
_nextFigure.y = _rows - _nextFigure.shape.extent + 1;
|
||||
}
|
||||
|
||||
/// New figure: put it on top of cup
|
||||
bool dropNextFigure() {
|
||||
if (_nextFigure.empty)
|
||||
genNextFigure();
|
||||
|
@ -412,6 +436,7 @@ struct Cup {
|
|||
return cellGroup(col, row) > 0;
|
||||
}
|
||||
|
||||
/// returns true if next figure is generated
|
||||
@property bool hasNextFigure() {
|
||||
return !_nextFigure.empty;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,8 @@ module dlangui.all;
|
|||
|
||||
public import dlangui.core.logger;
|
||||
public import dlangui.core.types;
|
||||
public import dlangui.platforms.common.platform;
|
||||
public import dlangui.core.i18n;
|
||||
public import dlangui.core.files;
|
||||
public import dlangui.graphics.images;
|
||||
public import dlangui.widgets.widget;
|
||||
public import dlangui.widgets.controls;
|
||||
|
@ -61,6 +62,11 @@ public import dlangui.widgets.editors;
|
|||
public import dlangui.widgets.grid;
|
||||
public import dlangui.widgets.tree;
|
||||
public import dlangui.widgets.combobox;
|
||||
public import dlangui.widgets.popup;
|
||||
public import dlangui.graphics.fonts;
|
||||
public import dlangui.core.i18n;
|
||||
public import dlangui.core.files;
|
||||
public import dlangui.graphics.drawbuf;
|
||||
public import dlangui.platforms.common.platform;
|
||||
|
||||
// some useful imports from Phobos
|
||||
public import std.conv : to;
|
||||
public import std.utf : toUTF32, toUTF8;
|
||||
|
|
|
@ -140,6 +140,10 @@ class Action {
|
|||
@property Accelerator[] accelerators() {
|
||||
return _accelerators;
|
||||
}
|
||||
/// returs const array of accelerators
|
||||
@property const(Accelerator)[] accelerators() const {
|
||||
return _accelerators;
|
||||
}
|
||||
/// returns text description for first accelerator of action; null if no accelerators
|
||||
@property dstring acceleratorText() {
|
||||
if (_accelerators.length < 1)
|
||||
|
@ -217,6 +221,13 @@ struct ActionMap {
|
|||
_map[acc] = a;
|
||||
}
|
||||
}
|
||||
/// Add array of actions
|
||||
void add(const Action[] items) {
|
||||
foreach(a; items) {
|
||||
foreach(acc; a.accelerators)
|
||||
_map[acc] = a.clone;
|
||||
}
|
||||
}
|
||||
/// Add action
|
||||
void add(Action a) {
|
||||
foreach(acc; a.accelerators)
|
||||
|
|
Loading…
Reference in New Issue