在SFML(C++)中启动一个新窗口

Launching a new window in SFML (C++)

本文关键字:新窗口 一个 窗口 启动 SFML C++      更新时间:2023-10-16

这学期我们必须用C++做一个游戏。作为C++游戏开发专业的大三学生,我选择了SFML进行图形处理(这是个好选择吗?(。一切都开始得很好,我做了菜单和按钮等等。但当我点击这个按钮时,我的窗口就关闭了。我想打开一扇新窗户。有人能帮我吗?

谢谢。

#include <iostream>
#include <SFML/Graphics.hpp>
#include "Button.h"
#include "game.h"
using namespace std;
int main() {
sf::RenderWindow window;
sf::Color Color;
sf::Vector2i centerWindow((sf::VideoMode::getDesktopMode().width / 2) - 445, (sf::VideoMode::getDesktopMode().height / 2) - 480);
window.create(sf::VideoMode(900, 900), "SFML Textbox", sf::Style::Titlebar | sf::Style::Close);
window.setPosition(centerWindow);
window.setKeyRepeatEnabled(true);
sf::Font font;
if (!font.loadFromFile("font.ttf"))
std::cout << "Font not found!n";
//Création de l'image
sf::Texture texture[1];
texture[0].loadFromFile("logo.jpg");
sf::RectangleShape rectangle;
sf::Sprite sprite[1];
rectangle.setSize(sf::Vector2f(750,182));
sprite[0].setTexture(texture[0]);
sprite[0].setPosition(100,50);
//Création du texte
sf::Text text;
text.setFont(font);
text.setCharacterSize(20);
text.setColor(sf::Color(200,0,0));
text.setString("~Made by Théo Manea - 2019/2020 Paris-Sud University~");
text.setStyle(sf::Text::Bold);
text.setPosition(300,850);

//Création du bouton
Button btn1("Jouer", { 200, 100 }, 30, sf::Color::Green, sf::Color::White);
btn1.setFont(font);
btn1.setPosition({ 350, 300 });

//Main Loop:
while (window.isOpen()) {
sf::Event Event;
//Event Loop:
while (window.pollEvent(Event)) {
switch (Event.type) {
case sf::Event::Closed:
window.close();
case sf::Event::MouseMoved:
if (btn1.isMouseOver(window)) {
btn1.setBackColor(sf::Color(200,0,0));
}
else {
btn1.setBackColor(sf::Color(6,164,154));
}
break;
case sf::Event::MouseButtonPressed:
if (btn1.isMouseOver(window)) {
Squadro squadro;
window.close();
}
}
}
window.clear(sf::Color::White);
btn1.drawTo(window);
window.draw(rectangle);
window.draw(sprite[0]);
window.draw(text);
window.display();
}
}

还有我的游戏。h:

''

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;

class Squadro{
private:
public:
void Test();
void MainFunctions();
};

void Squadro::Test()
{
cout << "okkkkkkkkkkkkkkkkkkkk" << endl;

}

void Squadro::MainFunctions()
{
sf::Window window(sf::VideoMode(800, 600), "My window");
// run the program as long as the window is open
while (window.isOpen())
{
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event))
{
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
window.close();
}
}

}

#endif // GAME_H_INCLUDED

''

我知道这可能是个愚蠢的问题,但我需要帮助!感谢:D

一般来说,SFML可以是图形库的一个很好的选择,就像SDL、Allegro等一样。你只需要正确使用它(是的,我知道这是困难的部分。:((但这真的很主观,所以这里偏离了主题。让我们来谈谈你的问题…

问题是这部分:

if (btn1.isMouseOver(window)) { // This is true, if the cursor is over the button
Squadro squadro; // Here you create an object of the other class that shows its own window
window.close(); // now you close the "main" window
} // once you reach this line, "squadro" is destroyed as well, since we're leaving the scope ({...}) it's defined in.

这能修好吗?当然你所要做的就是确保你的Squadro对象不会立即被破坏(加上外部程序代码必须确保它也能继续运行/更新Squadro代码。这可能会有点棘手,所以通常我建议只使用一个窗口。


这是我要使用的结构:

对于你的简单游戏,你应该首先了解两个基本概念:

  • 主循环:让您的程序在一个主循环中运行(即"当窗口打开且游戏正在运行时,重复此操作"(,在主循环中,您首先处理事件(如鼠标移动或键盘按压(,然后更新游戏并最终绘制
  • 有限状态机:它允许您的游戏具有不同的屏幕或状态(但它也可以用于更基本的元素,如按钮、敌人、对象、关卡等(

我绝对推荐的网站(和书!(是游戏编程模式。作为一名初学者,一次理解所有内容可能有点棘手,但本网站将向您解释最重要的概念,这些概念可以使开发(任何规模的(游戏变得更加容易。请记住,根据游戏的范围和大小,最好或最复杂的方法可能过于夸张。

如果你想了解更多关于有限状态机的信息,一定要看看他们关于它的部分


不需要过多的细节,这里有一个可以与SFML一起使用的主Game类的基本模板(代码是简化/浓缩的;这基本上就是您已经拥有的:

class Game {
private:
sf::RenderWindow mWindow;
public:
Game() {
mWindow.create({640, 480}, "My Game");
// Other initialization code
}
~Game() {
// Code to shutdown the game
}
// This is your main game loop
int run() {
while (mWindow.isOpen()) {
handleEvents();
updateGame();
drawGame();
}
return 0;
}
private:
handleEvents() {
// Event handling as you do already
}
updateGame() {
// Update the game
}
drawGame() {
// Draw the game
}
}

在程序的main()中,您现在只需要创建一个Game类的对象,并告诉它运行:

int main(int argc, char **argv) {
Game myGame;
return myGame.run();
}
Now to the actual finite state machine. There are many different approaches to this, but the most basic one is just using one variable and an enumeration to identify the current state of the game. Add both to the class:
```cpp
enum GameState {
TitleScreen = 0,
MainGame,
GameOver
} mCurrentState;```
When initializing the game, you set a default state:
```cpp
mCurrentState = TitleScreen;

现在,如果你想切换到不同的屏幕,你所要做的就是更新这个变量,例如,当玩家点击"开始"按钮时:

mCurrentState = MainGame;

主循环中的三个功能,处理事件、更新游戏和绘制所有内容,然后可以使用此变量来确定要做什么:

drawGame() {
switch (mCurrentState) {
case TitleScreen:
// Draw the title screen here
break;
case MainGame:
// Draw the actual game here
break;
case GameOver:
// Draw the game over screen here
break;
}
}

以一种非常相似的方式,你也可以给你的按钮它自己的内部状态:

enum ButtonState {
Idle = 0,
Hovered,
Pushed
} mCurrentState;```