SFML01: SFML 的安裝與測試

   
實習目標

這一個系列的實習讓大家運用 SFML 來設計有圖形以及多媒體網路介面的程式

能夠配合 VC2010 的 SFML 最後版本是 SFML 2.3.2 (2015/09)

2.4.2 (2017/02) Windows 上能夠配合 VC2012, VC2013, VC2015, g++4.9.2, 也支援 OSX 和 Linux, 每一個版本之間有相當的修改 (可惜還沒有 Android 版本)

如果要自己建置配合 VC2017 的 SFML 2.4.2 版本請參考 說明

目前最新的版本是 2.5.0 (2018/05) Windows 上能夠配合 VC2013, VC2015, VC2017, g++7.3.0, 也支援 OSX 和 Linux, 每一個版本之間有相當的修改

   
步驟一

SFML 2.3.2 下載

64位元 (SFML-2.3.2-windows-vc10-64-bit.zip)
下面的說明都是用 64位元作業系統為例, 32位元的設定要自己調整一下

HTML 文件下載, 線上參考文件, chm

步驟二

SFML 2.3.2 安裝

解壓縮 SFML-2.3.2-windows-vc10-64-bit.zip 至 C:\Program Files\SFML-2.3.2\

在環境變數 (environment variable) path 中加入 C:\Program Files\SFML-2.3.2\bin
(以便程式執行時可以找到動態連結函式庫 openal32.dll, sfml-system-2.dll, sfml_window-2.dll, sfml-graphics-2.dll, sfml-network-2.dll, sfml-audio-2.dll 或是 debug 的版本 sfml-system-d-2.dll, sfml_window-d-2.dll, sfml-graphics-d-2.dll, sfml-network-d-2.dll, sfml-audio-d-2.dll)

請注意完成以後要繼續之前,要把所有的 visual studio project 都關上, 重新開啟 visual studio, 設定才會生效

步驟三

SFML 2.3.2 標準範例

C:\Program Files\SFML-2.3.2\examples\

ftp\
opengl\
pong\
shader\
sockets\
sound\
sound-capture\
voip\
win32\
window\

步驟四

網路上的教學以及範例

SFML2.0 (40 lessons)

SFML 2.1
(52 lessons)

SFML 2.3.1 (21 lessons)

SFML 2.4 (13 lessons)

請搜尋 youtube SFML

SFML Mandelbrot 1, 2, 3

SFML Games 1, 2, 3, 4. 5, 6, 7, 8, 9, 10, 11, 12

步驟五

SFML books

  1. SFML Game Development
    https://www.packtpub.com/game-development/sfml-game-development
  2. SFML Essentials
    https://www.packtpub.com/game-development/sfml-essentials
  3. SFML Blueprints
    https://www.packtpub.com/game-development/sfml-blueprints
  4. SFML Game Development By Example
    https://www.packtpub.com/game-development/sfml-game-development-example
如果你需要電子書的話...
步驟六

Visual C++ 2010 專案

一般來說在開發的時候設定為 debug, 動態連結函式庫, Win32 console

Win32 主控台應用程式會多一個文字訊息視窗可以顯示偵錯的文字訊息

1. 開啟新專案 testSFML232, 已安裝的範本, Visual C++: Win32, Win32 主控台應用程式, 確定, 其他選項: 空專案, 完成
1.1. 建置 -> 組態管理員 -> 使用中的方案平台 -> 新增 -> 輸入或選擇新平台:x64, 複製設定值來源: Win32, 勾選建立新專案平台, 確定
1.2. 選擇 x64 平台

2. 專案 -> testSFML232 屬性 -> 組態屬性 -> 組態: 所有組態
2.1. 組態屬性 -> C/C++ -> 一般 -> 其他 Include 目錄: C:\Program Files\SFML-2.3.2\include
2.2. 組態屬性 -> 連結器-> 一般 -> 其他程式庫目錄: C:\Program Files\SFML-2.3.2\lib

3. 專案 -> testSFML232 屬性 -> 組態: Debug
3.1. 組態屬性 -> 連結器-> 輸入 -> 其他相依性: sfml-graphics-d.lib; sfml-window-d.lib; sfml-system-d.lib; sfml-audio-d.lib; sfml-network-d.lib; kernel32.lib; user32.lib; gdi32.lib; winspool.lib; comdlg32.lib; advapi32.lib; shell32.lib; ole32.lib; oleaut32.lib; uuid.lib; odbc32.lib; odbccp32.lib; %(AdditionalDependencies)

4. 專案 -> testSFML232 屬性 -> 組態: Release
4.1. 組態屬性 -> 連結器-> 輸入 -> 其他相依性: sfml-graphics.lib; sfml-window.lib; sfml-system.lib; sfml-audio.lib; sfml-network.lib; kernel32.lib; user32.lib; gdi32.lib; winspool.lib; comdlg32.lib; advapi32.lib; shell32.lib; ole32.lib; oleaut32.lib; uuid.lib; odbc32.lib; odbccp32.lib; %(AdditionalDependencies)

你也可以下載 SFML232 vc10 sample dynamic win32 console.7z 專案, 解壓縮以後,
點選 SFML test.sln, 上方工具列方案平台選擇 x64, 編譯執行,
在方案總管中以右鍵點選 SFML test 重新命名專案

這個設定下編譯出來的應用程式 (.exe) 如果你要拷貝到沒有安裝 SFML-2.3.2 的機器上執行的話, 需要附上 openal32.dll, sfml-system-2.dll, sfml-window-2.dll, sfml-graphics-2.dll, sfml-audio-2.dll, 和 .exe 放在同一個資料匣裡, 沒有安裝 SFML 的機器才能夠執行

開發完以後可以把設定改為 release, 靜態連結函式庫, Win32 application

1. 開啟新專案 testSFML232, 已安裝的範本, Visual C++: Win32, Win32 專案, 確定, 其他選項: 空專案, 完成
1.1. 建置 -> 組態管理員 -> 使用中的方案平台 -> 新增 -> 輸入或選擇新平台:x64, 複製設定值來源: Win32, 勾選建立新專案平台, 確定
1.2. 選擇 x64 平台

2. 專案 -> testSFML232 屬性 -> 組態屬性 -> 組態: 所有組態
2.1. 組態屬性 -> C/C++ -> 一般 -> 其他 Include 目錄: C:\Program Files\SFML-2.3.2\include
2.2. 組態屬性 -> 連結器-> 一般 -> 其他程式庫目錄: C:\Program Files\SFML-2.3.2\lib

3. 專案 -> testSFML232 屬性 -> 組態: Debug
3.1. 組態屬性 -> 連結器-> 輸入 -> 其他相依性: sfml-graphics-d.lib; sfml-window-d.lib; sfml-system-d.lib; sfml-audio-d.lib; sfml-network-d.lib; kernel32.lib; user32.lib; gdi32.lib; winspool.lib; comdlg32.lib; advapi32.lib; shell32.lib; ole32.lib; oleaut32.lib; uuid.lib; odbc32.lib; odbccp32.lib; %(AdditionalDependencies)

4. 專案 -> testSFML232 屬性 -> 組態: Release
4.1. 組態屬性 -> 連結器-> 輸入 -> 其他相依性: sfml-graphics.lib; sfml-window.lib; sfml-system.lib; sfml-audio.lib; sfml-network.lib; kernel32.lib; user32.lib; gdi32.lib; winspool.lib; comdlg32.lib; advapi32.lib; shell32.lib; ole32.lib; oleaut32.lib; uuid.lib; odbc32.lib; odbccp32.lib; %(AdditionalDependencies)

你也可以下載 SFML232 vc10 sample static win32 application.7z 專案, 解壓縮以後,
點選 SFML test.sln, 上方工具列方案平台選擇 x64, 編譯執行,
在方案總管中以右鍵點選 SFML test 重新命名專案


這個設定下編譯出來的應用程式 (.exe) 如果你要拷貝到沒有安裝 SFML-2.3.2 的機器上執行的話, 只需要附上 openal32.dll 就可以了 (openal32.dll 函式庫的授權要求一定要附上完整 DLL)

步驟七

基本範例說明

這個程式是 線上說明資料 裡放的第一個測試程式

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
int main()
{
    sf::RenderWindow window(sf::VideoMode(804, 993), "SFML window"); // 開啟視窗

    sf::Texture texture; // 載入影像檔案
    if (!texture.loadFromFile("cute_image.jpg")) // 支援 jpg, png 圖片格式
        return EXIT_FAILURE;

    sf::Sprite sprite(texture); // 可以旋轉放大移動的圖片物件, 與 Texture 物件關聯
                                                 // 可以整張影像作為一個圖片物件, 也可以指定部份的影像

    sf::Font font; // 字型物件
    if (!font.loadFromFile("ariblk.ttf")) // ariel black 字型
        return EXIT_FAILURE;

    sf::Text text("Hello SFML\nThis is a test!", font, 50); // 指定字型 為 50 點, ariel black

    sf::Music music;
    if (!music.openFromFile("Reggae8-84.ogg")) // 支援 ogg 格式
        return EXIT_FAILURE;

    music.play(); // 播放音樂
    music.setLoop(true); // 反覆播放

    while (window.isOpen()) // 除非先前執行過 window.close() 否則 isOpen() 回傳 true
    {
        sf::Event event;
        while (window.pollEvent(event)) // 由視窗的訊息佇列中取得訊息 (滑鼠、鍵盤、選單...)
        {
            if (event.type == sf::Event::Closed) // 此事件為使用者點選視窗右上角的 X 關閉視窗
                window.close();
            if (event.type == sf::Event::KeyPressed) // 鍵盤有按鍵被按下
                if (event.key.code==sf::Keyboard::Escape)  //  如果是 Esc  按鍵
                    window.close();
        }

        window.clear(); // 清除螢幕 (請注意 SFML 有 double buffer, 
                                     // 這裡是在一個還看不到的螢幕緩衝區上畫圖)

        window.draw(sprite); // 將圖片物件以預設的位置 (0,0), 比例 1.0, 角度 0 繪出

        window.draw(text); // 將文字物件以預設的位置 (0,0), 比例 1.0, 角度 0 繪出

        window.display(); // 將緩衝區裡的資料顯示在螢幕上
    }
    return EXIT_SUCCESS;
}
步驟八

修改視窗大小以及圖片大小

請下載 SFML232 vc10 sample dynamic win32 console.7z 專案, 解壓縮以後, 點選 SFML test.sln, 上方工具列方案平台選擇 x64, 編譯執行; 在方案總管中以右鍵點選 SFML test 重新命名專案為 SFML01

SFML 類別功能線上說明

請修改視窗大小為 480x660

請運用 RectangleShape 定義一個 420x520 的棕色 (128,42,42) 長方形, 在視窗的中間繪出以作為圖片的外框 (需要用到的類別與成員 sf::Vector2f, sf::RectangleShape::setFillColor(), sf::Transformable::setPosition(), sf::Color)

在 window.draw(sprite); 之前請運用 sprite.setScale(factorX, factorY) 調整原來 804x993 的圖片到寬度 402x496, 並且在視窗中央顯示 (需要用到 sf::Transformable::setScale(), sf::Transformable::setPosition())

能夠測試執行的時候一定要測試一下, 不要等到所有的都修改完才測試

接下來這幾個步驟的範例執行程式 (win7-x64, win8-x64, win10-x64)

步驟九

修改背景音樂的音量並且以按鍵 U, D 控制大小聲以 P 控制暫停播放

請運用 Music::setVolume(float) 來調整音量 (你需要定義一個紀錄目前音量的變數, 音量範圍在 0.0f ~ 100.0f 之間, 如果你希望像範例程式一樣顯示音量大小的話, 需要用到 std::string, std::ostringstream, std::ostringstream::str())

請運用 Music::pause() 來暫停播放聲音

按鍵對應到的常數為為 Keyboard::U, Keyboard::D, 以及 Keyboard::P

步驟十

修改字型為微軟正黑體, 調整文字顏色

請使用 C:\Windows\Fonts\msjh.ttc 字型, 字型大小設為 45, 中文常數字串請用 L"中文" 來指定 wchar_t 型態的常數字串

使用 Text::setColor(Color) 來調整顏色為棕色

請調整文字顯示的位置到圖片下方

請運用 Vertex 陣列在文字下方畫一黃綠直線

sf::Vertex line[2];
line[0].position = sf::Vector2f(20,630);
line[0].color  = sf::Color::Yellow;
line[1].position = sf::Vector2f(460,630);
line[1].color = sf::Color::Green;

window.draw(line,2,sf::LinesStrip);
步驟十一

程式偵錯

程式不太聽話, 有邏輯的錯誤該怎麼辦?

還好剛才是設定為 debug, 動態連結函式庫, Win32 console, 就用平常的偵錯方法吧

#include <iostream>
using namespace std;

cout << "Help! Help!" << endl;

步驟十二

為什麼繪圖需要放在迴圈裡面, 一直不斷地畫呢? 不會很浪費 CPU 時間嗎?

是有一點浪費, 你可以打開視窗系統的 "工作管理員", 觀察一下效能

果然有一個執行緒狠狠地佔據 CPU 的時間

如果希望稍微節省一點, 在迴圈內可以加上 sf::sleep(sf::milliseconds(10));
但是處理使用者的訊息也就會有最多 10 毫秒的延遲了, 如果程式和使用者的互動很多或是繪圖很花時間, 這個作法是不能夠接受的

為什麼不把繪圖部份拿到迴圈前面呢? 繪圖只做一次, 主要迴圈裡還是要處理訊息

繪圖程式片段

while (window.isOpen())
{ sf::Event event; while (window.pollEvent(event)) { .... } }

你可以試看看, 會看到圖形輸出, 按 U, D, P, <Esc> 也都有反應, 但是在"工作管理員", 觀察一下效能, 還是佔著 CPU 不放, 還是一直在執行無窮迴圈啊!! 如果從去掉外層的大迴圈, 訊息就只處理一次了, 執行緒做完以後程式直接結束!! 這樣的程式還有一個問題, 如果你的視窗縮到最小再還原, 就是全黑的了, 他要叫你的程式重新繪製一次, 但是你的程式的繪圖片段只執行一次! 所以還是請把繪圖片段放進迴圈裡吧!

對這個程式來說, 你可以試下面這樣的處理方式

while (window.isOpen())
{ sf::Event event; if (window.waitEvent(event)) // blocked until an event happens { .... } 繪圖程式片段 }

沒有訊息的時候 waitEvent 並不會回傳, 也不會使用 CPU, 因為這個程式並沒有要一直修改畫面所以是可以運作的, 但是對於一個 Game 來說就不行了, 沒有使用者的滑鼠和鍵盤事件時, 程式還是要一直繪圖...

這個問題在 SFML 裡沒有很簡單的解, SFML 沒有辦法定義自己的訊息, 所以不能用類似 Win32 的 GetMessage() 和 WM_TIMER 訊息來解決, SFML 裡你需要用一個獨立的執行緒執行訊息處理迴圈, 把 pollEvent 換成 waitEvent, 然後在主執行緒裡根據你的 framerate 來繪圖, 如果繪圖不太花 CPU 時間, 就用 sf:sleep 多休息一會兒

寫到這裡, 其實我有一點弄錯了, 不知道自己在講什麼了, 其實 SFML 是一個讓你用 C/C++ 寫遊戲的環境, 寫遊戲的時候不是就希望使用超快的 CPU, 超多的記憶體, 超級不公平地把玩遊戲的人虐到爆嗎?? 那我何必要讓 CPU 沒事多休息呢? CPU 裡面還有好多核心沒有用到才是寫遊戲的人該擔心的, 要想辦法開多個執行緒, 把場景人物音效弄到超炫才是重點吧!! 我以上面寫的你看看就好, 除了上面這種遊戲界面之外, 一般使用者介面是需要避免使用無窮迴圈把 CPU 資源吃完的!!

步驟十三

發佈你的程式

每次執行時出現那個 命令視窗 好不專業!!

請下載 SFML232 vc10 sample static win32 application.7z 專案, 解壓縮以後, 點選 SFML test.sln, 上方工具列方案平台選擇 x64, 編譯執行; 在方案總管中以右鍵點選 SFML test 重新命名專案為 SFML01

把剛才專案裡的 main.cpp 拷貝過來到這個專案裡, 編譯執行

這個設定下編譯出來的應用程式 (.exe) 如果你要拷貝到沒有安裝 SFML-2.3.2 的機器上執行的話, 只需要附上 openal32.dll 就可以了 (openal32.dll 函式庫的授權要求一定要附上完整 DLL)

步驟十三 請助教檢查後, 將所完成的 專案 (只需保留 .cpp, .h, .sln 以及 .vcxproj 檔案即可; 刪除掉 .suo, .sdf, .filters, .users, debug\ 資料匣, 以及 ipch\資料匣下的所有內容) 壓縮起來, 選擇 SFMLLab01上傳, 後面的實習課程可能需要使用這裡所完成的程式

C++ 物件導向程式設計課程 首頁

製作日期: 04/11/2013 by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw TEL: 02 24622192x6615
海洋大學 電機資訊學院 資訊工程學系 Lagoon