diff options
Diffstat (limited to 'src')
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 |
