/////////////////////////////////////////////////////////////////////
// 程序名称:超级蘑菇
// 编译环境:Visual Studio2008 ,EasyX_v20120603(beta)
// 作 者:木子念念
// 最后修改:2012-11-5
// 注:本游戏的每个算法思想都是由自己独立思考出来的,所以可能会有很
// 多不完善以及错误的地方,在此也希望大家能指出程序中的bug或错误。
// 游戏优点:使用了类和结构体,所以结构较为清晰明了。功能比较完全,包含图片和音乐。
// 游戏缺点:由于没有太多时间,所以只设置了一关游戏,而且游戏地图很小。
/////////////////////////////////////////////////////////////////////
/* 【自学去】网站收集 http://www.zixue7.com */
#include <graphics.h>
#include <conio.h>
#include<math.h>
#include "MyTimer.h" //一个保证精确延时的类。下载于easyx官网
#pragma comment(lib,"Winmm.lib") //给游戏添加音乐要用到它
#define G 9.8 //重力加速度
#define XSIZE 512 //屏幕大小
#define YSIZE 384
#define X 64 //主角起始位置
#define Y 192
#define W 32 //主角的宽和高
#define H 32
#define STEP 4 //主角走一步相距的像素个数
#define HIGH (2*role.w+1) //主角跳跃的最大高度
#define CMD_LEFT 1 //方向键的宏定义
#define CMD_RIGHT 2
#define CMD_UP 4
#define CMD_DOWN 8
#define CMD_SHOOT 16
#define CMD_ESC 32
int life; //全局变量,主角共有多少条生命
int score; //全局变量,主角获得的分数
struct ROLE
{
int id;
int x;//横坐标
int y;//纵坐标
int w;//图片宽度
int h;//图片高度
int xleft;//水平运动的左界限
int xright;//水平运动的右界限
int turn;//精灵的运动方向
int jump;//精灵是否跳跃
int iframe;//加载第几副精灵图,这样就能让精灵看上去动起来了
};
struct MAP //储存地图的结构体
{
int id;
int x;
int y;
};
struct BULLET //子弹的结构体
{
int x;
int y;
int turn;
int iframe;
int id;
};
struct COINT //硬币的结构体
{
int x;
int y;
double iframe;
};
struct ENEMY //敌人的结构体
{
int id;
int x;
int y;
int turn;
int iframe;
};
class game //整个游戏只设置了这一个类
{
private:
ROLE role;
MAP map[350];
BULLET bullet[20];
COINT coint[50];
ENEMY enemy[20];
IMAGE img_mapsky,img_p,img_map,img_ani,img_mapbk,img_home;
int xmapsky; //背景天空的起始横坐标
int xmap; //地图的起始坐标
double v0; //精灵跳跃的初速度
double h; //精灵跳跃的高度
double t; //精灵跳跃的时间
int ibullet; //第几颗子弹
int xbullet; //子弹的x坐标
int ybullet; //子弹的y坐标
int get_bullet; //是否获得武器,0表示没有获得,1表示已获得
POINT icoint; //储存硬币的坐标
POINT bomb[20]; //储存哪些地方爆炸了的坐标
POINT temp; //临时坐标。储存哪些地方爆炸了的坐标
double score_frame; //下面3个double型的变量用于控制各自图片的帧,以实现动画的效果。如画面中的流水
double bomb_frame;
double mapbk_frame;
int win; //玩家是否过关
int pause; //玩家是否按Esc(暂停键)
public:
game();
~game();
void start(); //处理游戏开始的界面,和按暂停键后的界面
void init(); //初始化各项变量
void move(); //控制主角移动
void show(); //显示画面
int isdie(); //判断主角是否已死
int GetCommand(); // 获取控制命令。参阅easyx
void left(); //主角向左运动
void right(); //主角向右运动
void up(); //主角跳跃
void init_shoot(); //初始化发射子弹
void fall(); //主角自由落体或者向上跳跃
int is_l_touch(int id);//主角的左边是否碰到墙或敌人,以及敌人是否碰到陆地的左边界
int is_r_touch(int id);//主角的右边是否碰到墙或敌人,以及敌人是否碰到陆地的右边界
int is_t_touch(); //主角的头是否碰到墙
int is_b_touch(int id);//主角是否踩到敌人。
int is_touch(); //主角是否吃到金币
int is_land(ENEMY e); //敌人是否站在陆地上
void getbullet(); //获取子弹
void shoot(); //发射子弹
int eat(BULLET b); //子弹是否打到敌人或者墙壁
void end(); //处理游戏结束
};
game::game()
{
initgraph(XSIZE,YSIZE);
}
game::~game()
{
closegraph();
}
void game::start()
{
if(pause==1)//如果按了暂停键
{
BeginBatchDraw();
int points[8]={XSIZE/2-45,YSIZE/3,XSIZE/2+45,YSIZE/3,XSIZE/2+45,YSIZE/3+90,XSIZE/2-45,YSIZE/3+90};
setfillstyle(GREEN);
fillpoly(4, points);
setbkmode(TRANSPARENT);
setfont(20,0,"黑体");
RECT r2={XSIZE/2-45,YSIZE/3,XSIZE/2+45,YSIZE/3+30};rectangle(XSIZE/2-45,YSIZE/3,XSIZE/2+45,YSIZE/3+30);
drawtext("回到游戏", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
RECT r3={XSIZE/2-45,YSIZE/3+30,XSIZE/2+45,YSIZE/3+60};rectangle(XSIZE/2-45,YSIZE/3+30,XSIZE/2+45,YSIZE/3+60);
drawtext("重新开始", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
RECT r4={XSIZE/2-45,YSIZE/3+60,XSIZE/2+45,YSIZE/3+90};rectangle(XSIZE/2-45,YSIZE/3+60,XSIZE/2+45,YSIZE/3+90);
drawtext(" 主 菜 单 ", &r4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
FlushBatchDraw();
MOUSEMSG m;
while(true)
{
BeginBatchDraw();
m=GetMouseMsg();
switch(m.uMsg)
{
case WM_LBUTTONDOWN:
EndBatchDraw();
if(m.x>XSIZE/2-45&&m.x<XSIZE/2+45&&m.y>YSIZE/3&&m.y<YSIZE/3+30)
return;
else if(m.x>XSIZE/2-45&&m.x<XSIZE/2+45&&m.y>YSIZE/3+30&&m.y<YSIZE/3+60)
{
mciSendString("close all", NULL, 0, NULL);
pause=0;
score=0;
return;
}
else if(m.x>XSIZE/2-45&&m.x<XSIZE/2+45&&m.y>YSIZE/3+60&&m.y<YSIZE/3+90)
{
mciSendString("close all", NULL, 0, NULL);
pause=0;
score=0;
life=0;
cleardevice();
break;
}
else
break;
case WM_MOUSEMOVE:
RECT r;
int i;
for(i=0;i<3;i++)
{
if(m.x>XSIZE/2-45&&m.x<XSIZE/2+45&&m.y>YSIZE/3+i*30&&m.y<YSIZE/3+30+i*30)
{
r.left=XSIZE/2-45;
r.top=YSIZE/3+i*30;
r.right=XSIZE/2+45;
r.bottom=YSIZE/3+30+i*30;
int points[8]={r.left,r.top,r.right,r.top,r.right,r.bottom,r.left,r.bottom};
setfillstyle(RED);
fillpoly(4, points);
setbkmode(TRANSPARENT);
switch(i)
{
case 0:
drawtext("回到游戏", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
break;
case 1:
drawtext("重新开始", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
break;
case 2:
drawtext(" 主 菜 单 ", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
break;
}
}
else
{
if(getpixel(XSIZE/2-45+1,YSIZE/3+i*30+1)==RED)
{
r.left=XSIZE/2-45;
r.top=YSIZE/3+i*30;
r.right=XSIZE/2+45;
r.bottom=YSIZE/3+30+i*30;
int points[8]={r.left,r.top,r.right,r.top,r.right,r.bottom,r.left,r.bottom};
setfillstyle(GREEN);
fillpoly(4, points);
setbkmode(TRANSPARENT);
switch(i)
{
case 0:
drawtext("回到游戏", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
break;
case 1:
drawtext("重新开始", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
break;
case 2:
drawtext(" 主 菜 单 ", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
break;
}
}
FlushBatchDraw();
}
}
}
if(pause==0)
break;
}
}
if(life==1||life==2)
return;
life=3;
score=0;
setfont(40,0,"方正舒体");
RECT r1 = {0, 0, XSIZE, YSIZE/3};
drawtext("超级蘑菇", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
setfont(20,0,"宋体");
RECT r2={XSIZE/2-45,YSIZE/3,XSIZE/2+45,YSIZE/3+30};rectangle(XSIZE/2-45,YSIZE/3,XSIZE/2+45,YSIZE/3+30);
drawtext("开始游戏", &r2, DT_CENTER | DT_VCENT