08年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大学生活。此系列是对四年专业课程学习的回顾,索引参见:http://blog.csdn.net/xiaowei_cqu/article/details/7747205
这是我们学习程序设计的第一课。我也在这门课上第一次接触程语言、写代码。我们以影印版的《C++ Program Design : An Introduction to Programming and Object-Oriented Design》为教材。
现在想来那段“入门”的经历真是痛苦不堪,很多概念难以理解,就只能一点点把书中的代码一遍遍的敲。但每次跑出一点小东西也都觉着兴奋到不行。大一末的时候有个“大”的课程设计:两人一组编写一个小游戏。我和小琦一组,写了一个比较简略的闯关游戏,这次经历之后才真的对编程有了“入门”的感觉。
enum Floor{FLoor1=0,Floor2,Floor3,Floor4};
class Player {
public:
//constructor
Player(SimpleWindow &w);
public:
//inspectors
SimpleWindow& GetWindow() const;//得到玩家所在窗口
Position GetPosition() const; //得到玩家当前位置
Direction GetDirection() const; //得到玩家当前的方向
BitMap& GetBmp(const Direction &d,int i); //得到玩家在相应的方向及步子上位图
const BitMap& GetBmp(const Direction &d,int i) const;
Floor GetFloor()const; //得到玩家当前所在层数
bool IsDying(); //检查玩家是否死掉
bool AtRightEdge() const; //检查玩家是否走到窗口边缘
bool AtLeftEdge() const;
//Facilitators
void Create(); //创建玩家(即将玩家“放”在游戏窗口中)
void Kill(); //“杀死”玩家(从窗口中擦掉)
void Move(); //使玩家在键盘操控下做相应的移动
void Fire(); //发射子弹
void OKUp(); //设置玩家是否可以在层之间跳跃
void OKDown();
void CannotUpDown();
//mutators
void SetPosition(const Position &p); //设置玩家当前所有位图的位置
void SetFloor(Floor &f); //玩家跳跃之后改变层的数据成员
void SetDirection(const Direction &d); //设置玩家当前的方向
//data member
vector bullets; /****************************************/
//方便GameController中检查子弹和敌人 //
//状况,所以放在public域中,设置为可见 //
/****************************************/
private:
//facilities
void Draw();
void Erase(); /****************************************************/
//用户不直接操纵图片,而是通过调用 Creat() 和 Kill() //
//所以定义为 private //
/*****************************************************/
// Data members
SimpleWindow &Window;
vector > Bmp;
Direction CurrentDirection;
Position CurrentPosition;
bool bUpOk;
bool bDownOk;
Floor CurrentFloor;//当前所处的层
//游戏中得到的不是类Layer的层,而是有枚举定义的Floor的层
//因为Layer继承自Map关键是一张图,没有什么特殊的属性
//而枚举定义的Layer有初始化的作用,是每层有了自己的值
//而相应GameController构造函数中分配的每层的敌人和篮球框Gap //的也都对应与向量中有自己的数值,所以在游戏控制器的一些函数中
//(如TestGap、TestEnemy)只检查当前层的篮球框和敌人,
//避免了跳跃效果的意外实现,也提高了检查的效率
int Steps; //玩家自游戏开始所走的步数
//用以连续轮流切换玩家位图,实现走动的效果
};
/***********************************************************/
// enemy.h //
// //
//类Enemy的声明与定义 //
//即游戏中的敌人,敌人在各自的Layer中不停的走动 //
/***********************************************************/
#ifndef ENEMY_H
#define ENEMY_H
const int EnemyBitMaps=2;
enum EnemyStatus {Alive,Dead,DeadAlready};
//DeadAlready 是保证enemy 不会重复被 Kill
class Enemy{
public:
//constructor
Enemy(SimpleWindow &W,const Position &p1=(0,0),const Position &p2=(0,0),double h=1 );
//需要提供一个窗口,敌人移动范围,以及每次位移大小(速度)
public:
//inspectors
SimpleWindow& GetWindow() const; //得到敌人所在窗口
Position GetPosition() const; //得到当前敌人位置
Direction GetDirection() const; //得到当前敌人的方向
double GetHorizMovement() const; //得到每次移动的水平位移
BitMap &GetBmp(const Direction &d); //得到相应方向位图
const BitMap &GetBmp(const Direction &d) const; //得到当前敌人的状态
EnemyStatus GetStatus()const;
//mutators
void SetWindow(SimpleWindow &W); //设置敌人窗口
void SetDirection(const Direction &d); //设置敌人的方向
void SetPosition(const Position &p); //设置敌人的位置
void SetStatus(EnemyStatus s); //更改敌人的状态(在后面你会看到他的重要性)
void SetHorizMovement(double h); //设置每次水平位移的大小以更改移动速度
void SetP1P2(const Position &pp1,const Position &pp2); //设置敌人移动的范围
//Facilitators
void Create(); //创建敌人(画在游戏窗口中)
void Kill(); //杀死敌人(从当前窗口擦除)
void Move(); //使敌人在timer下不停地移动
void Draw(); //画出当前位图
void Erase(); //擦掉
Position NewPosition() const; //设置下一刻敌人的方向
void ChangeDirection(); //检查如果超出移动范围,则更改方向
private:
//data members
SimpleWindow& Window;
vector Bmp;
double HorizMovement;
Direction CurrentDirection;
Position CurrentPosition;
Position P1,P2;
EnemyStatus CurrenStatus;
};
#endif
/***************************************/
//derive class Enemy_1 //
//分别为第一关、第二关的敌人 //
//均派生在类Enemy 只是位图不同,速度不同//
/***************************************/
#ifndef ENEMY_1_H
#define ENEMY_1_H
#include "enemy.h"
class Enemy_1 : public Enemy{
public:
Enemy_1(SimpleWindow &W,const Position &p1=(0,0),
const Position &p2=(0,0) ,double h=0.5);
};
#endif
/********************************/
//derive class Enemy_2 //
/********************************/
#ifndef ENEMY_2_H
#define ENEMY_2_H
#include"enemy.h"
class Enemy_2 : public Enemy{
public:
Enemy_2(SimpleWindow &W, const Position &p1=(0,0),
const Position &p2=(0,0),double h=0.8 );
};
#endif
/***************************************************/
//derive class Bullet
//即游戏中樱木发射的子弹 //
//自己在一个方向上水平自动移动,类似敌人 //
/***************************************************/
#ifndef BULLET_H
#define BULLET_H
#include "enemy.h"
class Bullet : public Enemy{
public :
Bullet(SimpleWindow &W,Direction d ,
const Position &p1=(0,0), const Position &p2=(0,0));
bool AtRightEdge() const; //子弹走出移动范围之后应被消灭
//所以增加相应的判断函数返回布尔值
bool AtLeftEdge() const;
void B_Creat(); //制造子弹
};
#endif
/***********************************************************/
// GameCoroller.h //
// 游戏控制台,控制检查游戏中各个角色的状态以及不同 //
//角色之间的交互,是游戏中最重要最也最操劳的部分 //
/***********************************************************/
#ifndef GAMECONTROL_H
#define GAMECONTROL_H
enum GameLevel { One, Second, Done };
class GameController {
public:
//constructor
GameController(const string &Title = "终结者(樱木花道版)",
const Position &WinPosition=Position(2.0,2.0),
const float WinLength =16, const float WinHeight = 13);
//标题、位置、窗口宽、高 用以初始化游戏窗口
// destructor
~GameController();
//inspectors
SimpleWindow *GetWindow();
GameLevel CurrentLevel() const; //检查器 分别得到窗口和当前所在关卡
//facilitators
void Play(const GameLevel Level); //设置游戏所在关卡
void TestGap(Player* player,vector gap);
//检查游戏中玩家是否走到篮筐下(如果在篮筐下可以跳跃,走出篮筐不可以)
void TestBullet(vector e,vector b);
void TestBullet(vector e,vector b);
//检查游戏中的子弹是否达到敌人,如果碰到则将子弹和敌人都从窗口中擦掉。
bool TestPlayer(Player* player,vector e);
bool TestPlayer(Player* player,vector e);
//检查游戏中玩家是否被敌人捉到(如果敌人碰到玩家,游戏失败)
int TimerTick();
//是TimerCallback调用的函数
//游戏窗口中玩家,敌人,子弹的走到效果都是由他实现的游戏关卡跳跃也是在这里实现的。
//但因为这个函数不断被调用,而我们想在第一关通过之后加一个小小的提示(Message)
//结果就是Message不段被弹出,所以用了一个全局变量PlayOne,
//保证提示的函数只执行一次,这个平白出来的“魔数”也许增加了代码阅读的困难
private:
//data members
SimpleWindow *GameWindow;
GameLevel Level;
//游戏中各种角色为GameController控制,
//所以作为控制台的数据成员包含在GameController的属性中
Player *player;
vector gaps;
vector layers;
vector enemy1;
vector enemy2;
};
#endif
/********************************************************************/
//resources.h //
// //
//游戏结束是显示界面的资源 //
//本想和 welreources.h 放在一起,因为其窗口都是独立于游戏窗口的 //
//并不作为GameControl的数据成员,而是一全局变量使用 //
//但放在一起可能是因为game.cpp和gamecontroll.cpp都要包含,会出错 //
/*********************************************************************/
#ifndef WEL_H
#define WEL_H
//包含在game.cpp中相当于全局变量
//保证函数 int TimerCallBack(void);
//和 int MouseClick(const Position &MousePosition);可以方便的使用
SimpleWindow End("终结者(樱木花道版)",15.0,12.0,Position(2.0,2.0));
BitMap WellDone(End);
BitMap Quit(End);
BitMap Fail(End);
void SetWindows(){
Fail.Load("bmp\\fail.bmp");
assert(Fail.GetStatus()==BitMapOkay);
WellDone.Load("bmp\\done.bmp");
assert(WellDone.GetStatus()==BitMapOkay);
double width=Fail.GetWidth();
double height=Fail.GetHeight();
Quit.Load("bmp\\quit.bmp");
Quit.SetPosition(Position(0.6*width,0.8*height));
assert(Quit.GetStatus()==BitMapOkay);
}
int MouseClickEnd(const Position& MousePosition){
if(Quit.IsInside(MousePosition)){
End.Close();
}
return 1;
}
#endif
/*******************************************************/
//welresources.h //
//并不是一个单独的类,是玩家开始进入游戏时的欢迎界面 //
//放在 *.h文件包含在 game.cpp中作为全局变量 //
/*******************************************************/
#ifndef WELCOME_H
#define WELCOME_H
#include "assert.h"
SimpleWindow Welcome("终结者(樱木花道版)",15.0,12.0,Position(2.0,2.0));
BitMap PlayButton(Welcome);
BitMap InstructionButton(Welcome);
BitMap Instruction(Welcome);
void SetWelcomeWindows(){
BitMap WelcomeBmp(Welcome);
WelcomeBmp.SetPosition(Position(0,0));
WelcomeBmp.Load("bmp\\hello.bmp");
WelcomeBmp.Draw();
assert(WelcomeBmp.GetStatus()==BitMapOkay);
double width=WelcomeBmp.GetWidth();
double height=WelcomeBmp.GetHeight();
PlayButton.SetPosition(Position(0.1*width,0.85*height));
PlayButton.Load("bmp\\play.bmp");
assert(PlayButton.GetStatus()==BitMapOkay);
Instruction.SetPosition(Position(0,0));
Instruction.Load("bmp\\in.bmp");
assert(Instruction.GetStatus()==BitMapOkay);
InstructionButton.SetPosition(Position(0.1*width,0.35*height));
InstructionButton.Load("bmp\\inbutton.bmp");
assert(InstructionButton.GetStatus()==BitMapOkay);
InstructionButton.Draw();
}
#endif
通过大一的C++语言学习后,我们小组完成了第一个项目编程—终结者(樱木花道版)。