C++ 學(xué)習(xí)之旅三 我和超級(jí)瑪麗有個(gè)約會(huì)
首先,我說說對(duì)C++的最直觀的感受吧!熟悉了.net 智能提示,開始一開始發(fā)現(xiàn)C++根本沒有提示了。后來google了一下,下載了一個(gè)visual assist 這個(gè)插件,比vs自動(dòng)提示強(qiáng)多了。 然后,就是習(xí)慣了在.net中,把所有的聲明和方法實(shí)現(xiàn)寫在同一文件中??墒荂++不是這么回事。 他一個(gè)聲明在頭文件中,實(shí)現(xiàn) 在源文件中,說實(shí)在話,一開始并怎么習(xí)慣。后來漸漸就習(xí)慣了。然后,寫C++的文件就是痛苦,他不比.net,微軟已經(jīng)比你封裝好了,在C++中,好多東西需要自己寫。 首先,一個(gè)析構(gòu)函數(shù),需要自己釋放資源。而.net有一個(gè)gc自動(dòng)進(jìn)行垃圾回收,資源釋不釋放,關(guān)你鳥事。沒辦法,只有自己釋放.做一個(gè)遵守規(guī)則的好程序員。這是我對(duì)C++最直觀感受。
言歸正卷,說一說這個(gè)超級(jí)瑪麗的游戲。 先看看,我對(duì)游戲的類結(jié)構(gòu)的分類,如果有不妥的地方,懇請大家指正。
從層次結(jié)構(gòu)來看,分成這幾個(gè)層①圖像層,②邏輯層,③結(jié)構(gòu)和表。
圖像層包括①圖像基類MYBITMAP,②游戲背景MYBKSKYàMYBITMAP,③游戲圖片MYANIOBJàMYBITMAP,④魔法攻擊MYANIMAGICàMYBITMA.
邏輯層包括①游戲邏輯GAMEMAP,②時(shí)鐘處理MYCLOCK,③字體處理MYFONT,④跟蹤打印FILEREPORT,⑥玩家控制MYROLEàMYBITMAP。
結(jié)構(gòu)和表包括①精靈結(jié)構(gòu)ROLE,②物品結(jié)構(gòu)MapObject,③地圖信息表MAPINFO。
那每個(gè)類的結(jié)構(gòu)又是那么樣子的,是騾子還是馬拉出來溜溜。我們在往下看一看。
圖像層的結(jié)構(gòu)就這樣簡單,邏輯層只需要確定“哪個(gè)圖像,哪一幀”這兩個(gè)參數(shù),就能在屏幕上繪制出所有圖片。
說一說一個(gè)圖片的基類。他的源代碼的架構(gòu)又是這個(gè)樣子的。
今天先講最基礎(chǔ)的圖像類 MYBITMAP:
成員函數(shù)功能列表:
//功能 根據(jù)一個(gè)位圖文件,初始化圖像
//入?yún)?應(yīng)用程序?qū)嵗浔?資源ID 橫向位圖個(gè)數(shù) 縱向位圖個(gè)數(shù)
void Init(HINSTANCE hInstance,int iResource,int row,int col);
//功能 設(shè)置環(huán)境信息
//入?yún)?目的DC(要繪制圖像的DC),臨時(shí)DC,要繪制區(qū)域的寬 高
void SetDevice(HDC hdest,HDC hsrc,int wwin,int hwin);C++中畫圖需要一個(gè)hdc,設(shè)備上下文需要是一種包含有關(guān)某個(gè)設(shè)備(如顯示器或打印機(jī))的繪制屬性信息的 Windows 數(shù)據(jù)結(jié)構(gòu)。所有繪制調(diào)用都通過設(shè)備上下文對(duì)象進(jìn)行,這些對(duì)象封裝了用于繪制線條、形狀和文本的 Windows API。設(shè)備上下文允許在 Windows 中進(jìn)行與設(shè)備無關(guān)的繪制。設(shè)備上下文可用于繪制到屏幕、打印機(jī)或者圖元文件。.net不需要了這個(gè) 上下文對(duì)象,他有了一個(gè).netframework 就不需要這個(gè)屁玩意了。
//功能 設(shè)置圖片位置1
//入?yún)?設(shè)置方法 橫縱坐標(biāo)
void SetPos(int istyle,int x,int y);
//功能 圖片顯示
//入?yún)?圖片顯示方式
void Draw(DWORD dwRop);
//功能 圖片縮放顯示
//入?yún)?橫縱方向縮放比例
void Stretch(int x,int y);
//功能 圖片縮放顯示
//入?yún)?橫縱方向縮放比例 縮放圖像ID(縱向第幾個(gè))
void Stretch(int x,int y,int id);
//功能 在指定位置顯示圖片
//入?yún)?橫縱坐標(biāo)
void Show(int x,int y);
//功能 橫向居中顯示圖片
//入?yún)?縱坐標(biāo)
void ShowCenter(int y);
//功能 將某個(gè)圖片平鋪在一個(gè)區(qū)域內(nèi)
//入?yún)?左上右下邊界的坐標(biāo) 圖片ID(橫向第幾個(gè))
void ShowLoop(int left,int top,int right,int bottom,int iframe);
//功能 不規(guī)則圖片顯示
//入?yún)?橫縱坐標(biāo) 圖片ID(橫向第幾個(gè))
void ShowNoBack(int x,int y,int iFrame);
//功能 不規(guī)則圖片橫向平鋪
//入?yún)?橫縱坐標(biāo) 圖片ID(橫向第幾個(gè)) 平鋪個(gè)數(shù)
void ShowNoBackLoop(int x,int y,int iFrame,int iNum);
//動(dòng)畫播放
//功能 自動(dòng)播放該圖片的所有幀,函數(shù)沒有實(shí)現(xiàn),但以后肯定要用:)
//入?yún)?無
void ShowAni();
//功能 設(shè)置動(dòng)畫坐標(biāo)
//入?yún)?橫縱坐標(biāo)
void SetAni(int x,int y);
成員數(shù)據(jù)
//跟蹤打印類
// FILEREPORT f;
//圖像句柄
HBITMAP hBm;
//按照行列平均分成幾個(gè)
int inum;
int jnum;
//按行列分割后,每個(gè)圖片的寬高(顯然各個(gè)圖片大小一致,派生后,這里的寬高已沒有使用意義)
int width;
int height;
//屏幕寬高
int screenwidth;
int screenheight;
//要繪制圖片的dc
HDC hdcdest;
//用來選擇圖片的臨時(shí)dc
HDC hdcsrc;
//當(dāng)前位置
int xpos;
int ypos;
//是否處于動(dòng)畫播放中
int iStartAni;
這個(gè)基類的部分函數(shù)和變量,在這個(gè)游戲中沒有使用,是從前幾個(gè)游戲中保留下來的,所以看起來有些零亂.這個(gè)游戲的主要圖像功能,由它的派生類完成.由于基類封裝了物理層信息(dc和句柄),派生類的編寫就容易一些,可以讓我專注于邏輯含義.
基類的函數(shù)實(shí)現(xiàn)上,很簡單,主要是以下幾點(diǎn):
1.圖片初始化:
//根據(jù)程序?qū)嵗浔?位圖文件的資源ID,導(dǎo)入該位圖,得到位圖句柄
hBm=LoadBitmap(hInstance,MAKEINTRESOURCE(iResource));
//獲取該位圖文件的相關(guān)信息
GetObject(hBm,sizeof(BITMAP),&bm);
//根據(jù)橫縱方向的圖片個(gè)數(shù),計(jì)算出每個(gè)圖片的寬高(對(duì)于超級(jí)瑪麗,寬高信息由派生類處理)
width=bm.bmWidth/inum;
height=bm.bmHeight/jnum;
下面再來說一說 游戲背景 類MYBKSKY
類說明:這是一個(gè)專門處理游戲背景的類。在橫版游戲或射擊游戲中,都有一個(gè)背景畫面,如山、天空、云、星空等等。這些圖片一般只有1到2倍屏幕寬度,然后像一個(gè)卷軸一樣循環(huán)移動(dòng),連成一片,感覺上像一張很長的圖片。這個(gè)類就是專門處理這個(gè)背景的。在超級(jí)瑪麗增強(qiáng)版中,主要關(guān)卡是3關(guān),各有一張背景圖片;從水管進(jìn)去,有兩關(guān),都用一張全黑圖片。共四張圖。這四張圖大小一致,縱向排列在一個(gè)位圖文件中。MYBKSKY這個(gè)類,派生于MYBITMAP。由于背景圖片只需要完成循環(huán)移動(dòng)的效果,只需要實(shí)現(xiàn)一個(gè)功能,而無需關(guān)心其他任何問題(例如句柄、dc)。編碼起來很簡單,再次反映出面向?qū)ο蟮暮锰帯?br /> 實(shí)現(xiàn)的原理:
怎樣讓一張圖片像卷軸一樣不停移動(dòng)呢?很簡單,假設(shè)有一條垂直分割線,把圖片分成左右兩部分。先顯示右邊部分,再把左邊部分接到圖片末尾。不停移動(dòng)向右移動(dòng)分割線,圖片就會(huì)循環(huán)地顯示。
成員函數(shù)功能列表:
class MYBKSKY:public MYBITMAP
{
public:
MYBKSKY();
~MYBKSKY();--析構(gòu)函數(shù),怎么樣 C++中,你有了資源 自己釋放。我們.net 有一個(gè)終結(jié)者函數(shù)也有點(diǎn)析構(gòu)函數(shù)的味道,但不一定自己釋放資源嗎。
//show
//功能 顯示一個(gè)背景.
//入?yún)?無
void DrawRoll(); //循環(huán)補(bǔ)空
//功能 顯示一個(gè)背景,并縮放圖片
//入?yún)?橫縱方向縮放比例
void DrawRollStretch(int x,int y);
//功能 指定顯示某一個(gè)背景,并縮放圖片,游戲中用的就是這個(gè)函數(shù)
//入?yún)?橫縱方向縮放比例 背景圖片ID(縱向第幾個(gè))
void DrawRollStretch(int x,int y,int id);--進(jìn)行中橫坐標(biāo)的操作
//功能 設(shè)置圖片位置
//入?yún)?新的橫縱坐標(biāo)
void MoveTo(int x,int y);
//功能 循環(huán)移動(dòng)分割線
//入?yún)?分割線移動(dòng)的距離
void MoveRoll(int x);
//data
//分割線橫坐標(biāo)
int xseparate;
};
看一看圖片顯示 類MYANIOBJ
類說明:這個(gè)類負(fù)責(zé)游戲中的圖片顯示。菜單背景、通關(guān)和游戲結(jié)束的提示圖片,由MYBITMAP處理(大小一致的靜態(tài)圖片)。游戲背景由MYBKSKY處理。其余圖片,也就是游戲過程中的所有圖片,都是MYANIOBJ處理。
技術(shù)原理:游戲中的圖片大小不一致,具體在超級(jí)瑪麗中,可以分成兩類:矩形圖片和不規(guī)則圖片。在位圖文件中,都是縱向排列各個(gè)圖片,橫向排列各幀。用兩個(gè)數(shù)組存儲(chǔ)各個(gè)圖片的寬和高。為了方便顯示某一個(gè)圖片,用一個(gè)數(shù)組存儲(chǔ)各個(gè)圖片的縱坐標(biāo)(即位圖文件中左上角的位置)。使用時(shí),由邏輯層指定“哪個(gè)圖片”的“哪一幀”,顯示在“什么位置”。這樣圖片的顯示功能就實(shí)現(xiàn)了。
成員函數(shù)功能列表:
class MYANIOBJ:public MYBITMAP
{
public:
MYANIOBJ();
~MYANIOBJ();
//init list
//功能 初始化寬度數(shù)組 高度數(shù)組 縱坐標(biāo)數(shù)組 是否有黑白圖
//入?yún)?寬度數(shù)組地址 高度數(shù)組地址 圖片數(shù)量 是否有黑白圖(0 沒有, 1 有)
//(圖片縱坐標(biāo)信息由函數(shù)計(jì)算得出)
void InitAniList(int *pw,int *ph,int inum,int ismask);
//功能 初始化一些特殊的位圖,例如各圖片大小一致,或者有其他規(guī)律
//入?yún)?初始化方式 參數(shù)1 參數(shù)2
//(留作以后擴(kuò)展, 目的是為了省去寬高數(shù)組的麻煩)
void InitAniList(int style,int a,int b);
//show
//功能 顯示圖片(不規(guī)則圖片)
//入?yún)?橫縱坐標(biāo)(要顯示的位置) 圖片id(縱向第幾個(gè)), 圖片幀(橫向第幾個(gè))
void DrawItem(int x,int y,int id,int iframe);
//功能 顯示圖片(矩形圖片)
//入?yún)?橫縱坐標(biāo)(要顯示的位置) 圖片id(縱向第幾個(gè)), 圖片幀(橫向第幾個(gè))
void DrawItemNoMask(int x,int y,int id,int iframe);
//功能 指定寬度, 顯示圖片的一部分(矩形圖片)
//入?yún)?橫縱坐標(biāo)(要顯示的位置) 圖片id(縱向第幾個(gè)), 顯示寬度 圖片幀(橫向第幾個(gè))
void DrawItemNoMaskWidth(int x,int y,int id,int w,int iframe);
//功能 播放一個(gè)動(dòng)畫 即循環(huán)顯示各幀
//入?yún)?橫縱坐標(biāo)(要顯示的位置) 圖片id(縱向第幾個(gè))
void PlayItem(int x,int y,int id);
//寬度數(shù)組 最多支持20個(gè)圖片
int wlist[20];
//高度數(shù)組 最多支持20個(gè)圖片
int hlist[20];
//縱坐標(biāo)數(shù)組 最多支持20個(gè)圖片
int ylist[20];
//動(dòng)畫播放時(shí)的當(dāng)前幀
int iframeplay;
};
看一看 魔法攻擊 類MYANIMAGIC
類說明:玩家有兩種攻擊方式:普通攻擊(子彈),魔法攻擊(旋風(fēng))。這個(gè)類是專門處理旋風(fēng)的。我最初的想法是用一些特殊的bitblt方法特效,例如或、與、異或。試了幾次,都失敗了。最后只能用“先與后或”的老方法。這個(gè)類可看成MYANIOBJ的一個(gè)簡化版,只支持不規(guī)則圖片的顯示。
成員函數(shù)功能列表:
class MYANIMAGIC:public MYBITMAP
{
public:
MYANIMAGIC();
~MYANIMAGIC();
//init list
//功能 初始化寬度數(shù)組 高度數(shù)組 縱坐標(biāo)數(shù)組(必須有黑白圖)
//入?yún)?寬度數(shù)組地址 高度數(shù)組地址 圖片數(shù)量
//(圖片縱坐標(biāo)信息由函數(shù)計(jì)算得出)
void InitAniList(int *pw,int *ph,int inum);
//功能 設(shè)置dc
//入?yún)?顯示dc 臨時(shí)dc(用于圖片句柄選擇) 臨時(shí)dc(用于特效實(shí)現(xiàn))
void SetDevice(HDC hdest,HDC hsrc,HDC htemp);
//show
//功能 顯示某個(gè)圖片的某幀
//入?yún)?橫縱坐標(biāo)(顯示位置) 圖片id(縱向第幾個(gè)) 幀(橫向第幾個(gè))
void DrawItem(int x,int y,int id,int iframe);
//寬度數(shù)組
int wlist[20];
//高度數(shù)組
int hlist[20];
//縱坐標(biāo)數(shù)組
int ylist[20];
//用于特效的臨時(shí)dc, 功能沒有實(shí)現(xiàn)L
HDC hdctemp;
};
這就是我的一些架構(gòu)
相關(guān)文章
Opencv檢測多個(gè)圓形(霍夫圓檢測,輪廓面積篩選)
本文主要介紹了Opencv檢測多個(gè)圓形(霍夫圓檢測,輪廓面積篩選),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08C語言中strcpy和strcat的使用和模擬實(shí)現(xiàn)
strcpy()?函數(shù)是?C語言中一個(gè)非常重要的字符串處理函數(shù),其功能是將一個(gè)字符串復(fù)制到另一個(gè)字符串中,strcat函數(shù)可以將一個(gè)字符串拼接到另一個(gè)字符串的末尾,本文給大家介紹了C語言中strcpy和strcat的使用和模擬實(shí)現(xiàn),需要的朋友可以參考下2024-03-03C語言字符串函數(shù)與內(nèi)存函數(shù)精講
這篇文章主要介紹一些c語言中常用字符串函數(shù)和內(nèi)存函數(shù)的使用,并且為了幫助讀者理解和使用,也都模擬實(shí)現(xiàn)了他們的代碼,需要的朋友可以參考一下2022-04-04探討C++中不能聲明為虛函數(shù)的有哪些函數(shù)
下面小編就為大家?guī)硪黄接慍++中不能聲明為虛函數(shù)的有哪些函數(shù)。希望對(duì)大家有所幫助。一起跟隨小編過來看看吧,祝大家游戲愉快哦2017-01-01C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷
這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷的相關(guān)資料,需要的朋友可以參考下2017-06-06Cocos2d-x保存用戶游戲數(shù)據(jù)之XML文件是否存在問題判斷方法
這篇文章主要介紹了Cocos2d-x保存用戶游戲數(shù)據(jù)之XML文件是否存在問題判斷方法,請注意代碼中包含大量注釋,需要的朋友可以參考下2014-09-09