几个月前,我开始使用 c++ 学习 QT,以及如何为大学目的开发游戏。我有一个太空射击游戏,其中玩家是一个 Qgraphics 项目,它不断播放动画(移动、空闲、更换武器......)以及敌人。
移动系统没问题,玩家在地图上移动没有问题,并且控制很流畅,可以做出应有的反应。
射击系统也ok!玩家可以创建其他物体直线移动并与它们碰撞的物体消失(从场景中删除),或者在到达场景边界时消失,敌人也可以射击。
当一个键被按下时,玩家响应任何命令都没有延迟,问题是敌人。
玩家有一个周期性的功能,在地图的上边界创造敌人,他们直接朝地图的下边界向下移动,如果他们没有被击落,他们就会像子弹一样消失。
但是过了一段时间他们就慢了很多,当我关闭允许他们射击的功能时,如果他们这样做会变得更糟并且游戏开始非常滞后,不应该发生的事情因为对我来说是“只是一堆在屏幕上移动的二维图片”。这是我认为有问题的代码,有人可以帮助我吗?这真的很烦人,有 2 或 3 个月我无法修复它或知道为什么会这样。
Enemy.h
#define ENEMY_H
#include <QObject>
#include <QGraphicsPixmapItem>
#include <QGraphicsItem>
#include <QTimer>
#include <QPixmap>
#include <QMediaPlayer>
#include <QPainter>
//works similiar to player controlled entity, but this one is controlled by algorithms
class Enemy: public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit Enemy(QObject *parent=0);
void move();
void shoot();
private slots:
void nextFrame();
void enemiesInrange();//peiodically checks if there is any enemies in it's front, if there is it will shoot periodically
private:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QRectF boundingRect() const;
QTimer *timer;//for load the next frame of the animation
QTimer *timer2;//for move
QTimer *timer3;//for look for enemies
QTimer *timer4;//for shoot in enemies
QPixmap *spriteImage;
int currentFrame;
int currentSequence;
QMediaPlayer *bullet_sound;
};
#endif // ENEMY_H
enemy.c
#include "enemy.h"
#include "player.h"
#include <QBitmap>
#include "bullet.h"
#include "game.h"
#include "stdlib.h"
extern Game *game;
using namespace std;
Enemy::Enemy(QObject *parent):
QObject(parent), QGraphicsItem()
{
spriteImage = new QPixmap(":/images/img/hizack spritesheet.png");
int random_number = rand()% 1200;
setPos(random_number,0);
currentFrame=0;
currentSequence=210;
timer = new QTimer();
connect(timer, &QTimer::timeout, this, &Enemy::nextFrame);
timer->start(100);
timer2 = new QTimer();
connect(timer2, &QTimer::timeout, this, &Enemy::move);
timer2->start(1);
timer3 = new QTimer();
connect(timer3, &QTimer::timeout, this, &Enemy::enemiesInrange);
timer3->start(1000);
}
void Enemy::move()
{
currentSequence = 210;
setPos(x(),y()+0.25);
if(pos().y() + spriteImage->height() < 0 || pos().y() >= 800)
{
game->scene->removeItem(this);
delete this;
return;
}
if(pos().x() >= 600 || pos().x() == 0)
{
game->scene->removeItem(this);
delete this;
return;
}
}
void Enemy::shoot()
{
if(currentSequence == 210)
{
Bullet * bullet = new Bullet(0,currentSequence,20,2);
bullet->setPos(this->pos().x()-20,this->pos().y()+50);
scene()->addItem(bullet);
}
else if(currentSequence == 70)
{
Bullet * bullet = new Bullet(0,currentSequence,30,2);
bullet->setPos(this->pos().x()-20,this->pos().y()-80);
scene()->addItem(bullet);
}
else if(currentSequence == 140)
{
Bullet * bullet = new Bullet(0,currentSequence,30,2);
bullet->setPos(this->pos().x()+20 ,this->pos().y()-50 );
scene()->addItem(bullet);
}
else if(currentSequence == 0)
{
Bullet * bullet = new Bullet(0,currentSequence,30,2);
bullet->setPos(this->pos().x()-50 ,this->pos().y()-50 );
scene()->addItem(bullet);
}
}
void Enemy::enemiesInrange()//fires player if him is at range
{
qInfo() << "Items in scene: " << scene()->items().size();
if(game->player1->pos().y() <= this->pos().y()+300 )
{
if(game->player1->pos().x() <= this->pos().x()+100 && game->player1->pos().x()>= this->pos().x()-100)
shoot();
}
}
void Enemy::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawPixmap(-35,-35, *spriteImage, currentFrame, currentSequence, 70,70);
Q_UNUSED(option);
Q_UNUSED(widget);
}
QRectF Enemy::boundingRect() const
{
return QRectF(-35,-35,70,70);
}
void Enemy::nextFrame()
{
currentFrame += 70;
if (currentFrame >= 210)
currentFrame = 0;
this->update(-35,-35,70,70);
}