red_bird 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +23 -0
- data/LICENSE.txt +21 -0
- data/README.md +47 -0
- data/Rakefile +10 -0
- data/bin/setup +8 -0
- data/ext/red_bird/bird.c +15 -0
- data/ext/red_bird/bird.h +10 -0
- data/ext/red_bird/color.c +95 -0
- data/ext/red_bird/color.h +27 -0
- data/ext/red_bird/dynamic_sprite.c +163 -0
- data/ext/red_bird/dynamic_sprite.h +30 -0
- data/ext/red_bird/engine.c +354 -0
- data/ext/red_bird/engine.h +40 -0
- data/ext/red_bird/extconf.rb +9 -0
- data/ext/red_bird/font.c +94 -0
- data/ext/red_bird/font.h +26 -0
- data/ext/red_bird/input_device.c +100 -0
- data/ext/red_bird/input_device.h +15 -0
- data/ext/red_bird/keycode.c +42 -0
- data/ext/red_bird/keycode.h +12 -0
- data/ext/red_bird/loader.c +154 -0
- data/ext/red_bird/loader.h +54 -0
- data/ext/red_bird/main.c +38 -0
- data/ext/red_bird/main.h +12 -0
- data/ext/red_bird/palette.c +132 -0
- data/ext/red_bird/palette.h +23 -0
- data/ext/red_bird/rect.c +257 -0
- data/ext/red_bird/rect.h +20 -0
- data/ext/red_bird/render.c +130 -0
- data/ext/red_bird/render.h +25 -0
- data/ext/red_bird/sprite.c +130 -0
- data/ext/red_bird/sprite.h +27 -0
- data/ext/red_bird/text.c +212 -0
- data/ext/red_bird/text.h +31 -0
- data/ext/red_bird/texture.c +157 -0
- data/ext/red_bird/texture.h +33 -0
- data/ext/red_bird/texture_imp.cpp +49 -0
- data/ext/red_bird/texture_imp.hpp +29 -0
- data/ext/red_bird/timer.c +134 -0
- data/ext/red_bird/timer.h +25 -0
- data/lib/red_bird.rb +15 -0
- data/lib/red_bird/animation.rb +133 -0
- data/lib/red_bird/camera.rb +61 -0
- data/lib/red_bird/controller.rb +44 -0
- data/lib/red_bird/dynamic_sprite.rb +38 -0
- data/lib/red_bird/engine.rb +81 -0
- data/lib/red_bird/entity.rb +74 -0
- data/lib/red_bird/entity_collision.rb +31 -0
- data/lib/red_bird/input_device.rb +86 -0
- data/lib/red_bird/palette.rb +23 -0
- data/lib/red_bird/relative_entity.rb +95 -0
- data/lib/red_bird/sprite.rb +40 -0
- data/lib/red_bird/stage.rb +60 -0
- data/lib/red_bird/tile_map.rb +118 -0
- data/lib/red_bird/tile_set.rb +56 -0
- data/lib/red_bird/uibox.rb +143 -0
- data/lib/red_bird/version.rb +3 -0
- data/lib/red_bird/vertical_menu.rb +110 -0
- data/red_bird.gemspec +37 -0
- metadata +149 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
module RedBird
|
3
|
+
# A rectangular part of a texture. It allows you to print only a portion of
|
4
|
+
# the image instead of it all. This will, for example, enable you to insert
|
5
|
+
# several animation frames into the same texture instead of having to load
|
6
|
+
# several small files.
|
7
|
+
# @author Frederico Linhares
|
8
|
+
class Sprite
|
9
|
+
# Create an array of sprites and return it. The array has homogeneous
|
10
|
+
# sprites that do not overlap and have no gaps between them.
|
11
|
+
#
|
12
|
+
# To create a grid starting from the position x 20, y 20, containing three
|
13
|
+
# columns and two rows, each sprite, having 100x80 pixels:
|
14
|
+
#
|
15
|
+
# RedBird::Texture.grid sprite, 20, 20, 3, 2, 100, 80
|
16
|
+
#
|
17
|
+
# @param texture [RedBird::Texture] a texture that will be used as the
|
18
|
+
# source for all sprites.
|
19
|
+
# @param init_x [Integer] initial x coordinate for the grid.
|
20
|
+
# @param init_y [Integer] initial y coordinate for the grid.
|
21
|
+
# @param num_hor_sprites [Integer] number of columns the grid will have.
|
22
|
+
# @param num_ver_sprites [Integer] number of rows the grid will have.
|
23
|
+
# @param width [Integer] width of every sprite.
|
24
|
+
# @param height [Integer] height of every sprite.
|
25
|
+
# @return [Array]
|
26
|
+
# @author Frederico Linhares
|
27
|
+
def self.grid(texture, init_x, init_y, num_hor_sprites, num_ver_sprites,
|
28
|
+
width, height)
|
29
|
+
sprites = []
|
30
|
+
num_ver_sprites.times do |v|
|
31
|
+
num_hor_sprites.times do |h|
|
32
|
+
sprites << Sprite.new(
|
33
|
+
texture, init_x + h * width, init_y + v * height, width, height)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
return sprites
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
module RedBird
|
3
|
+
# A game built with RedBird consists of a succession of Stages. A game has
|
4
|
+
# only a single Stage running at a time. Each Stage must have an
|
5
|
+
# {RedBird::InputDevice} instance and an Array of {RedBird::Entity}
|
6
|
+
# instances.
|
7
|
+
#
|
8
|
+
# This class contains a basic set of functionalities that every stage of a
|
9
|
+
# game needs.
|
10
|
+
#
|
11
|
+
# @!attribute [r] input_device
|
12
|
+
# @return [RedBird::InputDevice] the class that inherits from Stage must
|
13
|
+
# defines an variable +@input_device+ containing and instance of
|
14
|
+
# {RedBird::InputDevice}.
|
15
|
+
# @!attribute [r] entities
|
16
|
+
# @return [Array<RedBird::Entity>]
|
17
|
+
# @author Frederico Linhares
|
18
|
+
class Stage
|
19
|
+
attr_accessor :input_device, :entities
|
20
|
+
|
21
|
+
# @param global_data [Object] use this to share common data among different
|
22
|
+
# stages.
|
23
|
+
# @author Frederico Linhares
|
24
|
+
def initialize(global_data)
|
25
|
+
@global_data = global_data
|
26
|
+
@entities = []
|
27
|
+
end
|
28
|
+
|
29
|
+
# Add a new entity to this stage. This method organizes the entities as
|
30
|
+
# expected by some methods in {RedBird::Engine}.
|
31
|
+
#
|
32
|
+
# @param entities [Entity, Array<Entity>]
|
33
|
+
# @author Frederico Linhares
|
34
|
+
def add_entities(entities)
|
35
|
+
if entities.is_a? Array then
|
36
|
+
@entities.concat entities
|
37
|
+
else
|
38
|
+
@entities << entities
|
39
|
+
end
|
40
|
+
|
41
|
+
@entities.sort! { |a, b| a.priority <=> b.priority }
|
42
|
+
end
|
43
|
+
|
44
|
+
# {RedBird::Engine} calls this method before it ticks entities. Overwrite
|
45
|
+
# this to add routines that must run before entities tick.
|
46
|
+
#
|
47
|
+
# @author Frederico Linhares
|
48
|
+
def pre_tick
|
49
|
+
# By default do nothing.
|
50
|
+
end
|
51
|
+
|
52
|
+
# {RedBird::Engine} calls this method after it ticks entities. Overwrite
|
53
|
+
# this to add routines that must run after entities tick.
|
54
|
+
#
|
55
|
+
# @author Frederico Linhares
|
56
|
+
def post_tick
|
57
|
+
# By default do nothing.
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
require_relative "tile_set"
|
3
|
+
|
4
|
+
module RedBird
|
5
|
+
# A TileMap is a grid of {RedBird::Sprite}s; it works as a scenario. It has
|
6
|
+
# scrolling functionalities to control which portion of it is on the screen.
|
7
|
+
#
|
8
|
+
# @!attribute [rw] hor_offset
|
9
|
+
# @return [Integer] how much the tilemap scrolled from the left corner.
|
10
|
+
# @!attribute [rw] ver_offset
|
11
|
+
# @return [Integer] how much the tilemap scrolled from the top.
|
12
|
+
# @!attribute [r] tiles
|
13
|
+
# @return [Array<Integer>] tiles indexes.
|
14
|
+
# @!attribute [r] tile_set
|
15
|
+
# @return [RedBird::TileSet] tile set in use by this class.
|
16
|
+
# @!attribute [r] total_width
|
17
|
+
# @return [Integer] width of the entire tilemap (not only what is displayed
|
18
|
+
# in the screen).
|
19
|
+
# @!attribute [r] total_height
|
20
|
+
# @return [Integer] height of the entire tilemap (not only what is
|
21
|
+
# displayed in the screen).
|
22
|
+
# @author Frederico Linhares
|
23
|
+
class TileMap < Entity
|
24
|
+
attr_accessor :hor_offset, :ver_offset
|
25
|
+
attr_reader :tiles, :tile_set, :total_width, :total_height
|
26
|
+
|
27
|
+
# @param tile_set [RedBird::TileSet]
|
28
|
+
# @param pos_x [Integer] horizontal position of this map in the screen.
|
29
|
+
# @param pos_y [Integer] vertical position of this map in the screen.
|
30
|
+
# @param width [Integer] width of the region displayed in the screen.
|
31
|
+
# @param height [Integer] height of the region displayed in the screen.
|
32
|
+
# @param num_hor_tiles [Integer] total width in number of tiles.
|
33
|
+
# @param num_ver_tiles [Integer] total height in number of tiles.
|
34
|
+
# @param tiles [Array<Integer>] code of every tile to display, must be an
|
35
|
+
# one dimension array.
|
36
|
+
# @author Frederico Linhares
|
37
|
+
def initialize(tile_set, pos_x, pos_y, width, height, num_hor_tiles,
|
38
|
+
num_ver_tiles, tiles)
|
39
|
+
@tile_set = tile_set
|
40
|
+
@pos_x = pos_x
|
41
|
+
@pos_y = pos_y
|
42
|
+
|
43
|
+
@width = width
|
44
|
+
@height = height
|
45
|
+
|
46
|
+
@ver_offset = 0
|
47
|
+
@hor_offset = 0
|
48
|
+
|
49
|
+
@priority = -1
|
50
|
+
|
51
|
+
@tiles = tiles
|
52
|
+
|
53
|
+
# Number of tiles that are going to be rendered to screen.
|
54
|
+
@render_hor_tiles = @width / @tile_set.tile_width + 1
|
55
|
+
@render_ver_tiles = @height / @tile_set.tile_height + 1
|
56
|
+
|
57
|
+
@total_hor_tiles = num_hor_tiles
|
58
|
+
@total_ver_tiles = num_ver_tiles
|
59
|
+
|
60
|
+
@total_width = @total_hor_tiles * @tile_set.tile_width
|
61
|
+
@total_height = @total_ver_tiles * @tile_set.tile_height
|
62
|
+
end
|
63
|
+
|
64
|
+
# Load information from a yaml file and uses it create an instance of this
|
65
|
+
# class.
|
66
|
+
#
|
67
|
+
# @param data_dir [String] path to the directory containing the yaml and
|
68
|
+
# other files referenced in the yaml.
|
69
|
+
# @param map_file [String] path to the yaml file.
|
70
|
+
# @return [RedBird::TileMap]
|
71
|
+
# @author Frederico Linhares
|
72
|
+
def self.from_yml(data_dir, map_file, tile_set, pos_x, pos_y, width,
|
73
|
+
height)
|
74
|
+
yaml_file = data_dir + map_file
|
75
|
+
|
76
|
+
data = YAML.load_file(yaml_file)
|
77
|
+
num_hor_tiles = data["num_hor_tiles"]
|
78
|
+
num_ver_tiles = data["num_ver_tiles"]
|
79
|
+
tiles = data["tiles"].unpack("S*")
|
80
|
+
|
81
|
+
return self.new(
|
82
|
+
tile_set, pos_x, pos_y, width, height, num_hor_tiles,
|
83
|
+
num_ver_tiles, tiles)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Gets the {RedBird::Sprite} at position x, y.
|
87
|
+
#
|
88
|
+
# @param x [Integer]
|
89
|
+
# @param y [Integer]
|
90
|
+
# @author Frederico Linhares
|
91
|
+
def tile_xy(x, y)
|
92
|
+
return @tile_set.tiles[@tiles[y_to_tile(y) + x]][:type]
|
93
|
+
end
|
94
|
+
|
95
|
+
# Renders this tilemap to the screen.
|
96
|
+
#
|
97
|
+
# @author Frederico Linhares
|
98
|
+
def render
|
99
|
+
first_hor_tile = @hor_offset / @tile_set.tile_width
|
100
|
+
first_ver_tile = @ver_offset / @tile_set.tile_height
|
101
|
+
|
102
|
+
(first_ver_tile..(first_ver_tile + @render_ver_tiles)).each do |y|
|
103
|
+
(first_hor_tile..(first_hor_tile + @render_hor_tiles)).each do |x|
|
104
|
+
unless @tiles[y_to_tile(y) + x].nil? then
|
105
|
+
@tile_set.tiles[@tiles[y_to_tile(y) + x]].render_to_screen(
|
106
|
+
x * @tile_set.tile_width - @hor_offset + @pos_x,
|
107
|
+
y * @tile_set.tile_height - @ver_offset + @pos_y)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
def y_to_tile(y)
|
115
|
+
return y * @total_hor_tiles
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module RedBird
|
5
|
+
# A TileSet is a set of {RedBird::Sprite}s. It allows you to reuse the same
|
6
|
+
# {RedBird::Sprite} several times in the creation of a game scenario, making
|
7
|
+
# the level design more straightforward.
|
8
|
+
#
|
9
|
+
# @!attribute [r] tiles
|
10
|
+
# @return [Array<RedBird::TileSet::Sprite>]
|
11
|
+
# @!attribute [r] tile_width
|
12
|
+
# @return [Integer] width of each tile.
|
13
|
+
# @!attribute [r] tile_height
|
14
|
+
# @return [Integer] height of each tile.
|
15
|
+
# @author Frederico Linhares
|
16
|
+
class TileSet
|
17
|
+
attr_reader :tiles, :tile_width, :tile_height
|
18
|
+
|
19
|
+
# @param texture_file [String] this method uses the path as argument to
|
20
|
+
# create a {RedBird::Texture}.
|
21
|
+
# @param tile_width [Integer] width of each tile.
|
22
|
+
# @param tile_height [Integer] height of each tile.
|
23
|
+
# @author Frederico Linhares
|
24
|
+
def initialize(texture_file, texture_palette, tile_width, tile_height)
|
25
|
+
@texture = RedBird::Texture.new(texture_file, texture_palette)
|
26
|
+
|
27
|
+
@tile_width = tile_width
|
28
|
+
@tile_height = tile_height
|
29
|
+
|
30
|
+
horizontal_tiles = @texture.width / @tile_width
|
31
|
+
vertical_tiles = @texture.height / @tile_height
|
32
|
+
|
33
|
+
@tiles = Sprite.grid(
|
34
|
+
@texture, 0, 0, horizontal_tiles, vertical_tiles, @tile_width,
|
35
|
+
@tile_height)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Load information from a yaml file and uses it create an instance of this
|
39
|
+
# class.
|
40
|
+
#
|
41
|
+
# @param data_dir [String] path to the directory containing the yaml and
|
42
|
+
# other files referenced in the yaml.
|
43
|
+
# @param tile_file [String] path to the yaml file.
|
44
|
+
# @return [RedBird::TileSet]
|
45
|
+
# @author Frederico Linhares
|
46
|
+
def self.from_yml(data_dir, tile_file, palette)
|
47
|
+
yaml_file = data_dir + tile_file
|
48
|
+
|
49
|
+
data = YAML.load_file(yaml_file)
|
50
|
+
texture_path = data_dir + data["texture"]
|
51
|
+
|
52
|
+
return self.new(texture_path, palette, data["width"], data["height"])
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
module RedBird
|
3
|
+
# User Interface Box works as a visual background for texts, menus, or
|
4
|
+
# anything else.
|
5
|
+
#
|
6
|
+
# @author Frederico Linhares
|
7
|
+
class UIBox < Entity
|
8
|
+
# A style defines the visual appearance of a Box.
|
9
|
+
#
|
10
|
+
# @author Frederico Linhares
|
11
|
+
class Style
|
12
|
+
# @!attribute [r] texture
|
13
|
+
# @return [RedBird::Texture]
|
14
|
+
# @!attribute [r] bg_color
|
15
|
+
# @return [RedBird::Color]
|
16
|
+
# @!attribute [r] sprites
|
17
|
+
# @return [Array<RedBird::Sprite>]
|
18
|
+
# @!attribute [r] sprite_width
|
19
|
+
# @return [Integer]
|
20
|
+
# @!attribute [r] sprite_height
|
21
|
+
# @return [Integer]
|
22
|
+
attr_reader :texture, :bg_color, :sprites, :sprite_width, :sprite_height
|
23
|
+
|
24
|
+
# @param texture_file [String] path to a image file in the format
|
25
|
+
# required by this class.
|
26
|
+
# @param bg_color [RedBird::Color] color used to fill the background of
|
27
|
+
# the box.
|
28
|
+
# @param sprite_width [Integer] width of each sprite in the
|
29
|
+
# +texture_file+.
|
30
|
+
# @param sprite_height [Integer] height of each sprite in the
|
31
|
+
# +texture_file+.
|
32
|
+
# @author Frederico Linhares
|
33
|
+
def initialize(texture_file, texture_palette, bg_color, sprite_width,
|
34
|
+
sprite_height)
|
35
|
+
@texture = Texture.new(texture_file, texture_palette)
|
36
|
+
@bg_color = bg_color
|
37
|
+
@sprite_width = sprite_width
|
38
|
+
@sprite_height = sprite_height
|
39
|
+
|
40
|
+
@sprites = {}
|
41
|
+
@sprites[:arrow_select] = Sprite.new(
|
42
|
+
@texture, 1 * @sprite_width, 1 * @sprite_height,
|
43
|
+
@sprite_width, @sprite_height)
|
44
|
+
@sprites[:box_top_left] = Sprite.new(
|
45
|
+
@texture, 0, 0, @sprite_width, @sprite_height)
|
46
|
+
@sprites[:box_top] = Sprite.new(
|
47
|
+
@texture, 1 * @sprite_width, 0,
|
48
|
+
@sprite_width, @sprite_height)
|
49
|
+
@sprites[:box_top_right] = Sprite.new(
|
50
|
+
@texture, 2 * @sprite_height, 0,
|
51
|
+
@sprite_width, @sprite_height)
|
52
|
+
@sprites[:box_left] = Sprite.new(
|
53
|
+
@texture, 0, 1 * @sprite_height,
|
54
|
+
@sprite_width, @sprite_height)
|
55
|
+
@sprites[:box_right] = Sprite.new(
|
56
|
+
@texture, 2 * @sprite_width, 1 * @sprite_height,
|
57
|
+
@sprite_width, @sprite_height)
|
58
|
+
@sprites[:box_bottom_left] = Sprite.new(
|
59
|
+
@texture, 0, 2 * @sprite_height,
|
60
|
+
@sprite_width, @sprite_height)
|
61
|
+
@sprites[:box_bottom] = Sprite.new(
|
62
|
+
@texture, 1 * @sprite_width, 2 * @sprite_height,
|
63
|
+
@sprite_width, @sprite_height)
|
64
|
+
@sprites[:box_bottom_right] = Sprite.new(
|
65
|
+
@texture, 2 * @sprite_width, 2 * @sprite_height,
|
66
|
+
@sprite_width, @sprite_height)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param style [RedBird::Style]
|
71
|
+
# @param pos_x [Integer]
|
72
|
+
# @param pos_y [Integer]
|
73
|
+
# @param num_vertical_sprites [Integer] number of sprites rows.
|
74
|
+
# @param num_horizontal_sprites [Integer] number of sprites columns.
|
75
|
+
# @author Frederico Linhares
|
76
|
+
def initialize(style, pos_x, pos_y, num_vertical_sprites,
|
77
|
+
num_horizontal_sprites)
|
78
|
+
@style = style
|
79
|
+
@pos_x = pos_x
|
80
|
+
@pos_y = pos_y
|
81
|
+
@num_vertical_sprites = num_vertical_sprites
|
82
|
+
@num_horizontal_sprites = num_horizontal_sprites
|
83
|
+
end
|
84
|
+
|
85
|
+
# The height is defined by +num_horizontal_sprites+ plus two (the borders).
|
86
|
+
# The width of each sprite is defined by the style used.
|
87
|
+
#
|
88
|
+
# @return [Integer]
|
89
|
+
# @author Frederico Linhares
|
90
|
+
def width
|
91
|
+
@style.sprite_width * (@num_horizontal_sprites + 2)
|
92
|
+
end
|
93
|
+
|
94
|
+
# The height is defined by +num_vertical_sprites+ plus two (the borders).
|
95
|
+
# The height of each sprite is defined by the style used.
|
96
|
+
#
|
97
|
+
# @return [Integer]
|
98
|
+
# @author Frederico Linhares
|
99
|
+
def height
|
100
|
+
@style.sprite_height * (@num_vertical_sprites + 2)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Renders to the screen.
|
104
|
+
#
|
105
|
+
# @author Frederico Linhares
|
106
|
+
def render
|
107
|
+
Render.set_color(@style.bg_color)
|
108
|
+
Render.fill_rect(@pos_x, @pos_y, self.width, self.height)
|
109
|
+
|
110
|
+
# Draw the corners.
|
111
|
+
@style.sprites[:box_top_left].render_to_screen(@pos_x, @pos_y)
|
112
|
+
@style.sprites[:box_top_right].render_to_screen(
|
113
|
+
@style.sprite_width * (@num_horizontal_sprites + 1) + @pos_x,
|
114
|
+
@pos_y)
|
115
|
+
@style.sprites[:box_bottom_left].render_to_screen(
|
116
|
+
@pos_x,
|
117
|
+
@style.sprite_height * (@num_vertical_sprites + 1) + @pos_y)
|
118
|
+
@style.sprites[:box_bottom_right].render_to_screen(
|
119
|
+
@style.sprite_width * (@num_horizontal_sprites + 1) + @pos_x,
|
120
|
+
@style.sprite_height * (@num_vertical_sprites + 1) + @pos_y)
|
121
|
+
|
122
|
+
# Draw the edges.
|
123
|
+
@num_horizontal_sprites.times do |i|
|
124
|
+
# Top
|
125
|
+
@style.sprites[:box_top].render_to_screen(
|
126
|
+
@style.sprite_width * (i + 1) + @pos_x, @pos_y)
|
127
|
+
# Bottom
|
128
|
+
@style.sprites[:box_bottom].render_to_screen(
|
129
|
+
@style.sprite_width * (i + 1) + @pos_x,
|
130
|
+
@style.sprite_height * (@num_vertical_sprites + 1) + @pos_y)
|
131
|
+
end
|
132
|
+
@num_vertical_sprites.times do |i|
|
133
|
+
# Left
|
134
|
+
@style.sprites[:box_left].render_to_screen(
|
135
|
+
@pos_x, @style.sprite_height * (i + 1) + @pos_y)
|
136
|
+
# Right
|
137
|
+
@style.sprites[:box_right].render_to_screen(
|
138
|
+
@style.sprite_width * (@num_horizontal_sprites + 1) + @pos_x,
|
139
|
+
@style.sprite_height * (i + 1) + @pos_y)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
2
|
+
require_relative "uibox"
|
3
|
+
|
4
|
+
module RedBird
|
5
|
+
# VerticalMenu is an interactive menu that receives input from players. It
|
6
|
+
# consists of a vertical list of {RedBird::VerticalMenu::Option}.
|
7
|
+
#
|
8
|
+
# @author Frederico Linhares
|
9
|
+
class VerticalMenu < Entity
|
10
|
+
|
11
|
+
# An option to be used in {RedBird::VerticalMenu}.
|
12
|
+
#
|
13
|
+
# @!attribute [r] action
|
14
|
+
# @return [Proc] code for option selection
|
15
|
+
# @!attribute [r] text
|
16
|
+
# @return [String] option name
|
17
|
+
# @author Frederico Linhares
|
18
|
+
class Option
|
19
|
+
attr_accessor :action, :text
|
20
|
+
|
21
|
+
# @param text [String] option name
|
22
|
+
# @param action [Proc] code to use when this option is selected
|
23
|
+
# @author Frederico Linhares
|
24
|
+
def initialize(text, &action)
|
25
|
+
@text = text
|
26
|
+
@action = action
|
27
|
+
@priority = 100
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param style [RedBird::UIBox::Style]
|
32
|
+
# @param pos_x [Integer]
|
33
|
+
# @param pos_y [Integer]
|
34
|
+
# @param options [Array<RedBird::VerticalMenu::Option>]
|
35
|
+
# @author Frederico Linhares
|
36
|
+
def initialize(style, pos_x, pos_y, options)
|
37
|
+
@style = style
|
38
|
+
@pos_x = pos_x
|
39
|
+
@pos_y = pos_y
|
40
|
+
|
41
|
+
@options = options
|
42
|
+
@current_option = 0
|
43
|
+
@option_max_width = 0
|
44
|
+
@option_max_height = 0
|
45
|
+
|
46
|
+
@options.each do |i|
|
47
|
+
if @option_max_width < i.text.width then
|
48
|
+
@option_max_width = i.text.width
|
49
|
+
end
|
50
|
+
if @option_max_height < i.text.height then
|
51
|
+
@option_max_height = i.text.height
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Integer]
|
57
|
+
# @author Frederico Linhares
|
58
|
+
def width
|
59
|
+
@option_max_width
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Integer]
|
63
|
+
# @author Frederico Linhares
|
64
|
+
def height
|
65
|
+
@option_max_height * @options.size
|
66
|
+
end
|
67
|
+
|
68
|
+
# Executes the action in the selected option.
|
69
|
+
#
|
70
|
+
# @author Frederico Linhares
|
71
|
+
def activate
|
72
|
+
@options[@current_option].action.call
|
73
|
+
end
|
74
|
+
|
75
|
+
# Changes the selected {RedBird::VerticalMenu::Option} to the next one.
|
76
|
+
#
|
77
|
+
# @author Frederico Linhares
|
78
|
+
def next_opt
|
79
|
+
@current_option += 1
|
80
|
+
@current_option = 0 if @current_option >= @options.size
|
81
|
+
end
|
82
|
+
|
83
|
+
# Changes the selected {RedBird::VerticalMenu::Option} to the previous one.
|
84
|
+
#
|
85
|
+
# @author Frederico Linhares
|
86
|
+
def pred_opt
|
87
|
+
if @current_option <= 0 then
|
88
|
+
@current_option = @options.size - 1
|
89
|
+
else
|
90
|
+
@current_option -= 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Renders to the screen.
|
95
|
+
#
|
96
|
+
# @author Frederico Linhares
|
97
|
+
def render
|
98
|
+
# Render texts.
|
99
|
+
@options.each_with_index do |o, i|
|
100
|
+
o.text.render_to_screen(
|
101
|
+
@style.sprite_width * 2 + @pos_x,
|
102
|
+
@style.sprite_height * (i + 1) + @pos_y)
|
103
|
+
end
|
104
|
+
|
105
|
+
@style.sprites[:arrow_select].render_to_screen(
|
106
|
+
@style.sprite_width + @pos_x,
|
107
|
+
@style.sprite_height * (@current_option + 1) + @pos_y)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|