Udało mi się zedytować kod, dodając w niektórych miejscach wskaźnik prywatny na obiekt Game. Gra działa prawie tak jak bym chcial :( W przypadku kolizji z graczem, usuwa się przeciwnik ze sceny, kalkulacja punktów następuje poprawnie. W przypadku zestrzelenia przeciwnika pociskiem - gra po prostu wyłącza się. Mógłbym liczyć na wskazówkę - dlaczego tak się dzieje? Poniżej zamieszczam headery i źródła dla klas.
#ifndef BULLET_H
#define BULLET_H
#include <QGraphicsPixmapItem>
#include <QGraphicsItem>
#include <QObject>
#include "game.h"
class Game;
class Enemy;
class Bullet: public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
Bullet(QGraphicsItem *parent = 0, Game* game=nullptr);
public slots:
void move();
private:
Game* game; // Składowa przechowująca wskaźnik na obiekt Game
};
#endif // BULLET_H
#include "bullet.h"
#include "qgraphicsscene.h"
#include <QTimer>
#include <QList>
#include "enemy.h"
#include <QDebug>
#include "score.h"
#include "game.h"
#include "player.h"
Bullet::Bullet(QGraphicsItem *parent, Game *game): QObject(), QGraphicsPixmapItem(parent)
{
// draw graphics
setPixmap(QPixmap(":/images/bullet.png"));
// make/connect a timer to move() the bullet every so often
QTimer * timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(move()));
// start the timer
timer->start(50);
}
void Bullet::move(){
// get a list of all the items currently colliding with this bullet
QList<QGraphicsItem *> colliding_items = collidingItems();
// if one of the colliding items is an Enemy, destroy both the bullet and the enemy
for (int i = 0, n = colliding_items.size(); i < n; ++i){
if (typeid(*(colliding_items[i])) == typeid(Enemy)){
// increase the score
game->score->increase();
// remove them from the scene (still on the heap)
scene()->removeItem(colliding_items[i]);
scene()->removeItem(this);
// delete them from the heap to save memory
delete this;
// return (all code below refers to a non existint bullet)
return;
}
}
// if there was no collision with an Enemy, move the bullet forward
setPos(x(),y()-10);
// if the bullet is off the screen, destroy it
if (pos().y() < 0){
scene()->removeItem(this);
delete this;
}
}
#ifndef ENEMY_H
#define ENEMY_H
#include <QGraphicsPixmapItem>
#include <QObject>
#include "game.h"
#include "bullet.h"
class Game;
class Enemy: public QObject, public QGraphicsPixmapItem
{
Q_OBJECT
public:
Enemy(Game* game);
void collision();
public slots:
void move_to();
private:
Game* game;
};
#endif // ENEMY_H
#include "Enemy.h"
#include <QTimer>
#include <QGraphicsScene>
#include <QList>
#include <stdlib.h>
#include "qgraphicsscene.h"
#include "game.h"
#include "player.h"
#include "health.h"
Enemy::Enemy(Game* game) : game(game){
QTimer *timer = new QTimer();
int ranx,rany,ran;
ranx = rand() %200+200;
rany = rand() %200+200;
ran = rand() %4;
setPixmap(QPixmap(":/images/enemy.png"));
setTransformOriginPoint(50,50);
setRotation(180);
if(ran==0)
{
setPos(game->player->pos().x()+ranx,game->player->pos().y()+rany);
}
if(ran==1)
{
setPos(game->player->pos().x()-ranx,game->player->pos().y()+rany);
}
if(ran==2)
{
setPos(game->player->pos().x()+ranx,game->player->pos().y()-rany);
}
if(ran==3)
{
setPos(game->player->pos().x()-ranx,game->player->pos().y()-rany);
}
connect(timer,&QTimer::timeout,[&, this](){
move_to(); });
timer->start(50);
}
void Enemy::collision()
{
QList<QGraphicsItem *> colliding_items = collidingItems();
for(int i =0 , n = colliding_items.size(); i<n ; i++)
{
if(typeid(*(colliding_items[i]))==typeid(Player))
{
game -> health -> decrease();
game->ifGameOver();
scene()->removeItem(this);
}
}
}
void Enemy::move_to()
{
if(game->player->pos().x()>pos().x())
setPos(pos().x()+2,pos().y());
else if(game->player->pos().x()<pos().x())
setPos(pos().x()-2,pos().y());
if(game->player->pos().y()>pos().y())
setPos(pos().x(),pos().y()+2);
else if(game->player->pos().y()<pos().y())
setPos(pos().x(),pos().y()-2);
collision();
}
#ifndef PLAYER_H
#define PLAYER_H
#include <QGraphicsRectItem>
#include <QObject>
#include <vector>
#include "game.h"
// Forward declarations
class Enemy;
class Bullet;
class Motionless;
class Player : public QObject, public QGraphicsPixmapItem
{
Q_OBJECT
public:
Player(Game* game,QGraphicsItem *parent = 0);
void keyPressEvent(QKeyEvent *event);
~Player();
public slots:
void create();
void create_obstacle_fale();
void create_obstacle_ice_hill();
private:
void create_motionless(Motionless *object);
std::vector<Motionless *> objects;
std::vector<Enemy *> enemies;
std::vector<Bullet *> bullets;
int moveSpeed = 7;
Game *game;
};
#endif // PLAYER_H
#include "player.h"
#include "qevent.h"
#include "bullet.h"
#include "qgraphicsscene.h"
#include "obstacle_ice_hill.h"
#include "obstacle_fale.h"
#include "motionless.h"
#include "enemy.h"
#include <QTimer>
#include <QApplication>
#include "game.h"
Player::Player(Game* game, QGraphicsItem* parent) : QObject(), QGraphicsPixmapItem(parent), game(game)
{
setPixmap(QPixmap(":/images/player.png"));
}
void Player::keyPressEvent(QKeyEvent *event){
// move the player left and right
if(event->key() == Qt::Key_Left)
{ if(pos().x()>0)
{
setPos(x()-moveSpeed,y());
}
}
else if(event->key() == Qt::Key_Right)
{ if(pos().x()+50<900)
{
setPos(x()+moveSpeed,y());
}
}
else if(event->key() == Qt::Key_Up)
{ if(pos().y()>0){
setPos(x(),y()-moveSpeed);
}
}
else if(event->key() == Qt::Key_Down)
{ if(pos().y()+50<900)
{
setPos(x(),y()+moveSpeed);
}
}
else if (event->key() == Qt::Key_Space){
// create a bullet
Bullet * bullet = new Bullet();
bullet->setPos(x()+20,y());
scene()->addItem(bullet);
}
}
Player::~Player()
{
for (Motionless *object: objects)
{delete object;}
for (Enemy * enemy: enemies)
{delete enemy;}
for (Bullet * bullet: bullets)
{delete bullet;}
}
void Player::create()
{
Enemy * enemy = new Enemy(game);
enemies.push_back(enemy);
scene()->addItem(enemy);
}
void Player::create_obstacle_fale()
{
create_motionless(new Obstacle_fale(game));
}
void Player::create_obstacle_ice_hill()
{
create_motionless(new Obstacle_ice_hill(game));
}
void Player::create_motionless(Motionless *object)
{ objects.push_back(object);
scene()->addItem(object);
}