一个学期的软件工程课程终于结束了。个人项目和结对项目相关信息可以参考之前的博客,下面主要讲的是团队项目的总结。
我们的团队项目是一个2D像素风格的RPG网络游戏,我被分配到的任务主要是服务端的与怪物相关的内容。
我们创建了monster类,其中包括怪物的id、经验值、名字、血量、位置、图片等信息,并设有初始化以及移动、攻击AI等函数方法。代码如下:
class monster { public: int id; int killid; int getexp; char *name; double hp; double wx, wy; float damage; bool canfight; CImage *p; char buffer[30]; monster(); void initMap(CImage *i); void initPosition(); bool fight(double damage, int id); bool moveup(double d); bool movedown(double d); bool moveright(double d); bool moveleft(double d); void fightup(int pid); void fightdown(int pid); void fightleft(int pid); void fightright(int pid); void fightAI(); void moveAI(); };
具体实现如下:
怪物被打的话会运行下面的函数:
bool monster::fight(double damage, int id) { hp -= damage; if (hp <= 0) { hp = 10; initPosition(); killid = id; } //Send to 所有玩家 SendMonsterInformation(this); return true; }
怪物移动的函数(以向上移动为例,其他三个方向类似):
bool monster::moveup(double d) { if (p->GetPixel(wx*p->GetWidth() / mapmax, p->GetHeight() - (wy+d)*p->GetHeight() / mapmax) == 0){ return false; } else { wy += d; return true; } }
下面是怪物移动的AI:
void monster::moveAI() { double dx, dy; int pid; if (GetnearPlayer(id, &pid, &dx, &dy) > 0.2) { int moveto = random(8); switch (moveto) { case(0) : if (movedown(0.01)) { MonsterSend(id); } break; case(1) : if (moveup(0.01)) { MonsterSend(id); } break; case(2) : if (moveleft(0.01)) { MonsterSend(id); } break; case(3) : if (moveright(0.01)) { MonsterSend(id); } break; default: break; } } else { if (abs(dx) >=abs(dy)) { if (dx < -0.01) { if (moveleft(0.01)) { MonsterSend(id); } else { if (dy < -0.01) { if (movedown(0.01)) { MonsterSend(id); } } else if (dy >0.01) { if (moveup(0.01)) { MonsterSend(id); } } } } else if (dx > 0.01) { if (moveright(0.01)) { MonsterSend(id); } else { if (dy < -0.01) { if (movedown(0.01)) { MonsterSend(id); } } else if (dy >0.01) { if (moveup(0.01)) { MonsterSend(id); } } } } } else{ if (dy < -0.01) { if (movedown(0.01)) { MonsterSend(id); } else { if (dx < -0.01) { if (moveleft(0.01)) { MonsterSend(id); } } else if (dx > 0.01) { if (moveright(0.01)) { MonsterSend(id); } } } } else if (dy >0.01) { if (moveup(0.01)) { MonsterSend(id); } else { if (dx < -0.01) { if (moveleft(0.01)) { MonsterSend(id); } } else if (dx > 0.01) { if (moveright(0.01)) { MonsterSend(id); } } } } } } }
思路就是判断怪物周围(一定距离)有没有玩家,没有的话,怪物随机移动,这是用一个随机函数来实现的(random(8));而当周围有玩家了,就判断怪物与该玩家之间的dx值与dy值,dx>dy就需要横向移动,反之需要纵向移动,正负值可以判断该向哪个方向移动。
下面是怪物打架的函数(依然以向上为例):
void monster::fightup(int pid){ list<client>::iterator it3 = CL1.begin(); for (int i = 0; i < pid;i++){ it3++; } it3->p.hp -= damage; if (it3->p.hp <= 0) { it3->p.movenum = 0; it3->p.hp = it3->p.maxhp; it3->p.initPosition(); } }
而怪物打人的AI就相对容易:
void monster::fightAI() { double dx, dy; int pid; if (GetnearPlayer(id, &pid, &dx, &dy) < 0.06) { canfight = true; if (dx > 0 && (dy / dx) <= 1 && (dy / dx) >= -1) { //attack right fightright(pid); MonsterSend(id); } else if (dx < 0 && (dy / dx) >= -1 && (dy / dx) <= 1) { //attack left fightleft(pid); MonsterSend(id); } else if (dy > 0 && ((dy / dx) < -1 || (dy / dx) > 1)) { //attack up fightup(pid); MonsterSend(id); } else if (dy < 0 && ((dy / dx) < -1 || (dy / dx) > 1)) { //attack down fightdown(pid); MonsterSend(id); } } }
只要玩家与怪物的距离相距小于等于怪物攻击范围,怪物就开始攻击,玩家在哪个方向(根据dx与dy之间的关系),就向哪个方向攻击。
以上大概就是我在我们团队项目中负责的内容。
关于这门课程,我的感觉是没什么收获的,因为感觉上课老师只是在讲故事。但当我准备自己编一些程序的时候,我就意识到了这门课的重要性。我不觉得我上课听得有多认真,但我在构思我想要实现的程序的时候,我就想起了软件工程课上讲过的那些“故事”。我计划自己完成一款游戏,我首先想到的是写写类图,画个用例图,设计设计用户界面,再想想数据库设计之类的。对于一个软件的整体思路一下子就把握住了,这完全不同于之前的一上来就闷头写代码,写到最后也没有注释,不知道哪段是什么。所以这么一想,感觉连想编程这个意愿本身也是起源于软工课程吧。