C++打地鼠游戏一小时极限开发

ops/2024/12/19 2:19:52/

视频:【课设拯救计划/直播回放】C++打地鼠游戏一小时极限开发(完整版)_哔哩哔哩_bilibili

创建几个全局变量:

IMAGE img_menuBackground;   //主菜单背景图
IMAGE img_mole;				//地鼠图片
IMAGE img_empty;			//坑位图片
IMAGE img_hammer_idle;		//默认状态锤子
IMAGE img_hammer_down;		//敲击状态锤子bool is_quit = false;  //游戏是否退出
bool is_satrt = false; //游戏是否开始IMAGE img_menuBackground;   //主菜单背景图
IMAGE img_mole;				//地鼠图片
IMAGE img_empty;			//坑位图片
IMAGE img_hammer_idle;		//默认状态锤子
IMAGE img_hammer_down;		//敲击状态锤子bool is_quit = false;  //游戏是否退出
bool is_satrt = false; //游戏是否开始

创建一个窗口:

int main()
{initgraph(800, 950);hwnd = GetConsoleWindow(); // 获取控制台窗口句柄while (!is_quit) {FlushBatchDraw();}EndBatchDraw();return 0;
}

加载资源

void load_resource()
{loadimage(&img_menu,_T("resources/menu.jpg"));loadimage(&img_mole, _T("resources/mole.jpg"));loadimage(&img_empty, _T("resources/empty.jpg"));loadimage(&img_hammer_idle, _T("resources/hammer_idle.jpg"));loadimage(&img_hammer_down, _T("resources/hammer_down.jpg"));mciSendString(_T("open resources/bgm.mp3  alias bgm"), NULL, 0, NULL);mciSendString(_T("open resources/hit.mp3  alias hit"), NULL, 0, NULL);
}

创建地图


bool map[4][4] = {{false,false,false,false},{false,false,false,false},{false,false,false,false},{false,false,false,false},
};
int idx, idy;  //当前地鼠所在位置

false代表当前位置没有地鼠。

定义地鼠的坐标位置,锤子的坐标 ,砸中地鼠的得分,锤子的状态:

int idx, idy;  //当前地鼠所在位置
bool is_hammer_down; //锤子是否被按下
POINT pos_hammer = { 0,0 };  //锤子的坐标
int score;  //得分

逻辑部分

创建四个函数

void input_menu_scence(const ExMessage& msg)
{}
void input_game_scence(const ExMessage& msg)
{}
void render_menu_scence(const ExMessage& msg)
{putimage(0, 0, &img_menu);
}
void render_game_scence(const ExMessage& msg)
{}
void update_game_scence(const ExMessage& msg)
{}

菜单和进入游戏之间的逻辑

int main()
{.......
while (!is_quit) {ExMessage msg;while (peekmessage(&msg)){//如果当前未进入游戏,那么就进入菜单页面,否则就继续游戏if (!is_start){input_menu_scence(msg);}else{input_game_scence(msg);}}setbkcolor(RGB(251,251,251));cleardevice();  //清空绘图窗口//如果当前没有开始游戏,那么就进入菜单页面,否则就继续游戏if (!is_start){render_menu_scence(msg);}else{render_game_scence(msg);}FlushBatchDraw();Sleep(5);}}

设置按钮布局和样式以及功能

布局和样式

Button()
{
//设置按下按钮时的样式
void on_render()
{setlinecolor(RGB(20,20,20));         //设置按钮边框为深灰色if (is_pushed){setfillcolor(RGB(185,185,185));  //设置按下按钮时背景色为灰色}else if (is_hovered){setfillcolor(RGB(235,235,235));  //设置鼠标悬停时背景色为灰色}else{setfillcolor(RGB(205,205,205));  //设置普通状态下背景色为白色}fillrectangle(_rect.left, _rect.top, _rect.right, _rect.bottom);  //绘制矩形setbkmode(TRANSPARENT);  //设备背景:透明settextcolor(RGB(20,20,20)); //字体颜色drawtext(_text.c_str(), &_rect, DT_CENTER | DT_SINGLELINE | DT_VCENTER);   //绘制文本//水平居中    单行显示        垂直居中
}
}

调用

main.cpp

#include"button.h"//构建三个自定义按钮类按钮对象
Button btn_play(L"开 始 游 戏", {350,450,500,500});  //开始按钮
Button btn_info(L"游 戏 介 绍", { 350,500,500,550 });  
Button btn_quit(L"退 出 游 戏", { 350,550,500,600 });  int main()
{//对三个按钮通过调用on_input()进行设置布局和样式
void input_menu_scence(const ExMessage& msg)
{btn_play.on_input(msg);btn_info.on_input(msg);btn_quit.on_input(msg);
}//绘制这三个按钮
void render_menu_scence(const ExMessage& msg)
{putimage(0, 0, &img_menu);btn_play.on_render();btn_info.on_render();btn_quit.on_render();
}return 0;
}

按钮绑定回调函数

在初始化的时候就给按钮绑定回调函数。

button.h

class Button
{
public:Button(const std::wstring& text,const RECT& rect ){	
//设置按钮的回调函数void set_on_click(const std::function<void()>& func){on_click = func;}
}

main函数调用,单击按钮播放背景音乐

介绍按钮弹出信息弹窗。

退出按钮退出程序。

main.cpp

 int main()
{   
.....load_resource();btn_play.set_on_click([&] {is_start = true;mciSendString(_T("play bgm"),NULL,0,NULL);});btn_info.set_on_click([&] {SetForegroundWindow(hwnd);  // 确保当前窗口在最前面MessageBox(hwnd,_T("用鼠标左键点击地图上的空白位置,即可放置地鼠。\n\n游戏过程中,地鼠会自动向空白位置移动,\n\n玩家需要用锤子将地鼠击中,\n\n击中地鼠后,游戏将会加1分。\n\n游戏结束时,玩家可以选择重新开始或退出游戏。"),_T("游戏说明"),MB_OK);});btn_quit.set_on_click([&] {is_quit = true;});BeginBatchDraw();......
}

游戏主场景

砸中地鼠得分,没砸中减分

void input_game_scence(const ExMessage& msg)
{switch(msg.message){//更新鼠标位置case WM_MOUSEMOVE:pos_hammer.x = msg.x;pos_hammer.y = msg.y;break;//鼠标左键按下case WM_LBUTTONDOWN:{is_hammer_down = true;  //锤子被按下了static const int  width_mole=img_mole.getwidth();static const int height_mole = img_mole.getwidth();if (map[idx][idy]&&pos_hammer.x>=idx*width_mole+ offset_map.x&&pos_hammer.x <= (idx+1) * width_mole + offset_map.x&&pos_hammer.y >= idy * width_mole + offset_map.y&&pos_hammer.y <= (idy + 1) * width_mole + offset_map.y){score += 10;map[idx][idy] = false;  //地鼠被击中mciSendString(_T("play hit"), NULL, 0, NULL);  //播放击中音效}else{is_hammer_down = false;  //鼠标抬起切换为锤子默认状态score -= 10;}break;//鼠标左键松开case WM_LBUTTONUP:{is_hammer_down = false;  //锤子松开了}break;//键盘按下default:break;        }}
}

游戏更新

void update_game_scence(const ExMessage& msg)
{static int timer = 0;timer = timer++ % 100;  //每隔100帧触发一次地鼠移动if (timer == 0){map[idx][idy] = false;  //当前位置没有地鼠idx = rand() % 4;  //随机生成地鼠位置idy = rand() % 4;while (map[idx][idy])  //如果随机生成的位置已经有地鼠,则重新生成{idx = rand() % 4;idy = rand() % 4;}map[idx][idy] = true;  //随机生成地鼠} 
}

游戏渲染

void render_game_scence(const ExMessage& msg)
{//绘制地图static const int width_mole = img_mole.getwidth();std::cout<<"width_mole:"<<width_mole<<std::endl;static const int height_mole = img_mole.getheight();for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){std::cout<<"map[i][j]:" << map[i][j] <<std::endl;if (map[i][j])  //当前位置有地鼠{putimage(i * width_mole + offset_map.x, j * height_mole + offset_map.y, &img_mole);  //绘制地鼠std::cout<<"绘制地鼠成功"<<std::endl;}else{putimage(i * width_mole + offset_map.x, j * height_mole + offset_map.y, &img_empty);  //绘制空白位置std::cout << "绘制地鼠失败" << std::endl;}}}//绘制锤子static const int width_hammer_idle = img_hammer_idle.getwidth();static const int height_hammer__idle = img_hammer_idle.getheight();static const int width_hammer_down = img_hammer_down.getwidth();static const int height_hammer_down = img_hammer_down.getheight();if (is_hammer_down)  //锤子被按下{putimage(pos_hammer.x - width_hammer_down / 2, pos_hammer.y - height_hammer_down / 2, &img_hammer_down);}else{putimage(pos_hammer.x - width_hammer_down / 2, pos_hammer.y - height_hammer_down / 2, &img_hammer_idle);}//绘制游戏得分std::cout<<"score:"<<score<<std::endl;std::wstring score_str = L"游戏得分: "+std::to_wstring(score);settextstyle(25,0,_T("黑体"));settextcolor(RGB(255,15,105));outtextxy(10, 10, score_str.c_str());
}

此时有个问题,因为我的锤子的图片是png格式的,png的透明背景,在eaxys里会被处理为黑色背底:

我们这个时候就不用putimage()函数,用我们自己定义的函数:

void transparentimage3(IMAGE* dstimg, int x, int y, IMAGE* srcimg) //新版png
{HDC dstDC = GetImageHDC(dstimg);HDC srcDC = GetImageHDC(srcimg);int w = srcimg->getwidth();int h = srcimg->getheight();BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
}
void render_game_scence(const ExMessage& msg)
{//绘制地图static const int width_mole = img_mole.getwidth();std::cout<<"width_mole:"<<width_mole<<std::endl;static const int height_mole = img_mole.getheight();for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){std::cout<<"map[i][j]:" << map[i][j] <<std::endl;if (map[i][j])  //当前位置有地鼠{putimage(i * width_mole + offset_map.x, j * height_mole + offset_map.y, &img_mole);  //绘制地鼠std::cout<<"绘制地鼠成功"<<std::endl;}else{putimage(i * width_mole + offset_map.x, j * height_mole + offset_map.y, &img_empty);  //绘制空白位置std::cout << "绘制地鼠失败" << std::endl;}}}//绘制锤子static const int width_hammer_idle = img_hammer_idle.getwidth();static const int height_hammer__idle = img_hammer_idle.getheight();static const int width_hammer_down = img_hammer_down.getwidth();static const int height_hammer_down = img_hammer_down.getheight();if (is_hammer_down)  //锤子被按下{//putimage(pos_hammer.x - width_hammer_down / 2, pos_hammer.y - height_hammer_down / 2, &img_hammer_down);transparentimage3(NULL, pos_hammer.x - width_hammer_down / 2, pos_hammer.y - height_hammer_down / 2, & img_hammer_down);}else{//putimage(pos_hammer.x - width_hammer_down / 2, pos_hammer.y - height_hammer_down / 2, &img_hammer_idle);transparentimage3(NULL,pos_hammer.x - width_hammer_down / 2, pos_hammer.y - height_hammer_down / 2, &img_hammer_idle);}//绘制游戏得分std::cout<<"score:"<<score<<std::endl;std::wstring score_str = L"游戏得分: "+std::to_wstring(score);settextstyle(25,0,_T("黑体"));settextcolor(RGB(255,15,105));outtextxy(10, 10, score_str.c_str());
}


http://www.ppmy.cn/ops/143050.html

相关文章

MR30分布式 IO 模块:硅晶行业电池片导片机的智能 “心脏”

硅晶产业作为全球能源和电子领域的基石&#xff0c;其生产规模庞大且工艺复杂。从硅料的提纯、拉晶&#xff0c;到硅片的切割、电池片的制造&#xff0c;每一个环节都要求高精度与高稳定性。在电池片生产环节&#xff0c;导片机承担着硅片传输与定位的重要任务&#xff0c;其运…

短波红外相机

短波红外相机搭载采用 SenSWIR 技术的 Sony 高灵敏度传感器&#xff0c;能捕获到400nm~1700nm范围的可见光-短波红外宽波段图像信息&#xff0c;该相机可替代传统的“可见光相机短波红外相机”双相机检测方案&#xff0c;降低系统成本、提高处理速度、扩大检测范围&#xff0c;…

opencv Canny边缘检测

canny阈值越高,检测到的边缘数量越少 # 导入OpenCV库&#xff0c;用于图像处理 import cv2 import numpy as np # 从matplotlib库中导入pyplot模块&#xff0c;用于绘制图像 from matplotlib import pyplot as plt # 创建一个名为window的窗口&#xff0c;窗口大小自…

Web 毕设篇-适合小白、初级入门练手的 Spring Boot Web 毕业设计项目:教室信息管理系统(前后端源码 + 数据库 sql 脚本)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 1.0 项目介绍 开发工具&#xff1a;IDEA、VScode 服务器&#xff1a;Tomcat&#xff0c; JDK 17 项目构建&#xff1a;maven 数据库&#xff1a;mysql 8.0 系统用户前台和管理…

Linux应用开发————mysql数据库表

mysql数据库表操作 查看表的结构 mysql> desc / describe 表名; 或者&#xff1a; mysql> show create table 表名; 常见数据库引擎&#xff1a; innodb, myISAM... 删除表 mysql> drop tabl…

UOS AI 2.0 发布,开启原生 AIOS 时代!

PC 终端作为最主流最高频的生产力工具&#xff0c;其操作系统承载着用户的大量场景、数据以及技能。随着生成式人工智能浪潮的来临&#xff0c;新的技术架构、交互模式和新的生态&#xff0c;都需要操作系统承担起更多责任&#xff0c;即需要新一代的操作系统产品 ——AIOS&…

纯CSS实现文本或表格特效(连续滚动与首尾相连)

纯CSS实现文本连续向左滚动首尾相连 1.效果图&#xff1a; 2.实现代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, init…

中阳科技:量化交易模型的探索与发展前景

在数字化浪潮的推动下&#xff0c;金融市场迎来了一场技术革命。量化交易作为融合金融与科技的产物&#xff0c;正在全球范围内深刻改变交易方式和市场格局。中阳科技通过不断优化量化模型和算法技术&#xff0c;正在引领智能化交易的新方向。 量化交易的核心概念 量化交易是…