add render
This commit is contained in:
parent
f325ea6290
commit
bc4c5b6ec4
BIN
assets/basic.png
Normal file
BIN
assets/basic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.0 KiB |
@ -5,19 +5,25 @@
|
||||
#include <complex>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace arras {
|
||||
|
||||
using Float = float;
|
||||
using Vec2 = std::complex<Float>;
|
||||
|
||||
const Float eps = 1e-6;
|
||||
|
||||
Float cross(const Vec2& a, const Vec2& b) {
|
||||
inline Float cross(const Vec2& a, const Vec2& b) {
|
||||
return a.real() * b.imag() - a.imag() * b.real();
|
||||
}
|
||||
|
||||
Float dot(const Vec2& a, const Vec2& b) {
|
||||
inline Float dot(const Vec2& a, const Vec2& b) {
|
||||
return a.real() * b.real() + a.imag() * b.imag();
|
||||
}
|
||||
|
||||
inline Float asAngle(const Vec2& d) {
|
||||
return std::atan2(d.imag(), d.real());
|
||||
}
|
||||
|
||||
struct Circle {
|
||||
Vec2 o;
|
||||
Float r;
|
||||
@ -39,8 +45,10 @@ struct Polygon {
|
||||
Polygon(const std::array<Vec2, n>& v): vertex(v) {}
|
||||
Polygon(std::initializer_list<Vec2>&& v) {
|
||||
int i = 0;
|
||||
for (auto &&x : v) {
|
||||
if (i >= n) break;
|
||||
for (auto&& x : v) {
|
||||
if (i >= n) {
|
||||
break;
|
||||
}
|
||||
vertex[i] = x;
|
||||
i += 1;
|
||||
}
|
||||
@ -64,12 +72,12 @@ struct Polygon {
|
||||
}
|
||||
};
|
||||
|
||||
bool intersect(const Circle& a, const Circle& b) {
|
||||
inline bool intersect(const Circle& a, const Circle& b) {
|
||||
return abs(a.o - b.o) <= a.r + b.r;
|
||||
}
|
||||
|
||||
template<int n, int m>
|
||||
bool intersect(const Polygon<n>& a, const Polygon<m>& b) {
|
||||
inline bool intersect(const Polygon<n>& a, const Polygon<m>& b) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (b.contain(a[i])) {
|
||||
return true;
|
||||
@ -98,7 +106,7 @@ bool intersect(const Polygon<n>& a, const Polygon<m>& b) {
|
||||
}
|
||||
|
||||
template<int n>
|
||||
bool intersect(const Polygon<n>& a, const Circle& b) {
|
||||
inline bool intersect(const Polygon<n>& a, const Circle& b) {
|
||||
if (a.contain(b.o)) {
|
||||
return true;
|
||||
}
|
||||
@ -121,8 +129,9 @@ bool intersect(const Polygon<n>& a, const Circle& b) {
|
||||
}
|
||||
|
||||
template<int n>
|
||||
bool intersect(const Circle& b, const Polygon<n>& a) {
|
||||
inline bool intersect(const Circle& b, const Polygon<n>& a) {
|
||||
return intersect(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
98
include/render.h
Normal file
98
include/render.h
Normal file
@ -0,0 +1,98 @@
|
||||
#ifndef HEADER_ARRAS_RENDER_H
|
||||
#define HEADER_ARRAS_RENDER_H
|
||||
|
||||
extern "C" {
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
}
|
||||
|
||||
#include "2d.h"
|
||||
#include <fmt/core.h>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace arras {
|
||||
|
||||
struct Color {
|
||||
uint8_t r, g, b, a;
|
||||
|
||||
Color();
|
||||
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
};
|
||||
|
||||
std::shared_ptr<SDL_Rect> makeRect(int x, int y, int w, int h);
|
||||
std::shared_ptr<SDL_FRect> makeFRect(const arras::Vec2& pos, const arras::Vec2& size);
|
||||
|
||||
class RenderSurface {
|
||||
public:
|
||||
RenderSurface(RenderSurface&& rs);
|
||||
RenderSurface(const RenderSurface& rs);
|
||||
explicit RenderSurface(SDL_RWops* src);
|
||||
RenderSurface(int width, int height);
|
||||
|
||||
~RenderSurface();
|
||||
|
||||
SDL_Surface* nativeHandle() const noexcept;
|
||||
|
||||
int width() const noexcept;
|
||||
int height() const noexcept;
|
||||
|
||||
private:
|
||||
SDL_Surface* s;
|
||||
};
|
||||
|
||||
class RenderWindow;
|
||||
|
||||
class RenderTexture {
|
||||
RenderTexture(const RenderTexture&) = delete;
|
||||
RenderTexture& operator=(const RenderTexture&) = delete;
|
||||
|
||||
public:
|
||||
RenderTexture(RenderTexture&& rt);
|
||||
RenderTexture(const RenderWindow& rd, SDL_RWops* src);
|
||||
RenderTexture(const RenderWindow& rd, const RenderSurface& rs);
|
||||
|
||||
~RenderTexture();
|
||||
|
||||
SDL_Texture* nativeHandle() const noexcept;
|
||||
|
||||
int width() const noexcept;
|
||||
int height() const noexcept;
|
||||
|
||||
std::pair<int, int> calcRenderSize(int w, int h) const noexcept;
|
||||
|
||||
private:
|
||||
SDL_Texture* t;
|
||||
int w, h;
|
||||
};
|
||||
|
||||
class RenderWindow {
|
||||
RenderWindow(const RenderWindow&) = delete;
|
||||
RenderWindow& operator=(const RenderWindow&) = delete;
|
||||
|
||||
public:
|
||||
RenderWindow(RenderWindow&& rd);
|
||||
RenderWindow(int w, int h);
|
||||
|
||||
~RenderWindow();
|
||||
|
||||
SDL_Renderer* nativeHandle() const noexcept;
|
||||
|
||||
void renderTextureAt(const RenderTexture& t, const Vec2& pos) const;
|
||||
void renderTextureAt(const RenderTexture& t, const Vec2& pos, const Vec2& direction) const;
|
||||
|
||||
void present() const noexcept;
|
||||
void clear(const Color& c = {}) const;
|
||||
|
||||
int width() const noexcept;
|
||||
int height() const noexcept;
|
||||
|
||||
private:
|
||||
int w, h;
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
};
|
||||
} // namespace arras
|
||||
|
||||
#endif
|
32
main.cpp
Normal file
32
main.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "2d.h"
|
||||
#include "render.h"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <cmath>
|
||||
|
||||
int main() {
|
||||
arras::RenderWindow w(2360, 1240);
|
||||
arras::RenderTexture t(w, SDL_RWFromFile("assets/basic.png", "rb"));
|
||||
std::printf("%d %d\n", t.width(), t.height());
|
||||
|
||||
const float PI = acos(-1);
|
||||
arras::Vec2 d{1, 0}, v{std::cos(PI / 300), std::sin(PI / 300)};
|
||||
SDL_Event evt;
|
||||
while (true) {
|
||||
while (SDL_PollEvent(&evt)) {
|
||||
if (evt.type == SDL_QUIT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
w.clear();
|
||||
w.renderTextureAt(t, {200, 200}, d);
|
||||
w.present();
|
||||
d *= v;
|
||||
// pos += v;
|
||||
// if (pos.real() > 1000 || pos.real() < 200) {
|
||||
// v *= -1;
|
||||
// }
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
||||
}
|
||||
}
|
32
objects.hpp
Normal file
32
objects.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef HEADER_OBJECTS_HPP
|
||||
#define HEADER_OBJECTS_HPP
|
||||
|
||||
#include "2d.h"
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
namespace arras {
|
||||
|
||||
struct Transform {
|
||||
Vec2 position;
|
||||
};
|
||||
|
||||
struct Velocity {
|
||||
Vec2 velocity;
|
||||
};
|
||||
|
||||
struct EngineAcceleration {
|
||||
Vec2 ideal_velocity;
|
||||
Float acceleration;
|
||||
};
|
||||
|
||||
inline entt::entity makeTank(entt::registry &r, Vec2 position) {
|
||||
const auto e = r.create();
|
||||
r.emplace<Transform>(e, Transform{position});
|
||||
r.emplace<Velocity>(e, Velocity{{0, 0}});
|
||||
r.emplace<EngineAcceleration>(e, EngineAcceleration{{0, 0}, 1});
|
||||
return e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
42
src/render/misc.cpp
Normal file
42
src/render/misc.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "render.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class SDLLoader {
|
||||
private:
|
||||
SDLLoader() {
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
|
||||
IMG_Init(IMG_INIT_PNG);
|
||||
}
|
||||
|
||||
~SDLLoader() {
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
static const SDLLoader _;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
arras::Color::Color(): r(255), g(255), b(255), a(255) {}
|
||||
arras::Color::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a): r(r), g(g), b(b), a(a) {}
|
||||
|
||||
std::shared_ptr<SDL_Rect> arras::makeRect(int x, int y, int w, int h) {
|
||||
auto res = std::make_shared<SDL_Rect>();
|
||||
res->x = x;
|
||||
res->y = y;
|
||||
res->w = w;
|
||||
res->h = h;
|
||||
return res;
|
||||
}
|
||||
|
||||
std::shared_ptr<SDL_FRect> arras::makeFRect(const arras::Vec2& pos, const arras::Vec2& size) {
|
||||
auto res = std::make_shared<SDL_FRect>();
|
||||
res->x = pos.real();
|
||||
res->y = pos.imag();
|
||||
res->w = size.real();
|
||||
res->h = size.imag();
|
||||
return res;
|
||||
}
|
53
src/render/surface.cpp
Normal file
53
src/render/surface.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "render.h"
|
||||
|
||||
using namespace arras;
|
||||
|
||||
RenderSurface::RenderSurface(RenderSurface&& rs): s(rs.s) {
|
||||
rs.s = nullptr;
|
||||
}
|
||||
|
||||
RenderSurface::RenderSurface(const RenderSurface& rs) {
|
||||
s = SDL_CreateRGBSurfaceWithFormat(0, rs.width(), rs.height(), 32, SDL_PIXELFORMAT_RGBA8888);
|
||||
if (!s) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("SDL_CreateRGBSurfaceWithFormat() failed: {}", SDL_GetError()));
|
||||
}
|
||||
if (SDL_BlitSurface(rs.nativeHandle(),
|
||||
nullptr,
|
||||
s,
|
||||
makeRect(0, 0, rs.width(), rs.height()).get())
|
||||
!= 0) {
|
||||
throw std::runtime_error(fmt::format("SDL_BlitSurface() failed: {}", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
RenderSurface::RenderSurface(SDL_RWops* src) {
|
||||
s = IMG_Load_RW(src, 1);
|
||||
if (!s) {
|
||||
throw std::runtime_error(fmt::format("IMG_Load_RW() failed: {}", IMG_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
RenderSurface::RenderSurface(int width, int height) {
|
||||
s = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_RGBA8888);
|
||||
if (!s) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("SDL_CreateRGBSurfaceWithFormat() failed: {}", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
RenderSurface ::~RenderSurface() {
|
||||
SDL_FreeSurface(s);
|
||||
}
|
||||
|
||||
SDL_Surface* RenderSurface::nativeHandle() const noexcept {
|
||||
return s;
|
||||
}
|
||||
|
||||
int RenderSurface::width() const noexcept {
|
||||
return s->w;
|
||||
}
|
||||
|
||||
int RenderSurface::height() const noexcept {
|
||||
return s->h;
|
||||
}
|
63
src/render/texture.cpp
Normal file
63
src/render/texture.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
#include "render.h"
|
||||
|
||||
using namespace arras;
|
||||
|
||||
RenderTexture::RenderTexture(RenderTexture&& rt): t(rt.t) {
|
||||
rt.t = nullptr;
|
||||
}
|
||||
|
||||
RenderTexture::RenderTexture(const RenderWindow& rd, SDL_RWops* src) {
|
||||
t = IMG_LoadTexture_RW(rd.nativeHandle(), src, 1);
|
||||
if (!t) {
|
||||
throw std::runtime_error(fmt::format("IMG_LoadTexture_RW() failed: {}", IMG_GetError()));
|
||||
}
|
||||
if (SDL_QueryTexture(t, nullptr, nullptr, &w, &h) != 0) {
|
||||
throw std::runtime_error(fmt::format("SDL_QueryTexture() failed: {}", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
RenderTexture::RenderTexture(const RenderWindow& rd, const RenderSurface& rs) {
|
||||
t = SDL_CreateTextureFromSurface(rd.nativeHandle(), rs.nativeHandle());
|
||||
if (!t) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("SDL_CreateRGBSurfaceWithFormat() failed: {}", SDL_GetError()));
|
||||
}
|
||||
if (SDL_QueryTexture(t, nullptr, nullptr, &w, &h)) {
|
||||
throw std::runtime_error(fmt::format("SDL_QueryTexture() failed: {}", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
RenderTexture::~RenderTexture() {
|
||||
SDL_DestroyTexture(t);
|
||||
}
|
||||
|
||||
SDL_Texture* RenderTexture::nativeHandle() const noexcept {
|
||||
return t;
|
||||
}
|
||||
|
||||
int RenderTexture::width() const noexcept {
|
||||
return w;
|
||||
}
|
||||
|
||||
int RenderTexture::height() const noexcept {
|
||||
return h;
|
||||
}
|
||||
|
||||
std::pair<int, int> RenderTexture::calcRenderSize(int w, int h) const noexcept {
|
||||
int rw, rh;
|
||||
if (w == 0 && h == 0) {
|
||||
rw = width();
|
||||
rh = height();
|
||||
} else if (w == 0) {
|
||||
rw = (h * width() / height());
|
||||
rh = h;
|
||||
} else if (h == 0) {
|
||||
rw = w;
|
||||
rh = (w * height() / width());
|
||||
} else {
|
||||
rw = w;
|
||||
rh = h;
|
||||
}
|
||||
return {rw, rh};
|
||||
}
|
76
src/render/window.cpp
Normal file
76
src/render/window.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef HEADER_ARRAS_RENDER_WINDOW_HPP
|
||||
#define HEADER_ARRAS_RENDER_WINDOW_HPP
|
||||
|
||||
#include "render.h"
|
||||
#define Pi 3.14159265358979323846
|
||||
|
||||
using namespace arras;
|
||||
|
||||
RenderWindow::RenderWindow(RenderWindow&& rd)
|
||||
: w(rd.w), h(rd.h), window(rd.window), renderer(rd.renderer) {
|
||||
rd.renderer = nullptr;
|
||||
rd.window = nullptr;
|
||||
}
|
||||
|
||||
RenderWindow::RenderWindow(int w, int h): w(w), h(h) {
|
||||
if (SDL_CreateWindowAndRenderer(w, h, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI, &window, &renderer) != 0) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("SDL_CreateWindowAndRenderer() failed: {}", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
RenderWindow::~RenderWindow() {
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
|
||||
SDL_Renderer* RenderWindow::nativeHandle() const noexcept {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void RenderWindow::renderTextureAt(const RenderTexture& t, const Vec2& pos) const {
|
||||
if (SDL_RenderCopyF(renderer,
|
||||
t.nativeHandle(),
|
||||
NULL,
|
||||
makeFRect(pos, {t.width(), t.height()}).get())) {
|
||||
throw std::runtime_error(fmt::format("SDL_RenderCopy() failed: {}", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWindow::renderTextureAt(const RenderTexture& t,
|
||||
const Vec2& pos,
|
||||
const Vec2& direction) const {
|
||||
if (SDL_RenderCopyExF(renderer,
|
||||
t.nativeHandle(),
|
||||
NULL,
|
||||
makeFRect(pos, {t.width(), t.height()}).get(),
|
||||
-asAngle(direction) * 180 / Pi,
|
||||
nullptr,
|
||||
SDL_FLIP_NONE)) {
|
||||
throw std::runtime_error(fmt::format("SDL_RenderCopy() failed: {}", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWindow::present() const noexcept {
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
void RenderWindow::clear(const Color& c) const {
|
||||
if (SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a)) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("SDL_SetRenderDrawColor() failed: {}", SDL_GetError()));
|
||||
}
|
||||
if (SDL_RenderClear(renderer)) {
|
||||
throw std::runtime_error(fmt::format("SDL_RenderClear() failed: {}", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
int RenderWindow::width() const noexcept {
|
||||
return w;
|
||||
}
|
||||
|
||||
int RenderWindow::height() const noexcept {
|
||||
return h;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
#include "2d.hpp"
|
||||
#include "2d.h"
|
||||
#include "test/u.hpp"
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
@ -6,6 +6,7 @@
|
||||
namespace {
|
||||
|
||||
AddTestCase _(1, "2d.hpp", [](TestCase& t) {
|
||||
using namespace arras;
|
||||
t.expectEq<Float>([] { return cross({1, 2}, {4, 1}); }, -7);
|
||||
t.expectEq<Float>([] { return cross({.5, 2.5}, {4, 1.5}); }, -9.25);
|
||||
|
||||
|
10
test/cases/objects.cpp
Normal file
10
test/cases/objects.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "objects.hpp"
|
||||
#include "test/u.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
AddTestCase _(1, "objects.hpp", [](TestCase& t) {
|
||||
|
||||
});
|
||||
|
||||
}
|
24
xmake.lua
24
xmake.lua
@ -4,13 +4,31 @@ set_version("0.0a0")
|
||||
set_languages("c++17")
|
||||
set_targetdir(".")
|
||||
|
||||
target("test")
|
||||
add_requires("entt 3.11", "libsdl 2.26", "libsdl_image 2.6", "fmt 10")
|
||||
add_includedirs("include", ".")
|
||||
|
||||
|
||||
target("main")
|
||||
set_default(true)
|
||||
set_kind("binary")
|
||||
add_files("main.cpp")
|
||||
add_files("src/**/*.cpp")
|
||||
|
||||
add_packages("entt", "libsdl", "libsdl_image", "fmt")
|
||||
set_warnings("allextra")
|
||||
|
||||
target("test")
|
||||
set_default(false)
|
||||
set_kind("binary")
|
||||
set_prefixname("test-")
|
||||
|
||||
add_files("test/main.cpp")
|
||||
add_files("test/cases/*.cpp")
|
||||
add_includedirs(".")
|
||||
add_files("src/**/*.cpp")
|
||||
|
||||
add_packages("entt", "fmt")
|
||||
|
||||
set_warnings("allextra")
|
||||
set_optimize("none")
|
||||
set_symbols("debug")
|
||||
add_defines("DEBUG")
|
||||
set_prefixname("test-")
|
Loading…
x
Reference in New Issue
Block a user