mouse pos() returns wrong position
-
Hello !,
So whenever i press right click, my character moves towards that position and its all working just fine till i get to the land
check this video :
https://streamable.com/cjo0dyou can see when i print character current position and the positioning of the mouse ( when i press right click ) it gives me wrong coordinates ( from the mouse ) and i don't know why... Sea and Land are two different items ( classes ), both are QPixmap so maybe it has to do something with that ?
Here is the main class code:Game.h:
#ifndef GAME_H #define GAME_H #include "player.h" #include "button.h" #include "sea.h" #include "land.h" #include <QGraphicsView> #include <QGraphicsScene> #include <QObject> #include <QMouseEvent> #include <QGraphicsSceneMouseEvent> #include <QGraphicsScene> #include <QWidget> #include <QKeyEvent> class Game: public QGraphicsView{ Q_OBJECT public: // this class stuff static QString in_room; Game(QWidget *parent=NULL); QGraphicsScene *scene; void menu(); void createMap(); void createPlayer(); QPixmap darkenImage(QString image, float num); // other class stuff Player *player; Button *startButton; Button *quitButton; Land *land; Sea *sea; // static stuff int curr_pos_in_menu; void changeColorOfButton(); public slots: void start(); void mousePressEvent(QMouseEvent *event); }; #endif // GAME_H
Game.cpp:
#include "game.h" #include "player.h" #include "button.h" #include <QGraphicsRectItem> #include <QGraphicsScene> #include <QDebug> #include <QApplication> #include <QTimer> #include <QFont> #include <QMessageBox> #include <fstream> #include <cmath> #include <QRect> #include <QDesktopWidget> #include <QtMath> QString Game::in_room = "menu"; Game::Game(QWidget *parent) { scene = new QGraphicsScene(); scene->setSceneRect(0,0,350,300); setFixedSize(350,300); setScene(scene); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setBackgroundBrush(QBrush(QImage("red"))); show(); menu(); } void Game::menu() { QGraphicsTextItem *title = new QGraphicsTextItem("NIGHTLESS"); title->setPos(10,30); title->setFont(QFont("comic sans",40,70)); scene->addItem(title); qDebug() << width(); startButton = new Button("START", 200, 50); startButton->setPos(width()/2-startButton->rect().width()/2,125); connect(startButton,SIGNAL(clicked()),this,SLOT(start())); scene->addItem(startButton); quitButton = new Button("QUIT", 200, 50); quitButton->setPos(width()/2-quitButton->rect().width()/2,200); connect(quitButton,SIGNAL(clicked()),this,SLOT(close())); scene->addItem(quitButton); } void Game::createMap() { land = new Land; land->setPos(0,0); scene->addItem(land); sea = new Sea; sea->setPos(0,0); scene->addItem(sea); } void Game::createPlayer() { player = new Player; player->setFlag(QGraphicsItem::ItemIsFocusable); player->setFocus(); centerOn(player); scene->addItem(player); } QPixmap Game::darkenImage(QString file_name, float num) { QImage tmp( file_name ); for(int i=0;i<tmp.height();i++) { for(int k=0;k<tmp.width();k++) { QColor color( tmp.pixel( k, i ) ); // changed this from pixelColor() to ensure alpha is copied if ( tmp.pixel(k,i) != 0) // modify only the pixels with non-zero alpha { color.setRgb(color.red()*num,color.blue()*num,color.green()*num); tmp.setPixelColor(k,i,color); } } } // Now, convert the image to a pixmap and set it on the graphics object QPixmap t = QPixmap::fromImage( tmp ); return t; } void Game::start() { scene->clear(); in_room = "world"; // semi-transparent background /* QRect rec = QApplication::desktop()->screenGeometry(); int height = rec.height(); int width = rec.width(); */ setSceneRect(0,0,7097,7298); setFixedSize(1000,800); //setBackgroundBrush(QBrush(QImage(":/Images/Grass.png"))); //showFullScreen(); createMap(); createPlayer(); } void Game::mousePressEvent(QMouseEvent *event) { if(event->buttons() == Qt::RightButton && in_room!="menu"){ QLineF ln(event->pos(),player->pos()); int angle = -1 * ln.angle() + 460; int tmp = angle + 80; if(tmp>360) tmp-=360; if(angle > 360) angle += -360; player->setPlayerRotation(angle,tmp); QPointF t(event->pos()); player->setDestination(event->pos()); } }
In the Land and Sea class i just setPixmap to the image, put them into the scene,set position and that is it.
And i have one more question, how do i make a player stop when he reaches his destination ? i was thinking about making an QGraphicsRectItem whenever i press a right button and then checking if player has collided with that item and when he does he stops and then that item gets deleted or is there a better and easier way to do that, cause comparing mouse pos() and player pos() is not working.
Any kind of help or advice is appreciated !!!
-
Hi,
For the "collision" checking, you can take a look at the colliding mice example.
-
@FlyDoodle
Hi,
for collision detection you can use shape() method. The shape is used for many things, including collision detection, hit tests, and for the QGraphicsScene::items() functions.
https://doc.qt.io/archives/qt-4.8/qgraphicsitem.html#shape
For better conversion between view coordinates and scene coordinates you can use mapToScene(QPoint) method. This method returns the viewport coordinate point mapped to scene coordinates. See more:
https://doc.qt.io/archives/qt-4.8/qgraphicsview.html#mapToScene
Lastly, you can see my repo. I did simple game which use collision detecion. It may help you:bool Hero::onCollisionEnter(QString collider) { //Calculate a type of collision int sumOfCollision = 0; QList<QGraphicsItem*> colliderList = collidingItems(); for(int idx = 0; idx < colliderList.size(); ++idx) { if(collider == "Background") { //QGraphicsItem *item = qgraphicsitem_cast<BlueBackground*>(colliderList[idx]); if(qgraphicsitem_cast<BlueBackground*>(colliderList[idx])) { sumOfCollision += 1; } //Brick | Evil1 | Bullet | else if(qgraphicsitem_cast<Brick*>(colliderList[idx]) || qgraphicsitem_cast<Ground*>(colliderList[idx]) || qgraphicsitem_cast<Evil1*>(colliderList[idx]) || qgraphicsitem_cast<Bullet*>(colliderList[idx]) ) { sumOfCollision += 1; } } } if(sumOfCollision == 1) { return true; } return false; }
Link to this repo: https://github.com/Przemekkkth/Qt-C-SimpleGame
-
@Bondrusiek
Hello !
I tried using mapToScene before and i realized that when i was creating a QLine item between the player and the mouse position i forgot to use it and now it's working all fine.
About that colliding thingy i will take a look, thank you !
I have taken a look at your game and it's amazing, but i couldn't find how you did that player movement ? i tried looking for it and i found keyPressedEvent functions but there were no == Qt::key_W stuff and so on for movement, only for space.Tho i have one more question, how do i put waves (image) around my island in the game as the background. I want to make it so that for example 60 x 60 pixels waves fill the background ( or the item that is around the island ). Doing setBackgroundBrush(QBrush(QImage("path"))); will set the background the way i want it to, but the problem is when the player is moving and he gets near the water, he has to stop. I want to check if he is near the water using collision.I have class Land and class Sea and they are both QGraphicsPixmapItems and i could just check if the player has collided with the Sea class but the problem comes when i want the sea to be moving, and i would do that using 2 pictures and changing between them but changing pictures takes time especially if the image is that big and that's not optimal...
-
@FlyDoodle , I used GetAsyncKeyState() (https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate) to control my hero. This function monitore the status of the keyboard keys used by the function of the WinAPI.
When you want to collide one object with another object, Objects must be QGraphicsItem or descendant. You can creater bigger geometry for shape() than bouncingRect() for detect collision and next:QList<QGraphicsItem*> colliderList = collidingItems(); for(int idx = 0; idx < colliderList.size(); ++idx) { if(qgraphicsitem_cast<Land*>(colliderList[idx])) { //collide with Land } else if(qgraphicsitem_cast<Sea*>(colliderList[idx])) { //collide with Sea }
-
@Bondrusiek
Oh i see, I'll check that out !
And thank you for the code, everything is working fine now ! -
@FlyDoodle why not use QML?
-
@Cheng-shi-hua
QML ?