summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2019-05-15 15:00:52 +0200
committerSimon Rettberg2019-05-15 15:00:52 +0200
commit40174287f39e08fbeebb46c0e2099df4f83136ed (patch)
treef68c8147a1aeda17c9491b26d3707e2646ece7b0
parentUse Qt5 QObject::connect(), fix caplock message after failed login (diff)
downloadslxgreeter-40174287f39e08fbeebb46c0e2099df4f83136ed.tar.gz
slxgreeter-40174287f39e08fbeebb46c0e2099df4f83136ed.tar.xz
slxgreeter-40174287f39e08fbeebb46c0e2099df4f83136ed.zip
Improve graphics rendering
-rw-r--r--src/mainwindow.cpp20
-rw-r--r--src/mainwindow.h8
-rw-r--r--src/snake.cpp172
-rw-r--r--src/snake.h33
4 files changed, 232 insertions, 1 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 15736f0..a9ff11e 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -27,13 +27,16 @@
#include "settings.h"
#include "global.h"
+#include "snake.h"
+
MainWindow::MainWindow(bool primary, int screen, const QRect &screenRect, QWidget *parent) :
QWidget(parent),
m_ScreenRect(screenRect),
m_Primary(primary),
m_LoginForm(nullptr),
m_messages(nullptr),
- m_Clock(nullptr)
+ m_Clock(nullptr),
+ m_Snake(nullptr)
{
setObjectName(QString("MainWindow_%1").arg(screen));
@@ -109,6 +112,21 @@ MainWindow::~MainWindow()
{
}
+void MainWindow::paintEvent(QPaintEvent *event)
+{
+ QWidget::paintEvent(event);
+ if (m_Snake != nullptr) {
+ m_Snake->paint(event);
+ }
+}
+
+void MainWindow::mouseDoubleClickEvent(QMouseEvent *)
+{
+ if (m_Snake == nullptr) {
+ m_Snake = new Snake(this);
+ }
+}
+
QSize MainWindow::createLogo(QRect max)
{
QSize retval(0, 0);
diff --git a/src/mainwindow.h b/src/mainwindow.h
index b6a756c..02db75e 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -23,6 +23,8 @@ namespace Ui {
class QTextEdit;
+class Snake;
+
class MainWindow : public QWidget
{
Q_OBJECT
@@ -49,6 +51,11 @@ public:
LoginForm* loginForm() { return m_LoginForm; }
+protected:
+ virtual void paintEvent(QPaintEvent *event);
+
+ virtual void mouseDoubleClickEvent(QMouseEvent *);
+
public slots:
void showStandby();
void updateClock();
@@ -63,6 +70,7 @@ private:
QImage m_background;
QTextEdit *m_messages;
QLabel *m_Clock;
+ Snake *m_Snake;
};
#endif // MAINWINDOW_H
diff --git a/src/snake.cpp b/src/snake.cpp
new file mode 100644
index 0000000..6f18670
--- /dev/null
+++ b/src/snake.cpp
@@ -0,0 +1,172 @@
+#include "snake.h"
+
+#include <QWidget>
+#include <QPaintEvent>
+#include <QPainter>
+#include <QRectF>
+#include <QTimer>
+#include <QDebug>
+
+#define SCALING (16)
+
+#define DIR_UP 0
+#define DIR_DOWN 1
+#define DIR_LEFT 2
+#define DIR_RIGHT 3
+
+#define FIELD(x,y) _field[(x) + ((y) * _width)]
+#define FIELD_FREE 0
+#define FIELD_SNAKE 1
+#define FIELD_FOOD 2
+
+Snake::Snake(QWidget *widget)
+ : _widget(widget),
+ _field(nullptr),
+ _direction(DIR_UP)
+{
+ _width = widget->width() / SCALING;
+ _height = widget->height() / SCALING;
+ _snakeLen = 5;
+ if (_width <= 0 || _height <= 0)
+ return;
+ _field = (int*)calloc(_width * _height, sizeof(*_field));
+ _x = _y = -1;
+ qDebug() << "Field:" << _width << _height;
+ QTimer *t = new QTimer(widget);
+ t->start(100);
+ // Game logic
+ QTimer::connect(t, &QTimer::timeout, [this]() {
+ switch (_direction) {
+ case DIR_UP:
+ _y--; break;
+ case DIR_DOWN:
+ _y++; break;
+ case DIR_LEFT:
+ _x--; break;
+ case DIR_RIGHT:
+ _x++; break;
+ }
+ if (_x < 0 || _x >= _width || _y < 0 || _y >= _height ||
+ FIELD(_x, _y) == FIELD_SNAKE) {
+ // Snek ded
+ qDebug() << "DEATH";
+ memset(_field, 0, sizeof(*_field) * _width * _height);
+ _x = _width / 2;
+ _y = _height / 2;
+ _snake.clear();
+ _widget->update();
+ _snakeLen = 5;
+ addFood();
+ return;
+ }
+ // Normal
+ if (_snake.size() >= _snakeLen) {
+ const QPoint &p = _snake.front();
+ if (FIELD(p.x(), p.y()) == FIELD_SNAKE) {
+ FIELD(p.x(), p.y()) = FIELD_FREE;
+ _widget->update(p.x() * SCALING, p.y() * SCALING, SCALING, SCALING);
+ }
+ _snake.pop_front();
+ }
+ if (FIELD(_x, _y) == FIELD_FOOD) {
+ if (qrand() % _snakeLen > 40) {
+ _snakeLen = 10;
+ while (_snake.size() > _snakeLen) {
+ _snake.pop_front();
+ }
+ addFood();
+ } else {
+ _snakeLen += 5;
+ }
+ addFood();
+ }
+ FIELD(_x, _y) = FIELD_SNAKE;
+ _snake.append(QPoint(_x, _y));
+ _widget->update(_x * SCALING, _y * SCALING, SCALING, SCALING);
+ // AI
+ int what[4], dist[4];
+ int best = 0;
+ scanDir(0, -1, what[DIR_UP], dist[DIR_UP]);
+ scanDir(0, 1, what[DIR_DOWN], dist[DIR_DOWN]);
+ scanDir(-1, 0, what[DIR_LEFT], dist[DIR_LEFT]);
+ scanDir(1, 0, what[DIR_RIGHT], dist[DIR_RIGHT]);
+ for (int i = 1; i < 4; ++i) {
+ if (what[i] == FIELD_FOOD) {
+ if (what[best] != FIELD_FOOD || dist[best] > dist[i]) {
+ best = i;
+ }
+ } else if (what[best] != FIELD_FOOD && dist[i] > dist[best]) {
+ best = i;
+ }
+ }
+ if (what[best] == FIELD_FOOD) {
+ _direction = best;
+ } else if (dist[_direction] <= 1) {
+ _direction = best;
+ }
+ });
+}
+
+Snake::~Snake()
+{
+ free(_field);
+}
+
+void Snake::scanDir(int dx, int dy, int &what, int &dist)
+{
+ int x = _x;
+ int y = _y;
+ dist = 0;
+ for (;;) {
+ x += dx;
+ y += dy;
+ dist++;
+ if (x < 0 || x >= _width || y < 0 || y >= _height) {
+ what = FIELD_SNAKE;
+ return;
+ }
+ if (FIELD(x, y) != FIELD_FREE) {
+ what = FIELD(x, y);
+ return;
+ }
+ }
+}
+
+void Snake::addFood()
+{
+ for (int i = 0; i < 10; ++i) {
+ int x = qrand() % _width;
+ int y = qrand() % _height;
+ if (FIELD(x, y) != FIELD_FOOD) {
+ FIELD(x, y) = FIELD_FOOD;
+ _widget->update(x * SCALING, y * SCALING, SCALING, SCALING);
+ break;
+ }
+ }
+}
+
+void Snake::paint(QPaintEvent *event)
+{
+ QPainter p(_widget);
+ const int width = qMin(_width, (event->rect().x() + event->rect().width() + SCALING - 1) / SCALING);
+ const int height = qMin(_height, (event->rect().y() + event->rect().height() + SCALING - 1) / SCALING);
+ for (int y = event->rect().y() / SCALING; y < height; ++y) {
+ if (y < 0)
+ continue;
+ for (int x = event->rect().x() / SCALING; x < width; ++x) {
+ if (x < 0)
+ continue;
+ switch (FIELD(x, y)) {
+ case FIELD_FOOD:
+ p.setBrush(Qt::green);
+ break;
+ case FIELD_SNAKE:
+ p.setBrush(Qt::white);
+ break;
+ default:
+ continue;
+ }
+ p.drawRect(x * SCALING, y * SCALING, SCALING-1, SCALING-1);
+ }
+ }
+}
diff --git a/src/snake.h b/src/snake.h
new file mode 100644
index 0000000..502c53f
--- /dev/null
+++ b/src/snake.h
@@ -0,0 +1,33 @@
+#ifndef _SNAKE_H_
+#define _SNAKE_H_
+
+#include <QList>
+#include <QPoint>
+
+class QWidget;
+class QPaintEvent;
+
+class Snake
+{
+private:
+ QWidget *_widget;
+ int *_field;
+ int _width, _height;
+ int _x, _y;
+ int _direction;
+ int _snakeLen;
+ QList<QPoint> _snake;
+
+public:
+ Snake(QWidget *widget);
+
+ virtual ~Snake();
+
+ void paint(QPaintEvent *event);
+
+ void addFood();
+
+ void scanDir(int x, int y, int &what, int &dist);
+};
+
+#endif