summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <srodal@gmail.com>2008-11-27 23:13:02 +0100
committerSamuel Rødal <srodal@gmail.com>2008-11-27 23:13:02 +0100
commit2ede9ae62072af23fa92410c87c7aec1ffdf3364 (patch)
tree406d6f306c49f95e4d082fc1ac8e2a2d4b5bdba4
parentf2fb35cc3a227e8966bab9a9380fe9a543874eb6 (diff)
Collision detection.
-rw-r--r--main.cpp2
-rw-r--r--mazescene.cpp139
-rw-r--r--mazescene.h7
3 files changed, 103 insertions, 45 deletions
diff --git a/main.cpp b/main.cpp
index 4e872a0..0da599c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -17,7 +17,7 @@ int main(int argc, char **argv)
"# @@ # #"
"# #"
"###&%-##"
- "$ #"
+ "$ !"
"#&&&&&&#";
MazeScene *scene = new MazeScene(map, 8, 12);
diff --git a/mazescene.cpp b/mazescene.cpp
index f4a3c73..f8fddab 100644
--- a/mazescene.cpp
+++ b/mazescene.cpp
@@ -33,13 +33,15 @@ MazeScene::MazeScene(const char *map, int width, int height)
, m_cameraAngle(0.1)
, m_walkingVelocity(0)
, m_turningVelocity(0)
- , m_doorAnimation(0)
, m_simulationTime(0)
, m_walkTime(0)
- , m_dirty(true)
, m_width(width)
, m_height(height)
{
+ m_doorAnimation = new QTimeLine(1000, this);
+ m_doorAnimation->setUpdateInterval(20);
+ connect(m_doorAnimation, SIGNAL(valueChanged(qreal)), this, SLOT(moveDoors(qreal)));
+
QMap<char, int> types;
types[' '] = -2;
types['-'] = -1;
@@ -49,6 +51,7 @@ MazeScene::MazeScene(const char *map, int width, int height)
types['%'] = 3;
types['$'] = 4;
types['?'] = 5;
+ types['!'] = 6;
int type;
for (int y = 0; y < height; ++y) {
@@ -82,7 +85,7 @@ MazeScene::MazeScene(const char *map, int width, int height)
connect(timer, SIGNAL(timeout()), this, SLOT(move()));
m_time.start();
- move();
+ updateTransforms();
}
void MazeScene::addWall(const QPointF &a, const QPointF &b, int type)
@@ -399,69 +402,119 @@ bool MazeScene::handleKey(int key, bool pressed)
switch (key) {
case Qt::Key_Left:
case Qt::Key_Right:
- m_turningVelocity = (pressed ? (key == Qt::Key_Left ? -1 : 1) : 0) * 0.5;
+ m_turningVelocity = (pressed ? (key == Qt::Key_Left ? -1 : 1) * 0.5 : 0.0);
return true;
case Qt::Key_Up:
case Qt::Key_Down:
- m_walkingVelocity = (pressed ? (key == Qt::Key_Down ? -1 : 1) : 0) * 0.01;
+ m_walkingVelocity = (pressed ? (key == Qt::Key_Down ? -1 : 1) * 0.01 : 0.0);
return true;
}
return false;
}
-void MazeScene::move()
+static inline QRectF rectFromPoint(const QPointF &point, qreal size)
{
- long elapsed = m_time.elapsed();
- while (m_simulationTime <= elapsed) {
- m_cameraAngle += m_turningVelocity;
- m_cameraPos += m_walkingVelocity * rotatingTransform(-m_cameraAngle).map(QPointF(0, 1));
- m_simulationTime += 5;
+ return QRectF(point, point).adjusted(-size/2, -size/2, size/2, size/2);
+}
+
+bool MazeScene::blocked(const QPointF &pos) const
+{
+ const QRectF rect = rectFromPoint(pos, 0.4);
+
+ foreach (WallItem *item, m_walls) {
+ if (item->type() == 6
+ || item->type() == -1 && m_doorAnimation->state() != QTimeLine::Running
+ && m_doorAnimation->direction() == QTimeLine::Backward)
+ continue;
+
+ const QPointF a = item->a();
+ const QPointF b = item->b();
+
+ QRectF wallRect = QRectF(a, b).adjusted(-0.01, -0.01, 0.01, 0.01);
+
+ if (wallRect.intersects(rect))
+ return true;
+ }
+
+ foreach (Entity *entity, m_entities) {
+ QRectF entityRect = rectFromPoint(entity->pos(), 0.4);
+
+ if (entityRect.intersects(rect))
+ return true;
+ }
+
+ return false;
+}
- bool walking = m_walkingVelocity != 0;
- bool turning = m_turningVelocity != 0;
- if (!m_dirty)
- m_dirty = turning || walking;
+bool MazeScene::tryMove(QPointF &pos, const QPointF &delta) const
+{
+ bool moved = false;
+ if (!blocked(pos + QPointF(delta.x(), 0))) {
+ pos.setX(pos.x() + delta.x());
+ moved = true;
+ }
- if (walking)
- m_walkTime += 5;
+ if (!blocked(pos + QPointF(0, delta.y()))) {
+ pos.setY(pos.y() + delta.y());
+ moved = true;
}
- if (m_dirty) {
- m_dirty = false;
- foreach (WallItem *item, m_walls) {
- item->updateTransform(m_cameraPos, m_cameraAngle, m_walkTime * 0.001);
- if (item->isVisible()) {
- // embed recursive scene
- if (QGraphicsProxyWidget *child = item->childItem()) {
- View *view = qobject_cast<View *>(child->widget());
- if (view && !view->scene()) {
- const char *map = "#$###"
- "# #"
- "# @ #"
- "# #"
- "#####";
- MazeScene *embeddedScene = new MazeScene(map, 5, 5);
- view->setScene(embeddedScene);
- }
+ return moved;
+}
+
+void MazeScene::updateTransforms()
+{
+ foreach (WallItem *item, m_walls) {
+ item->updateTransform(m_cameraPos, m_cameraAngle, m_walkTime * 0.001);
+ if (item->isVisible()) {
+ // embed recursive scene
+ if (QGraphicsProxyWidget *child = item->childItem()) {
+ View *view = qobject_cast<View *>(child->widget());
+ if (view && !view->scene()) {
+ const char *map =
+ "#$###"
+ "# #"
+ "# @ #"
+ "# #"
+ "#####";
+ MazeScene *embeddedScene = new MazeScene(map, 5, 5);
+ view->setScene(embeddedScene);
}
}
}
- foreach (Entity *entity, m_entities)
- entity->updateTransform(m_cameraPos, m_cameraAngle, m_walkTime * 0.001);
- setFocusItem(0); // setVisible(true) might give focus to one of the items
- update();
}
+ foreach (Entity *entity, m_entities)
+ entity->updateTransform(m_cameraPos, m_cameraAngle, m_walkTime * 0.001);
+ setFocusItem(0); // setVisible(true) might give focus to one of the items
+ update();
}
-void MazeScene::toggleDoors()
+void MazeScene::move()
{
- if (!m_doorAnimation) {
- m_doorAnimation = new QTimeLine(1000, this);
- m_doorAnimation->setUpdateInterval(20);
- connect(m_doorAnimation, SIGNAL(valueChanged(qreal)), this, SLOT(moveDoors(qreal)));
+ qreal oldCameraAngle = m_cameraAngle;
+ QPointF oldCameraPos = m_cameraPos;
+
+ long elapsed = m_time.elapsed();
+ while (m_simulationTime <= elapsed) {
+ m_cameraAngle += m_turningVelocity;
+
+ if (m_walkingVelocity != 0) {
+ QPointF walkingDir = rotatingTransform(-m_cameraAngle).map(QPointF(0, 1));
+ QPointF walkingDelta = m_walkingVelocity * walkingDir;
+ if (tryMove(m_cameraPos, walkingDelta))
+ m_walkTime += 5;
+ }
+
+ m_simulationTime += 5;
}
+ if (oldCameraAngle != m_cameraAngle || oldCameraPos != m_cameraPos)
+ updateTransforms();
+}
+
+void MazeScene::toggleDoors()
+{
setFocusItem(0);
if (m_doorAnimation->state() == QTimeLine::Running)
diff --git a/mazescene.h b/mazescene.h
index f310082..2e0f1bc 100644
--- a/mazescene.h
+++ b/mazescene.h
@@ -65,6 +65,8 @@ public:
Entity(const QPointF &pos);
void updateTransform(const QPointF &cameraPos, qreal cameraRotation, qreal time);
+ QPointF pos() const { return m_pos; }
+
private:
QPointF m_pos;
};
@@ -94,6 +96,10 @@ private slots:
void moveDoors(qreal value);
private:
+ bool blocked(const QPointF &pos) const;
+ bool tryMove(QPointF &pos, const QPointF &delta) const;
+ void updateTransforms();
+
QVector<WallItem *> m_walls;
QVector<WallItem *> m_doors;
QVector<QGraphicsItem *> m_floorTiles;
@@ -109,7 +115,6 @@ private:
QTimeLine *m_doorAnimation;
long m_simulationTime;
long m_walkTime;
- bool m_dirty;
int m_width;
int m_height;
};