忙完了大一课设,就赶忙来写一篇博客,希望能对你们有用.项目灵感:游戏玩法:难点:
1.圣诞老人的睁眼闭眼2.人物的移动3.判断袜子与人物相撞4.鼠标 *** 作4.游戏音乐加载5. 我的头文件6. 透明背景贴图的工具(不用做掩码图啦!!!!!!)7.其他判断游戏失败成功,袜子的移动,等等杂七杂八的就不一一解释了,直接给你们放我的代码8.这个是我的图片素材有什么问题,后续会补充,评论区问.
先来大致了解一下我的游戏
下图是游戏主界面的样子
点击开始游戏
就会显示我的游戏说明,然后按任意键开始游戏
进入游戏的样子
游戏失败,游戏胜利的界面
玩法类似于三二一木头人,其实当时想做一个鱿鱼游戏,但是那个游戏3D的更好,所以我不会…,写课设的那一天刚好是圣诞节,就应景用圣诞老人写了这个游戏,素材是真的难找
游戏玩法:用方向键控制哆啦A梦移动,然后那个圣诞老人的眼睛会一睁一闭,当他看到你移动时就会发射一个圣诞袜来攻击你,你既要躲避还要碰到圣诞老人,然后你就获胜了.
难点: 1.圣诞老人的睁眼闭眼这个我当时想用多线程去写一个随机函数来控制他睁眼闭眼,但是发现游戏会一闪一闪的,加了双缓冲也没有用,所以最后就用了ps把素材搞成了一列帧序列图,让他自己一张一张切,这个样不会闪,但是就不能随机睁眼闭眼了(就很烦!!!)为了赶时间,也想不出其他办法,与没有大神来告诉我.
2.人物的移动这个其实也不难,就弄明白EasyX里面函数的原理就自己能写出来了
void KeyCont() {//键盘控制人物移动函数 int time = 60,v=13;//v就相当于人物的速度 if (GetAsyncKeyState(VK_UP) & 0x8000) { pl.img_x++; pl.img_y = 456; if (pl.img_x >= 4) { pl.img_x = 0; } pl.y-=v;//这个就是人物的y坐标减一,就相当于他往上走了一个v Sleep(time);//控制切图片的频率,不加的话太快了 } if (GetAsyncKeyState(VK_DOWN) & 0x8000) { pl.img_x++; pl.img_y = 0; if (pl.img_x >= 4) { pl.img_x = 0; } pl.y+=v; Sleep(time); } if (GetAsyncKeyState(VK_RIGHT) & 0x8000) { pl.img_x++; pl.img_y = 304; if (pl.img_x >= 4) { pl.img_x = 0; } pl.x+=v; Sleep(time); } if (GetAsyncKeyState(VK_LEFT) & 0x8000) { pl.img_x++; pl.img_y = 152; if (pl.img_x >= 4) { pl.img_x = 0; } pl.x-=v; Sleep(time); } if(1){ Man.img_x++; if (Man.img_x >= 11) { Man.img_x = 0; } Sleep(time); time -= 1; } }3.判断袜子与人物相撞
这个就用他俩之间的位置关系来判断
用一个简单的if函数
if (pl.x > bull[i].r_x && pl.x4.鼠标 *** 作bull[i].r_y && pl.y < bull[i].r_y + 60 || pl.x + 85>bull[i].r_x && pl.x + 85 < bull[i].r_x + 60 &&pl.y+150 > bull[i].r_y && pl.y+150 < bull[i].r_y + 60 || pl.x + 85 > bull[i].r_x && pl.x + 85 < bull[i].r_x + 60 && pl.y + 75 > bull[i].r_y && pl.y + 75 < bull[i].r_y + 60)
这个就封装一个函数来判断鼠标光标的位置,和左键右键,我只写了左键的
void Mouse() { ExMessage msg; if (peekmessage(&msg, EM_MOUSE)) { if (msg.x >= 515 && msg.x <= 515 + 172 && msg.y >= 700 && msg.y <= 700 + 64) { drawImg(515, 680, &开始游戏图标01); } else { drawImg(515, 680, &开始游戏图标); } switch (msg.message) { case WM_LBUTTONDOWN: if (msg.x >= 1150 && msg.x <= 1300 && msg.y >= 10 && msg.y <= 130) { 点击bgm(); mciSendString(_T("stop shengdan01.mp3"), NULL, 0, NULL); mciSendString(_T("close shengdan01.mp3"), NULL, 0, NULL); closegraph(); } //点击开始游戏后 if (msg.x >= 515 && msg.x <= 515 + 172 && msg.y >= 700 && msg.y <= 700 + 64) {4.游戏音乐加载
我是直接把音乐放到了资源文件里面
然后就加载:
mciSendString(L"open shengdan01.mp3", 0, 0, 0);
播放:
mciSendString(L"play shengdan01.mp3 repeat", 0, 0, 0);
注意:头文件一定要加上
5. 我的头文件我用了点c++的类,就顺便加了c++的头文件
#include6. 透明背景贴图的工具(不用做掩码图啦!!!)//#include using namespace std; #include //包含图形库头文件 #include #pragma comment(lib,"winmm.lib") #include #include"tool.h" #include #include #include
这里我解释一下我头文件里面的"tool.h"
这是一个透明背景贴图工具,就不用自己再做掩码图,怪麻烦的,直接把这个工具加到自己的头文件里面,然后就用这个函数:
drawImg(1200, 10, &退出图标); drawImg(pl.x, pl.y,100,150,&renwu,pl.img_x*100,pl.img_y);
用法和easyx里面的putimage一模一样
这个是我的工具代码:
把它直接复制粘贴到你的头文件里面;
#pragma once #include7.其他判断游戏失败成功,袜子的移动,等等杂七杂八的就不一一解释了,直接给你们放我的代码void drawImg(int x, int y, IMAGE* src) { // 变量初始化 DWORD* pwin = GetImageBuffer(); //窗口缓冲区指针 DWORD* psrc = GetImageBuffer(src); //图片缓冲区指针 int win_w = getwidth(); //窗口宽高 int win_h = getheight(); int src_w = src->getwidth(); //图片宽高 int src_h = src->getheight(); // 计算贴图的实际长宽 int real_w = (x + src_w > win_w) ? win_w - x : src_w; // 处理超出右边界 int real_h = (y + src_h > win_h) ? win_h - y : src_h; // 处理超出下边界 if (x < 0) { psrc += -x; real_w -= -x; x = 0; } // 处理超出左边界 if (y < 0) { psrc += (src_w * -y); real_h -= -y; y = 0; } // 处理超出上边界 // 修正贴图起始位置 pwin += (win_w * y + x); // 实现透明贴图 for (int iy = 0; iy < real_h; iy++) { for (int ix = 0; ix < real_w; ix++) { byte a = (byte)(psrc[ix] >> 24);//计算透明通道的值[0,256) 0为完全透明 255为完全不透明 if (a != 0) { pwin[ix] = psrc[ix]; } } //换到下一行 pwin += win_w; psrc += src_w; } } void drawImg(int x, int y, int dstW, int dstH, IMAGE* src, int srcX, int srcY) { // 变量初始化 DWORD* pwin = GetImageBuffer(); //窗口缓冲区指针 DWORD* psrc = GetImageBuffer(src); //图片缓冲区指针 int win_w = getwidth(); //窗口宽高 int win_h = getheight(); int src_w = src->getwidth(); //图片宽高 int src_h = src->getheight(); // 计算贴图的实际长宽 int real_w = (x + dstW > win_w) ? win_w - x : dstW; // 处理超出右边界 int real_h = (y + dstH > win_h) ? win_h - y : dstH; // 处理超出下边界 if (x < 0) { psrc += -x; real_w -= -x; x = 0; } // 处理超出左边界 if (y < 0) { psrc += (dstW * -y); real_h -= -y; y = 0; } // 处理超出上边界 //printf("realw,h(%d,%d)n", real_w, real_h); // 修正贴图起始位置 pwin += (win_w * y + x); // 实现透明贴图 for (int iy = 0; iy < real_h; iy++) { for (int ix = 0; ix < real_w; ix++) { byte a = (byte)(psrc[ix + srcX + srcY * src_w] >> 24);//计算透明通道的值[0,256) 0为完全透明 255为完全不透明 if (a > 100) { pwin[ix] = psrc[ix + srcX + srcY * src_w]; } } //换到下一行 pwin += win_w; psrc += src_w; } }
第一次写项目,那些函数的位置,代码就显得十分凌乱,看的可能会吃力点:
#include"swap.h" #include"tool.h" IMAGE sleep02, sleep01, zhujiemian, 退出图标01, 退出图标02,退出图标, 开始游戏图标,开始游戏图标01,close01; IMAGE 游戏背景, imgOldman, renwu2, youyu01, youyu02, 娃娃[2], renwu, socks,fail,success;//定义图片变量 IMAGE restar, close,gametip; enum My { bull_num = 1500, }; void Bgm() { mciSendString(L"open shengdan01.mp3", 0, 0, 0); mciSendString(L"play shengdan01.mp3 repeat", 0, 0, 0); } void 点击bgm() { mciSendString(L"open dianjibgm.mp3", 0, 0, 0); mciSendString(L"play dianjibgm.mp3", 0, 0, 0); } void Gamebgm() { mciSendString(L"open youxibgm.mp3", 0, 0, 0); mciSendString(L"play youxibgm.mp3 repeat", 0, 0, 0); } void Gamesuccessbgm() { mciSendString(L"open gamesuccess.mp3", 0, 0, 0); mciSendString(L"play gamesuccess.mp3", 0, 0, 0); } void Gamefailbgm() { mciSendString(L"open gamefail.mp3", 0, 0, 0); mciSendString(L"play gamefail.mp3", 0, 0, 0); } void shotbgm() { mciSendString(L"open shotbgm.mp3", 0, 0, 0); mciSendString(L"play shotbgm.mp3", 0, 0, 0); } //封装定时器 bool timesleep() { int ms = rand() % + 1; static DWORD t1, t2; if (t2 - t1 > ms) { t1 = t2; return true; } t2 = clock(); return false; } void init_Zhujiemian() { initgraph(1300, 781); loadimage(&zhujiemian, L"tupian\主界面背景.png"); loadimage(&sleep02, L"tupian\biaoti01.png"); loadimage(&sleep01, L"tupian\biaoti.png"); loadimage(&退出图标01, L"tupian\退出图标01.png"); loadimage(&退出图标02, L"tupian\退出图标02.png"); loadimage(&开始游戏图标, L"tupian\开始游戏图标.png"); loadimage(&success, L"tupian\success.png"); loadimage(&fail, L"tupian\fail.png"); loadimage(&restar, L"tupian\restar.png"); loadimage(&close, L"tupian\close.png"); loadimage(&imgOldman, L"tupian\oldman01.png"); loadimage(&游戏背景, L"tupian\游戏背景.png"); loadimage(&renwu, L"tupian\renwu111.png"); loadimage(&socks, L"tupian\socks.png"); loadimage(&退出图标, L"tupian\退出图标.png"); loadimage(&开始游戏图标01, L"tupian\开始游戏图标01.png"); loadimage(&close01, L"tupian\close01.png"); loadimage(&gametip, L"tupian\gametip.png"); } struct Oldman { int man_x = 980, man_y = 220; int img_x = 4, img_y = 0; int manimg = 0; }Man; struct Role//定义人物坐标变量 { //人物坐标 int x = 0, y = 300; int img_x = 0; int img_y = 0; }pl; //游戏过程中的鼠标 *** 作 void Mousegame() { ExMessage msg; if (peekmessage(&msg, EM_MOUSE)) { switch (msg.message) { case WM_LBUTTONDOWN: if (msg.x >= 1100 && msg.x <= 1300 && msg.y >= 10 && msg.y <= 200) { 点击bgm(); mciSendString(_T("stop youxibgm.mp3"), NULL, 0, NULL); mciSendString(_T("close youxibgm.mp3"), NULL, 0, NULL); closegraph(); } } } } //定义一个子弹类 class Bullet { public: int r_x = 1030; int r_y = 360; bool live = false; //初始化袜子图像 void drawfirstsock() { drawImg(bull[0].r_x, bull[0].r_y, &socks); } void creatbull() {//创建一个袜子 for (int i = 0; i < bull_num; i++) { if (!bull[i].live) { bull[i].r_x = 1030; bull[i].r_y = pl.y + 60; bull[i].live = true; shotbgm(); break; } } } void drawsock() { for (int i = 0; i < bull_num; i++) { if (bull[i].live) { drawImg(bull[i].r_x, bull[i].r_y, &socks); } } } void socksfight() { //获取键盘的信号; if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState(VK_UP) || GetAsyncKeyState(VK_DOWN) || GetAsyncKeyState(VK_RIGHT)) { shotbgm(); creatbull(); } } //袜子移动 void socksmove() { for (int i = 0; i < bull_num; i++) { if (bull[i].live) { bull[i].r_x -= 4; } } } }bull[bull_num]; //游戏结束的鼠标操作 void gameovermouse2() { ExMessage msg; if (peekmessage(&msg, EM_MOUSE)) { if (msg.x >= 1150 && msg.x <= 1300 && msg.y >= 0 && msg.y <= 120) { drawImg(650, 580, &close01); } else { drawImg(650, 580, &close); } switch (msg.message) { case WM_LBUTTONDOWN: if (msg.x >= 650 && msg.x <= 650 + 187 && msg.y >= 580 && msg.y <= 580 + 83) { 点击bgm(); closegraph(); } if (msg.x >= 450 && msg.x <= 450 + 150 && msg.y >= 580 && msg.y <= 580 +110 ) { 点击bgm(); closegraph(); } } } } //游戏结束判定 void gameover() { //当oldman睁眼 if (Man.img_x==0||Man.img_x==1) { //创建一个袜子 bull[bull_num].socksfight(); } //判断是否到达终点 if (pl.x + 90 >= 980 && pl.x + 90 <= 1300 && pl.y >= 230 && pl.y <= 490 || pl.x + 90 >= 970 && pl.x + 90 <= 1300 && pl.y + 142 >= 250 && pl.y + 142 <= 490) { mciSendString(_T("stop youxibgm.mp3"), NULL, 0, NULL); mciSendString(_T("close youxibgm.mp3"), NULL, 0, NULL); cleardevice(); Gamesuccessbgm(); drawImg(350, 240, &success); drawImg(450, 580, &restar); drawImg(650, 580, &close); while (1) { gameovermouse2(); } return; } //判断袜子是否与人物相撞 for (int i = 0; i < bull_num; i++) { if (pl.x > bull[i].r_x && pl.x8.这个是我的图片素材bull[i].r_y && pl.y < bull[i].r_y + 60 || pl.x + 85>bull[i].r_x && pl.x + 85 < bull[i].r_x + 60 &&pl.y+150 > bull[i].r_y && pl.y+150 < bull[i].r_y + 60 || pl.x + 85 > bull[i].r_x && pl.x + 85 < bull[i].r_x + 60 && pl.y + 75 > bull[i].r_y && pl.y + 75 < bull[i].r_y + 60) { cleardevice(); mciSendString(_T("stop youxibgm.mp3"), NULL, 0, NULL); mciSendString(_T("close youxibgm.mp3"), NULL, 0, NULL); Gamefailbgm(); drawImg(350, 240, &fail); drawImg(450, 580, &restar); drawImg(650, 580, &close); while (1) { gameovermouse2(); } } } } void draw() { putimage(0, 0, &zhujiemian); putimage(0, 0, &sleep02, SRCAND); putimage(0, 0, &sleep01, SRCPAINT); putimage(1200, 10, &退出图标02, SRCAND); putimage(1200, 10, &退出图标01, SRCPAINT); drawImg(515, 680, &开始游戏图标); } void KeyCont() {//键盘控制人物移动函数 int time = 60,v=13; if (GetAsyncKeyState(VK_UP) & 0x8000) { pl.img_x++; pl.img_y = 456; if (pl.img_x >= 4) { pl.img_x = 0; } pl.y-=v; Sleep(time); } if (GetAsyncKeyState(VK_DOWN) & 0x8000) { pl.img_x++; pl.img_y = 0; if (pl.img_x >= 4) { pl.img_x = 0; } pl.y+=v; Sleep(time); } if (GetAsyncKeyState(VK_RIGHT) & 0x8000) { pl.img_x++; pl.img_y = 304; if (pl.img_x >= 4) { pl.img_x = 0; } pl.x+=v; Sleep(time); } if (GetAsyncKeyState(VK_LEFT) & 0x8000) { pl.img_x++; pl.img_y = 152; if (pl.img_x >= 4) { pl.img_x = 0; } pl.x-=v; Sleep(time); } if(1){ Man.img_x++; if (Man.img_x >= 11) { Man.img_x = 0; } Sleep(time); time -= 1; } } void Mouse() { ExMessage msg; if (peekmessage(&msg, EM_MOUSE)) { if (msg.x >= 515 && msg.x <= 515 + 172 && msg.y >= 700 && msg.y <= 700 + 64) { drawImg(515, 680, &开始游戏图标01); } else { drawImg(515, 680, &开始游戏图标); } switch (msg.message) { case WM_LBUTTONDOWN: if (msg.x >= 1150 && msg.x <= 1300 && msg.y >= 10 && msg.y <= 130) { 点击bgm(); mciSendString(_T("stop shengdan01.mp3"), NULL, 0, NULL); mciSendString(_T("close shengdan01.mp3"), NULL, 0, NULL); closegraph(); } //点击开始游戏后 if (msg.x >= 515 && msg.x <= 515 + 172 && msg.y >= 700 && msg.y <= 700 + 64) { 点击bgm(); drawImg(150,90 , &gametip); _getch();//实现按任意键开始游戏 mciSendString(_T("stop shengdan01.mp3"), NULL, 0, NULL); mciSendString(_T("close shengdan01.mp3"), NULL, 0, NULL); cleardevice(); //Gamebgm(); while (1) { KeyCont(); BeginBatchDraw(); putimage(0, 0, &游戏背景); drawImg(1200, 10, &退出图标); drawImg(pl.x, pl.y,100,150,&renwu,pl.img_x*100,pl.img_y); drawImg(980, 220, 400, 280, &imgOldman, Man.img_x * 400+40, Man.img_y); bull[bull_num].socksmove(); bull[bull_num].drawsock(); EndBatchDraw(); gameover(); Mousegame(); } } } } } int main() { init_Zhujiemian(); draw(); //Bgm(); while (1) { Mouse(); }; return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)