基于opengl的2d机器人双人格斗游戏

  • Post author:
  • Post category:其他




  1. 2D 项目简介

项目的创意设想、实现功能、项目意义(200字左右)

作品代表图


项目名:

机器人双人格斗游戏


项目的创意设想:

当前ai大火,机器人也是日常生活中的一个热点,自己在小学乃至高中也经常玩格斗游戏。曾经也想过格斗游戏是怎么做的,可是那时候条件有限,而且也没有编程基础。这个想法就一直留到了大学。到大三学习计算机图形学,也有了一定的编程基础,认为这个格斗游戏可以自己完成了。便开始动手,经过几天的努力,终于把这个游戏实现了。


实现功能:

画了机器人1(乌巢之子),机器人2(关山之月)实现其的技能有:

  1. 上下左右移动:实现了平移
  2. 弹跳:使用了重力加速度实现了起跳落下的算法,
  3. 眼睛发射镭射光线:实现了平移
  4. 肚载大炮发射:实现了平移
  5. 手臂可以伸长:实现了平移
  6. 被炮弹击中会倒退:使用了旋转变换之类函数,实现了旋转
  7. 法天相地(放大):实现了放大 – 经过一段时间也会缩放到原来的大小

  1. 计时功能:使用了时间回调函数
  2. 使用了win32API函数,可以插入声音


项目意义:

自己在开始做这个游戏的时候,也上网百度看是否有类似的格斗游戏,这类型指的是使用opengl库制作的2D无游戏引擎的双人格斗游戏,发现找不到类似的游戏,可以说是网上几乎没人做过类似的2D无游戏引擎的双人格斗游戏。可以说这个游戏填补了当类游戏的空白,也可以给后来者加以参考。


作品代表图:



  1. 编程环境(电脑硬件、操作系统和VS平台)说明

  2. 电脑硬件:thinkpad x250,

    cpu:i3

    内存:4g

    操作系统:win10

    Vs:vs2017




  3. 程序操作说明



  4. 操作如下图:



    编程环境(电脑硬件、操作系统和VS平台)说明

电脑硬件:thinkpad x250,

cpu:i3

内存:4g

操作系统:win10

Vs:vs2017




  1. 程序操作说明



操作如下图:

按键b:开始游戏

对角色1(乌巢之子)进行操作有:

1、wsad:上下左右移动

2、z:长拳攻击

3、x:从眼部发射镭射光线

4、c:肚载大炮,肚子发射大炮,攻击力强于镭射光线

5、e:法天相地,变大

6、r:弹跳

对角色2(关山之月)进行操作有:

  1. ikjl:上下左右移动
  2. n:长拳攻击
  3. m:镭射光线
  4. O:肚载大炮,肚子发射大炮,攻击力强于镭射光线
  5. U:法天相地(变大)
  6. P:弹跳

当两者的某一方血条为0时,游戏结束,效果如下:



  1. 程序实现

  1. 创意详细说明:

    1. 算法类、模拟类: 算法说明,想要实现的效果说明


1、注册这几个函数,才可以使窗口不断回画,并计时,也是基于这几个注册函数才仿佛实现了同步,而不必使用多线程。


glutTimerFunc(1000, mytime, 10);


//注册闲时函数


glutDisplayFunc(&Display);


//在程序运行时是自动调用的,即程序会自动调用display函数重绘窗口


glutMainLoop();


//进入事件处理循环


2、使用了重力加速度公式设计的弹跳-起跳落下的模拟


在机器人1里写了一个弹跳函数(机器人2类似)


类成员:


jumpTime = 0;


jflag = 0;


h = 5.0;


函数


void


Robot1


::skillr()


//跳高


{


jumpTime++;


float


g = 0.00005;


if


(jflag == 1)


{


float


addh = 1.0 / 2.0 * g * jumpTime * jumpTime;


this


->y += addh;


this


->h -= addh;


if


(


this


->h <= 0)


{


jflag = 2;


jumpTime = 0;


}


}


else


if


(jflag == 2)


{


float


addh = 1.0 / 2.0 * g * jumpTime * jumpTime;


this


->y -= addh;


this


->h += addh;


if


(


this


->h >= 5.0)


{


jflag = 0;


jumpTime = 0;


}


}


}


主页面交互(键盘点击):


case


‘R’


:


case


‘r’


:


//robot1跳高


if


(rb1->jflag == 0)


{


rb1->jflag = 1;


rb1->skillr();


}


break


;


  1. 炸弹类的设计:设计炸弹类首先要知道炸弹的坐标x,y,因为这个才可以在界面上绘出炸弹,炸弹的朝向goAhead,有了这个才可以知道炸弹的移动方向,炸弹生命live是否存活,存活才画此炸弹,


Who(谁的炸弹),因为这个炸弹类不止一个人使用,robot1和robot2都使用,zy第三参数,这个参数的作用是记录发送炸弹的机器人的中心坐标


注:在这里说明一下,因为当前游戏是使用2D制作,两个机器人在一条有长有宽的道路上打斗,如果只有长,就只要直接有炸弹的x,y和敌方机器人作边界检测就行了,可是这道路有宽,就要设计看炸弹射出的轨迹是否与敌人在一条轴线上,所以我用zy保存发出炸弹机器人的y坐标,引入了第三个参数,这时就可以把这个界面看出了三维,到时再使用敌方机器人的x,y坐标和己方炸弹的x,zy作边界检测,就可以看炸弹是否击中敌人了。


#pragma


once


#pragma


once


#include


<glut.h>


//robot1子弹类


class


myBullet


{


public


:


float


x;


float


y;


bool


live;


int


goAhead;


//子弹朝向


float


mBsize;


//子弹大小


int


who;


//谁的子弹


float


zy;


//第三参数


float


zx;


//第四参数


myBullet();


~myBullet();


void


init(


float


x


,


float


y


,


float


size


,


int


who


,


float


zx


,


float


zy


);


void


die();


};


void


drawMyBullet(


float


x


,


float


y


,


int


goAhead


,


int


size


,


int


mBsize


)


{


//绘制点


glColor3f(1, 0, 0);


//设置蓝色绘制颜色


//glPointSize(2.0);//点的像素大小,默认值为1.0


if


(


goAhead


== 0)


{


glRectf(


x


– 1 *


size


,


y


– 0.05 *


size


*


mBsize


,


x


,


y


+ 0.05 *


size


*


mBsize


);


}


else


if


(


goAhead


== 1)


{


glRectf(


x


,


y


– 0.05 *


size


*


mBsize


,


x


+ 1 *


size


,


y


+ 0.05 *


size


*


mBsize


);


}


//glBegin(GL_POINTS);


//glVertex2f(x, y);


//glVertex2f(x+1, y+0.1);


//glEnd();


}


myBullet


::myBullet()


{


x = -23;


y = 23;


live =


false


;


goAhead = -1;


mBsize = 1;


who = -1;


zx = -99;


zy = -99;


}


void


myBullet


::init(


float


x


,


float


y


,


float


size


,


int


who


,


float


zx


,


float


zy


)


{


this


->x =


x


;


this


->y =


y


;


this


->mBsize =


size


;


live =


true


;


this


->who =


who


;


this


->zx =


zx


;


this


->zy =


zy


;


}


myBullet


::~myBullet()


{


}


void


myBullet


::die()


{


live =


false


;


}


炸弹是否击中敌人的边界检测函数:


//子弹边界检测函数


void


checkBulletSide()


{


for


(


int


i = 0; i <


MAXRB1BULLET


; i++)


{


if


(mb[i].live ==


true


)


{


if


(mb[i].x > -22.0 && mb[i].x < 22.0 && mb[i].y > -12.0 && mb[i].y < 12.0)


{


if


(mb[i].who == 1)


//机器人1的子弹


{


if


(abs(mb[i].x – rb2->x) < 0.6 * rb2->size && abs(mb[i].zy – rb2->y) < 0.7 * rb2->size)


//机器人1的子弹击中机器人2


{


for


(


int


j = 0; j <


MAXBOMB


; j++)


{


if


(bomb[j].live ==


false


)


{


bomb[j].init(mb[i].x, mb[i].y, mb[i].mBsize);


rb2->valueOfLife -= 20 * mb[i].mBsize;


if


(mb[i].mBsize == 1)


{


PlaySound


(


L”midb.wav”


,


NULL


,


SND_FILENAME


|


SND_ASYNC


);


//PlaySound(L”background.wav”, NULL, SND_FILENAME | SND_ASYNC);


}


else


{


PlaySound


(


L”bigb.wav”


,


NULL


,


SND_FILENAME


|


SND_ASYNC


);


//PlaySound(L”background.wav”, NULL, SND_FILENAME | SND_ASYNC);


}


break


;


}


}


if


(mb[i].goAhead == 0)


//子弹朝向左


{


//机器人robot2被左击中


rb2->beated = -1;


}


else


if


(mb[i].goAhead == 1)


//子弹朝向右


{


//机器人robot2被右击中


rb2->beated = 1;


}


mb[i].die();


}


}


else


if


(mb[i].who == 2)


//机器人2的子弹


{


if


(abs(mb[i].x – rb1->x) < 0.6 * rb1->size && abs(mb[i].zy – rb1->y) < 0.7 * rb1->size)


//机器人2的子弹击中机器人1


{


for


(


int


j = 0; j <


MAXBOMB


; j++)


{


if


(bomb[j].live ==


false


)


{


bomb[j].init(mb[i].x, mb[i].y, mb[i].mBsize);


rb1->valueOfLife -= 20 * mb[i].mBsize;


if


(mb[i].mBsize == 1)


{


PlaySound


(


L”midb.wav”


,


NULL


,


SND_FILENAME


|


SND_ASYNC


);


//PlaySound(L”background.wav”, NULL, SND_FILENAME | SND_ASYNC);


}


else


{


PlaySound


(


L”bigb.wav”


,


NULL


,


SND_FILENAME


|


SND_ASYNC


);


//PlaySound(L”background.wav”, NULL, SND_FILENAME | SND_ASYNC);


}


break


;


}


}


if


(mb[i].goAhead == 0)


//子弹朝向左


{


//机器人robot1被左击中


rb1->beated = -1;


}


else


if


(mb[i].goAhead == 1)


//子弹朝向右


{


//机器人robot1被右击中


rb1->beated = 1;


}


mb[i].die();


}


}


}


else


//子弹已到边界


{


mb[i].live =


false


;


}


}


}


}


  1. 炸弹爆炸类的设计:x,y确定爆炸的位置,size确定爆炸的范围,强度,live是否存活,livelong存活的时间


#pragma


once


#include


<glut.h>


#include


<math.h>


#include


<stdlib.h>


#define


MAXPOINTSIZE


200


class


Bomb


{


public


:


float


x;


float


y;


float


size;


bool


live;


int


liveLong;


Bomb()


{


x = -99;


y = -99;


size = 1;


live =


false


;


liveLong = 40;


}


void


init(


float


x


,


float


y


,


float


size


)


{


this


->x =


x


;


this


->y =


y


;


this


->size =


size


;


live =


true


;


liveLong = 160;


}


void


setLiveLong(


int


liveLong


)


{


this


->liveLong =


liveLong


;


}


void


die()


{


live =


false


;


}



版权声明:本文为guanshanyue96原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。