下图是游戏主界面的样子
点击开始游戏
就会显示我的游戏说明,然后按任意键开始游戏
进入游戏的样子
玩法类似于三二一木头人,其实当时想做一个鱿鱼游戏,但是那个游戏3D的更好,所以我不会…,写课设的那一天刚好是圣诞节,就应景用圣诞老人写了这个游戏,素材是真的难找
用方向键控制哆啦A梦移动,然后那个圣诞老人的眼睛会一睁一闭,当他看到你移动时就会发射一个圣诞袜来攻击你,你既要躲避还要碰到圣诞老人,然后你就获胜了.
这个我当时想用多线程去写一个随机函数来控制他睁眼闭眼,但是发现游戏会一闪一闪的,加了双缓冲也没有用,所以最后就用了ps把素材搞成了一列帧序列图,让他自己一张一张切,这个样不会闪,但是就不能随机睁眼闭眼了(就很烦!!!)为了赶时间,也想不出其他办法,与没有大神来告诉我.
这个其实也不难,就弄明白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;
}
}
这个就用他俩之间的位置关系来判断
用一个简单的if函数
if (pl.x > bull[i].r_x && pl.x<bull[i].r_x + 60
&& pl.y>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) {
mciSendString(L"open shengdan01.mp3", 0, 0, 0);
播放:
mciSendString(L"play shengdan01.mp3 repeat", 0, 0, 0);
注意:头文件一定要加上
我用了点c++的类,就顺便加了c++的头文件
#include
//#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
#include
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.x<bull[i].r_x + 60
&& pl.y>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;
}