国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

C++游戲編程教程(五)——項目實戰

phpmatt / 2179人閱讀

摘要:代碼下載點擊此處下載游戲截圖游戲編寫項目框架這個游戲主要的框架是這樣的其中有三個類派生自類,兩個派生自類。用于控制時間間隔。更新角色位置,并判斷是否與飛機或子彈碰撞。構造函數初始化成員。

今天,我們來用所學知識做一個簡易的飛機大戰游戲。

游戲介紹

游戲功能

玩家駕駛飛機在窗口下方左右移動,按下空格發射子彈(0.3秒一個),而上方會有石塊落下,打中飛機會死亡,玩家可以使用子彈攻擊石塊,如果打到了石塊就消失,同時之后的石塊下落會加速。屏幕上方還會有敵人的飛機出現,會隨機發射子彈,還會隨機移動,玩家碰到敵人發來的子彈會死亡,敵人碰到玩家的子彈也會消失。敵人有20個,隨機出現,同一時刻屏幕上最多有5個敵人。玩家消滅所有的敵人就勝利了。

代碼下載

點擊此處下載

游戲截圖


游戲編寫

項目框架

這個游戲主要的框架是這樣的:

其中有三個類派生自Actor類,兩個派生自DrawComponent類。

創建項目

首先,用我們的項目模板創建一個項目。
注意:在所有出現顯示中文內容的文件中都應該加入一行#pragma execution_character_set("utf-8"),否則是亂碼。

Plane類

這個類是玩家控制的飛機類,功能主要有移動和發射子彈。

代碼

Plane.h:

#pragma once#include"Actor.h"class Plane :    public Actor{public:    Plane(class Game* game, const Vector2& pos);    virtual void ActorInput(const uint8_t* keyState);    virtual void UpdateActor(float deltaTime);private:    short mPlaneDir;    Uint32 mTick;};

Plane.cpp:

#include "Plane.h"#include "Bullet.h"#include "DrawRectangleComponent.h"Plane::Plane(Game* game, const Vector2& pos) :Actor(game), mPlaneDir(0){	SetPosition(pos);	mTick = SDL_GetTicks();}void Plane::ActorInput(const uint8_t* keyState){	mPlaneDir = 0;	if (keyState[SDL_SCANCODE_RIGHT])		mPlaneDir += 1;	if (keyState[SDL_SCANCODE_LEFT])		mPlaneDir -= 1;	if (keyState[SDL_SCANCODE_SPACE] && SDL_TICKS_PASSED(SDL_GetTicks(), mTick + 300))//0.3秒發射一顆子彈	{		mTick = SDL_GetTicks();		Vector2 pos = GetPosition();		pos.x += 20;		pos.y -= 40;		new DrawRectangleComponent(new Bullet(GetGame(), pos, -700), Vector2(10, 20), 255, 0, 0, 0);	}}void Plane::UpdateActor(float deltaTime){	Vector2 pos = GetPosition();	pos.x += mPlaneDir * 300 * deltaTime;	if (pos.x < 0)		pos.x = 0;	if (pos.x > 1024 - 50)		pos.x = 1024 - 50;	SetPosition(pos);}

代碼分析

成員變量

mTick:上次發射子彈的時間。用于控制時間間隔。
mPlaneDir:飛機移動方向。

構造函數

初始化變量。

ActorInput

重寫的虛函數。首先設置移動方向,然后判斷是否按下空格,如果按下就new一個子彈。

UpdateActor

更新位置。

Stone類

這個類是石頭類。

代碼

Stone.h:

#pragma once#include"Actor.h"class Stone	:public Actor{public:	Stone(Game* game, const Vector2& pos, float speed);	virtual void UpdateActor(float deltaTime);private:	float mSpeed;};

Stone.cpp:

#include "Stone.h"#include"Bullet.h"#include"Plane.h"#include#pragma execution_character_set("utf-8")Stone::Stone(Game* game, const Vector2& pos, float speed):Actor(game),mSpeed(speed){	SetPosition(pos);}void Stone::UpdateActor(float deltaTime){	Vector2 pos = GetPosition();	pos.y += deltaTime * mSpeed;	if (pos.y > 768)		SetState(EDead);	SetPosition(pos);	for (auto i : GetGame()->mActors)	{		if (typeid(*i) == typeid(Bullet))//運行時類型檢查		{			Vector2 bPos = i->GetPosition();			if (bPos.x + 20 > pos.x && bPos.x < pos.x + 50 && bPos.y < pos.y + 50)			{				SetState(EDead);				i->SetState(EDead);				GetGame()->mStoneSpeed *= 1.02;			}		}		else if (typeid(*i) == typeid(Plane))		{			Vector2 bPos = i->GetPosition();			if (bPos.x + 50 > pos.x && bPos.x < pos.x + 50 && bPos.y < pos.y + 50 && bPos.y + 30>pos.y)			{				SetState(EDead);				i->SetState(EDead);				SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "游戲結束", "游戲結束,你輸了!", GetGame()->mWindow);				GetGame()->mIsRunning = false;			}		}	}}

代碼分析

成員變量

mSpeed:速度。

構造函數

初始化變量。

UpdateActor

更新角色位置,并判斷是否與飛機或子彈碰撞。
其實,這里的代碼我寫得非常非常非常非常非常非常非常非常非常非常(注:此處省略 1 0 1000000 10^{1000000} 101000000個非常)不規范。為什么呢?因為按照我們的代碼規范來說,這里應該建立一個專門的碰撞檢測組件,并把它加到Actor里,如果簡單地寫在UpdateActor里面,會使代碼混亂,非常非常非常
(注:此處省略 1 0 1000000 10^{1000000} 101000000個非常)不便于閱讀和后續添加代碼。不過這里比較簡單 (其實是我偷懶) ,就將就看吧。

Enemy類

這個類是敵方飛機類,它可以自動移動,并且隨機發射子彈。其實這里也寫得不太規范,其實我們大可不必建這個類,只需要建立Plane類,并不添加任何代碼,然后建兩個組件InputComponent和AutoMoveComponent,new對象的時候分別加上,這樣可以提高代碼復用率。在本例中,這個功能的好處并不明顯,但設想一下,如果飛機除了用戶控制和電腦控制之外,還有很多很多其它功能(比如為飛機添加彈夾和油量屬性),這樣專門寫兩個類就太麻煩了,不如使用組件。

代碼

Enemy.h:

#pragma once#include "Actor.h"class Enemy :    public Actor{public:    Enemy(Game* game, const Vector2& pos);    virtual void UpdateActor(float deltatime);private:    Uint32 mTicks;    Uint32 mMoveTicks;    short mMove;};

Enemy.cpp:

#include "Enemy.h"#include"Bullet.h"#include"DrawRectangleComponent.h"Enemy::Enemy(Game* game, const Vector2& pos) :Actor(game), mTicks(SDL_GetTicks()), mMoveTicks(SDL_GetTicks()){	SetPosition(pos);	mMove = 200 + rand() % 100;	if (rand() % 2)		mMove = -mMove;}void Enemy::UpdateActor(float deltatime){	Vector2 pos = GetPosition();	if (SDL_TICKS_PASSED(SDL_GetTicks(), mMoveTicks + 1000))//隨機移動位置	{		mMoveTicks = SDL_GetTicks();		mMove = 100 + rand() % 100;		if (rand() % 2)			mMove = -mMove;	}	pos.x += deltatime * mMove;	if (pos.x > 1024 - 50)		pos.x = 1024 - 50;	if (pos.x < 0)		pos.x = 0;	SetPosition(pos);	if (SDL_TICKS_PASSED(SDL_GetTicks(), mTicks + 1000)&&!(rand()%25))//1秒發射子彈	{		mTicks = SDL_GetTicks();		pos.x += 20;		pos.y += 40;		new DrawRectangleComponent(new Bullet(GetGame(), pos, 700), Vector2(10, 20), 255, 0, 0, 0);	}}

代碼分析

成員變量

mTicks:記錄上一次射擊的時間。
mMoveTicks:記錄以這個速度移動的時間(因為要隨機移動,所以需要頻繁更新移動速度和方向)。
mMove:移動速度。

構造函數

初始化成員。

UpdateActor

先更新隨機移動的速度,然后隨機移動位置,最后發射子彈(1秒后,每幀有 1 25 /frac{1}{25} 251?幾率發射子彈)。

Bullet類

這個類是子彈類。

代碼

Bullet.h:

#pragma once#include "Actor.h"class Bullet :    public Actor{public:    Bullet(class Game* game, const Vector2& pos, float speed);    virtual void UpdateActor(float deltaTime);private:    float mSpeed;};

Bullet.cpp:

#include "Bullet.h"#include"Plane.h"#include"Enemy.h"#include#pragma execution_character_set("utf-8")Bullet::Bullet(Game* game, const Vector2& pos, float speed) :Actor(game), mSpeed(speed){	SetPosition(pos);}void Bullet::UpdateActor(float deltaTime){	Vector2 pos = GetPosition();	pos.y += mSpeed * deltaTime;	SetPosition(pos);	if (pos.y > 768 || pos.y < 0)		SetState(EDead);	for (auto i : GetGame()->mActors)	{		if (typeid(*i) == typeid(Enemy))//運行時類型檢查		{			Vector2 bPos = i->GetPosition();			if (bPos.x - 10 < pos.x && bPos.x + 50 > pos.x && bPos.y + 50 > pos.y)			{				SetState(EDead);				i->SetState(EDead);			}		}		else if (typeid(*i) == typeid(Plane))		{			Vector2 bPos = i->GetPosition();			if (bPos.x - 10 < pos.x && bPos.x + 50 > pos.x && bPos.y < pos.y + 20 && bPos.y + 30 > pos.y)			{				SetState(EDead);				i->SetState(EDead);				SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "游戲結束", "游戲結束,你輸了!", GetGame()->mWindow);				GetGame()->mIsRunning = false;			}		}	}}

代碼分析

Bullet類的代碼和Stone類的代碼基本相同,此處不再介紹。

Game類

最后,我們的任務是修改Game類。
首先,要在Game.cpp中包含所有自定義類的頭文件:

#include "Game.h"#include "SDL_image.h"#include #include "Actor.h"#include"Plane.h"#include"DrawPlaneComponent.h"#include"DrawRectangleComponent.h"#include"Stone.h"#include"Enemy.h"#include #include

接著,在Game.h中加入:

	float mStoneSpeed;//石頭的速度	unsigned short mEnemyCount;//屏幕上敵人數量	unsigned short mAllEnemyCount;//剩余敵人數量

并在構造函數里初始化這幾個變量。
然后,在LoadData函數里添加:

new DrawPlaneComponent(new Plane(this, Vector2(492, 700)));

new出飛機對象。
然后在UpdateGame里添加:

if (!(rand() % 100))	{		new DrawRectangleComponent(new Stone(this, Vector2(rand() % (1024 - 50), 0), mStoneSpeed + rand() % 10), Vector2(50, 50), 255, 255, 0, 0);	}	if (mEnemyCount < 5 && mAllEnemyCount)	{		new DrawPlaneComponent(new Enemy(this, Vector2(rand() % 984, 10)), true);		--mAllEnemyCount;		++mEnemyCount;	}

用來new出敵人和石頭。
最后,在GenerateOutput函數里添加:

if (!mAllEnemyCount && !mEnemyCount)	{		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "游戲結束", "游戲結束,你贏了!", mWindow);		mIsRunning = false;	}

用來提示勝利。注:最好添加在SDL_RenderPresent后面,這樣能顯示最后一個敵人消失的場景,要不然提示結束的時候屏幕上還有一個敵人。

總結

到現在,整個的游戲就編寫完畢了,效果也就是開頭出示的那樣。通過這個項目,我們真正體會到了面向對象的好處,以及將程序模塊化的重要性。最后,祝大家編程順利,代碼無bug!
注:博主馬上就要開學了,可能最近無法更新。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/121856.html

相關文章

  • SegmentFault 技術周刊 Vol.40 - 2018,來學習一門新的編程語言吧!

    摘要:入門,第一個這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數式編程語言,它的代碼運行在之上。它通過編輯類工具,帶來了先進的編輯體驗,增強了語言服務。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經到來了,總結過去的 2017,相信小伙們一定有很多收獲...

    caspar 評論0 收藏0
  • SegmentFault 技術周刊 Vol.40 - 2018,來學習一門新的編程語言吧!

    摘要:入門,第一個這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數式編程語言,它的代碼運行在之上。它通過編輯類工具,帶來了先進的編輯體驗,增強了語言服務。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經到來了,總結過去的 2017,相信小伙們一定有很多收獲...

    nihao 評論0 收藏0
  • SegmentFault 技術周刊 Vol.40 - 2018,來學習一門新的編程語言吧!

    摘要:入門,第一個這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數式編程語言,它的代碼運行在之上。它通過編輯類工具,帶來了先進的編輯體驗,增強了語言服務。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經到來了,總結過去的 2017,相信小伙們一定有很多收獲...

    Drummor 評論0 收藏0
  • 系統地學習C++

    摘要:本書主要圍繞一系列逐漸復雜的程序問題,以及用以解決這些問題的語言特性展開講解。你不只學到的函數和結構,也會學習到它們的設計目的和基本原理。因此我們把精力集中在最有價值的地方。本書不僅是對模板的權威解釋,而且本書還深入地介紹了其他一般的思想。 C++ 入門教程(41課時) - 阿里云大學 C+...

    joyqi 評論0 收藏0
  • 區塊鏈開發中使用的最流行的編程語言

    摘要:我們目前正處于一個新興的區塊鏈開發行業中。,一種在以太坊開發人員中流行的新的簡單編程語言,因為它是用于開發以太坊智能合約的語言。它是全球至少萬開發人員使用的世界上最流行的編程語言之一。以太坊,主要是針對工程師使用進行區塊鏈以太坊開發的詳解。 我們目前正處于一個新興的區塊鏈開發行業中。區塊鏈技術處于初期階段,然而這種顛覆性技術已經成功地風靡全球,并且最近經歷了一場與眾不同的繁榮。由于許多...

    2shou 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<