C++实验课任务基于IMGUI的可视化小游戏
C++实验课任务基于IMGUI的可视化小游戏
-
运行环境: VS 2019
-
下面是核心文件air_combat_demo.cpp的分析, 具体分析见代码中以"/**/"注释的部分
-
对于黄色球如何调用红色球的位置坐标, 如果有别的方法, 欢迎在下方留言告知, 本人能力有限只想到了一种最简单的
-
具体源文件见源代码
//这是一个教学示范,属于CSU,2020秋,《面向对象编程(C++)》。
// 这个教学示范针对基于ImGUI的图形界面编程,并对继承和多态进行复习
// 请填充标记了“请填充此处代码”的代码
// by Lei, 2020-11-20#include "imgui.h"
#include
#include //用于获得随机数
#include
#include std::default_random_engine generator;//全局变量,用于生成随机数,因为这个游戏需要一定的随机性,比如随机运动的敌方
std::uniform_int_distribution<int> distribution(0, 100);//全局变量,用于生成均匀分布的随机数/*用于保存玩家的当前位置,设置成全局变量方便之后的FollowPlayerCircle类访问玩家的位置*/
double player_current_pos_x;
double player_current_pos_y;//飞行物的抽象类,所有派生类都是圆形的,这样便于进行碰撞检测。
class AbstractCircle
{
protected:ImVec2 _pos;//位置float _radius;//半径ImDrawList* _pen;//用于绘制的画笔,是ImGui库中的底层绘图对象。
public:AbstractCircle(ImDrawList* pen, ImVec2 pos, float radius) :_pen(pen), _pos(pos), _radius(radius) {};virtual void draw_self() = 0;//绘制自己virtual void live_step(double time) = 0;//度过一个时间片。在每个时间片中可以运动、可以改变。virtual std::string get_class_name() { return "AbstractCircle"; }//获得对象的类别名ImVec2 get_pos() { return _pos; }//获得当前位置float get_radius() { return _radius; }//获得半径
};class PlayerCircle : public AbstractCircle
{
private:float _speed = 1;//每次用户按键时的移动步长
public:PlayerCircle(ImDrawList* pen, ImVec2 pos, float radius) :AbstractCircle(pen, pos, radius) {};void draw_self() {_pen->AddCircleFilled(_pos, _radius, IM_COL32(255, 0, 0, 200));//就是一个简单的红色实心圆}void live_step(double time){//根据用户的输入改变位置if (ImGui::IsKeyPressed(37))//用户按下左箭头按键_pos.x -= _speed;if (ImGui::IsKeyPressed(39))//用户按下右箭头按键_pos.x += _speed;if (ImGui::IsKeyPressed(38))//用户按下上箭头按键_pos.y -= _speed;if (ImGui::IsKeyPressed(40))//用户按下下箭头按键_pos.y += _speed;}std::string get_class_name() { return "PlayerCircle"; }void set_speed(float speed) { _speed = speed; }//设置运动速度
};class RandomMoveCircle :public AbstractCircle
{
private:float _speed = 1;//每个时间片的运动步长
public:RandomMoveCircle(ImDrawList* pen, ImVec2 pos, float radius) : AbstractCircle(pen, pos, radius) {};void draw_self() {_pen->AddCircleFilled(_pos, _radius, IM_COL32(0, 0, 0, 200));//就是一个简单的黑色实心圆}void live_step(double time){//获得一个随机的水平方向,并沿该方向移动一个步长bool bLeft = distribution(generator) > 49;_pos.x = bLeft ? _pos.x - _speed : _pos.x + _speed;//获得一个随机的竖直方向,并沿该方向移动一个步长bool bUp = distribution(generator) > 49;_pos.y = bUp ? _pos.y - _speed : _pos.y + _speed;}std::string get_class_name() { return "RandomMoveCircle"; }void set_speed(float speed) { _speed = speed; }
};/* 请填充此处代码 -- 从AbstractCircle派生类FollowPlayerCircle
* 这个派生类能够在每个时间片朝玩家的红色圆球方向移动一个步长
* 要求这类小球以黄色填充圆显示,大小与红球和黑球一样。
* 要能够在设置窗口中设置这类小球的移动步长和数量。
* 要在函数AirCombatWindow的游戏初始化部分,创建并添加指定数量的这类小球
*
* !!!注意:这个要求比较难,建议你填充完其他部分的代码后再来尝试。
*//*下面的这个类仿照上面RandomMoveCircle类的写法即可,唯一要注意的是FollowPlayerCircle类中的黄色小球的移动方式不同*/
class FollowPlayerCircle :public AbstractCircle/*注意要public继承,否则会报错*/
{
private:float _speed = 1;
public:FollowPlayerCircle(ImDrawList* pen, ImVec2 pos, float radius) : AbstractCircle(pen, pos, radius) {};void draw_self(){_pen->AddCircleFilled(_pos, _radius, IM_COL32(255, 255, 0, 200));/*就是一个简单的黄色实心圆,这里的IM_COL32(255, 255, 0, 200)里面的前三个参数是RGB编码(即红色+绿色+蓝色三个颜色的值混合)*/}/**下面的成员函数是本次实验最难的部分,难点在于如何调访问玩家当前的位置*如果在live_step中传入玩家的x和y坐标,由于对应的x和y坐标都是函数里的静态变量,没有访问权限*且在该类的父类AbstractCircle中的live_step是抽象方法,不能调用静态变量,所以如何传入玩家当前的位置则是问题的关键*/void live_step(double time){_pos.x = player_current_pos_x > _pos.x ? _pos.x + 1 : _pos.x - 1;_pos.y = player_current_pos_y > _pos.y ? _pos.y + 1 : _pos.y - 1;}std::string get_class_name() { return "FollowPlayerCircle"; }void set_speed(float speed) { _speed = speed; }
};//全局变量
std::vector<AbstractCircle*> circles;//保存所有的飞行物对象,包括玩家。注意这是一个全局变量,//我们会在main.cpp的程序结束时手工delete该列表中的每个对象。
float player_speed = 5.0f;//玩家的移动速度
float random_circle_speed = 5.0f;//随机运动小球的速度
int num_random_circle = 20;//随机运动小球的数量
int num_follow_circle = 20;/*朝玩家运动小球的数量*/
float follow_circle_speed = 5.0f;/*朝玩家运动小球的速度*/void reset_game()//重置游戏
{//重置所有参数player_speed = 5.0f;random_circle_speed = 5.0f;//释放所有飞行物对象for (auto o : circles){delete o;}circles.clear();
};//游戏的主函数
void AirCombatWindow()
{static PlayerCircle* player = NULL;//保存指向玩家红色小球的指针 static bool bPauseGame = false;//标记是否要暂停游戏//进行游戏的初始化ImDrawList* pen = ImGui::GetBackgroundDrawList();//获得画笔对象ImVec2 screen_size = ImGui::GetIO().DisplaySize;if (circles.size() == 0){//创建玩家player = new PlayerCircle(pen, ImVec2(screen_size.x / 2, screen_size.y), 30);circles.push_back(player);//创建10个随机运动的RandomMoveCircle对象for (int i = 0; i < num_random_circle; i++){float rand_x = distribution(generator) / 100.0 * screen_size.x;RandomMoveCircle* obj = new RandomMoveCircle(pen, ImVec2(rand_x, 300), 30);circles.push_back(obj);}/*创建10个朝用户运动的FollowPlayerCircle对象*//*这个可以仿照上面的那个for循环写,把random相应的部分换成follow对应的部分*/for (int i = 0; i < num_follow_circle; i++){float rand_x = distribution(generator) / 100.0 * screen_size.x;FollowPlayerCircle* obj = new FollowPlayerCircle(pen, ImVec2(rand_x, 300), 30);circles.push_back(obj);}}// 创建一个控制面板窗口,在这个窗口中可以设置游戏的一些参数ImGui::Begin(u8"飞出重围"); // Create a window called "Hello, world!" and append into it.ImGui::Text(u8"你的任务就是:要控制红色圆球来躲避敌方飞行物,并移动到窗口顶部.\n\n你可以通过箭头按键来控制下方的红色圆球。\n\n其中黄球可以跟随红球移动\n \\n 失败条件:红色圆球碰到了其他飞行物;\n 成功条件:红色圆球移动到了窗口顶部");ImGui::Separator();ImGui::SliderFloat(u8"玩家速度", &player_speed, 0.0f, 20.0f); // Edit 1 float using a slider from 0.0f to 1.0fImGui::SliderInt(u8"黑色飞行物的数量", &num_random_circle, 10, 100);ImGui::SliderFloat(u8"黑色飞行物速度", &random_circle_speed, 0.0f, 20.0f);ImGui::SliderInt(u8"黄色飞行物的数量", &num_follow_circle, 10, 100); /*在设置面板添加黄色飞行物的数量*/ImGui::SliderFloat(u8"黄色飞行物的速度", &follow_circle_speed, 0.0f, 20.0f);/*在设置面板添加黄色飞行物的速度*/ImGui::Checkbox(u8"暂停游戏", &bPauseGame);if (ImGui::Button(u8"重置游戏")) // Buttons return true when clicked (most widgets return true when edited/activated){reset_game();}ImGui::End();// 根据窗口中的用户设置,调整每个对象的属性。注意:对象数量不能随时改变,而是在每次重置时生效。for (auto obj : circles){std::string name = obj->get_class_name();if (name == "RandomMoveCircle")((RandomMoveCircle*)obj)->set_speed(random_circle_speed);if (name == "PlayerCircle")((PlayerCircle*)obj)->set_speed(player_speed);if (name == "FollowPlayerCirle")/*添加FollowPlayerCirle类相应的重置操作*/((FollowPlayerCircle*)obj)->set_speed(follow_circle_speed);}// 让所有的飞行对象活一个时间片,并且绘制自己for (auto obj : circles){/*这里一定要添加对玩家位置的更新,以便于FollowPlayerCirle类中live_step方法对玩家位置的访问*/player_current_pos_x = (player->get_pos()).x;player_current_pos_y = (player->get_pos()).y;if (!bPauseGame){obj->live_step(ImGui::GetTime());}obj->draw_self();}// 进行碰撞检测,一旦发现红色小球被碰撞,就弹出游戏失败窗口,并且重置游戏bool bGameEnd = false;for (auto obj : circles){if (obj->get_class_name() != "PlayerCircle"&& obj->get_class_name() != "FollowPlayerCircle"){float dist_required = obj->get_radius() + player->get_radius();ImVec2 pos1, pos2;pos1 = obj->get_pos();pos2 = player->get_pos();float dist_real = sqrt((pos1.x - pos2.x) * (pos1.x - pos2.x) + (pos1.y - pos2.y) * (pos1.y - pos2.y));if (dist_real < dist_required){bGameEnd = true;bPauseGame = true;break;}}}if (bGameEnd){//显示对话框,提示玩家,游戏已经结束。ImGui::OpenPopup(u8"失败!");if (ImGui::BeginPopupModal(u8"失败!", NULL, ImGuiWindowFlags_AlwaysAutoResize)){ImGui::Text(u8"游戏结束了\n\n游戏将重新开始\n");ImGui::Separator();if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); reset_game(); bPauseGame = false; }ImGui::SetItemDefaultFocus();ImGui::EndPopup();}}/* 请填充此处代码 -- 对游戏是否成功进行判断,一旦成功,就弹出对话框提示用户,并重置游戏* 游戏成功的条件是:红色小球的边缘触碰到窗口顶部**//*下面的游戏是否成功可以仿照上面游戏是否结束的部分* 从上面的游戏是否结束的部分可以发现其分为两个部分:* 一部分是设置bGameEnd参数,并对参数bGameEnd是否更新进行判断,如果需要更新bGameEnd的值,则需将bPauseGame设置成true即中止程序* 一部分是如果满足游戏结束的条件,则输出相应的提示信息并重置是否重新开始游戏* 发现了上面的规律后下面的原理也是类似的,唯一的不同点是判断条件不同:游戏成功的判断条件为玩家的小球的纵坐标小于半径* 最后记得要将改过的bPauseGame还原*/bool bGameSuccess = false;ImVec2 pos_player;/*存储玩家的位置*/float _radius_player;/*存储玩家小球的半径*/pos_player = player->get_pos();_radius_player = player->get_radius();if (pos_player.y <= _radius_player){bGameSuccess = true;bPauseGame = true;}if (bGameSuccess){//显示对话框,提示玩家,游戏成功。ImGui::OpenPopup(u8"成功!");if (ImGui::BeginPopupModal(u8"成功!", NULL, ImGuiWindowFlags_AlwaysAutoResize)){ImGui::Text(u8"游戏成功了\n\n游戏将重新开始\n");ImGui::Separator();if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); reset_game(); bPauseGame = false; }ImGui::SetItemDefaultFocus();ImGui::EndPopup();}}
}
- 根据评论区提供的思路, 对球与球之间不互相重叠功能的实现具体如下
//这是一个教学示范,属于CSU,2020秋,《面向对象编程(C++)》。
// 这个教学示范针对基于ImGUI的图形界面编程,并对继承和多态进行复习
// 请填充标记了“请填充此处代码”的代码
// by Lei, 2020-11-20#include "imgui.h"
#include
#include //用于获得随机数
#include
#include std::default_random_engine generator;//全局变量,用于生成随机数,因为这个游戏需要一定的随机性,比如随机运动的敌方
std::uniform_int_distribution<int> distribution(0, 100);//全局变量,用于生成均匀分布的随机数/*用于保存玩家的当前位置,设置成全局变量方便之后的FollowPlayerCircle类访问玩家的位置*/
double player_current_pos_x;
double player_current_pos_y;//飞行物的抽象类,所有派生类都是圆形的,这样便于进行碰撞检测。
class AbstractCircle
{
protected:ImVec2 _pos;//位置float _radius;//半径ImDrawList* _pen;//用于绘制的画笔,是ImGui库中的底层绘图对象。
public:AbstractCircle(ImDrawList* pen, ImVec2 pos, float radius) :_pen(pen), _pos(pos), _radius(radius) {};virtual void draw_self() = 0;//绘制自己virtual void live_step(double time) = 0;//度过一个时间片。在每个时间片中可以运动、可以改变。virtual std::string get_class_name() { return "AbstractCircle"; }//获得对象的类别名static void reset_pos(std::vector<AbstractCircle*>& obj);/*声明让黑色球和黄色球互不重叠函数*/ImVec2 get_pos() { return _pos; }//获得当前位置float get_radius() { return _radius; }//获得半径
};class PlayerCircle : public AbstractCircle
{
private:float _speed = 1;//每次用户按键时的移动步长
public:PlayerCircle(ImDrawList* pen, ImVec2 pos, float radius) :AbstractCircle(pen, pos, radius) {};void draw_self() {_pen->AddCircleFilled(_pos, _radius, IM_COL32(255, 0, 0, 200));//就是一个简单的红色实心圆}void live_step(double time){//根据用户的输入改变位置if (ImGui::IsKeyPressed(37))//用户按下左箭头按键_pos.x -= _speed;if (ImGui::IsKeyPressed(39))//用户按下右箭头按键_pos.x += _speed;if (ImGui::IsKeyPressed(38))//用户按下上箭头按键_pos.y -= _speed;if (ImGui::IsKeyPressed(40))//用户按下下箭头按键_pos.y += _speed;}std::string get_class_name() { return "PlayerCircle"; }void set_speed(float speed) { _speed = speed; }//设置运动速度
};class RandomMoveCircle :public AbstractCircle
{
private:float _speed = 1;//每个时间片的运动步长
public:RandomMoveCircle(ImDrawList* pen, ImVec2 pos, float radius) : AbstractCircle(pen, pos, radius) {};void draw_self() {_pen->AddCircleFilled(_pos, _radius, IM_COL32(0, 0, 0, 200));//就是一个简单的黑色实心圆}void live_step(double time){//获得一个随机的水平方向,并沿该方向移动一个步长bool bLeft = distribution(generator) > 49;_pos.x = bLeft ? _pos.x - _speed : _pos.x + _speed;//获得一个随机的竖直方向,并沿该方向移动一个步长bool bUp = distribution(generator) > 49;_pos.y = bUp ? _pos.y - _speed : _pos.y + _speed;}std::string get_class_name() { return "RandomMoveCircle"; }void set_speed(float speed) { _speed = speed; }
};/* 请填充此处代码 -- 从AbstractCircle派生类FollowPlayerCircle
* 这个派生类能够在每个时间片朝玩家的红色圆球方向移动一个步长
* 要求这类小球以黄色填充圆显示,大小与红球和黑球一样。
* 要能够在设置窗口中设置这类小球的移动步长和数量。
* 要在函数AirCombatWindow的游戏初始化部分,创建并添加指定数量的这类小球
*
* !!!注意:这个要求比较难,建议你填充完其他部分的代码后再来尝试。
*//*下面的这个类仿照上面RandomMoveCircle类的写法即可,唯一要注意的是FollowPlayerCircle类中的黄色小球的移动方式不同*/
class FollowPlayerCircle :public AbstractCircle/*注意要public继承,否则会报错*/
{
private:float _speed = 1;
public:FollowPlayerCircle(ImDrawList* pen, ImVec2 pos, float radius) : AbstractCircle(pen, pos, radius) {};void draw_self(){_pen->AddCircleFilled(_pos, _radius, IM_COL32(255, 255, 0, 200));/*就是一个简单的黄色实心圆,这里的IM_COL32(255, 255, 0, 200)里面的前三个参数是RGB编码(即红色+绿色+蓝色三个颜色的值混合)*/}/**下面的成员函数是本次实验最难的部分,难点在于如何调访问玩家当前的位置*如果在live_step中传入玩家的x和y坐标,由于对应的x和y坐标都是函数里的静态变量,没有访问权限*且在该类的父类AbstractCircle中的live_step是抽象方法,不能调用静态变量,所以如何传入玩家当前的位置则是问题的关键*/void live_step(double time){_pos.x = player_current_pos_x > _pos.x ? _pos.x + 1 : _pos.x - 1;_pos.y = player_current_pos_y > _pos.y ? _pos.y + 1 : _pos.y - 1;}std::string get_class_name() { return "FollowPlayerCircle"; }void set_speed(float speed) { _speed = speed; }
};//全局变量
std::vector<AbstractCircle*> circles;//保存所有的飞行物对象,包括玩家。注意这是一个全局变量,//我们会在main.cpp的程序结束时手工delete该列表中的每个对象。
float player_speed = 5.0f;//玩家的移动速度
float random_circle_speed = 5.0f;//随机运动小球的速度
int num_random_circle = 20;//随机运动小球的数量
int num_follow_circle = 20;/*朝玩家运动小球的数量*/
float follow_circle_speed = 5.0f;/*朝玩家运动小球的速度*/void reset_game()//重置游戏
{//重置所有参数player_speed = 5.0f;random_circle_speed = 5.0f;//释放所有飞行物对象for (auto o : circles){delete o;}circles.clear();
};/*让球与球之间(不包括红球)互不重叠,原理为如果两球的距离小于两者的半径之和则各退一个半径*/
void AbstractCircle::reset_pos(std::vector<AbstractCircle*>& obj)
{for (std::vector<AbstractCircle*>::iterator i = obj.begin() + 1; obj.end() != i; i++)/*这里面的std::vector::iterator i也可以换成auto i*/ {for (auto j = i + 1; obj.end() != j; j++){float x1 = (*i)->get_pos().x, x2 = (*j)->get_pos().x;float y1 = (*i)->get_pos().y, y2 = (*j)->get_pos().y;float radius1 = (*i)->get_radius();float radius2 = (*j)->get_radius();float distence = pow(x1 - x2, 2) + pow(y1 - y2, 2) - pow(radius1 + radius2, 2);if (distence < 0){if (x1 < x2){(*i)->_pos.x -= radius1;(*j)->_pos.x += radius2;}else{(*i)->_pos.x += radius1;(*j)->_pos.x -= radius2;}if (y1 < y2){(*i)->_pos.y -= radius1;(*j)->_pos.y += radius2;}else{(*i)->_pos.y += radius1;(*j)->_pos.y -= radius2;}}}}
}//游戏的主函数
void AirCombatWindow()
{static PlayerCircle* player = NULL;//保存指向玩家红色小球的指针 static bool bPauseGame = false;//标记是否要暂停游戏//进行游戏的初始化ImDrawList* pen = ImGui::GetBackgroundDrawList();//获得画笔对象ImVec2 screen_size = ImGui::GetIO().DisplaySize;if (circles.size() == 0){//创建玩家player = new PlayerCircle(pen, ImVec2(screen_size.x / 2, screen_size.y), 30);circles.push_back(player);//创建10个随机运动的RandomMoveCircle对象for (int i = 0; i < num_random_circle; i++){float rand_x = distribution(generator) / 100.0 * screen_size.x;RandomMoveCircle* obj = new RandomMoveCircle(pen, ImVec2(rand_x, 300), 30);circles.push_back(obj);}/*创建10个朝用户运动的FollowPlayerCircle对象*//*这个可以仿照上面的那个for循环写,把random相应的部分换成follow对应的部分*/for (int i = 0; i < num_follow_circle; i++){float rand_x = distribution(generator) / 100.0 * screen_size.x;FollowPlayerCircle* obj = new FollowPlayerCircle(pen, ImVec2(rand_x, 300), 30);circles.push_back(obj);}}// 创建一个控制面板窗口,在这个窗口中可以设置游戏的一些参数ImGui::Begin(u8"飞出重围"); // Create a window called "Hello, world!" and append into it.ImGui::Text(u8"你的任务就是:要控制红色圆球来躲避敌方飞行物,并移动到窗口顶部.\n\n你可以通过箭头按键来控制下方的红色圆球。\n\n其中黄球可以跟随红球移动\n \\n 失败条件:红色圆球碰到了其他飞行物;\n 成功条件:红色圆球移动到了窗口顶部");ImGui::Separator();ImGui::SliderFloat(u8"玩家速度", &player_speed, 0.0f, 20.0f); // Edit 1 float using a slider from 0.0f to 1.0fImGui::SliderInt(u8"黑色飞行物的数量", &num_random_circle, 10, 100);ImGui::SliderFloat(u8"黑色飞行物速度", &random_circle_speed, 0.0f, 20.0f);ImGui::SliderInt(u8"黄色飞行物的数量", &num_follow_circle, 10, 100); /*在设置面板添加黄色飞行物的数量*/ImGui::SliderFloat(u8"黄色飞行物的速度", &follow_circle_speed, 0.0f, 20.0f);/*在设置面板添加黄色飞行物的速度*/ImGui::Checkbox(u8"暂停游戏", &bPauseGame);if (ImGui::Button(u8"重置游戏")) // Buttons return true when clicked (most widgets return true when edited/activated){reset_game();}ImGui::End();// 根据窗口中的用户设置,调整每个对象的属性。注意:对象数量不能随时改变,而是在每次重置时生效。for (auto obj : circles){std::string name = obj->get_class_name();if (name == "RandomMoveCircle")((RandomMoveCircle*)obj)->set_speed(random_circle_speed);if (name == "PlayerCircle")((PlayerCircle*)obj)->set_speed(player_speed);if (name == "FollowPlayerCirle")/*添加FollowPlayerCirle类相应的重置操作*/((FollowPlayerCircle*)obj)->set_speed(follow_circle_speed);}// 让所有的飞行对象活一个时间片,并且绘制自己for (auto obj : circles){/*这里一定要添加对玩家位置的更新,以便于FollowPlayerCirle类中live_step方法对玩家位置的访问*/player_current_pos_x = (player->get_pos()).x;player_current_pos_y = (player->get_pos()).y;if (!bPauseGame){obj->live_step(ImGui::GetTime());}obj->draw_self();}AbstractCircle::reset_pos(circles);// 进行碰撞检测,一旦发现红色小球被碰撞,就弹出游戏失败窗口,并且重置游戏bool bGameEnd = false;for (auto obj : circles){if (obj->get_class_name() != "PlayerCircle"&& obj->get_class_name() != "FollowPlayerCircle"){float dist_required = obj->get_radius() + player->get_radius();ImVec2 pos1, pos2;pos1 = obj->get_pos();pos2 = player->get_pos();float dist_real = sqrt((pos1.x - pos2.x) * (pos1.x - pos2.x) + (pos1.y - pos2.y) * (pos1.y - pos2.y));if (dist_real < dist_required){bGameEnd = true;bPauseGame = true;break;}}}if (bGameEnd){//显示对话框,提示玩家,游戏已经结束。ImGui::OpenPopup(u8"失败!");if (ImGui::BeginPopupModal(u8"失败!", NULL, ImGuiWindowFlags_AlwaysAutoResize)){ImGui::Text(u8"游戏结束了\n\n游戏将重新开始\n");ImGui::Separator();if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); reset_game(); bPauseGame = false; }ImGui::SetItemDefaultFocus();ImGui::EndPopup();}}/* 请填充此处代码 -- 对游戏是否成功进行判断,一旦成功,就弹出对话框提示用户,并重置游戏* 游戏成功的条件是:红色小球的边缘触碰到窗口顶部**//*下面的游戏是否成功可以仿照上面游戏是否结束的部分* 从上面的游戏是否结束的部分可以发现其分为两个部分:* 一部分是设置bGameEnd参数,并对参数bGameEnd是否更新进行判断,如果需要更新bGameEnd的值,则需将bPauseGame设置成true即中止程序* 一部分是如果满足游戏结束的条件,则输出相应的提示信息并重置是否重新开始游戏* 发现了上面的规律后下面的原理也是类似的,唯一的不同点是判断条件不同:游戏成功的判断条件为玩家的小球的纵坐标小于半径* 最后记得要将改过的bPauseGame还原*/bool bGameSuccess = false;ImVec2 pos_player;/*存储玩家的位置*/float _radius_player;/*存储玩家小球的半径*/pos_player = player->get_pos();_radius_player = player->get_radius();if (pos_player.y <= _radius_player){bGameSuccess = true;bPauseGame = true;}if (bGameSuccess){//显示对话框,提示玩家,游戏成功。ImGui::OpenPopup(u8"成功!");if (ImGui::BeginPopupModal(u8"成功!", NULL, ImGuiWindowFlags_AlwaysAutoResize)){ImGui::Text(u8"游戏成功了\n\n游戏将重新开始\n");ImGui::Separator();if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); reset_game(); bPauseGame = false; }ImGui::SetItemDefaultFocus();ImGui::EndPopup();}}
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
