#include"maoxiandao.h"
#define MaxBullet 30
HWND hDlg; //对话框句柄
HWND hWnd; //窗口句柄
HINSTANCE hInst;
HDC hDC, MemDC, MemBufferDC; //设备DC
HBITMAP bg, bullet, monster_bullet;
int X = 0; //绝对坐标 取值范围<-1280, +640> 2*640 //显示的宽度为<-1280, +1280>
VOID(*p)() = NULL; //函数指针 //用于保存当前的跳跃函数
int MoveBg = 30; //移动背景的标记值
int BGx0 = 0, BGx1 = 0, BGy = 0;
//int Buffer[2];
//人物类
MAN man;
//子弹
MY_BULLET Bullet[MaxBullet]; //人物子弹
MONSTER_BULLET monster_Bullet;
//怪兽类
MONSTER monster;
////播放数组
//#define MUSICNUM 3
//const TCHAR *Music[MUSICNUM] = { L"起风了", L"RightNow", L"TomorrowWithYou" };
//UINT Music_len; //记录当前歌曲的时间长度
//int sPosition[256]; //用于读取当前歌曲的毫秒数
int nMusic = 0; //记录当前播放歌曲
RECT RectMusicShow = { 450, 10, 640, 28 };
int BulletCount = 0;
DWORD tNow, tPre, tLaunch; //tNow此次准备绘图的时间, tPre上次绘图的时间
RECT RectManBlood_Show, RectMonsterBlood_Show;
RECT Rect_bullet, Rect_monster;
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow
)
{
MSG msg;
memset(&msg, 0, sizeof(MSG)); //初始化msg结构 其中的msg.message为WM_NULL
//创建窗口类
if (!InitWindow(hInstance, nCmdShow))
{
MessageBox(NULL, L"窗口类创建失败", L"窗口类创建", NULL);
return 0;
}
HBITMAP bmp;
//搜索当前路径下的music文件夹的音频文件
GetCurrentDirectory(MAX_PATH, path);
lstrcat(path, L"\\music");
EnumTree(path);
//开始播放音乐
MusicBegin();
hDC = GetDC(hWnd);
MemDC = CreateCompatibleDC(hDC); //人物
MemBufferDC = CreateCompatibleDC(hDC); //建立与设备相容的内存DC 背景
//加载背景
bg = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, 640, 480, LR_LOADFROMFILE);
//加载子弹
bullet = (HBITMAP)LoadImage(NULL, L"man_bullet.bmp", IMAGE_BITMAP, 200, 50, LR_LOADFROMFILE);
monster_bullet = (HBITMAP)LoadImage(NULL, L"monster_bullet.bmp", IMAGE_BITMAP, 400, 100, LR_LOADFROMFILE);
bmp = CreateCompatibleBitmap(hDC, 640, 480); //在内存DC中创建一个空位图
SelectObject(MemDC, bmp);
//加载人物图片
man.bmp[0] = (HBITMAP)LoadImage(NULL, L"man0.bmp", IMAGE_BITMAP, 240, 180, LR_LOADFROMFILE);
man.bmp[1] = (HBITMAP)LoadImage(NULL, L"man1.bmp", IMAGE_BITMAP, 240, 180, LR_LOADFROMFILE);
//加载怪物图片
monster.bmp[0] = (HBITMAP)LoadImage(NULL, L"monster0.bmp", IMAGE_BITMAP, 180, 360, LR_LOADFROMFILE);
monster.bmp[1] = (HBITMAP)LoadImage(NULL, L"monster1.bmp", IMAGE_BITMAP, 180, 360, LR_LOADFROMFILE);
//立刻贴上背景和人物,避免出现闪烁
My_BGPaint(hDC);
My_ManPaint();
BitBlt(hDC, 0, 0, 640, 480, MemDC, 0, 0, SRCCOPY);
//定时器
//SetTimer(hWnd, 50000, 2000, (TIMERPROC)NULL); //用于怪物的子弹发射
//用定时器来刷新太LOW了,这里用游戏循环,周期性的调用游戏主循环
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
tNow = GetTickCount();
if (tNow - tPre >= 40) //周期性的调用主循环,以此来刷新
{
//My_BGPaint(hDC);
if (My_GameMain() == Game_OVER)
{
//播放人物死亡身影
Special_Effects(1);
//点击OK按钮退出游戏
if (MessageBox(hWnd, L"游戏结束!", L"Game Over", MB_OK) == IDOK)
{
SendMessage(hWnd, WM_DESTROY, NULL, NULL);
}
}
BitBlt(hDC, 0, 0, 640, 480, MemDC, 0, 0, SRCCOPY);
}
}
}
return (int)msg.wParam;
}
/**********************************游戏主循环**********************************************/
BOOLEAN My_GameMain()
{
if (man.Attribute & JUMPING) //判断是否在跳跃中
{
p(); //函数指针,这里用来决定调用那个跳跃函数
return true; //默认人物存活
}
if (man.Attribute & EXIST) //判定人物是否是挂了
{
//怪物的周期性的子弹发射
if (monster.Attribute & EXIST) //发射子弹的前提条件是怪物活着
{
if (tNow - tLaunch >= 2000)
{
Monster_Launch();
}
}
if (man.Attribute & JUMP) //判定跳跃
{
//开启JUMPING属性
if (!(man.Attribute & JUMPING))
{
man.Attribute ^= JUMPING;
Sleep(6);
}
if (man.Attribute & WALK) //按着方向键代表左右跳,这时候的WALK属性是开启的
{
switch (man.dir)
{
case 0:
My_ManJumpR();
Sleep(6);
break;
case 1:
My_ManJumpL();
Sleep(6);
break;
}
}
else //没有按方向键,这时候是垂直跳
{
My_ManJump(); //My_ManJump()中调用了刷新背景函数和人物贴图函数
Sleep(10);
}
}//跳跃
/*判断人物的行走属性是否开启*/
else if (man.Attribute & WALK)
{
My_BGPaint(hDC);
My_ManMove();
My_ManPaint();
}
/*没用操作则按一定频率刷新,这里有子弹的话会刷新子弹*/
else
{
My_BGPaint(hDC);
My_ManPaint();
}
}
else
{
//人物死了
return Game_OVER;
}
tPre = GetTickCount();//记录执行完的时间
return Game;
}
/*************************************背景粘贴函数********************************************/
VOID My_BGPaint(HDC hdc)
{
SelectObject(MemBufferDC, bg); //将背景图载入背景DC中
//天空
BitBlt(MemDC, 0, 0, BGx0, 180, MemBufferDC, 640 - BGx0, 0, SRCCOPY);
BitBlt(MemDC, BGx0, 0, 640 - BGx0, 180, MemBufferDC, 0, 0, SRCCOPY);
//大地
BitBlt(MemDC, 0, 180, BGx1, 300, MemBufferDC, 640 - BGx1, 180, SRCCOPY);
BitBlt(MemDC, BGx1, 180, 640 - BGx1, 300, MemBufferDC, 0, 180, SRCCOPY);
//判定此时的和怪物的距离
if (monster.Attribute & EXIST)
{
MonsterShow();
}
//判定此时怪物是否需要显示
if (monster.Attribute & SHOW) //怪物显示
{
MonsterDir();
My_MonsterPaint();
}
MusicBotton_Paint(); //绘制音乐按钮
if (monster_Bullet.exist)
{
Monster_Bullet_Paint();
}
//重置随机数种子
//srand((unsigned)time(NULL));
//在背景上输出字体
//SetTextColor(MemDC, RGB(rand() % 255, rand() % 255, rand() % 255)); //可变色字体
//将字体背景设置为天蓝色,由PS中拾色器的可得色彩分量
SetBkColor(MemDC, RGB(94, 191, 236));
DrawText(MemDC, Vector[nMusic].FileName, wcslen(Vector[nMusic].FileName), &RectMusicShow, DT_CENTER);
SetTextColor(MemDC, RGB(0, 0, 0));//黑色字体
SetBkColor(MemDC, RGB(255, 0, 0)); //人物血条背景设置为红色
//人物和怪物的血量显示
TCHAR ManBlood_Show[20],
MonsterBlood_Show[20];
//如果怪物的血等于0 不在显示怪物的血量
if (monster.blood != 0)
{
wsprintf(MonsterBlood_Show, L"%d/%d", monster.blood, 100000);
RectMonsterBlood_Show = monster.GetBloodShow();
DrawText(MemDC, MonsterBlood_Show, wcslen(MonsterBlood_Show), &RectMonsterBlood_Show, DT_LEFT);
}
//人物血量的显示
wsprintf(ManBlood_Show, L"%d/%d", man.blood, 1000);
RectManBlood_Show = man.GetBloodShow();
DrawText(MemDC, ManBlood_Show, wcslen(ManBlood_Show), &RectManBlood_Show, DT_LEFT);
}
/*********************************怪物相关函数*****************************************************/
VOID My_MonsterPaint()
{
SelectObject(MemBufferDC, monster.bmp[monster.dir]);
//贴上怪物图
BitBlt(MemDC, monster.x, monster.y, 180, 180, MemBufferDC, 0, 180, SRCAND);
BitBlt(MemDC, monster.x, monster.y, 180, 180, MemBufferDC, 0, 0, SRCPAINT);
Rect_monster.left = monster.x;
Rect_monster.right = monster.x + 180;
Rect_monster.top = monster.y;
Rect_monster.bottom = monster.y + 180;
}
//判定怪兽是否显示函数
BOOLEAN MonsterShow()
{
//怪物显示的条件:在