mini-arcade-native-backend 0.3.0__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. mini_arcade_native_backend-0.3.1/.changelog_section +9 -0
  2. mini_arcade_native_backend-0.3.1/.version_to_tag +1 -0
  3. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/CHANGELOG.md +9 -0
  4. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/PKG-INFO +1 -1
  5. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/cpp/bindings.cpp +11 -2
  6. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/cpp/engine.cpp +92 -11
  7. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/cpp/engine.h +9 -1
  8. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/pyproject.toml +1 -1
  9. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/src/mini_arcade_native_backend/__init__.py +16 -2
  10. mini_arcade_native_backend-0.3.0/.changelog_section +0 -9
  11. mini_arcade_native_backend-0.3.0/.version_to_tag +0 -1
  12. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/.github/workflows/ci.yml +0 -0
  13. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/.github/workflows/create-release-branch.yml +0 -0
  14. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/.github/workflows/release-finalize.yml +0 -0
  15. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/.github/workflows/release-publish.yml +0 -0
  16. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/.gitignore +0 -0
  17. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/.vscode/settings.json +0 -0
  18. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/CMakeLists.txt +0 -0
  19. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/LICENSE +0 -0
  20. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/README.md +0 -0
  21. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/examples/native_backend_demo.py +0 -0
  22. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/poetry.lock +0 -0
  23. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/poetry.toml +0 -0
  24. {mini_arcade_native_backend-0.3.0 → mini_arcade_native_backend-0.3.1}/tests/test_init.py +0 -0
@@ -0,0 +1,9 @@
1
+ ## [0.3.1] - 2025-12-05
2
+
3
+ ### Added
4
+ - add capture_frame method to Engine and expose it in Python bindings
5
+ - add clear color customization and update draw_rect method
6
+
7
+ ### Other
8
+ - Merge branch 'release/0.3' of https://github.com/alexsc6955/mini-arcade-native-backend into release/0.3
9
+
@@ -0,0 +1 @@
1
+ 0.3.1
@@ -6,6 +6,15 @@ This project adheres to [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.1] - 2025-12-05
10
+
11
+ ### Added
12
+ - add capture_frame method to Engine and expose it in Python bindings
13
+ - add clear color customization and update draw_rect method
14
+
15
+ ### Other
16
+ - Merge branch 'release/0.3' of https://github.com/alexsc6955/mini-arcade-native-backend into release/0.3
17
+
9
18
  ## [0.3.0] - 2025-12-05
10
19
 
11
20
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mini-arcade-native-backend
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Native SDL2 backend for mini-arcade-core using SDL2 + pybind11.
5
5
  Author-Email: Santiago Rincon <rincores@gmail.com>
6
6
  License: Copyright (c) 2025 Santiago Rincón
@@ -27,11 +27,17 @@ PYBIND11_MODULE(_native, m) {
27
27
  .def("init", &mini::Engine::init,
28
28
  py::arg("width"), py::arg("height"), py::arg("title"))
29
29
 
30
+ .def("set_clear_color", &mini::Engine::set_clear_color,
31
+ py::arg("r"), py::arg("g"), py::arg("b"))
32
+
30
33
  .def("begin_frame", &mini::Engine::begin_frame)
31
34
  .def("end_frame", &mini::Engine::end_frame)
32
35
 
33
36
  .def("draw_rect", &mini::Engine::draw_rect,
34
- py::arg("x"), py::arg("y"), py::arg("w"), py::arg("h"))
37
+ py::arg("x"), py::arg("y"),
38
+ py::arg("w"), py::arg("h"),
39
+ py::arg("r"), py::arg("g"), py::arg("b"))
40
+
35
41
  .def("draw_sprite", &mini::Engine::draw_sprite,
36
42
  py::arg("texture_id"), py::arg("x"), py::arg("y"),
37
43
  py::arg("w"), py::arg("h"))
@@ -49,5 +55,8 @@ PYBIND11_MODULE(_native, m) {
49
55
  py::arg("g"),
50
56
  py::arg("b")
51
57
  )
52
- .def("poll_events", &mini::Engine::poll_events);
58
+ .def("poll_events", &mini::Engine::poll_events)
59
+
60
+ .def("capture_frame", &mini::Engine::capture_frame,
61
+ py::arg("path"));
53
62
  }
@@ -9,7 +9,8 @@ namespace mini {
9
9
  : window_(nullptr),
10
10
  renderer_(nullptr),
11
11
  initialized_(false),
12
- font_(nullptr)
12
+ font_(nullptr),
13
+ clear_color_{0, 0, 0, 255}
13
14
  {
14
15
  }
15
16
 
@@ -86,14 +87,34 @@ namespace mini {
86
87
  initialized_ = true;
87
88
  }
88
89
 
90
+ void Engine::set_clear_color(int r, int g, int b)
91
+ {
92
+ auto clamp = [](int v) {
93
+ if (v < 0) return 0;
94
+ if (v > 255) return 255;
95
+ return v;
96
+ };
97
+
98
+ clear_color_.r = static_cast<Uint8>(clamp(r));
99
+ clear_color_.g = static_cast<Uint8>(clamp(g));
100
+ clear_color_.b = static_cast<Uint8>(clamp(b));
101
+ clear_color_.a = 255;
102
+ }
103
+
89
104
  void Engine::begin_frame()
90
105
  {
91
106
  if (!initialized_ || renderer_ == nullptr) {
92
107
  return;
93
108
  }
94
109
 
95
- // Clear to black
96
- SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
110
+ // use stored clear color instead of hard-coded black
111
+ SDL_SetRenderDrawColor(
112
+ renderer_,
113
+ clear_color_.r,
114
+ clear_color_.g,
115
+ clear_color_.b,
116
+ clear_color_.a
117
+ );
97
118
  SDL_RenderClear(renderer_);
98
119
  }
99
120
 
@@ -106,21 +127,29 @@ namespace mini {
106
127
  SDL_RenderPresent(renderer_);
107
128
  }
108
129
 
109
- void Engine::draw_rect(int x, int y, int w, int h)
130
+ void Engine::draw_rect(int x, int y, int w, int h, int r, int g, int b)
110
131
  {
111
132
  if (!initialized_ || renderer_ == nullptr) {
112
133
  return;
113
134
  }
114
135
 
115
- SDL_Rect rect;
116
- rect.x = x;
117
- rect.y = y;
118
- rect.w = w;
119
- rect.h = h;
136
+ auto clamp = [](int v) {
137
+ if (v < 0) return 0;
138
+ if (v > 255) return 255;
139
+ return v;
140
+ };
120
141
 
121
- // White rectangle for now (you can parameterize later).
122
- SDL_SetRenderDrawColor(renderer_, 255, 255, 255, 255);
142
+ SDL_Rect rect{ x, y, w, h };
143
+
144
+ SDL_SetRenderDrawColor(
145
+ renderer_,
146
+ static_cast<Uint8>(clamp(r)),
147
+ static_cast<Uint8>(clamp(g)),
148
+ static_cast<Uint8>(clamp(b)),
149
+ 255
150
+ );
123
151
  SDL_RenderFillRect(renderer_, &rect);
152
+
124
153
  }
125
154
 
126
155
  void Engine::draw_sprite(int /*texture_id*/, int /*x*/, int /*y*/, int /*w*/, int /*h*/)
@@ -187,6 +216,58 @@ namespace mini {
187
216
  SDL_DestroyTexture(texture);
188
217
  }
189
218
 
219
+ bool Engine::capture_frame(const char* path)
220
+ {
221
+ if (!initialized_ || renderer_ == nullptr) {
222
+ return false;
223
+ }
224
+
225
+ int width = 0;
226
+ int height = 0;
227
+ if (SDL_GetRendererOutputSize(renderer_, &width, &height) != 0) {
228
+ std::cerr << "SDL_GetRendererOutputSize Error: " << SDL_GetError() << std::endl;
229
+ return false;
230
+ }
231
+
232
+ // Create a surface to hold the pixels (32-bit RGBA)
233
+ SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(
234
+ 0,
235
+ width,
236
+ height,
237
+ 32,
238
+ SDL_PIXELFORMAT_ARGB8888
239
+ );
240
+
241
+ if (!surface) {
242
+ std::cerr << "SDL_CreateRGBSurfaceWithFormat Error: " << SDL_GetError() << std::endl;
243
+ return false;
244
+ }
245
+
246
+ // Read pixels from the current render target into the surface
247
+ if (SDL_RenderReadPixels(
248
+ renderer_,
249
+ nullptr, // whole screen
250
+ surface->format->format,
251
+ surface->pixels,
252
+ surface->pitch) != 0)
253
+ {
254
+ std::cerr << "SDL_RenderReadPixels Error: " << SDL_GetError() << std::endl;
255
+ SDL_FreeSurface(surface);
256
+ return false;
257
+ }
258
+
259
+ // Save as BMP (simple, no extra dependencies).
260
+ // Use .bmp extension in the path you pass from Python.
261
+ if (SDL_SaveBMP(surface, path) != 0) {
262
+ std::cerr << "SDL_SaveBMP Error: " << SDL_GetError() << std::endl;
263
+ SDL_FreeSurface(surface);
264
+ return false;
265
+ }
266
+
267
+ SDL_FreeSurface(surface);
268
+ return true;
269
+ }
270
+
190
271
  std::vector<Event> Engine::poll_events()
191
272
  {
192
273
  std::vector<Event> events;
@@ -30,6 +30,9 @@ namespace mini {
30
30
  // Initialize the engine with a window of given width, height, and title.
31
31
  void init(int width, int height, const char* title);
32
32
 
33
+ // Set the clear color for the screen.
34
+ void set_clear_color(int r, int g, int b);
35
+
33
36
  // Clear the screen to a default color (black) and get ready to draw.
34
37
  void begin_frame();
35
38
 
@@ -37,7 +40,7 @@ namespace mini {
37
40
  void end_frame();
38
41
 
39
42
  // Draw a simple filled rectangle (we'll use a fixed color for now).
40
- void draw_rect(int x, int y, int w, int h);
43
+ void draw_rect(int x, int y, int w, int h, int r, int g, int b);
41
44
 
42
45
  // Sprite drawing stub for later.
43
46
  void draw_sprite(int texture_id, int x, int y, int w, int h);
@@ -51,11 +54,16 @@ namespace mini {
51
54
  // Draw text at specified position.
52
55
  void draw_text(const char* text, int x, int y, int r, int g, int b);
53
56
 
57
+ // Capture the current frame into an image file (BMP for now).
58
+ // Returns true on success, false on failure.
59
+ bool capture_frame(const char* path);
60
+
54
61
  private:
55
62
  SDL_Window* window_;
56
63
  SDL_Renderer* renderer_;
57
64
  bool initialized_;
58
65
  TTF_Font* font_;
66
+ SDL_Color clear_color_;
59
67
  };
60
68
 
61
69
  } // namespace mini
@@ -8,7 +8,7 @@ build-backend = "scikit_build_core.build"
8
8
 
9
9
  [project]
10
10
  name = "mini-arcade-native-backend"
11
- version = "0.3.0"
11
+ version = "0.3.1"
12
12
  description = "Native SDL2 backend for mini-arcade-core using SDL2 + pybind11."
13
13
  authors = [
14
14
  { name = "Santiago Rincon", email = "rincores@gmail.com" },
@@ -69,6 +69,9 @@ class NativeBackend(Backend):
69
69
  if self._font_path is not None:
70
70
  self._engine.load_font(self._font_path, self._font_size)
71
71
 
72
+ def set_clear_color(self, r: int, g: int, b: int) -> None:
73
+ self._engine.set_clear_color(int(r), int(g), int(b))
74
+
72
75
  def poll_events(self) -> list[Event]:
73
76
  """
74
77
  Poll for events from the backend and return them as a list of Event objects.
@@ -91,7 +94,14 @@ class NativeBackend(Backend):
91
94
  """End the current frame for rendering."""
92
95
  self._engine.end_frame()
93
96
 
94
- def draw_rect(self, x: int, y: int, w: int, h: int):
97
+ def draw_rect(
98
+ self,
99
+ x: int,
100
+ y: int,
101
+ w: int,
102
+ h: int,
103
+ color: tuple[int, int, int] = (255, 255, 255),
104
+ ):
95
105
  """
96
106
  Draw a rectangle at the specified position with given width and height.
97
107
 
@@ -107,7 +117,8 @@ class NativeBackend(Backend):
107
117
  :param h: Height of the rectangle.
108
118
  :type h: int
109
119
  """
110
- self._engine.draw_rect(x, y, w, h)
120
+ r, g, b = color
121
+ self._engine.draw_rect(x, y, w, h, int(r), int(g), int(b))
111
122
 
112
123
  def draw_text(
113
124
  self,
@@ -123,3 +134,6 @@ class NativeBackend(Backend):
123
134
  # We rely on C++ side to no-op if font is missing
124
135
  r, g, b = color
125
136
  self._engine.draw_text(text, x, y, int(r), int(g), int(b))
137
+
138
+ def capture_frame(self, path: str) -> bool:
139
+ return self._engine.capture_frame(path)
@@ -1,9 +0,0 @@
1
- ## [0.3.0] - 2025-12-05
2
-
3
- ### Added
4
- - add text rendering support with SDL2_ttf integration
5
-
6
- ### Other
7
- - Merge pull request #7 from alexsc6955/feature/text_support
8
- - Merge release/0.2 into develop
9
-
@@ -1 +0,0 @@
1
- 0.3.0