From 058aca46f433b3a36a341ca7272c39d2bef55c09 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Thu, 3 Jul 2014 22:37:47 -0500 Subject: [PATCH] Added level editor. --- src/app.cpp | 6 + src/app.h | 1 + src/editorwidget.cpp | 501 +++++++++++++++++++++++++++++++++++++++++ src/editorwidget.h | 72 ++++++ src/editorwindow.cpp | 85 +++++++ src/editorwindow.h | 27 +++ src/gameboard.h | 2 +- src/mainwin.cpp | 8 + src/mainwin.h | 2 + warehousemandeluxe.pro | 4 + 10 files changed, 707 insertions(+), 1 deletion(-) create mode 100644 src/editorwidget.cpp create mode 100644 src/editorwidget.h create mode 100644 src/editorwindow.cpp create mode 100644 src/editorwindow.h diff --git a/src/app.cpp b/src/app.cpp index e6fa79f..0abed26 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -26,6 +26,12 @@ App::App(int & argc, char * argv[]): QApplication(argc, argv) } +App::~App() +{ + delete mainWindow; +} + + // Here's the main application loop--short and simple... int main(int argc, char * argv[]) { diff --git a/src/app.h b/src/app.h index d0105a0..68bc82d 100644 --- a/src/app.h +++ b/src/app.h @@ -10,6 +10,7 @@ class App: public QApplication { public: App(int & argc, char * argv[]); + ~App(); public: MainWin * mainWindow; diff --git a/src/editorwidget.cpp b/src/editorwidget.cpp new file mode 100644 index 0000000..0c6ab28 --- /dev/null +++ b/src/editorwidget.cpp @@ -0,0 +1,501 @@ +// +// editorwidget.cpp: Game editor window widget +// +// by James Hammons +// (C) 2014 Underground Software +// +// JLH = James Hammons +// +// Who When What +// --- ---------- ------------------------------------------------------------ +// JLH 07/01/2014 Created this file +// + +#include "editorwidget.h" +#include // for usleep() +#include +#include "boards.h" +#include "gameboard.h" + + +#define GRIDSIZE 40 + + +EditorWidget::EditorWidget(QWidget * parent/*= 0*/): QWidget(parent), + currentLevel(0) +{ +// memset(¤tLevel, 0, sizeof(currentLevel)); +// currentLevel.corner.x = -1; +// currentLevel.corner.y = -1; +// levelStorage.push_back(currentLevel); +// Level * b1 = &level[0]; +// memset(board, 0, sizeof(board)); +// CreateBackground(); +// score->setTextFormat(Qt::PlainText); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + setFocusPolicy(Qt::StrongFocus); // Without this, it gets no keys + Load(); +} + + +// This never gets called...! +EditorWidget::~EditorWidget(void) +{ + Save(); +} + + +QSize EditorWidget::sizeHint() const +{ + return QSize(400, 400); +} + + +void EditorWidget::paintEvent(QPaintEvent * /*event*/) +{ + QPainter painter(this); + QFont font; + Level & level = levelStorage[currentLevel]; + + for(int y=0; y<=clientArea.height()/GRIDSIZE; y++) + { + for(int x=0; x<=clientArea.width()/GRIDSIZE; x++) + { + Point current(level.corner.x + x, level.corner.y + y); + + if ((current.x < 0) && (current.y < 0)) + { + painter.setBrush(Qt::black); + painter.drawRect(x + (GRIDSIZE / 2), y + (GRIDSIZE / 2), GRIDSIZE / 2, GRIDSIZE / 2); + } + else if (current.x < 0) + { + painter.setBrush(Qt::black); + painter.drawRect(x + (GRIDSIZE / 2), y * GRIDSIZE, GRIDSIZE / 2, GRIDSIZE); + } + else if (current.y < 0) + { + painter.setBrush(Qt::black); + painter.drawRect(x * GRIDSIZE, y + (GRIDSIZE / 2), GRIDSIZE, GRIDSIZE / 2); + } + else + { + uint8_t tile = level.board[current.x][current.y]; + + painter.setBrush(Qt::transparent); + painter.setPen(Qt::black); + painter.drawRect(x * GRIDSIZE, y * GRIDSIZE, GRIDSIZE, GRIDSIZE); + + if (tile & (GTWall | GTSpace | GTBox)) + { + if (tile & GTWall) + { + painter.setBrush(Qt::white); + painter.drawRect(x * GRIDSIZE, y * GRIDSIZE, GRIDSIZE, GRIDSIZE); + } + else if (tile & GTBox) + { + painter.setBrush(Qt::red); + painter.drawRect((x * GRIDSIZE) + (GRIDSIZE * 0.1), + (y * GRIDSIZE) + (GRIDSIZE * 0.1), GRIDSIZE * 0.8, GRIDSIZE * 0.8); + } + } + else if (tile & GTNull) + { + painter.setBrush(Qt::black); +// painter.setPen(Qt::black); + painter.drawRect(x * GRIDSIZE, y * GRIDSIZE, GRIDSIZE, GRIDSIZE); + } + else if (tile & GTMan) + { + painter.setBrush(Qt::yellow); + painter.drawEllipse((x * GRIDSIZE) + (GRIDSIZE * 0.1), + (y * GRIDSIZE) + (GRIDSIZE * 0.1), GRIDSIZE * 0.8, GRIDSIZE * 0.8); + } + + if ((tile & GTBoxSpot) && !(tile & (GTWall | GTNull))) + { + painter.setBrush(Qt::magenta); + painter.drawRect((x * GRIDSIZE) + (GRIDSIZE / 3), + (y * GRIDSIZE) + (GRIDSIZE / 3), GRIDSIZE / 3, GRIDSIZE / 3); + } + } + } + } + + int x = level.cursor.x - level.corner.x; + int y = level.cursor.y - level.corner.y; + + painter.setBrush(Qt::transparent); + painter.setPen(Qt::darkGreen); + painter.drawEllipse((x * GRIDSIZE) + 4, (y * GRIDSIZE) + 4, GRIDSIZE - 8, GRIDSIZE - 8); +} + + +void EditorWidget::mousePressEvent(QMouseEvent * event) +{ + if (event->button() == Qt::LeftButton) + { + event->accept(); + } +} + + +void EditorWidget::mouseMoveEvent(QMouseEvent * event) +{ + if (event->buttons() & Qt::LeftButton) + { + event->accept(); + } +} + + +void EditorWidget::mouseReleaseEvent(QMouseEvent * event) +{ + if (event->button() == Qt::LeftButton) + { + event->accept(); + } +} + + +void EditorWidget::mouseDoubleClickEvent(QMouseEvent * event) +{ + if (event->button() == Qt::LeftButton) + { + event->accept(); + } +} + + +void EditorWidget::keyPressEvent(QKeyEvent * event) +{ + int key = event->key(); + Level & level = levelStorage[currentLevel]; + Point & cursor = level.cursor; + Point & corner = level.corner; + + if (key == Qt::Key_Up) + { + if (cursor.y > 0) + cursor.y--; + + if (((cursor.y - corner.y) == 0) && (corner.y > -1)) + corner.y--; + } + else if (key == Qt::Key_Down) + { + if (cursor.y < (BOARDSIZE - 1)) + cursor.y++; + + if (cursor.y >= (range.y + corner.y - 1)) + { + if (corner.y < (BOARDSIZE - range.y)) + corner.y++; + } + } + else if (key == Qt::Key_Left) + { + if (cursor.x > 0) + cursor.x--; + + if (((cursor.x - corner.x) == 0) && (corner.x > -1)) + corner.x--; + } + else if (key == Qt::Key_Right) + { + if (cursor.x < (BOARDSIZE - 1)) + cursor.x++; + + if (cursor.x >= (range.x + corner.x - 1)) + { + if (corner.x < (BOARDSIZE - range.x)) + corner.x++; + } + } + else if (key == Qt::Key_Period) + { + level.board[cursor.x][cursor.y] ^= GTBoxSpot; + } + else if (key == Qt::Key_B) + { + level.board[cursor.x][cursor.y] &= ~(GTSpace | GTWall | GTBox); + level.board[cursor.x][cursor.y] |= GTBox; + } + else if (key == Qt::Key_W) + { + level.board[cursor.x][cursor.y] = GTWall; + } + else if (key == Qt::Key_Space) + { + level.board[cursor.x][cursor.y] &= ~(GTSpace | GTWall | GTBox); + level.board[cursor.x][cursor.y] |= GTSpace; + } + else if (key == Qt::Key_O) + { + // There can be only one! + for(int x=0; xsize(); + +//printf("Size of window is: %i x %i\n", s.width(), s.height()); +//printf("Size of game grid is: %i x %i\n", gameBoard->width, gameBoard->height); + ResizeGrid(); +} + + +void EditorWidget::CreateBackground(void) +{ +#if 0 + char BGRes[27][64] = { + ":/res/grfttile.bmp", + ":/res/cloth_6.bmp", + ":/res/bg_tech_3.bmp", + ":/res/bg_tech_2.bmp", + ":/res/bg_tech_1.bmp", + ":/res/bg_weave_3.bmp", + ":/res/bg_weave_2.bmp", + ":/res/bg_clouds_2.bmp", + ":/res/bg_floor_plate.bmp", + ":/res/bg_marble_b.bmp", + ":/res/bg_marble_g.bmp", + ":/res/bg_marble_p.bmp", + ":/res/bg_marble_r.bmp", + ":/res/bg_marble_rb.bmp", + ":/res/bg_money_1.bmp", + ":/res/bg_pinstripe2.bmp", + ":/res/bg_pinstripe7.bmp", + ":/res/bg_raindrops_large.bmp", + ":/res/bg_raindrops_small.bmp", + ":/res/bg_stucco.bmp", + ":/res/bg_wood_w.bmp", + ":/res/bg_wood_b1.bmp", + ":/res/bg_wood_d.bmp", + ":/res/bg_wood_f.bmp", + ":/res/bg_wood_mh.bmp", + ":/res/bg_wood_mv.bmp", + ":/res/bg_wood_ro.bmp" + }; + + QPalette pal = palette(); + pal.setBrush(backgroundRole(), QBrush(QPixmap(BGRes[m_nBackground]))); + setAutoFillBackground(true); + setPalette(pal); + + return true; // Ignore errors for now... +#else +// QPalette pal = palette(); +// pal.setBrush(backgroundRole(), QBrush(QPixmap(":/bg_marble_g.bmp"))); +// setAutoFillBackground(true); +// setPalette(pal); +#endif +} + + +void EditorWidget::ClearLevel(void) +{ +// gameBoard->ResetGame(); +// memset(board, 0, sizeof(board)); + update(); +} + + +bool EditorWidget::Load(void) +{ + FILE * f = fopen("./wmd-level.data", "rb"); + + if (f) + { + int numberOfLevels; + fscanf(f, "%i\n", &numberOfLevels); +//printf("Load: Looking for %i levels...\n", numberOfLevels); + + for(int i=0; iboard[x][y] == 0) + continue; + + if (min.x > x) + min.x = x; + + if (min.y > y) + min.y = y; + + if (max.x < x) + max.x = x; + + if (max.y < y) + max.y = y; + } + } + + size.x = max.x - min.x + 1; + size.y = max.y - min.y + 1; + corner.x = min.x; + corner.y = min.y; +} + + +void EditorWidget::ResizeGrid(void) +{ + clientArea = size(); + range.x = clientArea.width() / GRIDSIZE; + range.y = clientArea.height() / GRIDSIZE; +#if 0 + QSize s = size(); + + // Set some room for the board title (7.5%) + float titleHeight = s.height() * 0.075; + + // Find the constraints + float boxSizeX = s.width() / gameBoard->width; + float boxSizeY = (s.height() - titleHeight) / gameBoard->height; + + maxLength = (int)(boxSizeX > boxSizeY ? boxSizeY : boxSizeX); + + offsetX = (s.width() - (maxLength * gameBoard->width)) / 2; + offsetY = ((s.height() - titleHeight) - (maxLength * gameBoard->height)) / 2; + titleBox.setRect(0, offsetY, s.width(), titleHeight); + offsetY += titleHeight; // Add in the title's height +#endif +} + + +// +// Halt processing for 'count' milliseconds +// +void EditorWidget::Pause(int count) +{ +// DWORD endCount = GetTickCount() + count; +// while (GetTickCount() < endCount) {} // Still crude, but better control +#if 1 + usleep(count * 1000); +#else + // This causes it to lock up randomly. :-/ + QTime time; + time.start(); + + while (time.msec() < count) + ; // Do nothing... +#endif +} + diff --git a/src/editorwidget.h b/src/editorwidget.h new file mode 100644 index 0000000..0b29acb --- /dev/null +++ b/src/editorwidget.h @@ -0,0 +1,72 @@ +#ifndef __EDITORWIDGET_H__ +#define __EDITORWIDGET_H__ + +#include +#include +#include + +#define BOARDSIZE 128 + +struct Point +{ + Point(int xx = 0, int yy = 0) { x = xx; y = yy; } + int x, y; +}; + +struct Level +{ + uint8_t board[BOARDSIZE][BOARDSIZE]; + char name[41]; + Point corner; // Corner dimensions on screen + Point cursor; // Cursor location +// This stuff will go into the save file, but we don't need it here... +// Point size; // Actual dimensions of the level +// Point boardCorner; // Where on the gird the UL corner of the level is +}; + +class EditorWidget: public QWidget +{ + Q_OBJECT + + public: + EditorWidget(QWidget * parent = 0); + ~EditorWidget(); + + protected: + QSize sizeHint() const; + void paintEvent(QPaintEvent * event); + void mousePressEvent(QMouseEvent * event); + void mouseMoveEvent(QMouseEvent * event); + void mouseReleaseEvent(QMouseEvent * event); + void mouseDoubleClickEvent(QMouseEvent * event); + void keyPressEvent(QKeyEvent * event); + void keyReleaseEvent(QKeyEvent * event); + void resizeEvent(QResizeEvent * event); + +// signals: +// void UpdateScore(int); +// void GameWasWon(void); + + public: + void CreateBackground(void); + void ClearLevel(void); + bool Load(void); + bool Save(void); + void SetNameOnCurrentLevel(const char *); + private: + void GetSizeAndCorner(Level *, Point &, Point &); + void ResizeGrid(void); + void Pause(int); + + public: + std::vector levelStorage; + uint32_t currentLevel; + + private: +// Level currentLevel; + QSize clientArea; + Point range; +}; + +#endif // __EDITORWIDGET_H__ + diff --git a/src/editorwindow.cpp b/src/editorwindow.cpp new file mode 100644 index 0000000..1ccc14c --- /dev/null +++ b/src/editorwindow.cpp @@ -0,0 +1,85 @@ +// +// editorwindow.cpp: Game editor window +// +// by James Hammons +// (C) 2014 Underground Software +// +// JLH = James Hammons +// +// Who When What +// --- ---------- ------------------------------------------------------------ +// JLH 07/03/2014 Created this file +// + +#include "editorwindow.h" +#include "editorwidget.h" + + +EditorWindow::EditorWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Window) +{ + list = new QListWidget; + up = new QPushButton("^"); + down = new QPushButton("v"); + add = new QPushButton("+"); + remove = new QPushButton("-"); + editor = new EditorWidget(parent); + + list->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); +// editor->setFocus(); //DISNOWOK +// editor->Load(); + + for(unsigned int i=0; ilevelStorage.size(); i++) + { + list->addItem(QString(editor->levelStorage[i].name)); + QListWidgetItem * item = list->item(i); + item->setFlags(item->flags() | Qt::ItemIsEditable); + } + + QHBoxLayout * buttonBox = new QHBoxLayout; + QVBoxLayout * listBox = new QVBoxLayout; + QHBoxLayout * mainBox = new QHBoxLayout; + + buttonBox->addWidget(up); + buttonBox->addWidget(down); + buttonBox->addWidget(add); + buttonBox->addWidget(remove); + + listBox->addWidget(list); + listBox->addLayout(buttonBox); + + mainBox->addLayout(listBox); + mainBox->addWidget(editor); + + setLayout(mainBox); + setWindowTitle("Editor"); + + connect(list, SIGNAL(currentRowChanged(int)), this, SLOT(SetEditorLevel(int))); + connect(list->itemDelegate(), SIGNAL(closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint)), this, SLOT(SetNewName(QWidget *, QAbstractItemDelegate::EndEditHint))); +} + + +EditorWindow::~EditorWindow(void) +{ +// editor->Save(); + delete editor; + delete up; + delete down; + delete add; + delete remove; + delete list; +} + + +void EditorWindow::SetEditorLevel(int level) +{ + editor->currentLevel = level; + editor->update(); +} + + +void EditorWindow::SetNewName(QWidget * widget, QAbstractItemDelegate::EndEditHint) +{ + QString newName = reinterpret_cast(widget)->text(); + editor->SetNameOnCurrentLevel(newName.toAscii().data()); +} + diff --git a/src/editorwindow.h b/src/editorwindow.h new file mode 100644 index 0000000..3b50d7c --- /dev/null +++ b/src/editorwindow.h @@ -0,0 +1,27 @@ +#ifndef __EDITORWINDOW_H__ +#define __EDITORWINDOW_H__ + +#include + +class EditorWidget; + +class EditorWindow: public QWidget +{ + Q_OBJECT + + public: + EditorWindow(QWidget * parent = 0); + ~EditorWindow(); + + private slots: + void SetEditorLevel(int); + void SetNewName(QWidget *, QAbstractItemDelegate::EndEditHint); + + private: + QListWidget * list; + QPushButton * up, * down, * add, * remove; + EditorWidget * editor; +}; + +#endif // __EDITORWINDOW_H__ + diff --git a/src/gameboard.h b/src/gameboard.h index 229feb7..0bca19b 100644 --- a/src/gameboard.h +++ b/src/gameboard.h @@ -1,7 +1,7 @@ #ifndef __GAMEBOARD_H__ #define __GAMEBOARD_H__ -enum { GTSpace=0x00, GTWall=0x01, GTBox=0x02, GTBoxSpot=0x04, GTNull=0x08 }; +enum { GTSpace=0x00, GTWall=0x01, GTBox=0x02, GTBoxSpot=0x04, GTNull=0x08, GTMan=0x10 }; enum { PMInvalid, PMWalk, PMPush }; struct UndoMove diff --git a/src/mainwin.cpp b/src/mainwin.cpp index 010f27f..a4aec01 100644 --- a/src/mainwin.cpp +++ b/src/mainwin.cpp @@ -16,6 +16,7 @@ #include // For rand() #include // For time() #include "gameboard.h" +#include "editorwindow.h" // Actual mouse/drawing window #include "gamewidget.h" // Actual mouse/drawing window //#include "resource.h" //#include "optiondlg.h" // Options dialog class @@ -30,6 +31,12 @@ MainWin::MainWin() setWindowTitle("Warehouse Man Deluxe"); setWindowIcon(QIcon(":/wmd-icon.png")); +// editor = new QWindow(this); + editorWindow = new EditorWindow(this); +// editor->setCentralWidget(editorWidget); +// editorWidget->setFocusPolicy(Qt::StrongFocus); // Without this, it gets no keys + editorWindow->show(); + newGame = CreateAction(tr("&New"), tr("New Game"), tr("Start a new game of Warehouse Man Deluxe"), QIcon(), QKeySequence(tr("ctrl+n"))); // connect(newGame, SIGNAL(triggered()), this, SLOT(OnNewGame())); @@ -122,6 +129,7 @@ MainWin::MainWin() MainWin::~MainWin() { // ShutDownAudio(); + delete editorWindow; } diff --git a/src/mainwin.h b/src/mainwin.h index 9338343..51b4548 100644 --- a/src/mainwin.h +++ b/src/mainwin.h @@ -4,6 +4,7 @@ #include class GameWidget; +class EditorWindow; class MainWin: public QMainWindow { @@ -37,6 +38,7 @@ class MainWin: public QMainWindow private: GameWidget * gameWidget; + EditorWindow * editorWindow; QAction * newGame; QAction * undoAction; diff --git a/warehousemandeluxe.pro b/warehousemandeluxe.pro index a68a1e5..0c5c402 100644 --- a/warehousemandeluxe.pro +++ b/warehousemandeluxe.pro @@ -20,6 +20,8 @@ DEPENDPATH = \ HEADERS = \ app.h \ boards.h \ + editorwidget.h \ + editorwindow.h \ gameboard.h \ gamewidget.h \ mainwin.h @@ -27,6 +29,8 @@ HEADERS = \ SOURCES = \ app.cpp \ boards.cpp \ + editorwidget.cpp \ + editorwindow.cpp \ gameboard.cpp \ gamewidget.cpp \ mainwin.cpp -- 2.37.2