red_bird 0.1.1

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 (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +23 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +47 -0
  7. data/Rakefile +10 -0
  8. data/bin/setup +8 -0
  9. data/ext/red_bird/bird.c +15 -0
  10. data/ext/red_bird/bird.h +10 -0
  11. data/ext/red_bird/color.c +95 -0
  12. data/ext/red_bird/color.h +27 -0
  13. data/ext/red_bird/dynamic_sprite.c +163 -0
  14. data/ext/red_bird/dynamic_sprite.h +30 -0
  15. data/ext/red_bird/engine.c +354 -0
  16. data/ext/red_bird/engine.h +40 -0
  17. data/ext/red_bird/extconf.rb +9 -0
  18. data/ext/red_bird/font.c +94 -0
  19. data/ext/red_bird/font.h +26 -0
  20. data/ext/red_bird/input_device.c +100 -0
  21. data/ext/red_bird/input_device.h +15 -0
  22. data/ext/red_bird/keycode.c +42 -0
  23. data/ext/red_bird/keycode.h +12 -0
  24. data/ext/red_bird/loader.c +154 -0
  25. data/ext/red_bird/loader.h +54 -0
  26. data/ext/red_bird/main.c +38 -0
  27. data/ext/red_bird/main.h +12 -0
  28. data/ext/red_bird/palette.c +132 -0
  29. data/ext/red_bird/palette.h +23 -0
  30. data/ext/red_bird/rect.c +257 -0
  31. data/ext/red_bird/rect.h +20 -0
  32. data/ext/red_bird/render.c +130 -0
  33. data/ext/red_bird/render.h +25 -0
  34. data/ext/red_bird/sprite.c +130 -0
  35. data/ext/red_bird/sprite.h +27 -0
  36. data/ext/red_bird/text.c +212 -0
  37. data/ext/red_bird/text.h +31 -0
  38. data/ext/red_bird/texture.c +157 -0
  39. data/ext/red_bird/texture.h +33 -0
  40. data/ext/red_bird/texture_imp.cpp +49 -0
  41. data/ext/red_bird/texture_imp.hpp +29 -0
  42. data/ext/red_bird/timer.c +134 -0
  43. data/ext/red_bird/timer.h +25 -0
  44. data/lib/red_bird.rb +15 -0
  45. data/lib/red_bird/animation.rb +133 -0
  46. data/lib/red_bird/camera.rb +61 -0
  47. data/lib/red_bird/controller.rb +44 -0
  48. data/lib/red_bird/dynamic_sprite.rb +38 -0
  49. data/lib/red_bird/engine.rb +81 -0
  50. data/lib/red_bird/entity.rb +74 -0
  51. data/lib/red_bird/entity_collision.rb +31 -0
  52. data/lib/red_bird/input_device.rb +86 -0
  53. data/lib/red_bird/palette.rb +23 -0
  54. data/lib/red_bird/relative_entity.rb +95 -0
  55. data/lib/red_bird/sprite.rb +40 -0
  56. data/lib/red_bird/stage.rb +60 -0
  57. data/lib/red_bird/tile_map.rb +118 -0
  58. data/lib/red_bird/tile_set.rb +56 -0
  59. data/lib/red_bird/uibox.rb +143 -0
  60. data/lib/red_bird/version.rb +3 -0
  61. data/lib/red_bird/vertical_menu.rb +110 -0
  62. data/red_bird.gemspec +37 -0
  63. metadata +149 -0
@@ -0,0 +1,30 @@
1
+ // SPDX-License-Identifier: MIT
2
+ #ifndef RED_BIRD_DYNAMIC_SPRITE_H
3
+ #define RED_BIRD_DYNAMIC_SPRITE_H 1
4
+
5
+ #include "main.h"
6
+
7
+ extern VALUE bird_cDynamicSprite;
8
+
9
+ struct bird_dynamic_sprite_data
10
+ {
11
+ SDL_Rect rect;
12
+ double angle;
13
+ SDL_Point center;
14
+ SDL_RendererFlip flip;
15
+ };
16
+
17
+ VALUE
18
+ bird_alloc_dynamic_sprite(VALUE klass);
19
+
20
+ VALUE
21
+ bird_cDynamicSprite_initialize(VALUE self, VALUE texture, VALUE x, VALUE y,
22
+ VALUE width, VALUE height, VALUE mods);
23
+
24
+ VALUE
25
+ bird_cDynamicSprite_render_to_screen(VALUE self, VALUE x, VALUE y);
26
+
27
+ void
28
+ Init_red_bird_dynamic_sprite(void);
29
+
30
+ #endif // RED_BIRD_DYNAMIC_SPRITE_H
@@ -0,0 +1,354 @@
1
+ // SPDX-License-Identifier: MIT
2
+ #include "engine.h"
3
+
4
+ #include "input_device.h"
5
+
6
+ VALUE bird_mEngine;
7
+ SDL_bool engine_initialized;
8
+
9
+ /*
10
+ Document-module: RedBird::Engine
11
+
12
+ This module is responsible for the initialization, control of general
13
+ behavior, and finalization of a game.
14
+ @author Frederico Linhares
15
+ */
16
+ bird_sCore bird_core;
17
+
18
+ /*
19
+ Stretches the image to fill the screen vertically, horizontally, or both;
20
+ without changing the game aspect ratio.
21
+ */
22
+ static void
23
+ calculate_full_scale()
24
+ {
25
+ double screen_ratio, game_ratio, scale;
26
+
27
+ screen_ratio =
28
+ (double)bird_core.screen_width/(double)bird_core.screen_height;
29
+ game_ratio = (double)bird_core.game_width/(double)bird_core.game_height;
30
+
31
+ // If screen is proportionally taller than game.
32
+ if(screen_ratio < game_ratio)
33
+ {
34
+ scale = (double)bird_core.screen_width/(double)bird_core.game_width;
35
+
36
+ bird_core.screen_rect.w = bird_core.game_width * scale;
37
+ bird_core.screen_rect.h = bird_core.game_height * scale;
38
+ bird_core.screen_rect.x = 0;
39
+ bird_core.screen_rect.y = bird_core.screen_height/2 -
40
+ bird_core.screen_rect.h/2;
41
+ }
42
+ // If screen is proportionally wider than game.
43
+ else if(screen_ratio > game_ratio)
44
+ {
45
+ scale = (double)bird_core.screen_height/(double)bird_core.game_height;
46
+
47
+ bird_core.screen_rect.w = bird_core.game_width * scale;
48
+ bird_core.screen_rect.h = bird_core.game_height * scale;
49
+ bird_core.screen_rect.x = bird_core.screen_width/2 -
50
+ bird_core.screen_rect.w/2;
51
+ bird_core.screen_rect.y = 0;
52
+ }
53
+ // If they have the same aspect ratio.
54
+ else
55
+ {
56
+ bird_core.screen_rect.x = 0;
57
+ bird_core.screen_rect.y = 0;
58
+ bird_core.screen_rect.w = bird_core.screen_width;
59
+ bird_core.screen_rect.h = bird_core.screen_height;
60
+ }
61
+ }
62
+
63
+ static SDL_bool
64
+ load_variables(void *obj, LoaderStack *ls)
65
+ {
66
+ // TODO: make user define those variables instead of hard coded.
67
+ bird_core.game_name = "Red Bird Game";
68
+
69
+ return SDL_TRUE;
70
+ }
71
+
72
+ static void
73
+ unload_variables(void *obj, LoaderStack *ls)
74
+ {
75
+ }
76
+
77
+ static SDL_bool
78
+ load_sdl(void *obj, LoaderStack *ls)
79
+ {
80
+ if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
81
+ {
82
+ const char* base_error = "SDL could not initialize! SDL Error → ";
83
+ LoaderStack_set_error(ls, base_error, SDL_GetError());
84
+ return SDL_FALSE;
85
+ }
86
+
87
+ return SDL_TRUE;
88
+ }
89
+
90
+ static void
91
+ unload_sdl(void *obj, LoaderStack *ls)
92
+ {
93
+ SDL_Quit();
94
+ }
95
+
96
+ static SDL_bool
97
+ load_window(void *obj, LoaderStack *ls)
98
+ {
99
+ bird_core.window = NULL;
100
+ bird_core.window = SDL_CreateWindow(
101
+ bird_core.game_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
102
+ bird_core.screen_width, bird_core.screen_height, SDL_WINDOW_SHOWN);
103
+ if(bird_core.window == NULL)
104
+ {
105
+ const char* base_error = "Window could not be created! SDL_Error → ";
106
+ LoaderStack_set_error(ls, base_error, SDL_GetError());
107
+ return SDL_FALSE;
108
+ }
109
+
110
+ return SDL_TRUE;
111
+ }
112
+
113
+ static void
114
+ unload_window(void *obj, LoaderStack *ls)
115
+ {
116
+ SDL_DestroyWindow(bird_core.window);
117
+ }
118
+
119
+
120
+ static SDL_bool
121
+ load_sdl_renderer(void *obj, LoaderStack *ls)
122
+ {
123
+ bird_core.renderer = NULL;
124
+ bird_core.renderer = SDL_CreateRenderer(
125
+ bird_core.window, -1, SDL_RENDERER_ACCELERATED |
126
+ SDL_RENDERER_TARGETTEXTURE);
127
+ if(bird_core.renderer == NULL)
128
+ {
129
+ const char* base_error = "Could not create SDL renderer → ";
130
+ LoaderStack_set_error(ls, base_error, SDL_GetError());
131
+ return SDL_FALSE;
132
+ }
133
+
134
+ return SDL_TRUE;
135
+ }
136
+
137
+ static void
138
+ unload_sdl_renderer(void *obj, LoaderStack *ls)
139
+ {
140
+ SDL_DestroyRenderer(bird_core.renderer);
141
+ }
142
+
143
+ static SDL_bool
144
+ load_pre_screen(void *obj, LoaderStack *ls)
145
+ {
146
+ bird_core.pre_screen_buffer = SDL_CreateTexture(
147
+ bird_core.renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET,
148
+ bird_core.screen_width, bird_core.screen_height);
149
+
150
+ if(bird_core.pre_screen_buffer == NULL)
151
+ {
152
+ const char* base_error = "Could not create renderering buffer → ";
153
+ LoaderStack_set_error(ls, base_error, SDL_GetError());
154
+ return SDL_FALSE;
155
+ }
156
+
157
+ calculate_full_scale();
158
+
159
+ SDL_SetRenderTarget(bird_core.renderer, bird_core.pre_screen_buffer);
160
+
161
+ return SDL_TRUE;
162
+ }
163
+
164
+ static void
165
+ unload_pre_screen(void *obj, LoaderStack *ls)
166
+ {
167
+ SDL_DestroyTexture(bird_core.pre_screen_buffer);
168
+ }
169
+
170
+ static SDL_bool
171
+ load_sdl_ttf(void *obj, LoaderStack *ls)
172
+ {
173
+ if(TTF_Init())
174
+ {
175
+ const char* base_error = "Could not initialize SDL ttf → ";
176
+ LoaderStack_set_error(ls, base_error, TTF_GetError());
177
+ return SDL_FALSE;
178
+ }
179
+
180
+ return SDL_TRUE;
181
+ }
182
+
183
+ static void
184
+ unload_sdl_ttf(void *obj, LoaderStack *ls)
185
+ {
186
+ TTF_Quit();
187
+ }
188
+
189
+ /*
190
+ Defines the virtual number of pixels used by the game. When the real screen
191
+ resolution is higher than this, the frames are scaled.
192
+
193
+ @param width [Integer] number of columns.
194
+ @param height [Integer] number of rows.
195
+ @author Frederico Linhares
196
+ */
197
+
198
+ static VALUE
199
+ bird_mEngine_set_pixel_quantity(VALUE self, VALUE width, VALUE height)
200
+ {
201
+ RB_INTEGER_TYPE_P(width);
202
+ RB_INTEGER_TYPE_P(height);
203
+
204
+ bird_core.game_width = FIX2INT(width);
205
+ bird_core.game_height = FIX2INT(height);
206
+
207
+ calculate_full_scale();
208
+
209
+ return self;
210
+ }
211
+
212
+ /*
213
+ Use this method to define the game screen resolution. By default the
214
+ resolution is set to 480x320.
215
+
216
+ @param width [Integer] screen width.
217
+ @param height [Integer] screen height.
218
+ @author Frederico Linhares
219
+ */
220
+ static VALUE
221
+ bird_mEngine_set_screen_resolution(VALUE self, VALUE width, VALUE height)
222
+ {
223
+ // Variables converted to C.
224
+ int c_width, c_height;
225
+
226
+ RB_INTEGER_TYPE_P(width);
227
+ RB_INTEGER_TYPE_P(height);
228
+
229
+ c_width = FIX2INT(width);
230
+ c_height = FIX2INT(height);
231
+
232
+ if (c_width < bird_core.game_width)
233
+ rb_raise(rb_eArgError, "width must be bigger or equal to pixels width");
234
+ if (c_height < bird_core.game_height)
235
+ rb_raise(rb_eArgError, "height must be bigger or equal to pixels height");
236
+
237
+ bird_core.screen_width = c_width;
238
+ bird_core.screen_height = c_height;
239
+
240
+ calculate_full_scale();
241
+
242
+ // If window was already created, this is a resize.
243
+ if(engine_initialized)
244
+ SDL_SetWindowSize(
245
+ bird_core.window, bird_core.screen_width, bird_core.screen_height);
246
+
247
+ return self;
248
+ }
249
+
250
+ /*
251
+ By default, debug is false. If you set this to true, the engine displays some
252
+ information useful for debugging your project.
253
+
254
+ @param debug [Boolean] true turn bebug on.
255
+ @author Frederico Linhares
256
+ */
257
+ static VALUE
258
+ bird_mEngine_set_debug(VALUE self, VALUE debug)
259
+ {
260
+ switch (TYPE(debug))
261
+ {
262
+ case T_TRUE:
263
+ bird_core.debug = SDL_TRUE;
264
+ break;
265
+ case T_FALSE:
266
+ bird_core.debug = SDL_FALSE;
267
+ break;
268
+ default:
269
+ rb_raise(rb_eTypeError, "debug must be true or false");
270
+ break;
271
+ }
272
+
273
+ return self;
274
+ }
275
+
276
+ /*
277
+ It is only necessary to use this method in a game to change the default
278
+ behavior of the Engine. The {Engine.run} alredy uses it in a proper way, so
279
+ calling that method is enough for most games.
280
+
281
+ This method loads internal subsystems; most functionalities in this Engine
282
+ depend on those subsystems, so it is necessary to call this method before
283
+ instantiating any class from RedBird. This method must receive a block. After
284
+ the block finishes executing, it unloads all subsystems.
285
+
286
+ @author Frederico Linhares
287
+ */
288
+ VALUE
289
+ bird_mEngine_load(VALUE self)
290
+ {
291
+ VALUE result;
292
+
293
+ rb_need_block();
294
+
295
+ bird_core.loader = malloc(sizeof(LoaderStack));
296
+
297
+ LoaderStack_constructor(bird_core.loader, NULL);
298
+
299
+ LoaderStack_add(bird_core.loader, &load_variables, &unload_variables);
300
+ LoaderStack_add(bird_core.loader, &load_sdl, &unload_sdl);
301
+ LoaderStack_add(bird_core.loader, &load_window, &unload_window);
302
+ LoaderStack_add(bird_core.loader, &load_sdl_renderer, &unload_sdl_renderer);
303
+ LoaderStack_add(bird_core.loader, &load_pre_screen, &unload_pre_screen);
304
+ LoaderStack_add(bird_core.loader, &load_sdl_ttf, &unload_sdl_ttf);
305
+
306
+ // Load Engine
307
+ if(!LoaderStack_load(bird_core.loader))
308
+ {
309
+ rb_raise(rb_eRuntimeError, "%s", bird_core.loader->error_message);
310
+ LoaderStack_destructor(bird_core.loader);
311
+
312
+ free(bird_core.loader);
313
+
314
+ return self;
315
+ }
316
+
317
+ engine_initialized = SDL_TRUE;
318
+
319
+ // Execute block
320
+ result = rb_yield(Qundef);
321
+
322
+ // Ensure that objects using SDL are destroyed in case of errors.
323
+ rb_gc_mark(result);
324
+ rb_gc();
325
+ SDL_Delay(1000); // Wait one second to give garbage collector some time.
326
+
327
+ // Unload Engine
328
+ LoaderStack_destructor(bird_core.loader);
329
+
330
+ free(bird_core.loader);
331
+
332
+ engine_initialized = SDL_FALSE;
333
+ return self;
334
+ }
335
+
336
+ void
337
+ Init_red_bird_engine(void)
338
+ {
339
+ engine_initialized = SDL_FALSE;
340
+
341
+ bird_core.debug = SDL_FALSE;
342
+ bird_core.screen_width = 480;
343
+ bird_core.screen_height = 320;
344
+ bird_core.game_width = bird_core.screen_width;
345
+ bird_core.game_height = bird_core.screen_height;
346
+
347
+ bird_mEngine = rb_define_module_under(bird_m, "Engine");
348
+ rb_define_module_function(bird_mEngine, "set_pixel_quantity",
349
+ bird_mEngine_set_pixel_quantity, 2);
350
+ rb_define_module_function(bird_mEngine, "set_screen_resolution",
351
+ bird_mEngine_set_screen_resolution, 2);
352
+ rb_define_module_function(bird_mEngine, "debug=", bird_mEngine_set_debug, 1);
353
+ rb_define_module_function(bird_mEngine, "load", bird_mEngine_load, 0);
354
+ }
@@ -0,0 +1,40 @@
1
+ // SPDX-License-Identifier: MIT
2
+ #ifndef RED_BIRD_ENGINE_H
3
+ #define RED_BIRD_ENGINE_H 1
4
+
5
+ #include "loader.h"
6
+ #include "main.h"
7
+
8
+ extern VALUE bird_mEngine;
9
+ extern SDL_bool engine_initialized;
10
+
11
+ typedef struct
12
+ {
13
+ LoaderStack *loader;
14
+
15
+ SDL_bool debug;
16
+ const char *game_name;
17
+
18
+ SDL_Window *window;
19
+ int screen_width;
20
+ int screen_height;
21
+
22
+ int game_width;
23
+ int game_height;
24
+
25
+ SDL_Renderer *renderer;
26
+
27
+ // All rendering goes here before they are moved to the screen.
28
+ SDL_Texture *pre_screen_buffer;
29
+ SDL_Rect screen_rect;
30
+ } bird_sCore;
31
+
32
+ extern bird_sCore bird_core;
33
+
34
+ VALUE
35
+ bird_mEngine_load(VALUE self);
36
+
37
+ void
38
+ Init_red_bird_engine(void);
39
+
40
+ #endif /* RED_BIRD_ENGINE_H */
@@ -0,0 +1,9 @@
1
+ # SPDX-License-Identifier: MIT
2
+ require "mkmf"
3
+
4
+ $CXXFLAGS += " -std=gnu++17 "
5
+
6
+ libs = %w{SDL2 SDL2_ttf}
7
+ libs.each {|lib| have_library(lib)}
8
+
9
+ create_makefile("red_bird/red_bird")
@@ -0,0 +1,94 @@
1
+ // SPDX-License-Identifier: MIT
2
+ #include "font.h"
3
+
4
+ /*
5
+ Document-class: RedBird::Font
6
+
7
+ This class represents a font; it is necessary for rendering any text.
8
+
9
+ @author Frederico Linhares
10
+ */
11
+ VALUE bird_cFont;
12
+
13
+ /*
14
+ Basic functions all Ruby classes need.
15
+ */
16
+
17
+ void
18
+ bird_free_font(void* obj)
19
+ {
20
+ struct bird_font_data *ptr = obj;
21
+
22
+ TTF_CloseFont(ptr->data);
23
+ free(ptr);
24
+ }
25
+
26
+ size_t
27
+ bird_memsize_font(const void* obj)
28
+ {
29
+ // TODO
30
+ return 0;
31
+ }
32
+
33
+ static const rb_data_type_t
34
+ bird_font_type = {
35
+ "red_bird_font",
36
+ {0, bird_free_font, bird_memsize_font,},
37
+ 0, 0,
38
+ RUBY_TYPED_FREE_IMMEDIATELY,
39
+ };
40
+
41
+ VALUE
42
+ bird_alloc_font(VALUE klass)
43
+ {
44
+ VALUE obj;
45
+ struct bird_font_data *ptr;
46
+
47
+ obj = TypedData_Make_Struct(klass, struct bird_font_data, &bird_font_type,
48
+ ptr);
49
+
50
+ return obj;
51
+ }
52
+
53
+ /*
54
+ @param file_path [String] path to file containing the font.
55
+ @param size [Integer] size of text that will be rendered using this font.
56
+ @author Frederico Linhares
57
+ */
58
+
59
+ VALUE
60
+ bird_cFont_initialize(VALUE self, VALUE file_path, VALUE size)
61
+ {
62
+ struct bird_font_data *ptr;
63
+
64
+ SafeStringValue(file_path);
65
+ RB_INTEGER_TYPE_P(size);
66
+
67
+ TypedData_Get_Struct(self, struct bird_font_data, &bird_font_type, ptr);
68
+
69
+ ptr->data = TTF_OpenFont(StringValueCStr(file_path), NUM2INT(size));
70
+ if(!ptr->data)
71
+ {
72
+ rb_raise(rb_eArgError, "failed to load font: %s", TTF_GetError());
73
+ }
74
+
75
+ return self;
76
+ }
77
+
78
+ struct bird_font_data*
79
+ bird_cFont_get_data(VALUE self)
80
+ {
81
+ struct bird_font_data *ptr;
82
+
83
+ TypedData_Get_Struct(self, struct bird_font_data, &bird_font_type, ptr);
84
+
85
+ return ptr;
86
+ }
87
+
88
+ void
89
+ Init_red_bird_font(void)
90
+ {
91
+ bird_cFont = rb_define_class_under(bird_m, "Font", rb_cData);
92
+ rb_define_alloc_func(bird_cFont, bird_alloc_font);
93
+ rb_define_method(bird_cFont, "initialize", bird_cFont_initialize, 2);
94
+ }