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

问题描述 投票:0回答:1

这个学期,我们必须用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();
}
}

还有我的game.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

'''

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

c++ sfml
1个回答
2
投票

通常,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代码。这可能会有些棘手,因此在一般而言,我建议您仅坚持一个窗口。


这是我要使用的结构:

对于您的简单游戏,首先应该研究两个基本概念:

  • Main Loop:让您的程序在一个主循环中运行(即“在窗口打开且游戏正在运行时,重复此步骤”),在此循环中您首先处理事件(例如鼠标移动或键盘按下) ),然后更新游戏并最终绘制它。
  • 有限状态机:允许您的游戏具有不同的屏幕或状态(但也可以用于按钮,敌人,对象,关卡等更基本的元素。)>
  • 我绝对推荐的网站(和书!)是Game Programming Patterns。首先了解一下所有内容可能会有些棘手,但此网站将向您介绍最重要的概念,这些概念可以使开发各种规模的游戏变得更加容易。请记住,根据您游戏的范围和大小,最好或最复杂的方法可能会过大。

[如果您想了解有关有限状态机的更多信息,请绝对关注一下their section


[这里不做过多介绍,这是一个主要的Game类的基本模板,人们可以将其与SFML一起使用(代码已简化/压缩;这基本上是您已经拥有的:]

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;```
© www.soinside.com 2019 - 2024. All rights reserved.