Today, I created my first Qt Quick (QML) game named Chopper, game is simple and was created just for learning process.
UI Is implemented using QML and logic part is done using JavaScript and tested on Nokia Qt SDK emulator.
If you want to look at code then here is link to my gitorious repository.
Following is snap from game,
And below is video from game.
Sharing information related to Qt, Maemo development and some other information
Thursday, October 28, 2010
Saturday, October 23, 2010
Creating Qt game for mobile device with differnt screen size
Till now I have created few Qt games for Maemo 5 (N900) device, and now I wanted to run same games on Symbian device which support Qt.
First problem I encounter doing so is different screen size from N900, in my current game implementation I have hard coded screen size and coordination of game object.
After playing with graphics framework from some time, I created a small prototype application that shows two rectangle one on top left other on bottom right corner and can run on different Symbian device and N900 as well. So first thing I did is to remove all hard coded coordinate and implemented resize event, then scaled all graphics item which are added to graphics scene.
Following is my prototype code.
In below code, I have added QGraphicsView as QMainWindow's central widget and also reimplemented resizeEvent of QMainWindow.
And then in MyScene class, derived from QGraphicsScene, on sceneRectChanged signal i am scaling all item to scale factor according to my reference screen size, which is of n900 device's screen size.
First problem I encounter doing so is different screen size from N900, in my current game implementation I have hard coded screen size and coordination of game object.
After playing with graphics framework from some time, I created a small prototype application that shows two rectangle one on top left other on bottom right corner and can run on different Symbian device and N900 as well. So first thing I did is to remove all hard coded coordinate and implemented resize event, then scaled all graphics item which are added to graphics scene.
Following is my prototype code.
In below code, I have added QGraphicsView as QMainWindow's central widget and also reimplemented resizeEvent of QMainWindow.
GraphicsWidget::GraphicsWidget(QWidget *parent) : QMainWindow(parent) { _scene = new MyScene(); _scene->setItemIndexMethod(QGraphicsScene::NoIndex); _view = new QGraphicsView(_scene,this); _view->setDragMode(QGraphicsView::NoDrag); _view->setCacheMode(QGraphicsView::CacheBackground); _view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); setCentralWidget(_view); // Disable scrollbars _view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); _view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } void GraphicsWidget::resizeEvent(QResizeEvent* event) { _scene->setSceneRect(_view->rect()); QWidget::resizeEvent(event); }
And then in MyScene class, derived from QGraphicsScene, on sceneRectChanged signal i am scaling all item to scale factor according to my reference screen size, which is of n900 device's screen size.
MyScene::MyScene() :QGraphicsScene() { item1 = new MyGraphicsItem(); addItem( item1 ); item2 = new MyGraphicsItem(); addItem( item2 ); QObject::connect(this,SIGNAL(sceneRectChanged(QRectF)), this,SLOT(resize(QRectF))); } void MyScene::resize(const QRectF& newRect) { qreal w = (qreal)newRect.width()/800 ; qreal h = (qreal)newRect.height()/480; item1->resetMatrix(); item1->scale(w,h); item1->setPos(newRect.topLeft()); item2->resetMatrix(); item2->scale(w,h); item2->setPos(newRect.width()-(item2->boundingRect().width()*w), newRect.height() - (item2->boundingRect().height()*h)); }Finally in main function, I am showing QMainWindow in full screen mode.
int main(int argc, char* argv[] ) { QApplication app(argc,argv); GraphicsWidget widget; widget.showFullScreen(); return app.exec(); }Following are snaps from prototype running on emulator for different device.
Labels:
c++,
Code,
game,
games,
Graphics view,
n8,
N900,
n97,
qt,
resize event
Thursday, October 21, 2010
Using QStateMachine with sprite animation
In 4.6 Qt introduced new State machine framework. Framework looks quite easy to use and extensible for complex use-case.
To explore Qt's State machine framework I thought to use it with sprite animation, as a complex sprite also holds many state and maintaining sprite state and transition from one state to another can become pain if not done properly.
So following is my sample code for prince sprite which use QStateMachine to maintain sprite's state and transition from one state to another. From somewhere in Internet I found sprite sheet for Prince of Persia, to make it easy for sample code I created another simple version of original sprite sheet.
In above code I have create different state object for different sprite state, like for StandingState or Attack state.
This state classes are derived from QState class and listen to QTimer's timeout signal to change frame according to animation.
For example following code for Attack state.
So finally, I am not sure if this is correct approach to implement sprite or not, but using Qt's State machine framework is helping a lot to make it simpler.
Follwing is demo of my implementation.
To explore Qt's State machine framework I thought to use it with sprite animation, as a complex sprite also holds many state and maintaining sprite state and transition from one state to another can become pain if not done properly.
So following is my sample code for prince sprite which use QStateMachine to maintain sprite's state and transition from one state to another. From somewhere in Internet I found sprite sheet for Prince of Persia, to make it easy for sample code I created another simple version of original sprite sheet.
PrinceSprite::PrinceSprite(QGraphicsItem * parent) :QGraphicsObject(parent) { mSpriteImage = new QPixmap(":/prince.png"); changeDir(this); //creating different state object , //which are derived from QState and l //istening to timer's timeout signal //and also modify frame according to animation StandingState* standing = new StandingState(this); RunningState* running = new RunningState(this); PrepareForAttack* prepareForAttack = new PrepareForAttack(this); Attack* attack = new Attack(this); InAttackMode* inAttackMode = new InAttackMode(this); //adding transition to state //goto running state from stating state at left click standing->addTransition(this,SIGNAL(leftClick()),running); running->addTransition(this,SIGNAL(leftClick()),standing); standing->addTransition(this,SIGNAL(rightClick()) ,prepareForAttack); prepareForAttack->addTransition(prepareForAttack, SIGNAL(exited()),inAttackMode); inAttackMode->addTransition(this,SIGNAL(leftClick()),attack); attack->addTransition(attack,SIGNAL(exited()),inAttackMode); inAttackMode->addTransition(this, SIGNAL(rightClick()),standing); //adding all state to QStateMachine _stateMachine.addState(standing); _stateMachine.addState(running); _stateMachine.addState(prepareForAttack); _stateMachine.addState(attack); _stateMachine.addState(inAttackMode); //setting initial state and then starting state machine _stateMachine.setInitialState( standing); _stateMachine.start(); }
In above code I have create different state object for different sprite state, like for StandingState or Attack state.
This state classes are derived from QState class and listen to QTimer's timeout signal to change frame according to animation.
For example following code for Attack state.
#include <QState> class Attack : public QState { Q_OBJECT public: Attack(PrinceSprite* prince); void onEntry ( QEvent * event ); void onExit ( QEvent * event ); signals: void exited(); private slots: void nextFrame(); }; #include "attack.h" Attack::Attack(PrinceSprite* prince) :QState() {} void Attack::nextFrame() { _prince->_x += 1; _prince->setX(_prince->x() + 7); if (_prince->_x >= 4 ) { emit exited(); } } void Attack::onEntry ( QEvent * event ) { QObject::connect(_prince,SIGNAL(tick()), this,SLOT(nextFrame())); _prince->_x = 0; _prince->_y = 2; } void Attack::onExit ( QEvent * event ) { QObject::disconnect(_prince,SIGNAL(tick()), this,SLOT(nextFrame())); }
So finally, I am not sure if this is correct approach to implement sprite or not, but using Qt's State machine framework is helping a lot to make it simpler.
Follwing is demo of my implementation.
Saturday, October 9, 2010
Crazy chickens on Qt Ambassador Showcase
Finally yesterday my game Crazy Chickens successfully gone through Qt Ambassador Showcase process and now it is show cased in Qt Ambassador Showcase
Coincidently I received my Ambassador T-shirt also on same day. Following is snap of T shirt if you wonder how it looks.
Coincidently I received my Ambassador T-shirt also on same day. Following is snap of T shirt if you wonder how it looks.
Sunday, October 3, 2010
Detecting Swipe gesture in Qt
In continuation of my previous post of long press gesture in Qt, I created another simple gesture class to detect swipe gesture.
In my implementation, I am storing initial coordinate on mouse press event and comparing initial coordinate with coordinate on mouse release event.In this code I have not considered speed of swipe but we can easily measure speed of swipe by measuring time difference between two event.
myswipegesture.h file
In my implementation, I am storing initial coordinate on mouse press event and comparing initial coordinate with coordinate on mouse release event.In this code I have not considered speed of swipe but we can easily measure speed of swipe by measuring time difference between two event.
myswipegesture.h file
#ifndef MYSWIPEGESTURE_H #define MYSWIPEGESTURE_H #include <QObject> #include <QPoint> class MySwipeGesture : public QObject { Q_OBJECT public: explicit MySwipeGesture(QObject *parent = 0); void handleEvent( QEvent *event); public: enum SwipeDirection { Left = 0, Right, Up, Down }; signals: void handleSwipe( MySwipeGesture::SwipeDirection direction ); private: QPoint _startPoint; QPoint _endPoint; }; #endif // MYSWIPEGESTURE_Hmyswipegesture.cpp file
#include "myswipegesture.h" #include <QEvent> #include <QMouseEvent> MySwipeGesture::MySwipeGesture(QObject *parent) :QObject(parent),_startPoint(0,0),_endPoint(0,0) {} void MySwipeGesture::handleEvent( QEvent *event) { if( event->type() == QEvent::MouseButtonPress ) { QMouseEvent* mouseEvent = static_cast<QMouseEvent*> (event); _startPoint = mouseEvent->pos(); } else if( event->type() == QEvent::MouseButtonRelease ) { QMouseEvent* mouseEvent = static_cast<QMouseEvent*> (event); _endPoint = mouseEvent->pos(); //process distance and direction int xDiff = _startPoint.x() - _endPoint.x(); int yDiff = _startPoint.y() - _endPoint.y(); if( qAbs(xDiff) > qAbs(yDiff) ) { // horizontal swipe detected, now find direction if( _startPoint.x() > _endPoint.x() ) { emit handleSwipe( Left); } else { emit handleSwipe( Right); } } else { // vertical swipe detected, now find direction if( _startPoint.y() > _endPoint.y() ) { emit handleSwipe( Up); } else { emit handleSwipe( Down); } } } else if( event->type() == QEvent::MouseMove ) { //ignore event } }Some test code.
#include "myswipegesture.h" TestWidget::TestWidget(QWidget *parent) : QWidget(parent) { _swipeGesture = new MySwipeGesture(this); connect(_swipeGesture,SIGNAL(handleSwipe(MySwipeGesture::SwipeDirection)),this,SLOT(swipe(MySwipeGesture::SwipeDirection))); } bool TestWidget::event(QEvent *event) { _swipeGesture->handleEvent(event); return QWidget::event(event); } void TestWidget::swipe(MySwipeGesture::SwipeDirection direction) { qDebug() << "swipe" << direction; }Hope this helps.
Labels:
Code,
Gesture,
long press,
maemo,
qt,
Swipe gesture
Subscribe to:
Posts (Atom)