fantasy 0.1.13 → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +22 -1
  3. data/.yardopts +4 -0
  4. data/CHANGELOG.md +6 -0
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +55 -0
  7. data/README.md +14 -6
  8. data/docs/Actor.html +2737 -0
  9. data/docs/Background.html +961 -0
  10. data/docs/Camera.html +791 -0
  11. data/docs/Clock.html +753 -0
  12. data/docs/Color.html +776 -0
  13. data/docs/Coordinates.html +730 -0
  14. data/docs/Cursor.html +752 -0
  15. data/docs/Disk.html +236 -0
  16. data/docs/Draggable.html +198 -0
  17. data/docs/Fantasy.html +121 -0
  18. data/docs/Game.html +904 -0
  19. data/docs/Global.html +2791 -0
  20. data/docs/Gravitier.html +179 -0
  21. data/docs/HudImage.html +979 -0
  22. data/docs/HudText.html +1151 -0
  23. data/docs/Image.html +506 -0
  24. data/docs/Jumper.html +189 -0
  25. data/docs/Mouse.html +226 -0
  26. data/docs/MoveByCursor.html +374 -0
  27. data/docs/MoveByDirection.html +179 -0
  28. data/docs/Mover.html +305 -0
  29. data/docs/Music.html +524 -0
  30. data/docs/Shape.html +1057 -0
  31. data/docs/Sound.html +374 -0
  32. data/docs/Tilemap.html +491 -0
  33. data/docs/Tween.html +186 -0
  34. data/docs/UserInputs.html +879 -0
  35. data/docs/Utils.html +345 -0
  36. data/docs/_index.html +346 -0
  37. data/docs/class_list.html +51 -0
  38. data/docs/css/common.css +1 -0
  39. data/docs/css/full_list.css +58 -0
  40. data/docs/css/style.css +497 -0
  41. data/docs/file.CHANGELOG.html +121 -0
  42. data/docs/file.README.html +599 -0
  43. data/docs/file_list.html +61 -0
  44. data/docs/frames.html +17 -0
  45. data/docs/index.html +599 -0
  46. data/docs/js/app.js +314 -0
  47. data/docs/js/full_list.js +216 -0
  48. data/docs/js/jquery.js +4 -0
  49. data/docs/method_list.html +1931 -0
  50. data/docs/top-level-namespace.html +978 -0
  51. data/lib/fantasy/actor.rb +455 -123
  52. data/lib/fantasy/background.rb +109 -13
  53. data/lib/fantasy/base.rb +113 -1
  54. data/lib/fantasy/camera.rb +95 -11
  55. data/lib/fantasy/clock.rb +4 -2
  56. data/lib/fantasy/color.rb +158 -153
  57. data/lib/fantasy/coordinates.rb +5 -9
  58. data/lib/fantasy/cursor.rb +2 -1
  59. data/lib/fantasy/disk.rb +12 -8
  60. data/lib/fantasy/draggable.rb +22 -1
  61. data/lib/fantasy/global.rb +59 -31
  62. data/lib/fantasy/hud_image.rb +5 -3
  63. data/lib/fantasy/hud_text.rb +6 -2
  64. data/lib/fantasy/image.rb +12 -4
  65. data/lib/fantasy/includes/gravitier.rb +2 -0
  66. data/lib/fantasy/includes/jumper.rb +3 -2
  67. data/lib/fantasy/includes/log.rb +12 -0
  68. data/lib/fantasy/includes/move_by_cursors.rb +24 -15
  69. data/lib/fantasy/includes/move_by_direction.rb +2 -0
  70. data/lib/fantasy/includes/mover.rb +3 -0
  71. data/lib/fantasy/includes/user_inputs.rb +6 -0
  72. data/lib/fantasy/loop.rb +41 -44
  73. data/lib/fantasy/mouse.rb +2 -0
  74. data/lib/fantasy/music.rb +4 -2
  75. data/lib/fantasy/shape.rb +11 -2
  76. data/lib/fantasy/sound.rb +3 -1
  77. data/lib/fantasy/tilemap.rb +19 -13
  78. data/lib/fantasy/tween.rb +3 -1
  79. data/lib/fantasy/utils.rb +7 -13
  80. data/lib/fantasy/version.rb +1 -1
  81. data/lib/fantasy.rb +2 -0
  82. metadata +90 -4
  83. data/fantasy.gemspec +0 -40
  84. data/fonts/VT323-Regular.ttf +0 -0
@@ -1,9 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Represents on static image that will be rendered on every frame.
4
+ # Replicable (by default).
5
+ # The position is relative to `Camera.main`.
6
+ # ```
7
+ # on_game do
8
+ # background = Background.new(image_name: "beach")
9
+ # # background.replicable = false # if you don't want the image to replicate
10
+ # background.scale = 6
11
+ # end
12
+ # ```
1
13
  class Background
2
- attr_accessor :scale, :color, :visible, :position, :layer, :replicable
3
14
 
15
+ # In which layer the image of the Background is rendered.
16
+ # Smaller numbers are rendered behind higher numbers.
17
+ #
18
+ # Default `-100`.
19
+ #
20
+ # @example Set layer
21
+ # background = Background.new("image")
22
+ # background.layer = -50
23
+ attr_accessor :layer
24
+
25
+
26
+ # Coordinates object where x and y represent the position of the Background in the World
27
+ # (no necessarily in the Screen).
28
+ #
29
+ # Default `Coordinates.zero`.
30
+ #
31
+ # @example Setting position
32
+ # background = Background.new("image")
33
+ # background.position = Coordinates.new(10, 20)
34
+ # background.position.x # => 10
35
+ #
36
+ # @example Modify position
37
+ # background.position.x += 1
38
+ # background.position.x # => 11
39
+ attr_accessor :position
40
+
41
+ # [Boolean] When `true` the image will replicate itself to cover all the screen. Default `true`.
42
+ #
43
+ # Default `true`.
44
+ #
45
+ # @example Setting replicable
46
+ # background = Background.new("image")
47
+ # background.replicable = false
48
+ attr_accessor :replicable
49
+
50
+ # The value to scale the image of the Background when drawn.
51
+ # If the value is `2` the image will rendered at double of size.
52
+ # If the value is `0.5` the image will rendered at half of size.
53
+ #
54
+ # @note this value affects the attributes `width` and `height`
55
+ #
56
+ # Default `1`.
57
+ #
58
+ # @example Set scale
59
+ # background = Background.new("image")
60
+ # background.scale = 6
61
+ attr_accessor :scale
62
+
63
+ # When `false` the Background won't be rendered in the next frame.
64
+ #
65
+ # Default `true`.
66
+ #
67
+ # @example Set visible
68
+ # background = Background.new("image")
69
+ # background.visible = false
70
+ attr_accessor :visible
71
+
72
+ # Generates an Background with all the below default values:
73
+ # - **position**: `Coordinates.zero`.
74
+ # - **scale**: `1`.
75
+ # - **draggable_on_debug**: `true`.
76
+ # - **layer**: `-100`.
77
+ # - **image**: The Image generated by `image_name`
78
+ # - **name**: Same as `image_name`
79
+ # - **visible**: `true`
80
+ # - **replicable**: `true`
81
+ #
82
+ # @param image_name [string] the name of the image file from `./images/*`
83
+ # @return [Background] the Background
84
+ # @example Instantiate a new Background
85
+ # background = Background.new("background")
4
86
  def initialize(image_name:)
5
87
  @image = Image.new(image_name)
6
- @name = image_name
7
88
  @position = Coordinates.zero
8
89
  @scale = 1
9
90
  @visible = true
@@ -15,18 +96,19 @@ class Background
15
96
  Global.backgrounds.push(self)
16
97
  end
17
98
 
99
+ # @return [Fixnum] the Background width in pixels
18
100
  def width
19
- @image.width() * @scale
101
+ @image.width * @scale
20
102
  end
21
103
 
104
+ # @return [Fixnum] the Background height in pixels
22
105
  def height
23
- @image.height() * @scale
106
+ @image.height * @scale
24
107
  end
25
108
 
26
- def position_in_camera
27
- @position - Global.camera.position
28
- end
109
+ # rubocop:disable Style/GuardClause
29
110
 
111
+ # @!visibility private
30
112
  def draw
31
113
  if @visible
32
114
  if @replicable
@@ -36,18 +118,31 @@ class Background
36
118
  end
37
119
  end
38
120
  end
121
+ # rubocop:enable Style/GuardClause
39
122
 
40
- def draw_normal
41
- @image.draw(x: position_in_camera.x, y: position_in_camera.y, scale: @scale)
123
+ # Destroy this Background and it will not longer be rendered
124
+ #
125
+ # @example Destroy a Background
126
+ # background = Background.new("background")
127
+ # background.destroy
128
+ def destroy
129
+ Global.backgrounds.delete(self)
130
+ end
131
+
132
+ private
133
+
134
+ def position_in_camera
135
+ @position - Camera.main.position
42
136
  end
43
137
 
44
138
  # Camera relative Tiles
139
+ # rubocop:disable Metrics/AbcSize
45
140
  def draw_replicable
46
141
  tiles_delta_x = (position_in_camera.x % width) - width
47
142
  tiles_delta_y = (position_in_camera.y % height) - height
48
143
 
49
- tiles_needed_horizontal = ((SCREEN_WIDTH - (tiles_delta_x + width)) / width.to_f).ceil + 1
50
- tiles_needed_vertical = ((SCREEN_HEIGHT - (tiles_delta_y + height)) / height.to_f).ceil + 1
144
+ tiles_needed_horizontal = ((Global.screen_width - (tiles_delta_x + width)) / width.to_f).ceil + 1
145
+ tiles_needed_vertical = ((Global.screen_height - (tiles_delta_y + height)) / height.to_f).ceil + 1
51
146
 
52
147
  tiles_needed_horizontal.times do |index_horizontal|
53
148
  tiles_needed_vertical.times do |index_vertical|
@@ -55,8 +150,9 @@ class Background
55
150
  end
56
151
  end
57
152
  end
153
+ # rubocop:enable Metrics/AbcSize
58
154
 
59
- def destroy
60
- Global.backgrounds.delete(self)
155
+ def draw_normal
156
+ @image.draw(x: position_in_camera.x, y: position_in_camera.y, scale: @scale)
61
157
  end
62
158
  end
data/lib/fantasy/base.rb CHANGED
@@ -1,60 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Here there are all the methods that can be used in the root level
4
+
1
5
  Global.setup_proc = nil
2
6
  Global.loop_proc = nil
3
7
 
8
+ # Defines the presentation Scene
9
+ #
10
+ # ```
11
+ # on_presentation do
12
+ # HudText.new(position: Coordinates.new(10, 100), text: "Press space to start")
13
+ #
14
+ # on_space_bar do
15
+ # Global.go_to_game
16
+ # end
17
+ # end
18
+ # ```
4
19
  def on_presentation(&block)
5
20
  Global.presentation_proc = block
6
21
  end
7
22
 
23
+ # Defines the game Scene
24
+ #
25
+ # ```
26
+ # on_game do
27
+ # # [...]
28
+ # if player.dead
29
+ # Global.go_to_end
30
+ # end
31
+ # end
32
+ # ```
8
33
  def on_game(&block)
9
34
  Global.game_proc = block
10
35
  end
11
36
 
37
+ # Defines the end Scene
38
+ #
39
+ # ```
40
+ # on_end do
41
+ # HudText.new(position: Coordinates.new(10, 100), text: "You are dead. Press space to re-tart")
42
+ #
43
+ # on_space_bar do
44
+ # Global.go_to_presentation
45
+ # end
46
+ # end
47
+ # ```
12
48
  def on_end(&block)
13
49
  Global.end_proc = block
14
50
  end
15
51
 
52
+ # @!visibility private
16
53
  def on_setup(&block)
17
54
  Global.setup_proc = block
18
55
  end
19
56
 
57
+ # Executes on every frame. To be used inside one of the scene blocks (`on_presentation`, `on_game`, `on_end`)
58
+ # ```
59
+ # on_game do
60
+ # on_loop do
61
+ # Global.references.time = Time.at(Global.seconds_in_scene).utc.strftime("%M:%S")
62
+ # end
63
+ # end
64
+ # ```
20
65
  def on_loop(&block)
21
66
  Global.loop_proc = block
22
67
  end
23
68
 
69
+ # @!visibility private
24
70
  def on_button(&block)
25
71
  Global.button_proc = block
26
72
  end
27
73
 
74
+ # Triggered any time space bar key is pressed. To be used inside one of the scene blocks (`on_presentation`, `on_game`, `on_end`)
75
+ # ```
76
+ # on_game do
77
+ # on_space_bar do
78
+ # shoot_gun # for example
79
+ # end
80
+ # end
81
+ # ```
28
82
  def on_space_bar(&block)
29
83
  Global.space_bar_proc = block
30
84
  end
31
85
 
86
+ # Triggered any time cursor up key is pressed. To be used inside one of the scene blocks (`on_presentation`, `on_game`, `on_end`)
87
+ # ```
88
+ # on_game do
89
+ # on_cursor_up do
90
+ # look_ups # for example
91
+ # end
92
+ # end
93
+ # ```
32
94
  def on_cursor_up(&block)
33
95
  Global.cursor_up_proc = block
34
96
  end
35
97
 
98
+ # Triggered any time cursor down key is pressed. To be used inside one of the scene blocks (`on_presentation`, `on_game`, `on_end`)
99
+ # ```
100
+ # on_game do
101
+ # on_cursor_down do
102
+ # look_down # for example
103
+ # end
104
+ # end
105
+ # ```
36
106
  def on_cursor_down(&block)
37
107
  Global.cursor_down_proc = block
38
108
  end
39
109
 
110
+ # Triggered any time cursor left key is pressed. To be used inside one of the scene blocks (`on_presentation`, `on_game`, `on_end`)
111
+ # ```
112
+ # on_game do
113
+ # on_cursor_left do
114
+ # look_left # for example
115
+ # end
116
+ # end
117
+ # ```
40
118
  def on_cursor_left(&block)
41
119
  Global.cursor_left_proc = block
42
120
  end
43
121
 
122
+ # Triggered any time cursor right key is pressed. To be used inside one of the scene blocks (`on_presentation`, `on_game`, `on_end`)
123
+ # ```
124
+ # on_game do
125
+ # on_cursor_right do
126
+ # look_right # for example
127
+ # end
128
+ # end
129
+ # ```
44
130
  def on_cursor_right(&block)
45
131
  Global.cursor_right_proc = block
46
132
  end
47
133
 
134
+ # Triggered any time mouse left button is pressed. To be used inside one of the scene blocks (`on_presentation`, `on_game`, `on_end`)
135
+ # ```
136
+ # on_game do
137
+ # on_mouse_button_left do
138
+ # show_menu # for example
139
+ # end
140
+ # end
141
+ # ```
48
142
  def on_mouse_button_left(&block)
49
143
  Global.mouse_button_left_proc = block
50
144
  end
51
145
 
146
+ # Triggered any time mouse right button is pressed. To be used inside one of the scene blocks (`on_presentation`, `on_game`, `on_end`)
147
+ # ```
148
+ # on_game do
149
+ # on_mouse_button_right do
150
+ # show_menu # for example
151
+ # end
152
+ # end
153
+ # ```
52
154
  def on_mouse_button_right(&block)
53
155
  Global.mouse_button_right_proc = block
54
156
  end
55
157
 
158
+ # Starts the game. This method has to be called when all the desired scene blocks (`on_presentation`, `on_game`, `on_end`) have been declared.
159
+ # ```
160
+ # on_game do
161
+ # # do game stuff
162
+ # end
163
+ #
164
+ # start!
165
+ # ```
56
166
  def start!
167
+ raise "'SCREEN_WIDTH' and 'SCREEN_HEIGHT' both have to be set at the beginning of the program" unless defined?(SCREEN_WIDTH) && defined?(SCREEN_HEIGHT)
168
+
57
169
  Global.setup
58
- Global.game = Game.new
170
+ Global.game = Game.new(SCREEN_WIDTH, SCREEN_HEIGHT)
59
171
  Global.game.show
60
172
  end
@@ -1,31 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Represents Coordinates of the camera and it affects the screen position of all Actors and Backgrounds.
4
+ # There is only one active Camera and it is acceded by `Camera.main`. This Camera is initialized automatically
5
+ # and it is already accessible. It can also be changed by another `Camera` instance.`
6
+ #
7
+ # @example Set the camera position
8
+ # Camera.main.position = Coordinates.new(0, 100)
9
+ #
10
+ # @example Camera follows player vertically
11
+ # on_game do
12
+ # player = Actor.new("image")
13
+ #
14
+ # on_loop do
15
+ # Camera.main.position.y = player.position.y - (SCREEN_HEIGHT / 2)
16
+ # end
17
+ # end
18
+ #
19
+ # @example Switching between cameras
20
+ # camera_1 = Camera.new
21
+ # camera_2 = Camera.new(position: Coordinates.new(0, 10))
22
+ # Camera.main = camera_1
23
+ # Camera.main = camera_2
1
24
  class Camera
2
- include MoveByCursor
3
25
 
4
- attr_accessor :position, :direction, :speed
26
+ # Coordinates object where x and y represent the position of the Camera in the World (no necessarily in the Screen).
27
+ #
28
+ # Default `Coordinates.zero`.
29
+ #
30
+ # @return [Coordinates] the actual position
31
+ #
32
+ # @example Setting position
33
+ # Camera.main.position = Coordinates.new(10, 20)
34
+ # Camera.main.position.x # => 10
35
+ #
36
+ # @example Modify position
37
+ # Camera.main.position.x += 1
38
+ # Camera.main.position.x # => 11
39
+ attr_accessor :position
40
+
41
+ # Controls the direction in which the Camera will move in the next frame.
42
+ #
43
+ # Default `Coordinates.zero`.
44
+ #
45
+ # @return [Coordinates] the actual direction
46
+ #
47
+ # @note The the pixels per second is represented by the `@speed` attribute
48
+ #
49
+ # @example Set direction
50
+ # Camera.main.direction = Coordinates.right
51
+ attr_accessor :direction
52
+
53
+ # Controls the pixels per second which the Camera will move in the next frame.
54
+ #
55
+ # Default `0`.
56
+ #
57
+ # @return [Float] the actual speed
58
+ #
59
+ # @note The the direction is represented by the `@direction` attribute
60
+ #
61
+ # @example Set speed
62
+ # Camera.main.speed = 10
63
+ attr_accessor :speed
5
64
 
65
+ # Generates a Camera with all the default attribute values
66
+ # @example Generate an Camera
67
+ # camera = Camera.new
68
+ # camera.position # => Coordinates.zero
69
+ # camera.direction # => Coordinates.zero
70
+ # camera.speed # => 0
71
+ #
72
+ # @param position [Coordinates] the initial position of the camera. Default `Coordinates.zero`
73
+ # @return [Camera] the Camera
6
74
  def initialize(position: Coordinates.zero)
7
75
  @position = position
8
76
  @direction = Coordinates.zero
9
77
  @speed = 0
10
- @moving_with_cursors = false
11
78
  @on_after_move_callback = nil
12
79
  end
13
80
 
14
- def move_with_cursors
15
- @moving_with_cursors = true
16
- end
17
-
81
+ # @!visibility private
18
82
  def move
19
- calculate_direction_by_cursors if @moving_with_cursors
20
-
21
83
  if @direction != Coordinates.zero && !@speed.zero?
22
- @position = @position + (@direction * @speed * Global.frame_time)
84
+ @position += (@direction * @speed * Global.frame_time)
23
85
  end
24
86
 
25
- @on_after_move_callback.call unless @on_after_move_callback.nil?
87
+ @on_after_move_callback&.call
26
88
  end
27
89
 
90
+ # Triggered on every frame after the move has been executed
91
+ # @example Avoid Camera to move over limits
92
+ # Camera.main.on_after_move do
93
+ # if Camera.main.position.x > 100
94
+ # Camera.main.position.x = 100
95
+ # end
96
+ # end
28
97
  def on_after_move(&block)
29
98
  @on_after_move_callback = block
30
99
  end
100
+
101
+ class << self
102
+ # @return [Camera] The active Camera
103
+ attr_accessor :main
104
+
105
+ # @!visibility private
106
+ def initialize
107
+ reset
108
+ end
109
+
110
+ # @!visibility private
111
+ def reset
112
+ @main = Camera.new
113
+ end
114
+ end
31
115
  end
data/lib/fantasy/clock.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Clock
2
4
  attr_accessor :persistent
3
5
  attr_reader :thread
@@ -29,9 +31,9 @@ class Clock
29
31
  times_executed = 0
30
32
  @thread =
31
33
  Thread.new do
32
- while(times_executed < times)
34
+ while times_executed < times
33
35
  @block.call
34
- times_executed += 1;
36
+ times_executed += 1
35
37
 
36
38
  seconds_to_sleep = seconds.is_a?(Range) ? rand(seconds) : seconds
37
39
  sleep(seconds_to_sleep)