red_bird 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }