---
# System prepended metadata

title: 進階程式設計期末專題 - StarburstGame

---

# 進階程式設計期末專題 - StarburstGame

## 動機
暑假時有想到可以自己來做小遊戲，當時有嘗試用$RPGMaker$做出一個小遊戲，不過因為當時做出來的成品不是很滿意，趁這次專題再挑戰做一次小遊戲。
## 目標
使用$SFML(跨平台多媒體庫)$做出好玩又有趣的小遊戲
## SFML簡介
$SFML(簡單快速多媒體庫)$是一個跨平台的軟件開發庫，旨在為計算機中的各種多媒體組件提供簡單的應用程序編程接口。
### 程式庫簡單介紹
#### Window

建立和開啟視窗
```=c++
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML"); //建立新視窗

while (window.isOpen()) //開啟新視窗
{
    sf::Event event;
    
    while (window.pollEvent(event)) //偵測事件發生
    {
        if (event.type == sf::Event::Closed)
            window.close();
    }
}
```
#### Event
基本事件控制
```=c++
sf::Event event;
while (window.pollEvent(event))
{
    //不同事件條件偵測
    switch (event.type)
    {
        case sf::Event::Closed:
            window.close();
            break;

        case sf::Event::KeyPressed:
            // ...
            break;

        default:
            break;
    }
}
```
常用事件
```=c++
//文字輸入
sf::Event::TextEntered
//按下按鍵
sf::Event::KeyPressed
//放開按鍵
sf::Event::KeyReleased
//滾動滑鼠滾輪
sf::Event::MouseWheelScrolled
//滑鼠按下
sf::Event::MouseButtonPressed
//滑鼠鬆開
sf::Event::MouseButtonReleased
```
#### Texture&Sprite
$Texture$ $:$ 是一張圖片，但主要是用來改變物件的外觀。像是一個物品的材質。因為Texture本身不是物件，因此不能移動它。 
$Sprite$ $:$ 是一張圖片，同時也是一個物件，意思是他擁有座標(x, y)，你能移動/創建/刪除他。

$Texture$搭配$Sprite$
```=c++
sf::Texture texture; 
texture.loadFromFile("picture.png"); //引入texture的材質
sf::Sprite sprite;
sprite(texture); //使sprite(物體)包上材質

//在畫面上畫出sprite
window.clear(); // 畫面背景
window.draw(sprite);// 畫出物體
window.display();// 畫面更新表現
```
## 實作
### 遊戲想法
遊戲空間中有兩名玩家，互相碰撞，先碰到閃耀魔眼的玩家即輸。
### 遊戲方式
> GAMEPLAY:
PLAYER1(THE CYAN ONE)
↑---UP
↓---DOWN
←---LEFT
→---RIGHT

>PLAYER2(THE BLUE ONE)
W---UP
S---DOWN
A---LEFT
D---RIGHT

---------------------------------------------------
### 環境
$Microsoft$ $Visual$ $Studio$
$C++$
### code 
```c++= 
#include <iostream>
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
using namespace sf;

// 物體碰撞
bool intersects(const CircleShape& c1, const CircleShape& c2) {
    FloatRect circ1 = c1.getGlobalBounds();
    FloatRect circ2 = c2.getGlobalBounds();

    return circ1.intersects(circ2);
}

int main() {
    // 建立畫面
    VideoMode videomode(600, 600);
    RenderWindow window(videomode, "STARBURST GAME");

    // 建立Player1
    CircleShape circle;
    circle.setFillColor(Color::Cyan);
    circle.setPosition(100, 100);
    circle.setRadius(18);

    // 建立Player2
    CircleShape circle2;
    circle2.setFillColor(Color::Blue);
    circle2.setPosition(100, 500);
    circle2.setRadius(18);

    // 建立閃耀魔眼(NPC人物)
    CircleShape GlameEyes;
    Texture glameeyes;
    glameeyes.loadFromFile("resources/glameeyes.png");
    GlameEyes.setRadius(76);
    GlameEyes.setTexture(&glameeyes, true);
    GlameEyes.setPosition(470, 465);

    // 建立背景
    Texture background;
    background.loadFromFile("resources/floor74.jpg");
    Sprite BackGround;
    BackGround.setTexture(background);
    BackGround.setScale(Vector2f(0.6, 1.06571936057));

    // PLAYER1勝利畫面
    Texture CongratulationsCyan;
    CongratulationsCyan.loadFromFile("resources/congratulationscyan.jpg");
    Sprite congratulationscyan;
    congratulationscyan.setTexture(CongratulationsCyan);
    congratulationscyan.setScale(Vector2f(0.6, 1.06571936057));

    // PLAYER2勝利畫面
    Texture CongratulationsBlue;
    CongratulationsBlue.loadFromFile("resources/congratulationsblue.jpg");
    Sprite congratulationsblue;
    congratulationsblue.setTexture(CongratulationsBlue);
    congratulationsblue.setScale(Vector2f(0.6, 1.06571936057));

    // 建立BGM音樂
    Music music;
    music.openFromFile("resources/Swordland.ogg");
    music.setLoop(true);
    music.play();

    int dire = 1;
    while (window.isOpen()) {

        // 控制閃耀魔眼移動
        if (GlameEyes.getPosition().y > 0 && dire == 1) {
            GlameEyes.move(0, -1);
            if (GlameEyes.getPosition().y == 1) {
                dire = 0;
            }
        }
        else if (GlameEyes.getPosition().y < 570 && dire == 0) {
            GlameEyes.move(0, 1);
            if (GlameEyes.getPosition().y == 569) {
                dire = 1;
            }
        }

        //畫面呈現
        window.clear(Color::White);
        window.draw(BackGround);
        window.draw(circle);
        window.draw(circle2);
        window.draw(GlameEyes);

        window.display();

        // 事件控制
        Event event;
        if (window.pollEvent(event))
        {
            if (event.type == Event::Closed) {
                window.close();
            }
        }

        // 玩家鍵盤事件控制
        if (Keyboard::isKeyPressed(Keyboard::Up)) {
            if (circle.getPosition().y > 0) {
                circle.move(0, -1);
            }
        }
        if (Keyboard::isKeyPressed(Keyboard::Down)) {
            if (circle.getPosition().y < 570) {
                circle.move(0, 1);
            }
        }
        if (Keyboard::isKeyPressed(Keyboard::Left)) {
            if (circle.getPosition().x > 0) {
                circle.move(-1, 0);
            }
        }
        if (Keyboard::isKeyPressed(Keyboard::Right)) {
            if (circle.getPosition().x < 570) {
                circle.move(1, 0);
            }
        }
        if (Keyboard::isKeyPressed(Keyboard::W)) {
            if (circle2.getPosition().y > 0) {
                circle2.move(0, -1);
            }
        }
        if (Keyboard::isKeyPressed(Keyboard::S)) {
            if (circle2.getPosition().y < 570) {
                circle2.move(0, 1);
            }
        }
        if (Keyboard::isKeyPressed(Keyboard::A)) {
            if (circle2.getPosition().x > 0) {
                circle2.move(-1, 0);
            }
        }
        if (Keyboard::isKeyPressed(Keyboard::D)) {
            if (circle2.getPosition().x < 570) {
                circle2.move(1, 0);
            }
        }

        // 玩家碰撞事件控制
        if (intersects(circle, circle2)) {
            circle2.move(3, 0);
        }
        if (intersects(circle2, circle)) {
            circle.move(3, 0);
        }


        // 玩家勝利條件控制
        Time time = seconds(5);
        if (intersects(circle, GlameEyes)) {
            window.draw(congratulationsblue);
            window.display();
            sleep(time);
            window.close();
        }
        if (intersects(circle2, GlameEyes)) {
            window.draw(congratulationscyan);
            window.display();
            sleep(time);
            window.close();
        }

    }
}
```
### 實際遊玩影片
[Youtube影片-程式設計專題 星爆小遊戲](https://youtu.be/x05QOPOnZiM)

## 心得
這個遊戲計畫原本想做更大一點，不過學測在即時間實在是不太夠，之後有時間再好好開發出一款有介面又有好的畫面效果的遊戲，除此之外code也有很多地方可以再修改，像是把角色用struct統合會好很多，總之做遊戲還蠻有趣的，之後學學unity好了。
## 參考資料
[Youtube Playlist-SFML 2.4 For Beginners](https://www.youtube.com/playlist?list=PL21OsoBLPpMOO6zyVlxZ4S4hwkY_SLRW9)
[SFML-Game-Developme-By-Example.pdf](https://github.com/BijayanBhattarai/BooksCollection/blob/master/Game%20Developement/SFML-Game-Developme-By-Example.pdf)
[iT邦幫忙-寫遊戲初體驗](https://ithelp.ithome.com.tw/users/20130096/ironman/3531)