窗口创建
This commit is contained in:
parent
3711b12338
commit
637f087001
|
|
@ -10,3 +10,5 @@ build/
|
||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
*.json
|
*.json
|
||||||
|
|
||||||
|
.vscode/compile_commands.json
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,16 @@
|
||||||
[
|
[
|
||||||
]
|
{
|
||||||
|
"directory": "d:\\Game\\Frostbite2D",
|
||||||
|
"arguments": ["C:\\mingw64\\bin\\x86_64-w64-mingw32-g++.exe", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-std=c++17", "-Id:\\Game\\Frostbite2D\\Fostbite2D\\include", "-fexceptions", "-finput-charset=UTF-8", "-fexec-charset=UTF-8", "-isystem", "C:\\Users\\dongj\\AppData\\Local\\.xmake\\packages\\l\\libsdl2\\2.32.2\\9c98693a11f742888762f17ab57f7f01\\include", "-isystem", "C:\\Users\\dongj\\AppData\\Local\\.xmake\\packages\\l\\libsdl2\\2.32.2\\9c98693a11f742888762f17ab57f7f01\\include\\SDL2", "-DNDEBUG", "-o", "build\\.objs\\Frostbite2D\\windows\\x64\\release\\Fostbite2D\\src\\fostbite2D\\app\\application.cpp.obj", "Fostbite2D\\src\\fostbite2D\\app\\application.cpp"],
|
||||||
|
"file": "Fostbite2D\\src\\fostbite2D\\app\\application.cpp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"directory": "d:\\Game\\Frostbite2D",
|
||||||
|
"arguments": ["C:\\mingw64\\bin\\x86_64-w64-mingw32-g++.exe", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-std=c++17", "-Id:\\Game\\Frostbite2D\\Fostbite2D\\include", "-fexceptions", "-finput-charset=UTF-8", "-fexec-charset=UTF-8", "-isystem", "C:\\Users\\dongj\\AppData\\Local\\.xmake\\packages\\l\\libsdl2\\2.32.2\\9c98693a11f742888762f17ab57f7f01\\include", "-isystem", "C:\\Users\\dongj\\AppData\\Local\\.xmake\\packages\\l\\libsdl2\\2.32.2\\9c98693a11f742888762f17ab57f7f01\\include\\SDL2", "-DNDEBUG", "-o", "build\\.objs\\Frostbite2D\\windows\\x64\\release\\Fostbite2D\\src\\fostbite2D\\config\\app_config.cpp.obj", "Fostbite2D\\src\\fostbite2D\\config\\app_config.cpp"],
|
||||||
|
"file": "Fostbite2D\\src\\fostbite2D\\config\\app_config.cpp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"directory": "d:\\Game\\Frostbite2D",
|
||||||
|
"arguments": ["C:\\mingw64\\bin\\x86_64-w64-mingw32-g++.exe", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-std=c++17", "-Id:\\Game\\Frostbite2D\\Fostbite2D\\include", "-fexceptions", "-finput-charset=UTF-8", "-fexec-charset=UTF-8", "-isystem", "C:\\Users\\dongj\\AppData\\Local\\.xmake\\packages\\l\\libsdl2\\2.32.2\\9c98693a11f742888762f17ab57f7f01\\include", "-isystem", "C:\\Users\\dongj\\AppData\\Local\\.xmake\\packages\\l\\libsdl2\\2.32.2\\9c98693a11f742888762f17ab57f7f01\\include\\SDL2", "-DNDEBUG", "-o", "build\\.objs\\Frostbite2D\\windows\\x64\\release\\Fostbite2D\\src\\main.cpp.obj", "Fostbite2D\\src\\main.cpp"],
|
||||||
|
"file": "Fostbite2D\\src\\main.cpp"
|
||||||
|
}]
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <fostbite2D/module/module.h>
|
#include <fostbite2D/module/module.h>
|
||||||
#include <fostbite2D/config/app_config.h>
|
#include <fostbite2D/config/app_config.h>
|
||||||
|
#include <fostbite2D/platform/window.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace frostbite2D {
|
namespace frostbite2D {
|
||||||
|
|
@ -196,7 +197,7 @@ private:
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
std::vector<Module*> modules_;
|
std::vector<Module*> modules_;
|
||||||
// IWindow* window_ = nullptr;
|
Window* window_ = nullptr;
|
||||||
|
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
bool running_ = false;
|
bool running_ = false;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "fostbite2D/platform/window.h"
|
||||||
#include <fostbite2D/config/platform_config.h>
|
#include <fostbite2D/config/platform_config.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -25,6 +26,7 @@ struct AppConfig {
|
||||||
std::string appVersion = "1.0.0";
|
std::string appVersion = "1.0.0";
|
||||||
std::string organization = "";
|
std::string organization = "";
|
||||||
std::string configFile = "config.json";
|
std::string configFile = "config.json";
|
||||||
|
WindowConfig windowConfig;
|
||||||
PlatformType targetPlatform = PlatformType::Auto;
|
PlatformType targetPlatform = PlatformType::Auto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,550 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <fostbite2D/core/types.h>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 常量
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
constexpr float PI_F = 3.14159265358979323846f;
|
||||||
|
constexpr float DEG_TO_RAD = PI_F / 180.0f;
|
||||||
|
constexpr float RAD_TO_DEG = 180.0f / PI_F;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 2D 向量
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
struct Vec2 {
|
||||||
|
float x = 0.0f;
|
||||||
|
float y = 0.0f;
|
||||||
|
|
||||||
|
constexpr Vec2() = default;
|
||||||
|
constexpr Vec2(float x, float y) : x(x), y(y) {}
|
||||||
|
explicit Vec2(const glm::vec2 &v) : x(v.x), y(v.y) {}
|
||||||
|
|
||||||
|
glm::vec2 toGlm() const { return {x, y}; }
|
||||||
|
static Vec2 fromGlm(const glm::vec2 &v) { return {v.x, v.y}; }
|
||||||
|
|
||||||
|
// 基础运算
|
||||||
|
Vec2 operator+(const Vec2 &v) const { return {x + v.x, y + v.y}; }
|
||||||
|
Vec2 operator-(const Vec2 &v) const { return {x - v.x, y - v.y}; }
|
||||||
|
Vec2 operator*(float s) const { return {x * s, y * s}; }
|
||||||
|
Vec2 operator/(float s) const { return {x / s, y / s}; }
|
||||||
|
Vec2 operator-() const { return {-x, -y}; }
|
||||||
|
|
||||||
|
Vec2 &operator+=(const Vec2 &v) {
|
||||||
|
x += v.x;
|
||||||
|
y += v.y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Vec2 &operator-=(const Vec2 &v) {
|
||||||
|
x -= v.x;
|
||||||
|
y -= v.y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Vec2 &operator*=(float s) {
|
||||||
|
x *= s;
|
||||||
|
y *= s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Vec2 &operator/=(float s) {
|
||||||
|
x /= s;
|
||||||
|
y /= s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Vec2 &v) const { return x == v.x && y == v.y; }
|
||||||
|
bool operator!=(const Vec2 &v) const { return !(*this == v); }
|
||||||
|
|
||||||
|
// 向量运算
|
||||||
|
float length() const { return std::sqrt(x * x + y * y); }
|
||||||
|
float lengthSquared() const { return x * x + y * y; }
|
||||||
|
|
||||||
|
Vec2 normalized() const {
|
||||||
|
float len = length();
|
||||||
|
if (len > 0.0f)
|
||||||
|
return {x / len, y / len};
|
||||||
|
return {0.0f, 0.0f};
|
||||||
|
}
|
||||||
|
|
||||||
|
float dot(const Vec2 &v) const { return x * v.x + y * v.y; }
|
||||||
|
float cross(const Vec2 &v) const { return x * v.y - y * v.x; }
|
||||||
|
|
||||||
|
float distance(const Vec2 &v) const { return (*this - v).length(); }
|
||||||
|
float angle() const { return std::atan2(y, x) * RAD_TO_DEG; }
|
||||||
|
|
||||||
|
static Vec2 lerp(const Vec2 &a, const Vec2 &b, float t) {
|
||||||
|
return a + (b - a) * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr Vec2 Zero() { return {0.0f, 0.0f}; }
|
||||||
|
static constexpr Vec2 One() { return {1.0f, 1.0f}; }
|
||||||
|
static constexpr Vec2 UnitX() { return {1.0f, 0.0f}; }
|
||||||
|
static constexpr Vec2 UnitY() { return {0.0f, 1.0f}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Vec2 operator*(float s, const Vec2 &v) { return v * s; }
|
||||||
|
|
||||||
|
using Point = Vec2;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 3D 向量 (用于3D动作)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
struct Vec3 {
|
||||||
|
float x = 0.0f;
|
||||||
|
float y = 0.0f;
|
||||||
|
float z = 0.0f;
|
||||||
|
|
||||||
|
constexpr Vec3() = default;
|
||||||
|
constexpr Vec3(float x, float y, float z) : x(x), y(y), z(z) {}
|
||||||
|
explicit Vec3(const glm::vec3 &v) : x(v.x), y(v.y), z(v.z) {}
|
||||||
|
|
||||||
|
glm::vec3 toGlm() const { return {x, y, z}; }
|
||||||
|
static Vec3 fromGlm(const glm::vec3 &v) { return {v.x, v.y, v.z}; }
|
||||||
|
|
||||||
|
Vec3 operator+(const Vec3 &v) const { return {x + v.x, y + v.y, z + v.z}; }
|
||||||
|
Vec3 operator-(const Vec3 &v) const { return {x - v.x, y - v.y, z - v.z}; }
|
||||||
|
Vec3 operator*(float s) const { return {x * s, y * s, z * s}; }
|
||||||
|
Vec3 operator/(float s) const { return {x / s, y / s, z / s}; }
|
||||||
|
Vec3 operator-() const { return {-x, -y, -z}; }
|
||||||
|
|
||||||
|
Vec3 &operator+=(const Vec3 &v) {
|
||||||
|
x += v.x;
|
||||||
|
y += v.y;
|
||||||
|
z += v.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Vec3 &operator-=(const Vec3 &v) {
|
||||||
|
x -= v.x;
|
||||||
|
y -= v.y;
|
||||||
|
z -= v.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Vec3 &operator*=(float s) {
|
||||||
|
x *= s;
|
||||||
|
y *= s;
|
||||||
|
z *= s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Vec3 &operator/=(float s) {
|
||||||
|
x /= s;
|
||||||
|
y /= s;
|
||||||
|
z /= s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Vec3 &v) const {
|
||||||
|
return x == v.x && y == v.y && z == v.z;
|
||||||
|
}
|
||||||
|
bool operator!=(const Vec3 &v) const { return !(*this == v); }
|
||||||
|
|
||||||
|
float length() const { return std::sqrt(x * x + y * y + z * z); }
|
||||||
|
float lengthSquared() const { return x * x + y * y + z * z; }
|
||||||
|
|
||||||
|
Vec3 normalized() const {
|
||||||
|
float len = length();
|
||||||
|
if (len > 0.0f)
|
||||||
|
return {x / len, y / len, z / len};
|
||||||
|
return {0.0f, 0.0f, 0.0f};
|
||||||
|
}
|
||||||
|
|
||||||
|
float dot(const Vec3 &v) const { return x * v.x + y * v.y + z * v.z; }
|
||||||
|
|
||||||
|
static Vec3 lerp(const Vec3 &a, const Vec3 &b, float t) {
|
||||||
|
return a + (b - a) * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr Vec3 Zero() { return {0.0f, 0.0f, 0.0f}; }
|
||||||
|
static constexpr Vec3 One() { return {1.0f, 1.0f, 1.0f}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Vec3 operator*(float s, const Vec3 &v) { return v * s; }
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 2D 尺寸
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
struct Size {
|
||||||
|
float width = 0.0f;
|
||||||
|
float height = 0.0f;
|
||||||
|
|
||||||
|
constexpr Size() = default;
|
||||||
|
constexpr Size(float w, float h) : width(w), height(h) {}
|
||||||
|
|
||||||
|
bool operator==(const Size &s) const {
|
||||||
|
return width == s.width && height == s.height;
|
||||||
|
}
|
||||||
|
bool operator!=(const Size &s) const { return !(*this == s); }
|
||||||
|
|
||||||
|
float area() const { return width * height; }
|
||||||
|
bool empty() const { return width <= 0.0f || height <= 0.0f; }
|
||||||
|
|
||||||
|
static constexpr Size Zero() { return {0.0f, 0.0f}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 2D 矩形
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
struct Rect {
|
||||||
|
Point origin;
|
||||||
|
Size size;
|
||||||
|
|
||||||
|
constexpr Rect() = default;
|
||||||
|
constexpr Rect(float x, float y, float w, float h)
|
||||||
|
: origin(x, y), size(w, h) {}
|
||||||
|
constexpr Rect(const Point &o, const Size &s) : origin(o), size(s) {}
|
||||||
|
|
||||||
|
float left() const { return origin.x; }
|
||||||
|
float top() const { return origin.y; }
|
||||||
|
float right() const { return origin.x + size.width; }
|
||||||
|
float bottom() const { return origin.y + size.height; }
|
||||||
|
float width() const { return size.width; }
|
||||||
|
float height() const { return size.height; }
|
||||||
|
Point center() const {
|
||||||
|
return {origin.x + size.width * 0.5f, origin.y + size.height * 0.5f};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const { return size.empty(); }
|
||||||
|
|
||||||
|
bool containsPoint(const Point &p) const {
|
||||||
|
return p.x >= left() && p.x <= right() && p.y >= top() && p.y <= bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const Rect &r) const {
|
||||||
|
return r.left() >= left() && r.right() <= right() && r.top() >= top() &&
|
||||||
|
r.bottom() <= bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersects(const Rect &r) const {
|
||||||
|
return !(left() > r.right() || right() < r.left() || top() > r.bottom() ||
|
||||||
|
bottom() < r.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect intersection(const Rect &r) const {
|
||||||
|
float l = std::max(left(), r.left());
|
||||||
|
float t = std::max(top(), r.top());
|
||||||
|
float ri = std::min(right(), r.right());
|
||||||
|
float b = std::min(bottom(), r.bottom());
|
||||||
|
if (l < ri && t < b)
|
||||||
|
return {l, t, ri - l, b - t};
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect unionWith(const Rect &r) const {
|
||||||
|
if (empty())
|
||||||
|
return r;
|
||||||
|
if (r.empty())
|
||||||
|
return *this;
|
||||||
|
float l = std::min(left(), r.left());
|
||||||
|
float t = std::min(top(), r.top());
|
||||||
|
float ri = std::max(right(), r.right());
|
||||||
|
float b = std::max(bottom(), r.bottom());
|
||||||
|
return {l, t, ri - l, b - t};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Rect &r) const {
|
||||||
|
return origin == r.origin && size == r.size;
|
||||||
|
}
|
||||||
|
bool operator!=(const Rect &r) const { return !(*this == r); }
|
||||||
|
|
||||||
|
static constexpr Rect Zero() { return {0, 0, 0, 0}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 2D 变换矩阵(基于 glm::mat4,兼容 OpenGL)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
struct Transform2D {
|
||||||
|
glm::mat4 matrix{1.0f}; // 单位矩阵
|
||||||
|
|
||||||
|
Transform2D() = default;
|
||||||
|
explicit Transform2D(const glm::mat4 &m) : matrix(m) {}
|
||||||
|
|
||||||
|
static Transform2D identity() { return Transform2D{}; }
|
||||||
|
|
||||||
|
static Transform2D translation(float x, float y) {
|
||||||
|
Transform2D t;
|
||||||
|
t.matrix = glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f));
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Transform2D translation(const Vec2 &v) {
|
||||||
|
return translation(v.x, v.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Transform2D rotation(float degrees) {
|
||||||
|
Transform2D t;
|
||||||
|
t.matrix = glm::rotate(glm::mat4(1.0f), degrees * DEG_TO_RAD,
|
||||||
|
glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Transform2D scaling(float sx, float sy) {
|
||||||
|
Transform2D t;
|
||||||
|
t.matrix = glm::scale(glm::mat4(1.0f), glm::vec3(sx, sy, 1.0f));
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Transform2D scaling(float s) { return scaling(s, s); }
|
||||||
|
|
||||||
|
static Transform2D skewing(float skewX, float skewY) {
|
||||||
|
Transform2D t;
|
||||||
|
t.matrix = glm::mat4(1.0f);
|
||||||
|
t.matrix[1][0] = std::tan(skewX * DEG_TO_RAD);
|
||||||
|
t.matrix[0][1] = std::tan(skewY * DEG_TO_RAD);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform2D operator*(const Transform2D &other) const {
|
||||||
|
return Transform2D(matrix * other.matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform2D &operator*=(const Transform2D &other) {
|
||||||
|
matrix *= other.matrix;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 transformPoint(const Vec2 &p) const {
|
||||||
|
glm::vec4 result = matrix * glm::vec4(p.x, p.y, 0.0f, 1.0f);
|
||||||
|
return {result.x, result.y};
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform2D inverse() const { return Transform2D(glm::inverse(matrix)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 数学工具函数
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
namespace math {
|
||||||
|
|
||||||
|
inline float clamp(float value, float minVal, float maxVal) {
|
||||||
|
return std::clamp(value, minVal, maxVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float lerp(float a, float b, float t) { return a + (b - a) * t; }
|
||||||
|
|
||||||
|
inline float degrees(float radians) { return radians * RAD_TO_DEG; }
|
||||||
|
|
||||||
|
inline float radians(float degrees) { return degrees * DEG_TO_RAD; }
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 角度工具函数
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 规范化角度到 [0, 360) 范围
|
||||||
|
* @param degrees 输入角度(度数)
|
||||||
|
* @return 规范化后的角度,范围 [0, 360)
|
||||||
|
*/
|
||||||
|
inline float normalizeAngle360(float degrees) {
|
||||||
|
degrees = std::fmod(degrees, 360.0f);
|
||||||
|
if (degrees < 0.0f) {
|
||||||
|
degrees += 360.0f;
|
||||||
|
}
|
||||||
|
return degrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 规范化角度到 [-180, 180) 范围
|
||||||
|
* @param degrees 输入角度(度数)
|
||||||
|
* @return 规范化后的角度,范围 [-180, 180)
|
||||||
|
*/
|
||||||
|
inline float normalizeAngle180(float degrees) {
|
||||||
|
degrees = std::fmod(degrees + 180.0f, 360.0f);
|
||||||
|
if (degrees < 0.0f) {
|
||||||
|
degrees += 360.0f;
|
||||||
|
}
|
||||||
|
return degrees - 180.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 计算两个角度之间的最短差值
|
||||||
|
* @param from 起始角度(度数)
|
||||||
|
* @param to 目标角度(度数)
|
||||||
|
* @return 从 from 到 to 的最短角度差,范围 [-180, 180]
|
||||||
|
*/
|
||||||
|
inline float angleDifference(float from, float to) {
|
||||||
|
float diff = normalizeAngle360(to - from);
|
||||||
|
if (diff > 180.0f) {
|
||||||
|
diff -= 360.0f;
|
||||||
|
}
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 线性插值角度
|
||||||
|
* @param from 起始角度(度数)
|
||||||
|
* @param to 目标角度(度数)
|
||||||
|
* @param t 插值因子 [0, 1]
|
||||||
|
* @return 插值后的角度
|
||||||
|
*/
|
||||||
|
inline float lerpAngle(float from, float to, float t) {
|
||||||
|
return from + angleDifference(from, to) * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 向量工具函数
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 计算方向向量(从 from 指向 to 的单位向量)
|
||||||
|
* @param from 起始点
|
||||||
|
* @param to 目标点
|
||||||
|
* @return 归一化的方向向量
|
||||||
|
*/
|
||||||
|
inline Vec2 direction(const Vec2 &from, const Vec2 &to) {
|
||||||
|
return (to - from).normalized();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 计算两点之间的角度
|
||||||
|
* @param from 起始点
|
||||||
|
* @param to 目标点
|
||||||
|
* @return 角度(度数),范围 [-180, 180]
|
||||||
|
*/
|
||||||
|
inline float angleBetween(const Vec2 &from, const Vec2 &to) {
|
||||||
|
Vec2 dir = to - from;
|
||||||
|
return std::atan2(dir.y, dir.x) * RAD_TO_DEG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 根据角度创建方向向量
|
||||||
|
* @param degrees 角度(度数),0度指向右方,逆时针为正
|
||||||
|
* @return 单位方向向量
|
||||||
|
*/
|
||||||
|
inline Vec2 angleToVector(float degrees) {
|
||||||
|
float rad = degrees * DEG_TO_RAD;
|
||||||
|
return {std::cos(rad), std::sin(rad)};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将向量旋转指定角度
|
||||||
|
* @param v 原始向量
|
||||||
|
* @param degrees 旋转角度(度数),正值为逆时针旋转
|
||||||
|
* @return 旋转后的向量
|
||||||
|
*/
|
||||||
|
inline Vec2 rotateVector(const Vec2 &v, float degrees) {
|
||||||
|
float rad = degrees * DEG_TO_RAD;
|
||||||
|
float cosA = std::cos(rad);
|
||||||
|
float sinA = std::sin(rad);
|
||||||
|
return {v.x * cosA - v.y * sinA, v.x * sinA + v.y * cosA};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 坐标系转换工具
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Y轴向上坐标转Y轴向下坐标
|
||||||
|
* @param pos Y轴向上坐标系中的位置
|
||||||
|
* @param height 画布/屏幕高度
|
||||||
|
* @return Y轴向下坐标系中的位置
|
||||||
|
*/
|
||||||
|
inline Vec2 flipY(const Vec2 &pos, float height) {
|
||||||
|
return {pos.x, height - pos.y};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Y轴向下坐标转Y轴向上坐标
|
||||||
|
* @param pos Y轴向下坐标系中的位置
|
||||||
|
* @param height 画布/屏幕高度
|
||||||
|
* @return Y轴向上坐标系中的位置
|
||||||
|
*/
|
||||||
|
inline Vec2 unflipY(const Vec2 &pos, float height) {
|
||||||
|
return {pos.x, height - pos.y};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 矩阵工具函数
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从变换矩阵提取位置
|
||||||
|
* @param matrix 4x4变换矩阵
|
||||||
|
* @return 提取的位置向量
|
||||||
|
*/
|
||||||
|
inline Vec2 extractPosition(const glm::mat4 &matrix) {
|
||||||
|
return {matrix[3][0], matrix[3][1]};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从变换矩阵提取缩放
|
||||||
|
* @param matrix 4x4变换矩阵
|
||||||
|
* @return 提取的缩放向量
|
||||||
|
*/
|
||||||
|
inline Vec2 extractScale(const glm::mat4 &matrix) {
|
||||||
|
float scaleX = std::sqrt(matrix[0][0] * matrix[0][0] + matrix[0][1] * matrix[0][1]);
|
||||||
|
float scaleY = std::sqrt(matrix[1][0] * matrix[1][0] + matrix[1][1] * matrix[1][1]);
|
||||||
|
return {scaleX, scaleY};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从变换矩阵提取旋转角度
|
||||||
|
* @param matrix 4x4变换矩阵
|
||||||
|
* @return 提取的旋转角度(度数)
|
||||||
|
*/
|
||||||
|
inline float extractRotation(const glm::mat4 &matrix) {
|
||||||
|
return std::atan2(matrix[0][1], matrix[0][0]) * RAD_TO_DEG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 碰撞检测工具
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 判断点是否在矩形内
|
||||||
|
* @param point 要检测的点
|
||||||
|
* @param rect 矩形区域
|
||||||
|
* @return 如果点在矩形内返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
inline bool pointInRect(const Vec2 &point, const Rect &rect) {
|
||||||
|
return point.x >= rect.left() && point.x <= rect.right() &&
|
||||||
|
point.y >= rect.top() && point.y <= rect.bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 判断点是否在圆内
|
||||||
|
* @param point 要检测的点
|
||||||
|
* @param center 圆心
|
||||||
|
* @param radius 圆的半径
|
||||||
|
* @return 如果点在圆内返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
inline bool pointInCircle(const Vec2 &point, const Vec2 ¢er, float radius) {
|
||||||
|
float dx = point.x - center.x;
|
||||||
|
float dy = point.y - center.y;
|
||||||
|
return (dx * dx + dy * dy) <= (radius * radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 判断两个矩形是否相交
|
||||||
|
* @param a 第一个矩形
|
||||||
|
* @param b 第二个矩形
|
||||||
|
* @return 如果矩形相交返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
inline bool rectsIntersect(const Rect &a, const Rect &b) {
|
||||||
|
return a.intersects(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 判断两个圆是否相交
|
||||||
|
* @param center1 第一个圆的圆心
|
||||||
|
* @param radius1 第一个圆的半径
|
||||||
|
* @param center2 第二个圆的圆心
|
||||||
|
* @param radius2 第二个圆的半径
|
||||||
|
* @return 如果圆相交返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
inline bool circlesIntersect(const Vec2 ¢er1, float radius1,
|
||||||
|
const Vec2 ¢er2, float radius2) {
|
||||||
|
float dx = center2.x - center1.x;
|
||||||
|
float dy = center2.y - center1.y;
|
||||||
|
float distSq = dx * dx + dy * dy;
|
||||||
|
float radiusSum = radius1 + radius2;
|
||||||
|
return distSq <= (radiusSum * radiusSum);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
} // namespace extra2d
|
||||||
|
|
@ -0,0 +1,270 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <fostbite2D/core/math_types.h>
|
||||||
|
#include <fostbite2D/core/types.h>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \~chinese
|
||||||
|
* @brief 鼠标指针类型
|
||||||
|
*/
|
||||||
|
enum class CursorType {
|
||||||
|
Arrow, ///< 指针
|
||||||
|
TextInput, ///< 文本
|
||||||
|
Hand, ///< 手
|
||||||
|
SizeAll, ///< 指向四个方向的箭头
|
||||||
|
SizeWE, ///< 指向左右方向的箭头
|
||||||
|
SizeNS, ///< 指向上下方向的箭头
|
||||||
|
SizeNESW, ///< 指向左下到右上方向的箭头
|
||||||
|
SizeNWSE, ///< 指向左上到右下方向的箭头
|
||||||
|
No, ///< 禁止
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \~chinese
|
||||||
|
* @brief 分辨率
|
||||||
|
*/
|
||||||
|
struct Resolution {
|
||||||
|
uint32_t width = 0; ///< 分辨率宽度
|
||||||
|
uint32_t height = 0; ///< 分辨率高度
|
||||||
|
uint32_t refresh_rate = 0; ///< 刷新率
|
||||||
|
|
||||||
|
Resolution() = default;
|
||||||
|
|
||||||
|
Resolution(uint32_t width, uint32_t height, uint32_t refresh_rate)
|
||||||
|
: width(width), height(height), refresh_rate(refresh_rate) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \~chinese
|
||||||
|
* @brief 图标
|
||||||
|
*/
|
||||||
|
struct Icon {
|
||||||
|
Icon() = default;
|
||||||
|
|
||||||
|
Icon(std::string file_path) : file_path(file_path) {}
|
||||||
|
|
||||||
|
std::string file_path; ///< 文件路径
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
uint32_t resource_id = 0; ///< 资源ID,仅在windows上生效
|
||||||
|
|
||||||
|
Icon(uint32_t resource_id) : resource_id(resource_id) {}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \~chinese
|
||||||
|
* @brief 窗口设置
|
||||||
|
*/
|
||||||
|
struct WindowConfig {
|
||||||
|
uint32_t width = 640; ///< 窗口宽度
|
||||||
|
uint32_t height = 480; ///< 窗口高度
|
||||||
|
std::string title = "fostbite2D Game"; ///< 窗口标题
|
||||||
|
Icon icon; ///< 窗口图标
|
||||||
|
bool resizable = false; ///< 窗口大小可调整
|
||||||
|
bool fullscreen = false; ///< 窗口全屏
|
||||||
|
bool borderless = false; ///< 无边框窗口
|
||||||
|
bool decorated = true; ///< 窗口装饰
|
||||||
|
int multisamples = 0; ///< 多重采样数
|
||||||
|
bool centered = true; ///< 窗口是否居中
|
||||||
|
bool vsync = true; ///< 是否启用垂直同步
|
||||||
|
bool showCursor = true; ///< 是否显示光标
|
||||||
|
};
|
||||||
|
|
||||||
|
class Window {
|
||||||
|
public:
|
||||||
|
Window() = default;
|
||||||
|
virtual ~Window() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建窗口
|
||||||
|
* @param cfg 窗口配置
|
||||||
|
* @return 创建是否成功
|
||||||
|
*/
|
||||||
|
virtual bool create(const WindowConfig &cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 销毁窗口
|
||||||
|
*/
|
||||||
|
virtual void destroy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 轮询事件
|
||||||
|
*/
|
||||||
|
virtual void poll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 交换缓冲区
|
||||||
|
*/
|
||||||
|
virtual void swap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置窗口关闭标志
|
||||||
|
*/
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置窗口标题
|
||||||
|
*/
|
||||||
|
virtual void setTitle(const std::string &title);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置窗口大小
|
||||||
|
*/
|
||||||
|
virtual void setSize(int w, int h);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置窗口位置
|
||||||
|
*/
|
||||||
|
virtual void setPos(int x, int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置全屏模式
|
||||||
|
*/
|
||||||
|
virtual void setFullscreen(bool fs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置垂直同步
|
||||||
|
*/
|
||||||
|
virtual void setVSync(bool vsync);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置窗口可见性
|
||||||
|
*/
|
||||||
|
virtual void setVisible(bool visible);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口宽度
|
||||||
|
*/
|
||||||
|
virtual int width() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口高度
|
||||||
|
*/
|
||||||
|
virtual int height() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口大小
|
||||||
|
*/
|
||||||
|
virtual Size size() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口位置
|
||||||
|
*/
|
||||||
|
virtual Vec2 pos() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 是否全屏
|
||||||
|
*/
|
||||||
|
virtual bool fullscreen() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 是否启用垂直同步
|
||||||
|
*/
|
||||||
|
virtual bool vsync() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 窗口是否获得焦点
|
||||||
|
*/
|
||||||
|
virtual bool focused() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 窗口是否最小化
|
||||||
|
*/
|
||||||
|
virtual bool minimized() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取内容缩放X
|
||||||
|
*/
|
||||||
|
virtual float scaleX() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取内容缩放Y
|
||||||
|
*/
|
||||||
|
virtual float scaleY() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置光标形状
|
||||||
|
*/
|
||||||
|
virtual void setCursor(CursorType cursor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 显示/隐藏光标
|
||||||
|
*/
|
||||||
|
virtual void showCursor(bool show);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 锁定/解锁光标
|
||||||
|
*/
|
||||||
|
virtual void lockCursor(bool lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 窗口大小改变回调
|
||||||
|
*/
|
||||||
|
using ResizeCb = std::function<void(int, int)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 窗口关闭回调
|
||||||
|
*/
|
||||||
|
using CloseCb = std::function<void()>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 窗口焦点改变回调
|
||||||
|
*/
|
||||||
|
using FocusCb = std::function<void(bool)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置大小改变回调
|
||||||
|
*/
|
||||||
|
virtual void onResize(ResizeCb cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置关闭回调
|
||||||
|
*/
|
||||||
|
virtual void onClose(CloseCb cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置焦点改变回调
|
||||||
|
*/
|
||||||
|
virtual void onFocus(FocusCb cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取原生窗口句柄
|
||||||
|
*/
|
||||||
|
virtual void *native() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取 SDL 窗口句柄
|
||||||
|
*/
|
||||||
|
SDL_Window *sdlWindow() const { return sdlWindow_; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取 OpenGL 上下文
|
||||||
|
*/
|
||||||
|
SDL_GLContext glContext() const { return glContext_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_Window *sdlWindow_ = nullptr;
|
||||||
|
SDL_GLContext glContext_ = nullptr;
|
||||||
|
|
||||||
|
int width_ = 1280;
|
||||||
|
int height_ = 720;
|
||||||
|
bool fullscreen_ = false;
|
||||||
|
bool vsync_ = true;
|
||||||
|
bool focused_ = true;
|
||||||
|
bool minimized_ = false;
|
||||||
|
bool shouldClose_ = false;
|
||||||
|
float scaleX_ = 1.0f;
|
||||||
|
float scaleY_ = 1.0f;
|
||||||
|
bool cursorVisible_ = true;
|
||||||
|
bool cursorLocked_ = false;
|
||||||
|
|
||||||
|
ResizeCb resizeCb_;
|
||||||
|
CloseCb closeCb_;
|
||||||
|
FocusCb focusCb_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace frostbite2D
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,4 @@
|
||||||
#include "SDL2/SDL_log.h"
|
|
||||||
#include <fostbite2D/app/application.h>
|
#include <fostbite2D/app/application.h>
|
||||||
#include <iostream>
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
namespace frostbite2D {
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
|
@ -37,7 +35,13 @@ bool Application::init(const AppConfig &config) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Log("Frostbite2D 启动成功!");
|
WindowConfig windowConfig;
|
||||||
|
this->window_ = new Window();
|
||||||
|
|
||||||
|
if (!window_->create(config.windowConfig)) {
|
||||||
|
SDL_Log("Failed to create window");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ AppConfig AppConfig::createDefault() {
|
||||||
config.organization = "";
|
config.organization = "";
|
||||||
config.configFile = "config.json";
|
config.configFile = "config.json";
|
||||||
config.targetPlatform = PlatformType::Auto;
|
config.targetPlatform = PlatformType::Auto;
|
||||||
|
config.windowConfig.title = "Frostbite2D";
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
#include "SDL_log.h"
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <fostbite2D/platform/window.h>
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
bool Window::create(const WindowConfig &cfg) {
|
||||||
|
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
||||||
|
SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
|
#else
|
||||||
|
if (cfg.fullscreen) {
|
||||||
|
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
|
} else if (cfg.borderless) {
|
||||||
|
flags |= SDL_WINDOW_BORDERLESS;
|
||||||
|
}
|
||||||
|
if (cfg.resizable) {
|
||||||
|
flags |= SDL_WINDOW_RESIZABLE;
|
||||||
|
}
|
||||||
|
if (!cfg.decorated) {
|
||||||
|
flags |= SDL_WINDOW_BORDERLESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||||
|
|
||||||
|
if (cfg.multisamples > 0) {
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, cfg.multisamples);
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = SDL_WINDOWPOS_CENTERED;
|
||||||
|
int y = SDL_WINDOWPOS_CENTERED;
|
||||||
|
if (!cfg.centered) {
|
||||||
|
x = SDL_WINDOWPOS_UNDEFINED;
|
||||||
|
y = SDL_WINDOWPOS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建窗口
|
||||||
|
sdlWindow_ =
|
||||||
|
SDL_CreateWindow(cfg.title.c_str(), x, y, cfg.width, cfg.height, flags);
|
||||||
|
|
||||||
|
if (!sdlWindow_) {
|
||||||
|
SDL_Log("Failed to create window: %s", SDL_GetError());
|
||||||
|
SDL_Quit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glContext_ = SDL_GL_CreateContext(sdlWindow_);
|
||||||
|
if (!glContext_) {
|
||||||
|
SDL_Log("Failed to create OpenGL context: %s", SDL_GetError());
|
||||||
|
SDL_DestroyWindow(sdlWindow_);
|
||||||
|
sdlWindow_ = nullptr;
|
||||||
|
SDL_Quit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gladLoadGLES2Loader((GLADloadproc)SDL_GL_GetProcAddress)) {
|
||||||
|
SDL_Log("Failed to initialize GLAD GLES2");
|
||||||
|
SDL_GL_DeleteContext(glContext_);
|
||||||
|
glContext_ = nullptr;
|
||||||
|
SDL_DestroyWindow(sdlWindow_);
|
||||||
|
sdlWindow_ = nullptr;
|
||||||
|
SDL_Quit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GL_SetSwapInterval(cfg.vsync ? 1 : 0);
|
||||||
|
|
||||||
|
SDL_GetWindowSize(sdlWindow_, &width_, &height_);
|
||||||
|
fullscreen_ = (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
|
||||||
|
vsync_ = cfg.vsync;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::destroy() {}
|
||||||
|
|
||||||
|
void Window::poll() {}
|
||||||
|
|
||||||
|
void Window::swap() {}
|
||||||
|
|
||||||
|
void Window::close() { shouldClose_ = true; }
|
||||||
|
|
||||||
|
void Window::setTitle(const std::string &title) {}
|
||||||
|
|
||||||
|
void Window::setSize(int w, int h) {
|
||||||
|
width_ = w;
|
||||||
|
height_ = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setPos(int x, int y) {}
|
||||||
|
|
||||||
|
void Window::setFullscreen(bool fs) { fullscreen_ = fs; }
|
||||||
|
|
||||||
|
void Window::setVSync(bool vsync) { vsync_ = vsync; }
|
||||||
|
|
||||||
|
void Window::setVisible(bool visible) {}
|
||||||
|
|
||||||
|
int Window::width() const { return width_; }
|
||||||
|
|
||||||
|
int Window::height() const { return height_; }
|
||||||
|
|
||||||
|
Size Window::size() const {
|
||||||
|
return Size{static_cast<float>(width_), static_cast<float>(height_)};
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Window::pos() const { return Vec2{0.0f, 0.0f}; }
|
||||||
|
|
||||||
|
bool Window::fullscreen() const { return fullscreen_; }
|
||||||
|
|
||||||
|
bool Window::vsync() const { return vsync_; }
|
||||||
|
|
||||||
|
bool Window::focused() const { return focused_; }
|
||||||
|
|
||||||
|
bool Window::minimized() const { return minimized_; }
|
||||||
|
|
||||||
|
float Window::scaleX() const { return scaleX_; }
|
||||||
|
|
||||||
|
float Window::scaleY() const { return scaleY_; }
|
||||||
|
|
||||||
|
void Window::setCursor(CursorType cursor) {}
|
||||||
|
|
||||||
|
void Window::showCursor(bool show) { cursorVisible_ = show; }
|
||||||
|
|
||||||
|
void Window::lockCursor(bool lock) { cursorLocked_ = lock; }
|
||||||
|
|
||||||
|
void Window::onResize(ResizeCb cb) { resizeCb_ = cb; }
|
||||||
|
|
||||||
|
void Window::onClose(CloseCb cb) { closeCb_ = cb; }
|
||||||
|
|
||||||
|
void Window::onFocus(FocusCb cb) { focusCb_ = cb; }
|
||||||
|
|
||||||
|
void *Window::native() const { return nullptr; }
|
||||||
|
|
||||||
|
} // namespace frostbite2D
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,93 +1,92 @@
|
||||||
|
#include "SDL_log.h"
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
#include <fostbite2D/app/application.h>
|
#include <fostbite2D/app/application.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <SDL2/SDL.h>
|
#include <fostbite2D/platform/window.h>
|
||||||
|
|
||||||
using namespace frostbite2D;
|
using namespace frostbite2D;
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
// AppConfig config = AppConfig::createDefault();
|
AppConfig config = AppConfig::createDefault();
|
||||||
// config.appName = "Extra2D Scene Graph Demo";
|
config.appName = "Extra2D Scene Graph Demo";
|
||||||
// config.appVersion = "1.0.0";
|
config.appVersion = "1.0.0";
|
||||||
|
|
||||||
// Application &app = Application::get();
|
Application &app = Application::get();
|
||||||
// if (!app.init(config)) {
|
if (!app.init(config)) {
|
||||||
// std::cerr << "Failed to initialize application!" << std::endl;
|
std::cerr << "Failed to initialize application!" << std::endl;
|
||||||
// return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 初始化 SDL
|
||||||
|
// if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
|
// std::cerr << "SDL 初始化失败: " << SDL_GetError() << std::endl;
|
||||||
|
// return 1;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// 初始化 SDL
|
// // 创建窗口
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
// SDL_Window *window =
|
||||||
std::cerr << "SDL 初始化失败: " << SDL_GetError() << std::endl;
|
// SDL_CreateWindow("Frostbite2D - SDL2 Demo", SDL_WINDOWPOS_CENTERED,
|
||||||
return 1;
|
// SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
|
||||||
}
|
|
||||||
|
|
||||||
// 创建窗口
|
// if (!window) {
|
||||||
SDL_Window* window = SDL_CreateWindow(
|
// std::cerr << "窗口创建失败: " << SDL_GetError() << std::endl;
|
||||||
"Frostbite2D - SDL2 Demo",
|
// SDL_Quit();
|
||||||
SDL_WINDOWPOS_CENTERED,
|
// return 1;
|
||||||
SDL_WINDOWPOS_CENTERED,
|
// }
|
||||||
800, 600,
|
|
||||||
SDL_WINDOW_SHOWN
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!window) {
|
// // 创建渲染器
|
||||||
std::cerr << "窗口创建失败: " << SDL_GetError() << std::endl;
|
// SDL_Renderer *renderer =
|
||||||
SDL_Quit();
|
// SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
return 1;
|
// if (!renderer) {
|
||||||
}
|
// std::cerr << "渲染器创建失败: " << SDL_GetError() << std::endl;
|
||||||
|
// SDL_DestroyWindow(window);
|
||||||
|
// SDL_Quit();
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
|
||||||
// 创建渲染器
|
// SDL_Log("Frostbite2D 启动成功!");
|
||||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1,
|
// SDL_Log("按 ESC 键退出程序");
|
||||||
SDL_RENDERER_ACCELERATED); if (!renderer) {
|
|
||||||
std::cerr << "渲染器创建失败: " << SDL_GetError() << std::endl;
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
SDL_Quit();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Frostbite2D 启动成功!" << std::endl;
|
// // 主循环
|
||||||
std::cout << "按 ESC 键退出程序" << std::endl;
|
// bool running = true;
|
||||||
|
// SDL_Event event;
|
||||||
|
|
||||||
// 主循环
|
// while (running) {
|
||||||
bool running = true;
|
// // 处理事件
|
||||||
SDL_Event event;
|
// while (SDL_PollEvent(&event)) {
|
||||||
|
// if (event.type == SDL_QUIT) {
|
||||||
|
// running = false;
|
||||||
|
// }
|
||||||
|
// if (event.type == SDL_KEYDOWN) {
|
||||||
|
// if (event.key.keysym.sym == SDLK_ESCAPE) {
|
||||||
|
// running = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
while (running) {
|
// // 清屏 (黑色)
|
||||||
// 处理事件
|
// SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
while (SDL_PollEvent(&event)) {
|
// SDL_RenderClear(renderer);
|
||||||
if (event.type == SDL_QUIT) {
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
if (event.type == SDL_KEYDOWN) {
|
|
||||||
if (event.key.keysym.sym == SDLK_ESCAPE) {
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清屏 (黑色)
|
// // 绘制一个红色矩形
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
// SDL_Rect rect = {350, 250, 100, 100};
|
||||||
SDL_RenderClear(renderer);
|
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
||||||
|
// SDL_RenderFillRect(renderer, &rect);
|
||||||
|
|
||||||
// 绘制一个红色矩形
|
// // 绘制一个绿色边框
|
||||||
SDL_Rect rect = {350, 250, 100, 100};
|
// SDL_Rect border = {300, 200, 200, 200};
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
// SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
||||||
SDL_RenderFillRect(renderer, &rect);
|
// SDL_RenderDrawRect(renderer, &border);
|
||||||
|
|
||||||
// 绘制一个绿色边框
|
// // 更新屏幕
|
||||||
SDL_Rect border = {300, 200, 200, 200};
|
// SDL_RenderPresent(renderer);
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
// }
|
||||||
SDL_RenderDrawRect(renderer, &border);
|
|
||||||
|
|
||||||
// 更新屏幕
|
// // 清理资源
|
||||||
SDL_RenderPresent(renderer);
|
// SDL_DestroyRenderer(renderer);
|
||||||
}
|
// SDL_DestroyWindow(window);
|
||||||
|
// SDL_Quit();
|
||||||
// 清理资源
|
|
||||||
SDL_DestroyRenderer(renderer);
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
SDL_Quit();
|
|
||||||
|
|
||||||
std::cout << "程序正常退出" << std::endl;
|
std::cout << "程序正常退出" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,14 @@
|
||||||
set_toolchains("mingw")
|
set_toolchains("mingw")
|
||||||
|
|
||||||
add_requires("libsdl2", {configs = {shared = true}})
|
add_requires("libsdl2", {configs = {shared = true}})
|
||||||
|
add_requires("glm")
|
||||||
|
|
||||||
target("Frostbite2D")
|
target("Frostbite2D")
|
||||||
set_kind("binary")
|
set_kind("binary")
|
||||||
add_files(path.join(os.projectdir(), "Fostbite2D/src/**.cpp"))
|
add_files(path.join(os.projectdir(), "Fostbite2D/src/**.cpp"))
|
||||||
|
add_files(path.join(os.projectdir(), "Fostbite2D/src/**.c"))
|
||||||
add_includedirs(path.join(os.projectdir(), "Fostbite2D/include"))
|
add_includedirs(path.join(os.projectdir(), "Fostbite2D/include"))
|
||||||
|
|
||||||
add_packages("libsdl2")
|
add_packages("libsdl2")
|
||||||
|
add_packages("glm")
|
||||||
target_end()
|
target_end()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue