自己设计一个游戏通用的2D摄像机累。Camera2D
在2D游戏开发中,摄像机是一个至关重要的组件,允许开发者控制玩家的视角,决定他们能看到游戏世界的哪些部分。这对于引导玩家的注意力和提供沉浸式体验非常重要,在战斗场景中聚焦于战斗区域;而在探索场景中扩大视野以展示更多的环境细节,跟随主要角色移动,确保玩家始终能够看到控制中的角色和周围的环境,将摄像机焦点对准可交互对象,用来提示玩家这些对象的存在和重要性,还可以用来实现特殊效果,如震动或动态缩放等,在下文中我们将会实现这样一个摄像机类用于自己的游戏。
一个合格的摄像机应该具有以下功能。
本人习惯已屏幕中心为基准处理数据,并且正向使用坐标,所有以下实现已本人使用舒适维主进行实现,我们来弄一些碎片吧。
- 视口控制:设置视口大小适应不同的分辨率和屏幕尺寸。
1
2
3
4
5
6void SetCameraCenter(short int Viewport_Width, short int Viewport_Height) {
ViewportWidth = Viewport_Width;
ViewportHeight = Viewport_Height;
ViewportCenterX = ViewportWidth * 0.5f;
ViewportCenterY = ViewportHeight * 0.5f;
} - 焦点跟随:视点跟随焦点移动。
1
2
3
4
5
6
7
8void SetTarget(float targetX, float targetY) {
TargetX = targetX;
TargetY = targetY;
}
void SmoothMoveToPosition(float smoothing = 0.5f) {
CameraFocusX += (targetX - CameraFocusX) * smoothing;
CameraFocusY += (targetY - CameraFocusY) * smoothing;
} - 坐标转换:屏幕坐标与世界坐标之间转换,便于处理用户输入和游戏对象的位置。
1
2
3
4
5
6
7
8
9void ScreenToWorld(float screenX, float screenY, float& worldX, float& worldY) const {
worldX = CameraFocusX - (screenX - ViewportCenterX) / Zoom;
worldY = CameraFocusY - (screenY - ViewportCenterY) / Zoom;
}
void WorldToScreen(float worldX, float worldY, float& screenX, float& screenY) const {
screenX = ViewportCenterX + (CameraFocusX - worldX) * Zoom;
screenY = ViewportCenterY + (CameraFocusY - worldY) * Zoom;
} - 缩放功能:适应不同的游戏场景和提供不同的视觉体验。
1
2
3
4
5
6float GetScale() const { return Zoom; }
void SetScale(float zoom = 1)
{
Zoom = zoom;
} - 边界限制:设置移动边界,防止摄像机移动到游戏世界之外。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31void SetWorldSize(float Width, float Height) {
WorldBoundaryLeft = -Width * 0.5f;
WorldBoundaryTop = -Height * 0.5f;
WorldBoundaryRight = Width * 0.5f;
WorldBoundaryBottom = Height * 0.5f;
}
bool SetWorldBoundaries(float left, float top, float right, float bottom) {
if (left < right && top < bottom) {
WorldBoundaryLeft = left;
WorldBoundaryTop = top;
WorldBoundaryRight = right;
WorldBoundaryBottom = bottom;
return true;
}
return false;
}
void ViewportCheckBoundaries() {
float scaledOffsetX = ViewportCenterX / Zoom;
float scaledOffsetY = ViewportCenterY / Zoom;
CameraFocusX = std::max(WorldBoundaryLeft + scaledOffsetX, std::min(CameraFocusX, WorldBoundaryRight - scaledOffsetX));
CameraFocusY = std::max(WorldBoundaryTop + scaledOffsetY, std::min(CameraFocusY, WorldBoundaryBottom - scaledOffsetY));
if (ViewportWidth / Zoom > WorldBoundaryRight - WorldBoundaryLeft) {
CameraFocusX = (WorldBoundaryLeft + WorldBoundaryRight) * 0.5f;
}
if (ViewportHeight / Zoom > WorldBoundaryBottom - WorldBoundaryTop) {
CameraFocusY = (WorldBoundaryTop + WorldBoundaryBottom) * 0.5f;
}
} - 平滑过渡:避免视角突变给玩家带来不适。
1
2
3
4
5
6
7
8void SmoothMoveToPosition(float targetX, float targetY, float smoothing = 0.5f) {
CameraFocusX += (targetX - CameraFocusX) * smoothing;
CameraFocusY += (targetY - CameraFocusY) * smoothing;
}
void Scale(float zoom = 1){
Zoom += zoom;
} - 抖动效果:模拟冲击爆炸等效果来增强游戏的氛围和反馈。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15void Shake(float intensityX = 5.5f, float intensityY = 5.5f) {
std::uniform_real_distribution<float> disX(-intensityX, intensityX);
std::uniform_real_distribution<float> disY(-intensityY, intensityY);
CameraFocusX += disX(gen);
CameraFocusY += disY(gen);
}
void ShakeCircle(float intensityX = 5.5f, float intensityY = 5.5f) {
std::uniform_real_distribution<float> disX(-intensityX, intensityX);
std::uniform_real_distribution<float> disY(-intensityY, intensityY);
std::uniform_real_distribution<float> angle(-360.0f, 360.0f);
float radian = angle(gen) / 360 * m_PI * 2;
CameraFocusX += disX(gen) * std::cos(radian);
CameraFocusY += disY(gen) * std::sin(radian);
}
此刻Camera2D类的所有碎片都已经获得,我们把他拼起来吧。
1 | class Camera2D { |
这是什么?
自己设计一个游戏通用的2D摄像机累。Camera2D