窗口创建

This commit is contained in:
lenheart 2026-02-17 13:38:56 +08:00
parent 3711b12338
commit 637f087001
13 changed files with 11700 additions and 75 deletions

2
.gitignore vendored
View File

@ -10,3 +10,5 @@ build/
.cache/
*.json
.vscode/compile_commands.json

View File

@ -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"
}]

View File

@ -2,6 +2,7 @@
#include <fostbite2D/module/module.h>
#include <fostbite2D/config/app_config.h>
#include <fostbite2D/platform/window.h>
#include <string>
namespace frostbite2D {
@ -196,7 +197,7 @@ private:
void render();
std::vector<Module*> modules_;
// IWindow* window_ = nullptr;
Window* window_ = nullptr;
bool initialized_ = false;
bool running_ = false;

View File

@ -1,5 +1,6 @@
#pragma once
#include "fostbite2D/platform/window.h"
#include <fostbite2D/config/platform_config.h>
#include <string>
@ -25,6 +26,7 @@ struct AppConfig {
std::string appVersion = "1.0.0";
std::string organization = "";
std::string configFile = "config.json";
WindowConfig windowConfig;
PlatformType targetPlatform = PlatformType::Auto;
/**

View File

@ -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 &center, 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 &center1, float radius1,
const Vec2 &center2, 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

View File

@ -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

View File

@ -1,6 +1,4 @@
#include "SDL2/SDL_log.h"
#include <fostbite2D/app/application.h>
#include <iostream>
#include <SDL2/SDL.h>
namespace frostbite2D {
@ -37,7 +35,13 @@ bool Application::init(const AppConfig &config) {
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;
}

View File

@ -10,6 +10,7 @@ AppConfig AppConfig::createDefault() {
config.organization = "";
config.configFile = "config.json";
config.targetPlatform = PlatformType::Auto;
config.windowConfig.title = "Frostbite2D";
return config;
}

View File

@ -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

3602
Fostbite2D/src/glad/glad.c Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,93 +1,92 @@
#include "SDL_log.h"
#include <SDL2/SDL.h>
#include <fostbite2D/app/application.h>
#include <iostream>
#include <SDL2/SDL.h>
#include <fostbite2D/platform/window.h>
using namespace frostbite2D;
int main(int argc, char **argv) {
// AppConfig config = AppConfig::createDefault();
// config.appName = "Extra2D Scene Graph Demo";
// config.appVersion = "1.0.0";
AppConfig config = AppConfig::createDefault();
config.appName = "Extra2D Scene Graph Demo";
config.appVersion = "1.0.0";
// Application &app = Application::get();
// if (!app.init(config)) {
// std::cerr << "Failed to initialize application!" << std::endl;
// return -1;
Application &app = Application::get();
if (!app.init(config)) {
std::cerr << "Failed to initialize application!" << std::endl;
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) {
std::cerr << "SDL 初始化失败: " << SDL_GetError() << std::endl;
return 1;
}
// // 创建窗口
// SDL_Window *window =
// SDL_CreateWindow("Frostbite2D - SDL2 Demo", SDL_WINDOWPOS_CENTERED,
// SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
// 创建窗口
SDL_Window* window = SDL_CreateWindow(
"Frostbite2D - SDL2 Demo",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800, 600,
SDL_WINDOW_SHOWN
);
// if (!window) {
// std::cerr << "窗口创建失败: " << SDL_GetError() << std::endl;
// SDL_Quit();
// return 1;
// }
if (!window) {
std::cerr << "窗口创建失败: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
// // 创建渲染器
// SDL_Renderer *renderer =
// SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// if (!renderer) {
// std::cerr << "渲染器创建失败: " << SDL_GetError() << std::endl;
// SDL_DestroyWindow(window);
// SDL_Quit();
// return 1;
// }
// 创建渲染器
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1,
SDL_RENDERER_ACCELERATED); if (!renderer) {
std::cerr << "渲染器创建失败: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
// SDL_Log("Frostbite2D 启动成功!");
// SDL_Log("按 ESC 键退出程序");
std::cout << "Frostbite2D 启动成功!" << std::endl;
std::cout << "按 ESC 键退出程序" << std::endl;
// // 主循环
// bool running = true;
// SDL_Event event;
// 主循环
bool running = true;
SDL_Event event;
// while (running) {
// // 处理事件
// 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) {
// 处理事件
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;
}
}
}
// // 清屏 (黑色)
// SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
// SDL_RenderClear(renderer);
// 清屏 (黑色)
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// // 绘制一个红色矩形
// SDL_Rect rect = {350, 250, 100, 100};
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
// SDL_RenderFillRect(renderer, &rect);
// 绘制一个红色矩形
SDL_Rect rect = {350, 250, 100, 100};
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderFillRect(renderer, &rect);
// // 绘制一个绿色边框
// SDL_Rect border = {300, 200, 200, 200};
// SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
// SDL_RenderDrawRect(renderer, &border);
// 绘制一个绿色边框
SDL_Rect border = {300, 200, 200, 200};
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderDrawRect(renderer, &border);
// // 更新屏幕
// SDL_RenderPresent(renderer);
// }
// 更新屏幕
SDL_RenderPresent(renderer);
}
// 清理资源
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
// // 清理资源
// SDL_DestroyRenderer(renderer);
// SDL_DestroyWindow(window);
// SDL_Quit();
std::cout << "程序正常退出" << std::endl;
return 0;

View File

@ -2,11 +2,14 @@
set_toolchains("mingw")
add_requires("libsdl2", {configs = {shared = true}})
add_requires("glm")
target("Frostbite2D")
set_kind("binary")
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_packages("libsdl2")
add_packages("glm")
target_end()