爲了爲了傳遞帶有Qt中的信號和時隙的參數,信號參數必須與時隙的參數(或自Qt 5以來的函數)匹配。
解決此問題的一種方法是在TheDarkKnight的答案中使用lambda。
我建議使用封裝 - 你可以創建一個Spawner
對象,專用於產生敵人並保持內部位置。通過這種方式,產卵者將管理該位置,並且您可以擁有像Spawner::createWave()
插槽這樣的無參數插槽,因爲該位置是內部的。然後設置計時器並將其連接到createWave()
,然後設置好。
此外,硬編碼這樣的東西是非常糟糕的主意,你真的需要更多的靈活性,選擇改變敵人和波數,波浪時間以及屏幕寬度,以便你的遊戲可以改變這些東西因爲它變得更難。
class Spawner : public QObject {
Q_OBJECT
public:
Spawner(int wCount = 5, int eCount = 9, int time = 2000, int sWidth = 1000)
: waveCount(wCount), enemyCount(eCount), currentWave(0), screenWidth(sWidth) {
timer.setInterval(time);
connect(&timer, SIGNAL(timeout()), this, SLOT(createWave()));
}
void set(int wCount, int eCount, int time) {
timer.setInterval(time);
waveCount = wCount;
enemyCount = eCount;
}
void changeWidth(int w) { screenWidth = w; }
public slots:
void start() { timer.start(); }
void stop() {
timer.stop();
currentWave = 0;
}
private slots:
void createWave() {
int pos = screenWidth/(enemyCount + 1);
int step = pos;
for (int i = 0; i < enemyCount; ++i) {
Game::spawnEnemyAt(pos);
pos += step;
}
if (++currentWave >= waveCount) stop();
}
private:
QTimer timer;
int waveCount, enemyCount, currentWave, screenWidth;
};
創建Spawner
對象和遊戲新臺階連接到start()
- 這將跨越均勻地分佈在遊戲畫面的敵人給定數量的波浪,當你完成盪漾開,你調整產卵設置和啓動新的水平。
隨着遊戲變得越來越不像測試,更像真實的遊戲 - 隨着難度的增加,產卵和攻擊模式的變化等等,這種封裝將會在以後派上用場。因此,從一開始就實施它是一個好主意,並且建立在良好而靈活的設計之上,而不是回頭和改變周圍的東西,這可能會破壞其他代碼。如果沒有好的設計並且稍後進行設計更改,你真的不想開始。因此需要封裝功能和責任,只需連接各個部分,而不是在一堆意大利麪代碼的基礎上構建。在這一思路中,我注意到你使用的是player->spawn_in_pos(pos);
--這是一個糟糕的設計的例子,因爲產卵應該是Game
類的職責,而不是Player
類。一個好的設計不僅靈活,而且乾淨。該物體只負責產生敵人的波浪,其可見接口限於start()
,stop()
和set()
。
編輯:
class Game : public QObject {
Q_OBJECT
public:
Game() {
if (!scene) scene = new QGraphicsScene(this);
connect(this, SIGNAL(newLevel()), &spawner, SLOT(start()));
}
static void spawnEnemyAt(int x = 0) {
scene->addItem(new Enemy(x, 0));
qDebug() << "enemy created";
}
public slots:
void newGame() {
// initialize game
emit newLevel(); // begin spawning
}
void onLevelEnd() {
// spawner.set(new level settings);
emit newLevel();
}
void onGameEnded() {
// ...
}
signals:
void newLevel();
private:
Spawner spawner;
static QGraphicsScene * scene;
};
// in game.cpp
QGraphicsScene * Game::scene = nullptr;
如果你不希望使用靜態成員,可以使spawnEnemyAt()
和scene
實例成員,但隨後你將不得不通過Game
實例的Spawner
在構造函數,因此你可以參考產卵者操作的遊戲並使用game->spawnEnemyAt()
代替。這樣你就可以用自己的專用場景創建多個遊戲。或者讓遊戲中的親生父親參與遊戲,並將產卵者的parent()
投射到Game *
以訪問有點冒險的遊戲實例,但通過重用父代來保存額外的成員。
您無法將值傳遞給連接方法內的插槽。我建議你閱讀關於信號和插槽的內容:http://doc.qt.io/qt-5/signalsandslots.html –
你是否希望通過詢問關於每一步的問題來製作整個遊戲?看起來你正在超越自己。我建議你拿起一本關於遊戲編程的書,並在你開始製作遊戲之前研究這個主題。你的方法非常天真,從根本上說是錯誤的。一種尺寸並不適合所有人,僅僅因爲計時器是產生敵方波的好方案並不意味着你應該爲每個遊戲對象使用專用計時器。這不是遊戲的工作原理。同時,堅持一個問題,這個問題是關於產生敵人,而不是敵人的運動。 – dtech