aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSamu Laaksonen <laaksonen.sj@gmail.com>2012-09-25 20:00:41 +0300
committerSamu Laaksonen <laaksonen.sj@gmail.com>2012-09-25 20:00:41 +0300
commit685fe05def77b039221edf06c74af74915d536c5 (patch)
tree9c1a14b8f68bc0f801bdec3edc447d04fdbf7a4c /src
parent29eabac0670574efd384182c065f53d08c42a483 (diff)
downloadprism-685fe05def77b039221edf06c74af74915d536c5.tar.gz
prism-685fe05def77b039221edf06c74af74915d536c5.zip
Initial code commit
Added some stuff for project base - tiled sources - few Qt based classes for gfx
Diffstat (limited to 'src')
-rw-r--r--src/ActionScene.cpp150
-rw-r--r--src/ActionScene.h83
-rw-r--r--src/BasicEnemy.cpp38
-rw-r--r--src/BasicEnemy.h21
-rw-r--r--src/Character.cpp113
-rw-r--r--src/Character.h65
-rw-r--r--src/Collectible.cpp25
-rw-r--r--src/Collectible.h19
-rw-r--r--src/CreditsScene.cpp64
-rw-r--r--src/CreditsScene.h25
-rw-r--r--src/GameScene.cpp96
-rw-r--r--src/GameScene.h55
-rw-r--r--src/GameView.cpp174
-rw-r--r--src/GameView.h57
-rw-r--r--src/GraphicsButtonObject.cpp137
-rw-r--r--src/GraphicsButtonObject.h59
-rw-r--r--src/GraphicsPixmapObject.cpp7
-rw-r--r--src/GraphicsPixmapObject.h30
-rw-r--r--src/Hero.cpp41
-rw-r--r--src/Hero.h25
-rw-r--r--src/LevelSelectionScene.cpp98
-rw-r--r--src/LevelSelectionScene.h36
-rw-r--r--src/MainWindow.cpp17
-rw-r--r--src/MainWindow.h23
-rw-r--r--src/MenuScene.cpp53
-rw-r--r--src/MenuScene.h32
-rw-r--r--src/ParallaxScrollerItem.cpp47
-rw-r--r--src/ParallaxScrollerItem.h24
-rw-r--r--src/ParallaxScrollerStatic.cpp29
-rw-r--r--src/ParallaxScrollerStatic.h26
-rw-r--r--src/SceneChanger.cpp107
-rw-r--r--src/SceneChanger.h74
-rw-r--r--src/Sprite.cpp108
-rw-r--r--src/Sprite.h70
-rw-r--r--src/main.cpp33
-rw-r--r--src/src.pro55
36 files changed, 2116 insertions, 0 deletions
diff --git a/src/ActionScene.cpp b/src/ActionScene.cpp
new file mode 100644
index 0000000..9d7013c
--- /dev/null
+++ b/src/ActionScene.cpp
@@ -0,0 +1,150 @@
+#include <QPainter>
+#include <QPainterPath>
+#include <QColor>
+#include <QBrush>
+#include <QDebug>
+#include <QGraphicsPixmapItem>
+#include <QGraphicsSceneMouseEvent>
+
+#include <QSettings>
+
+#include <QApplication>
+#include <QTime>
+#include <QFileInfo>
+#include <QMessageBox>
+
+#include "MainWindow.h"
+#include "GameView.h"
+#include "Hero.h"
+#include "ParallaxScrollerStatic.h"
+#include "Collectible.h"
+
+#include "layer.h"
+#include "objectgroup.h"
+#include "mapobject.h"
+#include "tile.h"
+
+#include "ActionScene.h"
+
+using Tiled::Map;
+using Tiled::MapReader;
+using Tiled::OrthogonalRenderer;
+using Tiled::Layer;
+using Tiled::ObjectGroup;
+using Tiled::Tile;
+
+ActionScene::ActionScene(const QString &name, const QRectF &rect, GameView *parent)
+ : GameScene(name, parent)
+{
+ setSceneRect(rect);
+ m_clearAlert = false;
+ m_mapReader = new MapReader;
+
+ qsrand(QTime::currentTime().msec());
+
+ m_hpText = new QGraphicsTextItem("HP: ", 0, this);
+ m_hpText->setPos(100, 10);
+ m_scoreText = new QGraphicsTextItem("Score: 0", 0, this);
+ m_scoreText->setPos(100, 20);
+
+ m_hero = new Hero(this, QPointF(100, 300));
+ connect(m_hero, SIGNAL(removeMe()), this, SLOT(removeSprite()));
+}
+
+ActionScene::~ActionScene()
+{
+ delete m_map;
+ delete m_mapReader;
+ delete m_mapRenderer;
+}
+
+void ActionScene::updateLogic()
+{
+ if(!m_clearAlert)
+ {
+ advance();
+ update();
+ }
+}
+
+void ActionScene::keyPressEvent(QKeyEvent *event)
+{
+ QGraphicsScene::keyPressEvent(event);
+}
+
+void ActionScene::loadMap(QString target)
+{
+ QFileInfo f(target);
+ m_levelName = f.fileName();
+
+ QSettings set;
+ m_levelScore = set.value(m_levelName).toInt();
+
+ m_map = m_mapReader->readMap(target);
+
+ if (m_map == NULL)
+ {
+ qDebug() << "error:" << m_mapReader->errorString();
+ return;
+ }
+
+ m_mapRenderer = new OrthogonalRenderer(m_map);
+
+ qDebug() << "size" << m_map->width() << "x" << m_map->height();
+ qDebug() << "layers" << m_map->layerCount();
+
+ QImage img(m_map->width() * m_map->tileWidth(),
+ m_map->height() * m_map->tileHeight(),
+ QImage::Format_ARGB32);
+
+ QPainter painter(&img);
+ m_mapRenderer->drawTileLayer(&painter, m_map->layerAt(0)->asTileLayer());
+
+ m_mapPixmap = QPixmap::fromImage(img);
+
+ qDebug() << "hasAlpha" << m_mapPixmap.hasAlpha() << "\n"
+ << "hasAlphaChannel" << m_mapPixmap.hasAlphaChannel();
+
+ m_mapPixmapItem = addPixmap(m_mapPixmap);
+ m_mapPixmapItem->setPos(0, 0);
+ m_mapPixmapItem->setData(ITEM_OBJECTNAME, QString("SolidGround"));
+ m_mapPixmapItem->setShapeMode(QGraphicsPixmapItem::MaskShape);
+ m_mapPixmapItem->setZValue(1);
+
+ m_mapPixmapItem->setPixmap(m_mapPixmap);
+
+ ObjectGroup* fish = NULL;
+
+ if(m_map->indexOfLayer("fish") >= 0)
+ fish = m_map->layerAt(m_map->indexOfLayer("fish"))->asObjectGroup();
+
+ if(fish)
+ {
+ Q_FOREACH(Tiled::MapObject *obj, fish->objects())
+ {
+ Collectible *fish = new Collectible(0, this);
+ fish->setData(ITEM_OBJECTNAME, QString("fish"));
+ connect(fish, SIGNAL(removeMe()), this, SLOT(removeSprite()));
+
+ fish->setPos((obj->x()) * m_map->tileWidth(),
+ (obj->y() - 1) * m_map->tileHeight());
+
+ fish->setZValue(2);
+
+ qDebug() << obj->position() << fish->pos();
+ }
+ }
+ m_clearAlert = false;
+}
+
+void ActionScene::removeSprite()
+{
+ qDebug() << "removing a sprite";
+
+ Sprite* sp = (Sprite*) sender();
+ if(sp)
+ {
+ removeItem(sp);
+ sp->deleteLater();
+ }
+}
diff --git a/src/ActionScene.h b/src/ActionScene.h
new file mode 100644
index 0000000..49fdb20
--- /dev/null
+++ b/src/ActionScene.h
@@ -0,0 +1,83 @@
+#ifndef ActionScene_H
+#define ActionScene_H
+
+#include <QObject>
+#include <QRectF>
+#include <QGraphicsRectItem>
+
+#include "GameScene.h"
+#include "Sprite.h"
+
+#include "map.h"
+#include "mapreader.h"
+#include "orthogonalrenderer.h"
+
+class QGraphicsPixmapItem;
+class Hero;
+
+class ActionScene : public GameScene
+{
+ Q_OBJECT
+
+public:
+ explicit ActionScene(const QString &name, const QRectF &rect, GameView *parent = 0);
+ virtual ~ActionScene();
+
+ void updateLogic();
+ void keyPressEvent(QKeyEvent *event);
+
+ /**
+ * Loads level from target location.
+ */
+ void loadMap(QString target);
+
+private:
+
+ Tiled::Map *m_map;
+ Tiled::MapReader *m_mapReader;
+ Tiled::OrthogonalRenderer *m_mapRenderer;
+
+ //! Level name used for records.
+ QString m_levelName;
+
+ //! Levelscore used for records.
+ int m_levelScore;
+
+ //! Map layer is drawn to this pixmap
+ QPixmap m_mapPixmap;
+
+ //! Item for map layer
+ QGraphicsPixmapItem *m_mapPixmapItem;
+
+ //! What portion of the map to draw
+ QSize m_mapWindow;
+
+ //! Background pixmap
+ QPixmap m_bgPixmap;
+ QGraphicsPixmapItem *m_bgPixmapItem;
+
+ //! What portion of the bg pixmap to draw
+ QRectF m_bgWindow;
+
+ //! Pointer for forwarding commands to main character
+ Hero* m_hero;
+
+ //! Stops graphics rendering while scene is cleared.
+ bool m_clearAlert;
+
+ //! HP text item
+ QGraphicsTextItem* m_hpText;
+ //! Score text item
+ QGraphicsTextItem* m_scoreText;
+
+signals:
+ void gameOver();
+
+public slots:
+ /**
+ * Removes a sprite from the scene
+ */
+ void removeSprite();
+};
+
+#endif // ActionScene_H
diff --git a/src/BasicEnemy.cpp b/src/BasicEnemy.cpp
new file mode 100644
index 0000000..c42f961
--- /dev/null
+++ b/src/BasicEnemy.cpp
@@ -0,0 +1,38 @@
+#include <QGraphicsScene>
+#include <QApplication>
+#include <QDebug>
+
+#include "BasicEnemy.h"
+
+BasicEnemy::BasicEnemy(QGraphicsScene* scene, QPointF pos, QGraphicsItem* parent)
+ : Character(parent, scene)
+{
+ m_velocityY = 0;
+ m_velocityX = 1;
+
+ setPos(pos);
+ setZValue(2);
+ setShapeMode(QGraphicsPixmapItem::MaskShape);
+}
+
+BasicEnemy::~BasicEnemy()
+{
+
+}
+
+void BasicEnemy::advance(int phase)
+{
+ if(phase == 0)
+ return;
+
+ if(m_state == STATE_DEAD)
+ {
+ qDebug() << "this baddy be dead now";
+ removeMe();
+ }
+
+ if(phase == 1)
+ {
+ return;
+ }
+}
diff --git a/src/BasicEnemy.h b/src/BasicEnemy.h
new file mode 100644
index 0000000..37ce25e
--- /dev/null
+++ b/src/BasicEnemy.h
@@ -0,0 +1,21 @@
+#ifndef BasicEnemy_h
+#define BasicEnemy_h
+
+#include <QGraphicsPixmapItem>
+#include <QGraphicsScene>
+
+#include "Character.h"
+
+class BasicEnemy : public Character
+{
+public:
+ BasicEnemy(QGraphicsScene* scene, QPointF pos, QGraphicsItem* parent = 0);
+ virtual ~BasicEnemy();
+
+ void advance(int phase);
+
+private:
+
+};
+
+#endif // BasicEnemy_h
diff --git a/src/Character.cpp b/src/Character.cpp
new file mode 100644
index 0000000..83b18ce
--- /dev/null
+++ b/src/Character.cpp
@@ -0,0 +1,113 @@
+#include "Character.h"
+
+Character::Character(QGraphicsItem *parent, QGraphicsScene *scene)
+ : Sprite(parent, scene),
+ m_healthPoints(10),
+ m_shieldCapacity(0),
+ m_meleeDamage(5),
+ m_rangedDamage(0),
+ m_velocityX(0),
+ m_velocityY(0),
+ m_state(STATE_IDLE)
+{
+
+}
+
+Character::~Character()
+{
+}
+
+void Character::increaseHealthPoints(int hp)
+{
+ m_healthPoints += hp;
+}
+
+void Character::decreaseHealthPoints(int hp)
+{
+ m_healthPoints -= hp;
+
+ if(m_healthPoints <= 0)
+ {
+ m_state = STATE_DEAD;
+ }
+}
+
+void Character::setHealthPoints(int hp)
+{
+ m_healthPoints = hp;
+}
+
+int Character::getHealthPoints()
+{
+ return m_healthPoints;
+}
+
+void Character::increaseShieldCapacity(int shieldCapacity)
+{
+ m_shieldCapacity += shieldCapacity;
+}
+
+void Character::decreaseShieldCapacity(int shieldCapacity)
+{
+ m_shieldCapacity -= shieldCapacity;
+}
+
+void Character::setShieldCapacity(int shieldCapacity)
+{
+ m_shieldCapacity = shieldCapacity;
+}
+
+int Character::getShieldCapacity()
+{
+ return m_shieldCapacity;
+}
+
+void Character::setMeleeDamage(int damage)
+{
+ m_meleeDamage = damage;
+}
+
+int Character::getMeleeDamage()
+{
+ return m_meleeDamage;
+}
+
+void Character::setRangedDamage(int damage)
+{
+ m_rangedDamage = damage;
+}
+
+int Character::getRangedDamage()
+{
+ return m_rangedDamage;
+}
+
+void Character::setVelocityX(int x)
+{
+ m_velocityX = x;
+}
+
+void Character::setVelocityY(int y)
+{
+ m_velocityY = y;
+}
+
+int Character::getVelocityX()
+{
+ return m_velocityX;
+}
+
+int Character::getVelocityY()
+{
+ return m_velocityY;
+}
+
+void Character::setState(State s)
+{
+ m_state = s;
+}
+
+State Character::getState()
+{
+ return m_state;
+}
diff --git a/src/Character.h b/src/Character.h
new file mode 100644
index 0000000..b246169
--- /dev/null
+++ b/src/Character.h
@@ -0,0 +1,65 @@
+#ifndef Character_h
+#define Character_h
+
+#include "Sprite.h"
+
+enum State
+{
+ STATE_IDLE,
+ STATE_MOVING_RIGHT,
+ STATE_MOVING_LEFT,
+ STATE_DEAD,
+ STATE_JUMPING,
+ STATE_LANDING,
+ STATE_JUMPING_DOUBLE,
+ STATE_LANDING_DOUBLE_FORCE,
+ STATE_SPRINTING_RIGHT,
+ STATE_SPRINTING_LEFT,
+ STATE_CLIMB_UP,
+ STATE_CLIMG_DOWN
+};
+
+class Character: public Sprite
+{
+public:
+ explicit Character(QGraphicsItem *parent = 0, QGraphicsScene *scene = 0);
+ virtual ~Character();
+
+ void increaseHealthPoints(int);
+ void decreaseHealthPoints(int);
+ void setHealthPoints(int);
+ int getHealthPoints();
+
+ void increaseShieldCapacity(int);
+ void decreaseShieldCapacity(int);
+ void setShieldCapacity(int);
+ int getShieldCapacity();
+
+ void setMeleeDamage(int);
+ int getMeleeDamage();
+
+ void setRangedDamage(int);
+ int getRangedDamage();
+
+ void setVelocityX(int);
+ void setVelocityY(int);
+ int getVelocityX();
+ int getVelocityY();
+
+ void setState(State);
+ State getState();
+
+protected:
+ int m_healthPoints;
+ int m_shieldCapacity;
+
+ int m_meleeDamage;
+ int m_rangedDamage;
+
+ int m_velocityX;
+ int m_velocityY;
+
+ State m_state;
+};
+
+#endif // Character_h
diff --git a/src/Collectible.cpp b/src/Collectible.cpp
new file mode 100644
index 0000000..3bf298c
--- /dev/null
+++ b/src/Collectible.cpp
@@ -0,0 +1,25 @@
+#include "Collectible.h"
+
+#include <QSettings>
+
+Collectible::Collectible(QGraphicsItem *parent, QGraphicsScene *scene)
+ : Sprite(parent, scene)
+{
+
+}
+
+void Collectible::collected()
+{
+ setData(0, "colllected");
+ removeMe();
+}
+
+void Collectible::setValue(int value)
+{
+ m_value = value;
+}
+
+int Collectible::getValue() const
+{
+ return m_value;
+}
diff --git a/src/Collectible.h b/src/Collectible.h
new file mode 100644
index 0000000..7ac79d3
--- /dev/null
+++ b/src/Collectible.h
@@ -0,0 +1,19 @@
+#ifndef Collectible_H
+#define Collectible_H
+
+#include "Sprite.h"
+
+class Collectible : public Sprite
+{
+public:
+ Collectible(QGraphicsItem *parent = 0, QGraphicsScene *scene = 0);
+ void collected();
+
+ void setValue(int value);
+ int getValue() const;
+
+private:
+ int m_value;
+};
+
+#endif // Collectible_H
diff --git a/src/CreditsScene.cpp b/src/CreditsScene.cpp
new file mode 100644
index 0000000..cd1558c
--- /dev/null
+++ b/src/CreditsScene.cpp
@@ -0,0 +1,64 @@
+#include <QApplication>
+#include <QGraphicsTextItem>
+
+#include <QDebug>
+
+#include "GameView.h"
+#include "GraphicsButtonObject.h"
+#include "ParallaxScrollerStatic.h"
+
+#include "CreditsScene.h"
+
+CreditsScene::CreditsScene(const QString &name, const QRectF &rect, GameView *parent)
+ : GameScene(name, parent)
+{
+ setSceneRect(rect);
+
+ QString appDir = qApp->applicationDirPath();
+
+ m_background = new ParallaxScrollerStatic(this);
+ m_background->setLayerWidth(rect.width());
+ m_background->addParallaxScrollItem(QString(appDir + "/gfx/bg/layer1.png"), QPointF(0,0), -2, 6);
+ m_background->addParallaxScrollItem(QString(appDir + "/gfx/bg/layer2.png"), QPointF(0,0), -1, 4);
+
+ initializeScene();
+}
+
+CreditsScene::~CreditsScene()
+{
+ delete m_background;
+}
+
+void CreditsScene::initializeScene()
+{
+ addTitle("Credits");
+
+ QGraphicsTextItem* creditText = new QGraphicsTextItem(0, this);
+ creditText->setHtml("<b>WalRush</b> (v. 1.0) <br><br>"\
+ "WalRush was originally a project "\
+ "for course in TAMK.<br><br>"\
+ "Programming by:<br>"\
+ "Samu Laaksonen<br>"\
+ "Oskari Timperi<br><br>"\
+ "Graphics by: <br>"\
+ "Lauri Paakinaho<br><br>"\
+ "Copyright (c) 2010 of aforementioned persons. All rights reserved.<br>");
+ creditText->setPos(140, 130);
+ creditText->setFont(QFont("Arial", 14));
+
+ GraphicsButtonObject *btn;
+ btn = new GraphicsButtonObject(QPixmap(qApp->applicationDirPath() + "/gfx/buttons/back-arrow1.png"),
+ 0, this);
+ btn->setPressedPixmap(QPixmap(qApp->applicationDirPath() + "/gfx/buttons/back-arrow2.png"));
+ btn->setPos(720, 400);
+ btn->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
+ btn->setZValue(2);
+
+ connect(btn, SIGNAL(clicked()), gameView(), SLOT(showMenuScene()));
+}
+
+void CreditsScene::updateLogic()
+{
+ advance();
+ update();
+}
diff --git a/src/CreditsScene.h b/src/CreditsScene.h
new file mode 100644
index 0000000..144d135
--- /dev/null
+++ b/src/CreditsScene.h
@@ -0,0 +1,25 @@
+#ifndef CreditsScene_h
+#define CreditsScene_h
+
+#include "GameScene.h"
+
+#include "ParallaxScrollerStatic.h"
+
+class CreditsScene : public GameScene
+{
+public:
+ CreditsScene(const QString &name, const QRectF &rect, GameView *parent = 0);
+ virtual ~CreditsScene();
+
+ void updateLogic();
+
+ /**
+ * Initializes resources used on scene.
+ */
+ void initializeScene();
+
+private:
+ ParallaxScrollerStatic* m_background;
+};
+
+#endif // CreditsScene_h
diff --git a/src/GameScene.cpp b/src/GameScene.cpp
new file mode 100644
index 0000000..ed011c1
--- /dev/null
+++ b/src/GameScene.cpp
@@ -0,0 +1,96 @@
+#include <QPainter>
+#include <QGraphicsPixmapItem>
+#include <QDebug>
+
+#include "GameView.h"
+
+#include "GameScene.h"
+
+GameScene::GameScene(const QString &name, GameView *parent) :
+ QGraphicsScene(parent)
+{
+ setObjectName(name);
+ m_gameView = parent;
+}
+
+GameView* GameScene::gameView() const
+{
+ return m_gameView;
+}
+
+void GameScene::enterScene(GameScene *)
+{
+ qDebug() << __FUNCTION__ << objectName();
+}
+
+void GameScene::leaveScene(GameScene *)
+{
+ qDebug() << __FUNCTION__ << objectName();
+}
+
+QGraphicsPixmapItem* GameScene::addTitle(const QString &title, int pointSize)
+{
+ // // Draw text with a black outline and using a gradient as a brush :-)
+ QLinearGradient grad;
+
+ grad.setCoordinateMode(QGradient::ObjectBoundingMode);
+
+ grad.setStart(0, 0);
+ grad.setFinalStop(0, 1);
+
+ /* the old gradient
+ grad.setColorAt(0, Qt::white);
+ grad.setColorAt(0.25, QColor(226, 174, 31));
+ grad.setColorAt(0.5, QColor(149, 113, 16));
+ grad.setColorAt(0.51, Qt::white);
+ grad.setColorAt(1, QColor(68, 153, 213));
+ */
+
+ grad.setColorAt(0, Qt::white);
+ grad.setColorAt(0.20, QColor(137, 175, 201));
+ grad.setColorAt(0.35, QColor(35, 136, 207));
+ grad.setColorAt(0.5, QColor(32, 98, 145));
+ grad.setColorAt(0.65, QColor(35, 136, 207));
+ grad.setColorAt(0.80, QColor(137, 175, 201));
+ grad.setColorAt(1, Qt::white);
+
+ QFont font("Arial", pointSize);
+ font.setUnderline(true);
+ font.setLetterSpacing(QFont::PercentageSpacing, 95);
+ font.setWordSpacing(-20);
+
+ QFontMetrics metrics(font);
+// QRect bbox = metrics.boundingRect(title);
+
+// qDebug() << metrics.boundingRect("MAZENNUS");
+// qDebug() << metrics.width("MAZENNUS") << metrics.height();
+
+ QPainterPath path;
+ // path.addText(pixmap.width()/2-bbox.width()/2, 20+metrics.ascent(), font, "MAZENNUS");
+ path.addText(0, metrics.ascent(), font, title);
+
+ QImage img(metrics.width(title), metrics.height()+3, QImage::Format_ARGB32);
+
+ QPainter painter(&img);
+
+ // set dst pixels to transparent regardless of src
+ painter.setCompositionMode(QPainter::CompositionMode_Clear);
+ painter.fillRect(img.rect(), Qt::white);
+
+ // switch back to normal
+ painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setPen(QPen(Qt::black, 3));
+ painter.setBrush(grad);
+
+ painter.drawPath(path);
+
+ QPixmap pixmap = QPixmap::fromImage(img);
+
+ QGraphicsPixmapItem *i = addPixmap(pixmap);
+
+ i->setPos(sceneRect().width()/2 - pixmap.width()/2, 20);
+
+ return i;
+}
diff --git a/src/GameScene.h b/src/GameScene.h
new file mode 100644
index 0000000..0d1921a
--- /dev/null
+++ b/src/GameScene.h
@@ -0,0 +1,55 @@
+#ifndef GameScene_h
+#define GameScene_h
+
+#include <QGraphicsScene>
+
+class GameView;
+
+//! Used in QGraphicsItem::setData()/data()
+static const int ITEM_OBJECTNAME = 0;
+
+
+/**
+ * The base class for all scenes in the game. GameScene class offers some
+ * convenience methods for all its children. This also helps the management
+ * of the scenes in GameView.
+ */
+class GameScene : public QGraphicsScene
+{
+ Q_OBJECT
+public:
+ explicit GameScene(const QString &name, GameView *parent = 0);
+
+ /**
+ * This should be called when the scene is entered, i.e. the scene
+ * becomes the active scene.
+ */
+ virtual void enterScene(GameScene *prev = 0);
+
+ /**
+ * This should be called when the scene is losing its active status.
+ */
+ virtual void leaveScene(GameScene *next = 0);
+
+ /**
+ * Used for updating contents of scene.
+ */
+ virtual void updateLogic() = 0;
+
+ /**
+ * Convenience method to get the associated GameView instance.
+ */
+ GameView* gameView() const;
+
+ QGraphicsPixmapItem *addTitle(const QString &title, int pointSize = 75);
+
+protected:
+ GameView* m_gameView;
+
+signals:
+
+public slots:
+
+};
+
+#endif // GameScene_h
diff --git a/src/GameView.cpp b/src/GameView.cpp
new file mode 100644
index 0000000..3ba2631
--- /dev/null
+++ b/src/GameView.cpp
@@ -0,0 +1,174 @@
+#include <QScrollBar>
+#include <QDebug>
+#include <QtOpenGL/QGLWidget>
+
+#include "ActionScene.h"
+#include "LevelSelectionScene.h"
+#include "CreditsScene.h"
+#include "SceneChanger.h"
+#include "MenuScene.h"
+
+#include "GameView.h"
+
+GameView *GameView::m_instance = NULL;
+
+GameView::GameView(QWidget *parent) :
+ QGraphicsView(parent)
+{
+ setViewport(new QGLWidget);
+
+ m_actionScene = new ActionScene("ActionScene", QRectF(0, 0, 6400, 480), this);
+ connect(m_actionScene, SIGNAL(gameOver()), this, SLOT(gameOver()));
+
+ LevelSelectionScene* levelSelectionScene = new LevelSelectionScene("LevelSelectionScene", QRectF(0, 0, 800, 480), this);
+ CreditsScene* creditsScene = new CreditsScene("CreditsScene", QRectF(0, 0, 800, 480), this);
+ MenuScene* menuScene = new MenuScene("MenuScene", QRectF(0, 0, 800, 480), this);
+
+ m_scenes.append(m_actionScene);
+ m_scenes.append(levelSelectionScene);
+ m_scenes.append(creditsScene);
+ m_scenes.append(menuScene);
+
+ m_sceneChanger = new SceneChanger("ChangerScene", QRectF(0, 0, 800, 480), this);
+
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setViewportUpdateMode(FullViewportUpdate);
+ setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
+
+ m_gameTimer = new QTimer(this);
+ connect(m_gameTimer, SIGNAL(timeout()), this, SLOT(updateSceneLogic()));
+
+ showScene(menuScene);
+}
+
+GameView *GameView::instance()
+{
+ if (m_instance == NULL)
+ {
+ m_instance = new GameView;
+ }
+
+ return m_instance;
+}
+
+GameScene *GameView::getScene(const QString &name)
+{
+ Q_FOREACH(GameScene *scene, m_scenes)
+ {
+ if (scene->objectName() == name)
+ {
+ return scene;
+ }
+ }
+
+ qDebug() << "GameScene" << name << "not found";
+
+ return NULL;
+}
+
+GameScene *GameView::getCurrentScene()
+{
+ return qobject_cast<GameScene *>(scene());
+}
+
+void GameView::showScene(const QString &name)
+{
+ GameScene *scene = NULL;
+
+ Q_FOREACH(GameScene *s, m_scenes)
+ {
+ if (s->objectName() == name)
+ {
+ scene = s;
+ break;
+ }
+ }
+
+ if (scene)
+ {
+ changeScene(scene);
+ }
+ else
+ {
+ qDebug() << "no such scene:" << name;
+ }
+}
+
+void GameView::changeScene(GameScene* scene)
+{
+ GameScene *current = getCurrentScene();
+ showScene(m_sceneChanger);
+
+ if( current->objectName() == "CreditsScene" && scene->objectName() == "MenuScene" )
+ m_sceneChanger->changeScene(current, scene, true);
+ else if( current->objectName() == "MenuScene" && scene->objectName() == "LevelSelectionScene" )
+ m_sceneChanger->changeScene(current, scene, true);
+ else if( current->objectName() == "LevelSelectionScene" && scene->objectName() == "ActionScene" )
+ m_sceneChanger->changeScene(current, scene, true);
+ else
+ m_sceneChanger->changeScene(current, scene, false);
+}
+
+void GameView::showScene(GameScene *scene)
+{
+ Q_ASSERT(scene != NULL);
+
+ GameScene *old = getCurrentScene();
+
+ if (scene == old)
+ return;
+
+ m_gameTimer->stop();
+
+ if (old)
+ old->leaveScene(scene);
+
+ setScene(scene);
+
+ scene->enterScene(old);
+
+ m_gameTimer->start(1000.0f / 60.0f);
+}
+
+void GameView::updateSceneLogic()
+{
+ GameScene *scene = getCurrentScene();
+
+ if (scene)
+ {
+ scene->updateLogic();
+ }
+}
+
+ActionScene* GameView::getActionScene()
+{
+ return m_actionScene;
+}
+
+void GameView::gameOver()
+{
+ qDebug() << __FUNCTION__;
+ // not so simple, man
+ showScene("LevelSelectionScene");
+}
+
+void GameView::showMenuScene()
+{
+ showScene("MenuScene");
+}
+
+void GameView::showLevelSelectionScene()
+{
+ showScene("LevelSelectionScene");
+}
+
+void GameView::showCreditsScene()
+{
+ showScene("CreditsScene");
+}
+
+void GameView::showActionScene()
+{
+ showScene("ActionScene");
+}
diff --git a/src/GameView.h b/src/GameView.h
new file mode 100644
index 0000000..b45dfb6
--- /dev/null
+++ b/src/GameView.h
@@ -0,0 +1,57 @@
+#ifndef GameView_h
+#define GameView_h
+
+#include <QGraphicsView>
+#include <QList>
+#include <QTimer>
+
+class ActionScene;
+class GameScene;
+class SceneChanger;
+
+class GameView : public QGraphicsView
+{
+ Q_OBJECT
+public:
+ static GameView *instance();
+
+ GameScene *getScene(const QString &);
+ GameScene *getCurrentScene();
+
+ ActionScene* getActionScene();
+
+signals:
+
+public slots:
+
+ void gameOver();
+
+ void showMenuScene();
+ void showLevelSelectionScene();
+ void showCreditsScene();
+ void showActionScene();
+
+ void changeScene(GameScene* );
+ void showScene(GameScene *);
+ void showScene(const QString &);
+
+private slots:
+
+ //! Calls GameScene::updateLogic of the current scene
+ void updateSceneLogic();
+
+private:
+ explicit GameView(QWidget *parent = 0);
+
+ static GameView *m_instance;
+
+ ActionScene* m_actionScene;
+ SceneChanger* m_sceneChanger;
+
+ QList<GameScene *> m_scenes;
+
+ //! Timer used to scene updates
+ QTimer *m_gameTimer;
+};
+
+#endif // GameView_h
diff --git a/src/GraphicsButtonObject.cpp b/src/GraphicsButtonObject.cpp
new file mode 100644
index 0000000..d5697fa
--- /dev/null
+++ b/src/GraphicsButtonObject.cpp
@@ -0,0 +1,137 @@
+#include <QDebug>
+#include <QGraphicsSceneMouseEvent>
+#include <QPainter>
+#include <QPainterPath>
+#include <QFontMetrics>
+
+#include "GraphicsButtonObject.h"
+
+QPixmap *GraphicsButtonObject::s_tmpGfx = 0;
+int GraphicsButtonObject::s_ref = 0;
+
+GraphicsButtonObject::GraphicsButtonObject(const QPixmap &releasedPixmap,
+ QGraphicsPixmapItem *parent,
+ QGraphicsScene *scene)
+ : QObject(0),
+ QGraphicsPixmapItem(releasedPixmap, parent, scene)
+
+{
+ s_ref++;
+ m_releasedGfx = releasedPixmap;
+}
+
+GraphicsButtonObject::GraphicsButtonObject(QGraphicsPixmapItem *parent,
+ QGraphicsScene *scene)
+ : QObject(0),
+ QGraphicsPixmapItem(parent, scene)
+
+{
+ s_ref++;
+}
+
+GraphicsButtonObject::GraphicsButtonObject(const QString &str,
+ QGraphicsPixmapItem *parent,
+ QGraphicsScene *scene)
+ : QObject(0),
+ QGraphicsPixmapItem(parent, scene)
+{
+ s_ref++;
+
+ int pw = 280;
+ int ph = 60;
+
+ // Draw the gradients only once
+ if (!s_tmpGfx)
+ {
+ //DBG("generating button gradients");
+
+ s_tmpGfx = new QPixmap(pw, ph);
+ QPainter painter(s_tmpGfx);
+
+ painter.setPen(Qt::NoPen);
+
+ painter.setBrush(Qt::white);
+ painter.drawRect(s_tmpGfx->rect());
+
+ QLinearGradient grad;
+
+ grad.setCoordinateMode(QGradient::ObjectBoundingMode);
+
+ grad.setStart(0, 0);
+ grad.setFinalStop(0, 1);
+
+ grad.setColorAt(0, Qt::white);
+ grad.setColorAt(0.20, QColor(137, 175, 201));
+ grad.setColorAt(0.35, QColor(35, 136, 207));
+ grad.setColorAt(0.5, QColor(32, 98, 145));
+ grad.setColorAt(0.65, QColor(35, 136, 207));
+ grad.setColorAt(0.80, QColor(137, 175, 201));
+ grad.setColorAt(1, Qt::white);
+
+ painter.setBrush(QBrush(grad));
+ painter.drawRect(4, 4, pw-8, ph-8);
+ }
+
+ QPixmap released = QPixmap(*s_tmpGfx);
+ QPainter painter(&released);
+
+ QFont font("Arial", 36);
+ font.setLetterSpacing(QFont::PercentageSpacing, 95);
+
+ QFontMetrics metrics(font);
+ QRect bbox = metrics.boundingRect(str);
+
+ QPainterPath path;
+
+ int x = (ph - metrics.height()) / 2;
+ path.addText(pw/2-bbox.width()/2, x + metrics.ascent(), font, str);
+
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setPen(QPen(Qt::black, 3));
+ painter.setBrush(Qt::white);
+ painter.drawPath(path);
+
+ QPixmap pressed(released);
+
+ QPainter painter2(&pressed);
+ painter2.setBrush(QColor(0, 0, 0, 127));
+ painter2.drawRect(pressed.rect());
+
+ m_releasedGfx = released;
+ m_pressedGfx = pressed;
+
+ setPixmap(released);
+}
+
+GraphicsButtonObject::~GraphicsButtonObject()
+{
+ s_ref--;
+
+ if (s_tmpGfx && s_ref == 0)
+ {
+ delete s_tmpGfx;
+ s_tmpGfx = 0;
+ }
+}
+
+void GraphicsButtonObject::setPressedPixmap(const QPixmap &pixmap)
+{
+ m_pressedGfx = pixmap;
+}
+
+void GraphicsButtonObject::setReleasedPixmap(const QPixmap &pixmap)
+{
+ m_releasedGfx = pixmap;
+}
+
+void GraphicsButtonObject::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ setPixmap(m_releasedGfx);
+ emit clicked();
+}
+
+void GraphicsButtonObject::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ setPixmap(m_pressedGfx);
+}
+
diff --git a/src/GraphicsButtonObject.h b/src/GraphicsButtonObject.h
new file mode 100644
index 0000000..dbbcaa3
--- /dev/null
+++ b/src/GraphicsButtonObject.h
@@ -0,0 +1,59 @@
+#ifndef GraphicsButtonObject_h
+#define GraphicsButtonObject_h
+
+#include <QObject>
+#include <QGraphicsPixmapItem>
+#include <QGraphicsLayoutItem>
+#include <QPixmap>
+
+/**
+ * Used for creating nice buttons to menus.
+ */
+class GraphicsButtonObject :
+ public QObject,
+ public QGraphicsPixmapItem
+{
+ Q_OBJECT
+
+public:
+ explicit GraphicsButtonObject(const QPixmap &releasedPixmap,
+ QGraphicsPixmapItem *parent = 0,
+ QGraphicsScene *scene = 0);
+
+ explicit GraphicsButtonObject(QGraphicsPixmapItem *parent = 0,
+ QGraphicsScene *scene = 0);
+
+ GraphicsButtonObject(const QString &str,
+ QGraphicsPixmapItem *parent = 0,
+ QGraphicsScene *scene = 0);
+
+ ~GraphicsButtonObject();
+
+ /**
+ * Sets gfx to indicate pressed-state on button.
+ * @param &pixmap The pixmap used as gfx
+ */
+ void setPressedPixmap(const QPixmap &pixmap);
+
+ /**
+ * Sets gfx to indicate released/normal-state on button.
+ * @param &pixmap The pixmap used as gfx
+ */
+ void setReleasedPixmap(const QPixmap &pixmap);
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+private:
+ QPixmap m_pressedGfx;
+ QPixmap m_releasedGfx;
+
+ static QPixmap *s_tmpGfx;
+ static int s_ref;
+
+signals:
+ void clicked();
+};
+
+#endif // GraphicsButtonObject_h
diff --git a/src/GraphicsPixmapObject.cpp b/src/GraphicsPixmapObject.cpp
new file mode 100644
index 0000000..b916bfc
--- /dev/null
+++ b/src/GraphicsPixmapObject.cpp
@@ -0,0 +1,7 @@
+#include "GraphicsPixmapObject.h"
+
+GraphicsPixmapObject::GraphicsPixmapObject(const QPixmap &pixmap,
+ QGraphicsItem *parent) :
+ QGraphicsPixmapItem(pixmap, parent)
+{
+}
diff --git a/src/GraphicsPixmapObject.h b/src/GraphicsPixmapObject.h
new file mode 100644
index 0000000..4ca8005
--- /dev/null
+++ b/src/GraphicsPixmapObject.h
@@ -0,0 +1,30 @@
+#ifndef GraphicsPixmapObject_h
+#define GraphicsPixmapObject_h
+
+#include <QObject>
+#include <QGraphicsPixmapItem>
+
+/**
+ * Used for the animation in SceneChanger. As QPropertyAnimation uses
+ * Qt's property system, we have to derive from QObject to use properties.
+ * So GraphicsPixmapObject derives from QObject and QGraphicsPixmapItem
+ * and publishes the opacity as a property.
+ */
+class GraphicsPixmapObject : public QObject, public QGraphicsPixmapItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity);
+ Q_PROPERTY(QPointF pos READ pos WRITE setPos);
+
+public:
+ explicit GraphicsPixmapObject(const QPixmap &pixmap,
+ QGraphicsItem *parent = 0);
+
+signals:
+
+public slots:
+
+};
+
+#endif // GraphicsPixmapObject_h
diff --git a/src/Hero.cpp b/src/Hero.cpp
new file mode 100644
index 0000000..5af9b6a
--- /dev/null
+++ b/src/Hero.cpp
@@ -0,0 +1,41 @@
+#include <QApplication>
+#include <QGraphicsScene>
+#include <QGraphicsPixmapItem>
+#include <QSettings>
+#include <QDebug>
+
+#include "Hero.h"
+#include "GameScene.h"
+
+Hero::Hero(QGraphicsScene* scene, QPointF pos, QGraphicsItem* parent)
+ : Character(parent, scene)
+{
+ m_state = STATE_IDLE;
+
+ // something small for testing purposes
+ setHealthPoints(15);
+
+ setPos(pos);
+ setZValue(2);
+
+ setShapeMode(QGraphicsPixmapItem::MaskShape);
+}
+
+Hero::~Hero()
+{
+}
+
+void Hero::advance(int phase)
+{
+ Character::advance(phase);
+
+ if (phase == 0)
+ return;
+
+ // err, no good.
+ if(m_state == STATE_DEAD)
+ {
+ gameOver();
+ //removeMe();
+ }
+}
diff --git a/src/Hero.h b/src/Hero.h
new file mode 100644
index 0000000..ec25944
--- /dev/null
+++ b/src/Hero.h
@@ -0,0 +1,25 @@
+#ifndef Hero_h
+#define Hero_h
+
+#include "Character.h"
+
+class Hero: public Character
+{
+ Q_OBJECT
+
+public:
+ Hero(QGraphicsScene* scene, QPointF pos, QGraphicsItem* parent = 0);
+ virtual ~Hero();
+
+ void advance(int phase);
+
+signals:
+ void gameOver();
+ void levelComplete();
+ void updateUI();
+
+private:
+
+};
+
+#endif // Hero_h
diff --git a/src/LevelSelectionScene.cpp b/src/LevelSelectionScene.cpp
new file mode 100644
index 0000000..02516b1
--- /dev/null
+++ b/src/LevelSelectionScene.cpp
@@ -0,0 +1,98 @@
+#include <QApplication>
+#include <QDir>
+#include <QSettings>
+#include <QDebug>
+
+#include "ParallaxScrollerStatic.h"
+#include "GraphicsButtonObject.h"
+#include "GameView.h"
+#include "ActionScene.h"
+
+#include "LevelSelectionScene.h"
+
+LevelSelectionScene::LevelSelectionScene(const QString &name, const QRectF &rect, GameView *parent)
+ : GameScene(name, parent)
+{
+ setSceneRect(rect);
+
+ QString appDir = qApp->applicationDirPath();
+
+ m_background = new ParallaxScrollerStatic(this);
+ m_background->setLayerWidth(rect.width());
+ m_background->addParallaxScrollItem(QString(appDir + "/gfx/bg/layer1.png"), QPointF(0,0), -2, 6);
+ m_background->addParallaxScrollItem(QString(appDir + "/gfx/bg/layer2.png"), QPointF(0,0), -1, 4);
+
+ initializeScene();
+}
+
+LevelSelectionScene::~LevelSelectionScene()
+{
+ delete m_background;
+}
+
+void LevelSelectionScene::initializeScene()
+{
+ addTitle("Level Selection");
+
+ QSettings settings;
+
+ QDir levelDirectory(settings.value("path/levels").toString());
+
+ /* TODO: check levels directory for levels (should be 6) and create corresponding buttons
+ that react when pressed and lauch the level
+ */
+ int yoff = 200;
+ int xoff = 50;
+ int count = 1;
+
+ Q_FOREACH(QString f, levelDirectory.entryList(QDir::Files, QDir::Name))
+ {
+ QString lvlNum;
+ lvlNum.setNum(count);
+ GraphicsButtonObject *btn = new GraphicsButtonObject(lvlNum, 0, this);
+ btn->setPos(210 + xoff, yoff);
+ btn->setProperty("level_path", levelDirectory.filePath(f));
+
+ qDebug() << levelDirectory.filePath(f);
+
+ connect(btn, SIGNAL(clicked()), this, SLOT(levelSelection()));
+
+// if(count % 4 == 0)
+// {
+// yoff += btn->boundingRect().bottom() + 20;
+// xoff = 50;
+// }
+
+ count++;
+ //xoff += btn->boundingRect().bottom() + 20;
+ yoff += btn->boundingRect().bottom() + 10;
+ }
+
+ GraphicsButtonObject *btn;
+ btn = new GraphicsButtonObject(QPixmap(QApplication::applicationDirPath() + "/gfx/buttons/back-arrow1.png"), 0, this);
+ btn->setPressedPixmap(QPixmap(QApplication::applicationDirPath() + "/gfx/buttons/back-arrow2.png"));
+ btn->setPos(720, 400);
+ btn->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
+ btn->setZValue(2);
+
+ connect(btn, SIGNAL(clicked()), gameView(), SLOT(showMenuScene()));
+}
+
+void LevelSelectionScene::levelSelection()
+{
+ QVariant level_path = sender()->property("level_path");
+
+ Q_ASSERT(level_path.isValid());
+
+ QString levelPath = level_path.toString();
+
+ gameView()->getActionScene()->loadMap(levelPath);
+ gameView()->showActionScene();
+}
+
+void LevelSelectionScene::updateLogic()
+{
+ advance();
+ update();
+}
+
diff --git a/src/LevelSelectionScene.h b/src/LevelSelectionScene.h
new file mode 100644
index 0000000..61eb70a
--- /dev/null
+++ b/src/LevelSelectionScene.h
@@ -0,0 +1,36 @@
+#ifndef LevelSelectionScene_h
+#define LevelSelectionScene_h
+
+#include "GameScene.h"
+
+#include "ParallaxScrollerStatic.h"
+
+class LevelSelectionScene : public GameScene
+{
+ Q_OBJECT
+public:
+ LevelSelectionScene(const QString &name, const QRectF &rect, GameView *parent = 0);
+ virtual ~LevelSelectionScene();
+
+ /**
+ * Updates graphics on scene. Mainly background but levelselectionbuttons too.
+ */
+ void updateLogic();
+
+ /**
+ * Loads level data and creates selection grid
+ */
+ void initializeScene();
+
+private slots:
+ /**
+ * This function calls ActionScene with information about what level to load.
+ */
+ void levelSelection();
+
+private:
+ ParallaxScrollerStatic* m_background;
+
+};
+
+#endif // LevelSelectionScene_h
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
new file mode 100644
index 0000000..cac85c1
--- /dev/null
+++ b/src/MainWindow.cpp
@@ -0,0 +1,17 @@
+#include "GameView.h"
+
+#include "MainWindow.h"
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent)
+{
+ resize(800, 480);
+ setWindowTitle("Generic platformer base, version 0.0.1 alpha");
+
+ setCentralWidget(m_gameView->instance());
+}
+
+MainWindow::~MainWindow()
+{
+
+}
diff --git a/src/MainWindow.h b/src/MainWindow.h
new file mode 100644
index 0000000..d6246f8
--- /dev/null
+++ b/src/MainWindow.h
@@ -0,0 +1,23 @@
+#ifndef MainWindow_h
+#define MainWindow_h
+
+#include <QMainWindow>
+
+class GameView;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ explicit MainWindow(QWidget *parent = 0);
+ virtual ~MainWindow();
+
+signals:
+
+public slots:
+
+private:
+ GameView* m_gameView;
+};
+
+#endif // MainWindow_h
diff --git a/src/MenuScene.cpp b/src/MenuScene.cpp
new file mode 100644
index 0000000..1deaa66
--- /dev/null
+++ b/src/MenuScene.cpp
@@ -0,0 +1,53 @@
+#include <QApplication>
+
+#include "ParallaxScrollerStatic.h"
+#include "GraphicsButtonObject.h"
+#include "GameView.h"
+
+#include "MenuScene.h"
+
+MenuScene::MenuScene(const QString &name, const QRectF &rect, GameView *parent)
+ : GameScene(name, parent)
+{
+ setSceneRect(rect);
+
+ QString appDir = qApp->applicationDirPath();
+
+ m_background = new ParallaxScrollerStatic(this);
+ m_background->setLayerWidth(rect.width());
+ m_background->addParallaxScrollItem(QString(appDir + "/gfx/bg/layer1.png"), QPointF(0,0), -2, 6);
+ m_background->addParallaxScrollItem(QString(appDir + "/gfx/bg/layer2.png"), QPointF(0,0), -1, 4);
+
+ initializeScene();
+}
+
+MenuScene::~MenuScene()
+{
+ delete m_background;
+}
+
+void MenuScene::updateLogic()
+{
+ advance();
+ update();
+}
+
+void MenuScene::initializeScene()
+{
+ int yoff = 200;
+
+ GraphicsButtonObject *btn1 = new GraphicsButtonObject("Play", 0, this);
+ btn1->setPos(260, yoff);
+
+ GraphicsButtonObject *btn2 = new GraphicsButtonObject("Credits", 0, this);
+ btn2->setPos(260, btn1->pos().y() + btn1->boundingRect().bottom() + 20);
+
+ GraphicsButtonObject *btn3 = new GraphicsButtonObject("Quit", 0, this);
+ btn3->setPos(260, btn2->pos().y() + btn2->boundingRect().bottom() + 20);
+
+ connect(btn1, SIGNAL(clicked()), gameView(), SLOT(showLevelSelectionScene()));
+ connect(btn2, SIGNAL(clicked()), gameView(), SLOT(showCreditsScene()));
+ connect(btn3, SIGNAL(clicked()), qApp, SLOT(quit()));
+
+ addTitle("Platformer");
+}
diff --git a/src/MenuScene.h b/src/MenuScene.h
new file mode 100644
index 0000000..501550b
--- /dev/null
+++ b/src/MenuScene.h
@@ -0,0 +1,32 @@
+#ifndef MenuScene_h
+#define MenuScene_h
+
+#include "GameScene.h"
+
+#include "ParallaxScrollerStatic.h"
+
+class GameView;
+
+/**
+ * Scene for first view displayed when application launches.
+ */
+class MenuScene : public GameScene
+{
+ Q_OBJECT
+public:
+ MenuScene(const QString &name, const QRectF &rect, GameView *parent = 0);
+ virtual ~MenuScene();
+
+ void initializeScene();
+
+ void updateLogic();
+
+signals:
+
+public slots:
+
+private:
+ ParallaxScrollerStatic* m_background;
+};
+
+#endif // MenuScene_h
diff --git a/src/ParallaxScrollerItem.cpp b/src/ParallaxScrollerItem.cpp
new file mode 100644
index 0000000..0480b29
--- /dev/null
+++ b/src/ParallaxScrollerItem.cpp
@@ -0,0 +1,47 @@
+#include "ParallaxScrollerItem.h"
+
+#include <QGraphicsView>
+#include <QGraphicsScene>
+#include <QScrollBar>
+
+#include <QPainter>
+#include <QDebug>
+
+ParallaxScrollerItem::ParallaxScrollerItem(QString layer, QPointF pos,
+ qreal depthFactor, qreal speed,
+ qreal factor, QGraphicsScene *scene,
+ QGraphicsItem *parent)
+ : QGraphicsPixmapItem(parent, scene), m_scrollSpeed(speed), m_factor(factor)
+{
+ m_scrollingSpeedSlowingFactor = 0;
+ m_layer.load(layer);
+ setPixmap(m_layer);
+ setPos(pos);
+ setZValue(depthFactor);
+}
+
+ParallaxScrollerItem::~ParallaxScrollerItem()
+{
+
+}
+
+void ParallaxScrollerItem::advance(int phase)
+{
+ if(phase == 1)
+ {
+ m_scrollingSpeedSlowingFactor++;
+ if(m_scrollingSpeedSlowingFactor % m_factor == 0)
+ {
+ m_scrollingSpeedSlowingFactor = 0;
+ setPos(x()-m_scrollSpeed, y());
+
+ QGraphicsView* v = scene()->views().first();
+ QPointF p = v->mapToScene(v->viewport()->x(), 0);
+
+ if(x() <= p.x()-pixmap().width())
+ {
+ setPos(p.x()+pixmap().width()-m_scrollSpeed, y());
+ }
+ }
+ }
+}
diff --git a/src/ParallaxScrollerItem.h b/src/ParallaxScrollerItem.h
new file mode 100644
index 0000000..13269c8
--- /dev/null
+++ b/src/ParallaxScrollerItem.h
@@ -0,0 +1,24 @@
+#ifndef ParallaxScrollerItem_h
+#define ParallaxScrollerItem_h
+
+#include <QGraphicsPixmapItem>
+
+class ParallaxScrollerItem : public QGraphicsPixmapItem
+{
+public:
+ ParallaxScrollerItem(QString layer, QPointF pos,
+ qreal depthFactor, qreal speed,
+ qreal factor, QGraphicsScene* scene,
+ QGraphicsItem* parent = 0);
+ virtual ~ParallaxScrollerItem();
+
+ void advance(int phase);
+
+private:
+ int m_scrollingSpeedSlowingFactor;
+ int m_factor;
+ qreal m_scrollSpeed;
+ QPixmap m_layer;
+};
+
+#endif // ParallaxScrollerItem_h
diff --git a/src/ParallaxScrollerStatic.cpp b/src/ParallaxScrollerStatic.cpp
new file mode 100644
index 0000000..c2642e9
--- /dev/null
+++ b/src/ParallaxScrollerStatic.cpp
@@ -0,0 +1,29 @@
+#include "ParallaxScrollerItem.h"
+
+#include "ParallaxScrollerStatic.h"
+
+ParallaxScrollerStatic::ParallaxScrollerStatic(QGraphicsScene *scene)
+{
+ m_parent = scene;
+}
+
+ParallaxScrollerStatic::~ParallaxScrollerStatic()
+{
+
+}
+
+void ParallaxScrollerStatic::setLayerWidth(int width)
+{
+ m_layerWidth = width;
+}
+
+void ParallaxScrollerStatic::addParallaxScrollItem(const QString &layer, QPointF pos, qreal depth, qreal slowingFactor)
+{
+ ParallaxScrollerItem* firstPartOfLayer = new ParallaxScrollerItem(layer, QPointF(pos.x(), pos.y()),
+ depth, 1, slowingFactor, m_parent);
+ ParallaxScrollerItem* secondPartOfLayer = new ParallaxScrollerItem(layer, QPointF(pos.x()+m_layerWidth, 0),
+ depth, 1, slowingFactor, m_parent);
+
+ m_layersFirstWave.append(firstPartOfLayer);
+ m_layerSecondWave.append(secondPartOfLayer);
+}
diff --git a/src/ParallaxScrollerStatic.h b/src/ParallaxScrollerStatic.h
new file mode 100644
index 0000000..04e9547
--- /dev/null
+++ b/src/ParallaxScrollerStatic.h
@@ -0,0 +1,26 @@
+#ifndef ParallaxScrollerStatic_h
+#define ParallaxScrollerStatic_h
+
+#include <QStringList>
+#include <QPointF>
+#include <QGraphicsScene>
+
+class ParallaxScrollerItem;
+
+class ParallaxScrollerStatic
+{
+public:
+ ParallaxScrollerStatic(QGraphicsScene* scene);
+ virtual ~ParallaxScrollerStatic();
+
+ void setLayerWidth(int width);
+ void addParallaxScrollItem(const QString& layer, QPointF pos, qreal depth, qreal slowingFactor);
+
+private:
+ QGraphicsScene* m_parent;
+ QVector<ParallaxScrollerItem*> m_layersFirstWave;
+ QVector<ParallaxScrollerItem*> m_layerSecondWave;
+ int m_layerWidth;
+};
+
+#endif // ParallaxScrollerStatic_h
diff --git a/src/SceneChanger.cpp b/src/SceneChanger.cpp
new file mode 100644
index 0000000..2aa8b86
--- /dev/null
+++ b/src/SceneChanger.cpp
@@ -0,0 +1,107 @@
+#include "SceneChanger.h"
+#include "GameScene.h"
+#include "GameView.h"
+#include "GraphicsPixmapObject.h"
+
+#include <QTimer>
+#include <QParallelAnimationGroup>
+#include <QPropertyAnimation>
+
+SceneChanger::SceneChanger(QString name, const QRectF &rect, GameView *parent) :
+ GameScene(name, parent)
+{
+ setSceneRect(rect);
+
+ m_anim = new QParallelAnimationGroup(this);
+ connect(m_anim, SIGNAL(finished()), this, SLOT(animationFinished()));
+ setDuration(500);
+
+ m_updateTimer = new QTimer(this);
+ connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(update()));
+}
+
+void SceneChanger::updateLogic()
+{
+ advance();
+ update();
+}
+
+void SceneChanger::setDuration(int msecs)
+{
+ m_duration = msecs;
+}
+
+void SceneChanger::changeScene(GameScene *from, GameScene *to, bool rightToLeft)
+{
+ m_fromScene = from;
+ m_toScene = to;
+
+ int width = from->sceneRect().width();
+ int height = from->sceneRect().height();
+
+ clear();
+ m_anim->clear();
+
+ QPixmap from_pixmap(width, height);
+ QPixmap to_pixmap(width, height);
+
+ QPainter from_painter(&from_pixmap);
+ QPainter to_painter(&to_pixmap);
+
+ from->render(&from_painter);
+ to->render(&to_painter);
+
+ GraphicsPixmapObject *from_obj = new GraphicsPixmapObject(from_pixmap);
+ from_obj->setPos(0, 0);
+
+ GraphicsPixmapObject *to_obj = new GraphicsPixmapObject(to_pixmap);
+ to_obj->setPos(0, 0);
+
+ addItem(from_obj);
+ addItem(to_obj);
+
+ QPropertyAnimation *from_anim = new QPropertyAnimation(from_obj, "pos",
+ this);
+
+ QPropertyAnimation *to_anim = new QPropertyAnimation(to_obj, "pos",
+ this);
+
+ if( rightToLeft )
+ {
+ from_anim->setDuration(m_duration);
+ from_anim->setStartValue(QPointF(0.0, 0.0));
+ from_anim->setEndValue(QPointF(-(float)width, 0.0));
+ from_anim->setEasingCurve(QEasingCurve::OutCubic); //or OutBounce, OutQuint...
+
+ to_anim->setDuration(m_duration);
+ to_anim->setStartValue(QPointF((float)width, 0.0));
+ to_anim->setEndValue(QPointF(0.0, 0.0));
+ to_anim->setEasingCurve(QEasingCurve::OutCubic); //or OutBounce, OutQuint...
+ }
+ else
+ {
+ from_anim->setDuration(m_duration);
+ from_anim->setStartValue(QPointF(0.0, 0.0));
+ from_anim->setEndValue(QPointF((float)width, 0.0));
+ from_anim->setEasingCurve(QEasingCurve::OutCubic); //or OutBounce, OutQuint...
+
+ to_anim->setDuration(m_duration);
+ to_anim->setStartValue(QPointF(-(float)width, 0.0));
+ to_anim->setEndValue(QPointF(0.0, 0.0));
+ to_anim->setEasingCurve(QEasingCurve::OutCubic); //or OutBounce, OutQuint...
+
+ }
+ m_anim->addAnimation(from_anim);
+ m_anim->addAnimation(to_anim);
+
+ // Use a little more frequent update than normally
+ m_updateTimer->start(1000 / 100);
+ m_anim->start();
+}
+
+void SceneChanger::animationFinished()
+{
+ m_updateTimer->stop();
+
+ gameView()->showScene(m_toScene);
+}
diff --git a/src/SceneChanger.h b/src/SceneChanger.h
new file mode 100644
index 0000000..fee3b48
--- /dev/null
+++ b/src/SceneChanger.h
@@ -0,0 +1,74 @@
+#ifndef SceneChanger_h
+#define SceneChanger_h
+
+#include "GameScene.h"
+
+class QParallelAnimationGroup;
+class QTimer;
+class GameView;
+
+/**
+ * Animates the change from a scene to another. Start the change
+ * with SceneChanger::changeScene(). After the animation is done,
+ * SceneChanger calls MainView::showScene for the scene that is
+ * to be shown.
+ *
+ * Basically changeScene() just takes a "screenshot" of both the
+ * scenes, adds the shots to itself and uses QPropertyAnimation
+ * to do the animation.
+ */
+class SceneChanger : public GameScene
+{
+ Q_OBJECT
+public:
+ explicit SceneChanger(QString name, const QRectF &rect, GameView *parent = 0);
+
+ /**
+ * Start the scene change animation.
+ *
+ * @param from The scene we are changing from
+ * @param to The scene we are changing to
+ */
+ void changeScene(GameScene *from, GameScene *to, bool rightToLeft);
+
+ /**
+ * Sets the duration of the animation in milliseconds. Default
+ * duration is 250 milliseconds.
+ */
+ void setDuration(int msecs);
+
+ void updateLogic();
+
+private:
+
+ /**
+ * Center of all the animation.
+ */
+ QParallelAnimationGroup *m_anim;
+
+ GameScene *m_fromScene;
+ GameScene *m_toScene;
+
+ /**
+ * Time in ms how long it takes to animate from view to an other.
+ */
+ int m_duration;
+
+ /**
+ * Used for faster update on animating transition
+ * than normal rendering needs.
+ */
+ QTimer *m_updateTimer;
+
+signals:
+
+private slots:
+ /**
+ * Called after m_anim has finished the animation. Calls
+ * MainView::showScene() to show the new scene.
+ */
+ void animationFinished();
+
+};
+
+#endif // SceneChanger_h
diff --git a/src/Sprite.cpp b/src/Sprite.cpp
new file mode 100644
index 0000000..b921394
--- /dev/null
+++ b/src/Sprite.cpp
@@ -0,0 +1,108 @@
+#include "Sprite.h"
+
+Sprite::Sprite(QGraphicsItem *parent, QGraphicsScene *scene)
+ : QObject(0),
+ QGraphicsPixmapItem(parent, scene),
+ m_currentFrame(0),
+ m_interval(1000/20)
+{
+ addAnimation("default", FrameList());
+ setAnimation("default");
+
+ m_timer.invalidate();
+}
+
+void Sprite::addFrame(const QString &anim, QPixmap frame)
+{
+ if (!m_animations.contains(anim))
+ {
+ FrameList l;
+ m_animations[anim] = l;
+ }
+
+ m_animations[anim].append(frame);
+}
+
+void Sprite::addAnimation(const QString &anim, const FrameList &frames)
+{
+ if (!m_animations.contains(anim))
+ {
+ m_animations[anim] = frames;
+ }
+ else
+ {
+ m_animations[anim].append(frames);
+ }
+}
+
+void Sprite::setFrame(int frame)
+{
+ if (frame < 0 || frame >= getCurrentAnimation().size())
+ {
+ qWarning("invalid frame number %d", frame);
+ return;
+ }
+
+ m_currentFrame = frame;
+ setPixmap(getFramePixmap());
+}
+
+int Sprite::getFrame() const
+{
+ return m_currentFrame;
+}
+
+QPixmap Sprite::getFramePixmap() const
+{
+ return getCurrentAnimation()[m_currentFrame];
+}
+
+int Sprite::getFrameCount() const
+{
+ return getCurrentAnimation().size();
+}
+
+Sprite::FrameList Sprite::getCurrentAnimation() const
+{
+ return m_animations[m_currentAnimation];
+}
+
+void Sprite::nextFrame()
+{
+ m_currentFrame++;
+
+ if (m_currentFrame >= getCurrentAnimation().size())
+ m_currentFrame = 0;
+
+ setFrame(m_currentFrame);
+}
+
+void Sprite::setAnimation(const QString &anim)
+{
+ if (!m_animations.contains(anim))
+ {
+ qWarning("animation '%s' doesn't exist", anim.toUtf8().data());
+ return;
+ }
+
+ if (m_currentAnimation != anim)
+ m_currentAnimation = anim;
+}
+
+void Sprite::advance(int phase)
+{
+ if (phase == 1)
+ return;
+
+ if (m_timer.isValid() && m_timer.elapsed() >= m_interval)
+ {
+ nextFrame();
+ m_timer.start();
+ }
+
+ // this should be run the first time advance() is called
+ if (!m_timer.isValid())
+ {
+ m_timer.start();
+ }
+}
diff --git a/src/Sprite.h b/src/Sprite.h
new file mode 100644
index 0000000..88679b3
--- /dev/null
+++ b/src/Sprite.h
@@ -0,0 +1,70 @@
+#ifndef SPRITE_H
+#define SPRITE_H
+
+#include <QList>
+#include <QMap>
+#include <QString>
+#include <QPixmap>
+#include <QGraphicsPixmapItem>
+#include <QElapsedTimer>
+#include <QObject>
+
+class Sprite: public QObject, public QGraphicsPixmapItem
+{
+ Q_OBJECT
+
+public:
+ typedef QList<QPixmap> FrameList;
+
+ explicit Sprite(QGraphicsItem *parent = 0, QGraphicsScene *scene = 0);
+
+ //! Adds a frame to an animation
+ void addFrame(const QString &anim, QPixmap frame);
+
+ //! Adds a list of frames to an animation
+ void addAnimation(const QString &anim, const FrameList &frames);
+
+ //! Set current frame in the current animation
+ void setFrame(int frame);
+
+ //! Get current frame
+ int getFrame() const;
+
+ //! Change to next frame
+ void nextFrame();
+
+ QPixmap getFramePixmap() const;
+
+ //! Get frame count in current animation
+ int getFrameCount() const;
+
+ FrameList getCurrentAnimation() const;
+
+ void setAnimation(const QString &anim);
+
+ void setFrameInterval(int msecs) { m_interval = msecs; }
+ int frameInterval() const { return m_interval; }
+
+ virtual void advance(int phase);
+
+signals:
+ //! Marks this sprite for removal
+ void removeMe();
+
+protected:
+
+ //! Map of animations (i.e. running, idle, jumping, ...)
+ QMap<QString, FrameList> m_animations;
+
+ QString m_currentAnimation;
+
+ //! Current frame
+ int m_currentFrame;
+
+ //! How often frames should be changed
+ int m_interval;
+
+ QElapsedTimer m_timer;
+};
+
+#endif // SPRITE_H
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..5691abc
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,33 @@
+#include <QtGui/QApplication>
+#include <QSettings>
+
+#include "MainWindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+
+ QApplication::setApplicationName("prism");
+ QApplication::setOrganizationName("aarg");
+ QApplication::setOrganizationDomain("aarg.eu");
+
+ QSettings::setDefaultFormat(QSettings::IniFormat);
+
+ // set some default settings
+
+ QSettings s;
+
+ if (!s.contains("path/data"))
+ {
+ const QString &app_path = QApplication::applicationDirPath();
+
+ s.setValue("path/data", app_path);
+ s.setValue("path/gfx", app_path + "/gfx");
+ s.setValue("path/levels", app_path + "/levels");
+ }
+
+ MainWindow mw;
+ mw.show();
+
+ return a.exec();
+}
diff --git a/src/src.pro b/src/src.pro
new file mode 100644
index 0000000..ff63d79
--- /dev/null
+++ b/src/src.pro
@@ -0,0 +1,55 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Thu Mar 24 21:28:35 2011
+######################################################################
+
+include(../platformer.pri)
+
+QT += core gui opengl
+TEMPLATE = app
+TARGET = platformer
+DEPENDPATH += .
+INCLUDEPATH += . ../libtiled
+INSTALLS += target
+target.path = $${BINDIR}
+unix:DESTDIR = ../bin
+unix:LIBS += -L../lib -L/usr/local/lib -L/usr/lib -ltiled
+win32:LIBS += G:/Projects/Qt/platformer/platformer-build-desktop/lib/tiled.dll
+
+OBJECTS_DIR = .obj
+
+HEADERS += MainWindow.h \
+ GameScene.h \
+ CreditsScene.h \
+ MenuScene.h \
+ LevelSelectionScene.h \
+ GraphicsPixmapObject.h \
+ GraphicsButtonObject.h \
+ ActionScene.h \
+ ParallaxScrollerStatic.h \
+ ParallaxScrollerItem.h \
+ SceneChanger.h \
+ GameView.h \
+ Character.h \
+ Sprite.h \
+ Collectible.h \
+ Hero.h \
+ BasicEnemy.h
+
+SOURCES += main.cpp \
+ MainWindow.cpp \
+ GameScene.cpp \
+ CreditsScene.cpp \
+ MenuScene.cpp \
+ LevelSelectionScene.cpp \
+ GraphicsPixmapObject.cpp \
+ GraphicsButtonObject.cpp \
+ ActionScene.cpp \
+ ParallaxScrollerStatic.cpp \
+ ParallaxScrollerItem.cpp \
+ SceneChanger.cpp \
+ GameView.cpp \
+ Character.cpp \
+ Sprite.cpp \
+ Collectible.cpp \
+ Hero.cpp \
+ BasicEnemy.cpp