如何解决如何呈现开始菜单?用户需要按一个键才能开始游戏
我正在做一项需要使用 C++ 进行 OOP 游戏概念的作业。但是,我无法呈现另一个菜单,该菜单需要用户按下游戏键才能开始。这是当前的代码实现。我还提供了一些屏幕截图以提供更清晰的上下文(见图)
到目前为止,每当我运行该程序时,游戏都会自动启动,并且石头会开始掉落。但是,我希望实现一个弹出菜单,要求玩家按 ENTER 按钮开始游戏。
#include "Engine.h"
#include "Graphics\TextureManager.h"
#include "Inputs\Input.h"
#include "Characters\Warrior.h"
#include "DeltaTime\DeltaTime.h"
#include "Map\MapParser.h"
#include <iostream>
#include "SDL_image.h"
#include "Camera/Camera.h"
#include "Characters/Rocks.h"
#include "SDL.h"
#include <string>
#include "Characters/Rocks.h"
#include "UILabel/UILabel.h"
#include "SDL_ttf.h"
//initialise the instance because this is a static object
Engine* Engine::s_Instance = nullptr;
Warrior* player;
Rocks* rock;
std::vector<Rocks*> fallingRocks;
int points;
bool Engine::Init()
{
//We need to initialise SDL and ensure that SDL is properly initialise
//So we always check to see if SDL was initialise properly
if (SDL_Init(SDL_INIT_VIDEO) != 0 && IMG_Init(IMG_INIT_JPG || IMG_INIT_PNG) != 0)
{
//when sdl init is unsuccessful it returns !0
SDL_Log("Failed to initialize SDL: %s",SDL_GetError());
return false;
}
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
//create window
m_Window = SDL_CreateWindow("Bullet Barrage",SDL_WINDOWPOS_CENTERED,SCREEN_WIDTH,SCREEN_HEIGHT,window_flags);
if (m_Window == nullptr)
{
//window not initialised
SDL_Log("Failed to create window SDL: %s",SDL_GetError());
return false;
}
//create renderer
m_Renderer = SDL_CreateRenderer(m_Window,-1,SDL_RENDERER_ACCELERATED || SDL_RENDERER_PRESENTVSYNC);
if (m_Renderer == nullptr)
{
//renderer not initialised
SDL_Log("Failed to create renderer SDL: %s",SDL_GetError());
return false;
}
//check if map generator is working
if (!MapParser::GetInstance()->Load()) {
std::cout << "Failed to load map" << std::endl;
return false;
}
//use the id from map generator to generate the map
m_LevelMap = MapParser::GetInstance()->GetMap("level1");
//check if font is loaded properly
if (TTF_Init() == -1) {
std::cout << "Error: SDL_TTF" << std::endl;
}
//load map texture
TextureManager::GetInstance()->Load("background","assets/maps/BG.png");
TextureManager::GetInstance()->Load("player","assets/adventurer.png");
TextureManager::GetInstance()->Load("rock","assets/Lava.png");
TextureManager::GetInstance()->Load("end","assets/gameover.png");
//load font
TextureManager::GetInstance()->AddFont("arial","assets/arial.ttf",30);
//start state of player is idle,animation is idle
//load image of player
player = new Warrior(new Properties("player",100,560,50,37)); //initialise player
for (int i = 0; i < TOTALROCKS; ++i) {
int temp = rand() % 1024;
int temp2 = rand() % 100+49;
rock = new Rocks(new Properties("rock",temp,-200,temp2,temp2),rand() %6+2); //x,y,w,h
fallingRocks.push_back(rock);
}
//Camera::GetInstance()->SetTarget(player->Getorigin());
}
void Engine::Render()
{
if (player_dead == false) {
SDL_RenderClear(m_Renderer);
//render background
TextureManager::GetInstance()->Draw("background",1024,640);
// Show score top right (Fm)
SDL_Color color = { 0,0 };
std::string result = "Current score = " + std::to_string(points);
UILabel test(750,20,result,"arial",color);
test.draw();
// Show Life top right (Fm)
std::string result2 = "Current HP = " + std::to_string(player->health);
UILabel test2(750,result2,color);
test2.draw();
//throw loaded map onto the screen
for (int i = 0; i < TOTALROCKS; ++i) {
fallingRocks[i]->Draw();
}
m_LevelMap->Render();
player->Draw(); //draw player
}
else {
SDL_Color color= { 0,0 };
std::string result = "Total score = " + std::to_string(points);
UILabel test(380,380,color);
test.draw();
TextureManager::GetInstance()->Draw("end",270,500,250);
//TTF_Font* font = TTF_OpenFont("assets/arial.ttf",24); //this opens a font style and sets a size
//SDL_Color White = { 255,0}; // this is the color in rgb format,maxing out all would give you the color white,and it will be your text's color
//SDL_Surface* surfaceMessage = TTF_RenderText_Solid(font,"put your text here",White); // as TTF_RenderText_Solid Could only be used on SDL_Surface then you have to create the surface first
//SDL_Texture* Message = SDL_CreateTextureFromSurface(Engine::GetInstance()->GetRenderer(),surfaceMessage); //Now you can convert it into a texture
//SDL_Rect Message_rect; //create a rect
//Message_rect.x = 0; //controls the rect's x coordinate
//Message_rect.y = 0; // controls the rect's y coordinte
//Message_rect.w = 100; // controls the width of the rect
//Message_rect.h = 100; // controls the height of the rect
////Mind you that (0,0) is on the top left of the window/screen,think a rect as the text's Box,that way it would be very simple to understand
////Now since it's a texture,you have to put Rendercopy in your game loop area,the area where the whole code executes
//SDL_Rendercopy(Engine::GetInstance()->GetRenderer(),Message,NULL,&Message_rect);
}
//player died,so draw out menu
//just rendering some random color
SDL_SetRenderDrawColor(m_Renderer,124,218,254,255);
SDL_RenderPresent(m_Renderer);
//points == total rocks dodge. do a congrats u died u dodge xx rocks
}
void Engine::Update()
{
if (player_dead == false) {
float dt = DeltaTime::GetInstance()->GetDeltaTime(); //store delta time into dt
//use delta time as parameter ensure that it runs smoothly from com to com
m_LevelMap->Update();
player->CheckCollision(rock->getBox());
player->Update(dt);
if (player->health == 0) {
player_dead = true;
}
for (int i = 0; i < TOTALROCKS; ++i) {
if (player->CheckCollision(fallingRocks[i]->getBox())) {
//remove object and reinsert
fallingRocks[i] = nullptr;
int temp = rand() % 1024;
int temp2 = rand() % 100 + 49;
rock = new Rocks(new Properties("rock",rand() % 6 + 2); //x,h
fallingRocks[i] = rock;
}
if (fallingRocks[i]->offScreen()) {
fallingRocks[i] = nullptr;
int temp = rand() % 1024;
int temp2 = rand() % 100 + 49;
rock = new Rocks(new Properties("rock",h
fallingRocks[i] = rock;
points++;
}
fallingRocks[i]->Update(dt);
}
}
//Camera::GetInstance()->Update(dt);
}
void Engine::Events()
{
Input::GetInstance()->Listen(); //listen for player inputs.
}
bool Engine::Clean()
{
//when clean function is called from main
//will destriy and clean up all textures to free memory
TextureManager::GetInstance()->Clean();
MapParser::GetInstance()->Clean();
SDL_DestroyRenderer(m_Renderer);
SDL_DestroyWindow(m_Window);
IMG_Quit();
SDL_Quit();
return true;
}
void Engine::Quit()
{
m_IsRunning = false; //set isrunning to false to stop the event
}
解决方法
我这样做的方法是创建一些像这样的位标志:
enum GameFlags {
Menu = 0x01,Gameplay = 0x02
};
现在只需在主要游戏的代码周围添加一个 if 语句,如下所示:
if (flag & GameFlags::Gameplay) { }
然后菜单代码也一样。因此,您可以将标志变量初始化为菜单,然后在用户使用 sdl 事件单击时将其更改为游戏玩法。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。