• 使用C++与SFML编写一个简单的撞球游戏Part3——创建游戏启动界面


    有游戏窗口了,接下来就为游戏添加一个启动界面吧!!!

    我们将以SplashScreen.png跟MainMenu.png两幅图做为启动界面,资源可以点击这里下载

    下载后请在项目文件夹里新建一个名为images的文件夹,然后把两幅图拷贝进去。

    接下来就需要为两幅图分别创建一个类,以及进行相关设置,首先是SplashScreen,代码如下:

    SplashScreen.h

    1 #pragma once
    2 class SplashScreen
    3 {
    4 public:
    5     void Show(sf::RenderWindow& window);
    6 };

    SplashScreen.cpp

     1 #include "StdAfx.h"
     2 #include "SplashScreen.h"
     3 
     4 void SplashScreen::Show(sf::RenderWindow& renderWindow)
     5 {
     6     //创建texture对象来读取图片
     7     sf::Texture image;
     8     if(image.loadFromFile("images/SplashScreen.png") != true)
     9     {
    10         return;
    11     }
    12 
    13     //创建sprite对象来存储图片
    14     sf::Sprite sprite(image);
    15 
    16     //如果图片成功创建则将其显示到游戏窗口里
    17     renderWindow.draw(sprite);
    18     renderWindow.display();
    19 
    20     sf::Event event;
    21     while(true)
    22     {
    23         //跟上一part一样,用renderWindow对象来监听鼠标动作事件
    24         while(renderWindow.pollEvent(event))
    25         {
    26             if(event.type == sf::Event::EventType::KeyPressed 
    27                 || event.type == sf::Event::EventType::MouseButtonPressed
    28                 || event.type == sf::Event::EventType::Closed )
    29             {
    30                 return;
    31             }
    32         }
    33     }
    34 }

    然后是MainMenu,代码如下:

    MainMenu.h

     1 #pragma once
     2 #include "SFML\Window.hpp"
     3 #include "SFML\Graphics.hpp"
     4 #include <list>
     5 
     6 class MainMenu
     7 {
     8 
     9 public:
    10     enum MenuResult { Nothing, Exit, Play };    
    11 
    12     //用结构体来存储矩形点击区域的属性参数信息
    13     struct MenuItem
    14     {
    15     public:
    16         //用来存储矩形区域范围的点的模板对象
    17         //一个点包含两个坐标值,两点形成一矩形区域
    18         sf::Rect<int> rect;
    19         MenuResult action;
    20     };
    21 
    22     MenuResult Show(sf::RenderWindow& window);
    23 
    24 private:
    25     MenuResult GetMenuResponse(sf::RenderWindow& window);
    26     MenuResult HandleClick(int x, int y);
    27 
    28     //用来存储点击区域的容器
    29     std::list<MenuItem> _menuItems;
    30 };

    MainMenu.cpp

     1 #include "stdafx.h"
     2 #include "MainMenu.h"
     3 
     4 
     5 MainMenu::MenuResult MainMenu::Show(sf::RenderWindow& window)
     6 {
     7     sf::Texture image;
     8     image.loadFromFile("images/mainmenu.png");
     9     sf::Sprite sprite(image);
    10 
    11     //设置鼠标点击矩形区域范围
    12 
    13     //play的点击范围
    14     MenuItem playButton;
    15     playButton.rect.top= 145;
    16     playButton.rect.left = 0;
    17     playButton.rect.width = 380;
    18     playButton.rect.height = 1023;
    19     playButton.action = Play;
    20 
    21     //Exit的点击范围
    22     MenuItem exitButton;
    23     exitButton.rect.top = 383;
    24     exitButton.rect.left = 0;
    25     exitButton.rect.height = 1023;
    26     exitButton.rect.width = 560;
    27     exitButton.action = Exit;
    28 
    29     //把点击范围放进容器里面
    30     _menuItems.push_back(playButton);
    31     _menuItems.push_back(exitButton);
    32 
    33     window.draw(sprite);
    34     window.display();
    35 
    36     return GetMenuResponse(window);
    37 }
    38 
    39 //判断鼠标点击位置是否在矩形区域里面从而返回状态参数
    40 MainMenu::MenuResult MainMenu::HandleClick(int x, int y)
    41 {
    42     //迭代器遍历list容器里面存放的点击区域以供判断
    43     std::list<MenuItem>::iterator it;
    44 
    45     for ( it = _menuItems.begin(); it != _menuItems.end(); it++)
    46     {
    47         sf::Rect<int> menuItemRect = (*it).rect;
    48         if( menuItemRect.width > y 
    49             && menuItemRect.top < y 
    50             && menuItemRect.left < x 
    51             && menuItemRect.height > x)
    52         {
    53             return (*it).action;
    54         }
    55     }
    56 
    57     return Nothing;
    58 }
    59 
    60 //根据鼠标动作来做出相应的响应
    61 MainMenu::MenuResult  MainMenu::GetMenuResponse(sf::RenderWindow& window)
    62 {
    63     sf::Event menuEvent;
    64 
    65     //这里的42!=43可以理解为true
    66     while(42 != 43)
    67     {
    68 
    69         while(window.pollEvent(menuEvent))
    70         {
    71             if(menuEvent.type == sf::Event::MouseButtonPressed)
    72             {
    73                 return HandleClick(menuEvent.mouseButton.x,menuEvent.mouseButton.y);
    74             }
    75             if(menuEvent.type == sf::Event::Closed)
    76             {
    77                 return Exit;
    78             }
    79         }
    80     }
    81 }

    补充点:如果是用添加类的方式创建类的话,在添加MainMenu的时候会被禁止,因为MainMenu是被MFC保留的类名,所以还是乖乖地先添加.h再添加.cpp吧。

        值得一提的是,MainMenu.h中的容器list应该是被include在stdafx.h里面的,原文解释说包含在MainMenu.h里是方便起见而已.

    最后要回到Game.h里面添加两个函数与private下面:

    static void ShowSplashScreen();
    static void ShowMenu();

    当然还要实现它们,在Game.cpp里面添加(记得要include MainMenu.h 和 SplashScreen.h):

     1 void Game::ShowSplashScreen()
     2 {
     3     SplashScreen splashScreen;
     4     splashScreen.Show(_mainWindow);
     5     _gameState = Game::ShowingMenu;
     6 }
     7 
     8 void Game::ShowMenu()
     9 {
    10     MainMenu mainMenu;
    11     MainMenu::MenuResult result = mainMenu.Show(_mainWindow);
    12     switch(result)
    13     {
    14     case MainMenu::Exit:
    15         _gameState = Exiting;
    16         break;
    17     case MainMenu::Play:
    18         _gameState = Playing;
    19         break;
    20     }
    21 }

    再把Start方法里面的_gameState 改为 Game::ShowingSplash;

    让GameLoop方法变成如下样子就大功告成了:

     1 void Game::GameLoop()
     2 {
     3     sf::Event currentEvent;
     4     //从消息队列里面拿出消息
     5     _mainWindow.pollEvent(currentEvent);
     6   
     7     switch(_gameState)
     8     {
     9     case Game::ShowingSplash:
    10         {
    11             ShowSplashScreen();
    12             break;
    13         }
    14     case Game::ShowingMenu:
    15         {
    16             ShowMenu();
    17             break;
    18         }
    19     case Game::Playing:
    20         {
    21             //用黑色填充游戏画面
    22             _mainWindow.clear(sf::Color(0,0,0));
    23             _mainWindow.display();
    24         
    25             if(currentEvent.type == sf::Event::Closed)
    26             {
    27                 _gameState = Game::Exiting;
    28             }
    29             if(currentEvent.type == sf::Event::KeyPressed)
    30             {
    31                 if(currentEvent.key.code == sf::Keyboard::Escape) ShowMenu();
    32             } 
    33           break;
    34         }
    35      }  
    36 }

    现在按F5试试吧~~~~

  • 相关阅读:
    详解Go变量类型的内存布局
    saltstack手册(含官方pdf)
    Linux之《荒岛余生》(三)内存篇
    linux之网络
    Linux之IO
    【WPF】提高InkAnalyer手写汉字识别的准确率
    mssql 小技巧
    WCF Data Service
    jQuery基础之选择器
    Window程序的安装与部署
  • 原文地址:https://www.cnblogs.com/tomboy/p/2567324.html
Copyright © 2020-2023  润新知