---
# System prepended metadata

title: 多元選修專題研究 C++ SFML函式庫學習
tags: [note]

---

---
tags: note
---

# 多元選修專題研究 C++ SFML函式庫學習

> 作者: 高一319班 12 施羿廷, 高一322班 24 歐祐睿

### 摘要
本專題是運用SFML程式庫製作出皮卡丘打排球，結果如下：
1.玩家能自由控制皮卡丘
2.球在碰到皮卡丘以及邊界時會反彈

### 計畫內容
* 透過SFML Game Development By Example這本書來學習SFML的內容
並希望在計畫的最後寫出經典遊戲⸺皮卡丘打排球的重製版

### 專題動機
國中考完會考後我們的班級上颳起了一陣皮卡丘打排球的風潮，幾乎只要一下
課，一堆人就會聚在電腦前爭先恐後的搶著要打，其中當然也包刮了我們兩個
，後來到了程設班後，在學期末時也舉辦了皮卡丘大賽，這個遊戲讓我們著實
瘋狂了一陣子，選了這次的課程後，在我們討論要做什麼時，這個遊戲又再次
浮現在我們腦海中

### 預計進度
1. 看完SFML Game Development By Example
> 預計要花8堂但可以跟以下進度並進
2. 寫出可以在畫面上操控的皮卡丘
> 預計前3堂內
3. 加上會在畫面上彈跳的球
> 預計第6堂前
4. 設定勝利條件
> 預計第10堂前
5. 加上背景&背景音效
> 預計第12堂前
6. 優化球和人物下落的物理引擎
> 學期結束前



### 最終完成進度
完成可操控的皮卡丘、球與皮卡丘彈性碰撞以及球與邊界的彈性碰撞

### 中途遇到之困難
1. 球在與邊緣碰撞時，球會卡在邊界
解決方法:
    - (1) 將四個邊界分開處理
    - (2) 改變球彈的方法，若照原本方法單純將方向相反，有時會出現下個tick球還
在邊界，所以又返回，之後就產生在邊界持續彈，卻無法離開邊界的情形
    - (3) 程式碼:
```cpp!
void Ball::physicEngine(float fElapsed) {
	auto size = m_texture.getSize();
	auto pos = m_sprite.getPosition();
	auto& sprite = m_sprite;
	//m_speed = Vector(m_speed.x(), -m_speed.y());
	if (pos.y > cScreenSize_y - size.y / 2)
		sprite.setPosition(pos.x, cScreenSize_y - size.y / 2), m_speed.theta = -m_speed.theta;
	if (pos.y < size.y / 2)
		sprite.setPosition(pos.x, size.y / 2), m_speed.theta = -m_speed.theta;
	//m_speed = Vector(-m_speed.x(), m_speed.y());
	if (pos.x > cScreenSize_x - size.x / 2)
		sprite.setPosition(cScreenSize_x - size.x / 2, pos.y), m_speed.theta = cPi - m_speed.theta;
	if (pos.x < size.x / 2)
		sprite.setPosition(size.x / 2, pos.y), m_speed.theta = cPi - m_speed.theta;
}
```

(註解起來的為原本方法)
2. 球在與皮卡丘碰撞時，球會不規則方向亂彈
解決方法:
    - 改變速度表示方式，將表示方式由原本的X分量與Y分量改為向量的形式
```cpp!
struct Vector {
	float val;
	float theta;

	float x() {return val * cos(theta);}
	float y() {return val * sin(theta);}

	Vector(float x = std::numeric_limits<float>::min(), float y = std::numeric_limits<float>::min()):
		val(sqrt(x * x + y * y)), theta(atan2(y, x)) {};

	friend Vector operator+(Vector a, Vector b) {
		return Vector(a.x() + b.x(), a.y() + b.y());
	}
	Vector& operator+=(Vector b) {
		return *this = Vector(x() + b.x(), y() + b.y());
	}
};
```

### 心得

這次遇到蠻多障礙，很大的一個原因是因為我們對於數理尤其是向量和彈性碰撞等等不太熟，不過之後要做的東西應該就會比較少用到了。
再來是說之後我們可以增加遊戲的其他要素，像是背景、背景音樂、音效、分數、結束條件等，但理解函式庫的功能花了比想像中長的時間，導致時間不足所以沒有完成，之後有機會的話希望可以做出完整的一個遊戲。
最後就是中間一度有想要增加搖桿的控制，不過code寫上去什麼都沒有發生，這也需要做一些修正。

## 成品

### 影片成果展現
https://youtu.be/Q-yNo6X-wzA

### 程式碼與檔案
https://drive.google.com/drive/folders/1UBxPLLqJt04XOUSHzuYQJbhveBrhaB8V?usp=sharing

