summaryrefslogtreecommitdiff
path: root/src/FLD.hpp
blob: 958a724d98dcb07a294ae5f57e70038082805319 (plain)
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#pragma once
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_scancode.h>
#include <SDL2/SDL_gamecontroller.h>
#include <string>
#include <map>
#include <array>
#include <climits>
#include "soloud.h"

#define READONLY(T, X, V) private: T _##X = V; public: decltype(_##X) const& X = _##X

class FLD {
public:
	using Error = int;
	using Uint = unsigned int;
	using MainLoop = int (*)(FLD& fld, void *udata);
	enum class InputState {
		Up,
		Down,
		Release,
		Press
	};
	using InputStateArray = std::array<InputState, SDL_NUM_SCANCODES>;
	using MouseStateArray = std::array<InputState, 256>;
	using JoyStateArray = std::array<InputState, SDL_CONTROLLER_BUTTON_MAX>;
	struct Config {
		int width = 640;
		int height = 480;
		int scale = 1;
		int target_fps = 60;
		bool pixel_perfect = true;
		bool hide_cursor = true;
		std::string title = "FLD project";
	};
	struct Color {
		float r = -1.0f;
		float g = -1.0f;
		float b = -1.0f;
		float a = -1.0f;
	};
	struct Point {
		int x;
		int y;
	};
	struct Rectangle {
		int x;
		int y;
		int w;
		int h;
	};
	struct DrawImageOpts {
		const Point& p;
		int ix = 0;
		int iy = 0;
		int w = INT_MIN;
		int h = INT_MIN;
		float r = 0.0f;
		float sx = 1.0f;
		float sy = 1.0f;
		Uint f = NONE;
	};
	struct Image {
		FLD *fld = nullptr;
		std::string path = "";
		bool valid = true;
		SDL_Texture *ptr = nullptr;
		int width = 0;
		int height = 0;

		[[nodiscard]] Error invalid() const;
		Error draw(const DrawImageOpts& opts) const;
		Error setScaleMode(SDL_ScaleMode scale_mode) const;
	};
	enum DrawFlag {
		NONE = 0,
		FILL = 1,
		CENTER = 2,
		FLIP_X = 4,
		FLIP_Y = 8,
	};
	static constexpr Color BLACK {0.0f, 0.0f, 0.0f, -1.0f};
	static constexpr Color RED {1.0f, 0.0f, 0.0f, -1.0f};
	static constexpr Color GREEN {0.0f, 1.0f, 0.0f, -1.0f};
	static constexpr Color BLUE {0.0f, 0.0f, 1.0f, -1.0f};
	static constexpr Color YELLOW {1.0f, 1.0f, 0.0f, -1.0f};
	static constexpr Color PURPLE {1.0f, 0.0f, 1.0f, -1.0f};
	static constexpr Color CYAN {0.0f, 1.0f, 1.0f, -1.0f};
	static constexpr Color WHITE {1.0f, 1.0f, 1.0f, -1.0f};
	Point viewport = {0, 0};

	const Config config;
	SoLoud::Soloud soloud = {};
	READONLY(SDL_Window *, window, nullptr);
	READONLY(SDL_Renderer *, renderer, nullptr);
	READONLY(SDL_Texture *, target, nullptr);
	READONLY(unsigned long, tick, 0);
	READONLY(Color, drawColor, Color({0, 0, 0, 1}));
	READONLY(InputStateArray, keystates, {});
	READONLY(MouseStateArray, mousestates, {});
	READONLY(JoyStateArray, joystates, {});
public:
	FLD(const Config& config);
	FLD(const Config&& config);
	~FLD();

	[[nodiscard]] Error init();
	[[nodiscard]] Error init(MainLoop main_loop, void *udata=nullptr);
	void run(MainLoop main_loop, void *udata = nullptr);

	[[nodiscard]] Error drawBegin() const;
	[[nodiscard]] Error drawEnd();
	Error drawSetColor(const Color& c);
	Error drawClear() const;
	Error drawPoint(const Point& p) const;
	Error drawLine(const Point& p0, const Point& p1) const;
	Error drawRectangle(const Rectangle& rect, Uint flags=NONE) const;

	[[nodiscard]] Image& image(const std::string& path);

	[[nodiscard]] InputState keyGet(SDL_Scancode sc) const;
	[[nodiscard]] bool keyDown(SDL_Scancode sc) const;
	[[nodiscard]] bool keyUp(SDL_Scancode sc) const;
	[[nodiscard]] bool keyPressed(SDL_Scancode sc) const;
	[[nodiscard]] bool keyReleased(SDL_Scancode sc) const;

	[[nodiscard]] InputState mouseGet(SDL_Scancode sc) const;
	[[nodiscard]] bool mouseDown(SDL_Scancode sc) const;
	[[nodiscard]] bool mouseUp(SDL_Scancode sc) const;
	[[nodiscard]] bool mousePressed(SDL_Scancode sc) const;
	[[nodiscard]] bool mouseReleased(SDL_Scancode sc) const;

	[[nodiscard]] InputState joyGet(SDL_Scancode sc) const;
	[[nodiscard]] bool joyDown(SDL_Scancode sc) const;
	[[nodiscard]] bool joyUp(SDL_Scancode sc) const;
	[[nodiscard]] bool joyPressed(SDL_Scancode sc) const;
	[[nodiscard]] bool joyReleased(SDL_Scancode sc) const;
private:
	bool shouldQuit = false;
	struct {
		bool managed = false;
		Uint64 min_dt;
		Uint64 next_time;
	} fps;
	struct {
		float scale = 1.0;
		int off_x = 0;
		int off_y = 0;
	} transform;
	std::map<const std::string, Image> images = {};

	Error sdlError(const std::string& msg="") const;
	Error soloudError(SoLoud::result result) const;
	[[nodiscard]] Error initBasepath() const;
	[[nodiscard]] Error initWindow();
	[[nodiscard]] Error initRenderer();
	[[nodiscard]] Error initTarget();
	[[nodiscard]] Error initSoloud();
	void cycleEvents();
};