fantasy 0.1.5 → 0.1.9
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +57 -7
- data/lib/fantasy/actor.rb +161 -28
- data/lib/fantasy/clock.rb +1 -0
- data/lib/fantasy/coordinates.rb +4 -0
- data/lib/fantasy/global.rb +30 -6
- data/lib/fantasy/hud_image.rb +1 -1
- data/lib/fantasy/hud_text.rb +28 -6
- data/lib/fantasy/includes/gravitier.rb +5 -0
- data/lib/fantasy/includes/jumper.rb +30 -0
- data/lib/fantasy/includes/move_by_cursors.rb +21 -10
- data/lib/fantasy/includes/move_by_direction.rb +5 -0
- data/lib/fantasy/includes/mover.rb +20 -0
- data/lib/fantasy/music.rb +49 -0
- data/lib/fantasy/{tile_map.rb → tilemap.rb} +10 -4
- data/lib/fantasy/utils.rb +5 -0
- data/lib/fantasy/version.rb +1 -1
- data/lib/fantasy.rb +8 -2
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c4d46c2a62a78651a3e571f5728ad846010dace93462f0c980b2235291a7f76
|
4
|
+
data.tar.gz: ceea378b0edd7b58155a9d05eb659236b4c70a0253e42167084e88cc41853170
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1c7f7e63529fc52adfe955152a76820da1f7df3e9274184d5f8b93df3f647a529eba55bd6b8b64b2270f3d54780b3c39ea3a5066bb21e2114ca5e79ce78602f
|
7
|
+
data.tar.gz: 418dc874ae30413c064a63074fe54b67840bdf1cd38bff01c6288b6b9bf287abe5c5e6c3aab7830be23fe0660d390b6dbc8e86565f81e667b156bb9f6150e453
|
data/CHANGELOG.md
CHANGED
@@ -3,3 +3,21 @@
|
|
3
3
|
## [0.1.0] - 2022-03-11
|
4
4
|
|
5
5
|
- Initial release
|
6
|
+
|
7
|
+
## [0.1.5] - 2022-03-16
|
8
|
+
|
9
|
+
- Background color or image
|
10
|
+
- Tilemap
|
11
|
+
- Camera can be controlled by cursors
|
12
|
+
- Background image can be replicable
|
13
|
+
|
14
|
+
## [0.1.7] - 2022-03-17
|
15
|
+
|
16
|
+
- HudText accepts alignment property. Valid values: 'top-left, top-right, center'
|
17
|
+
|
18
|
+
## [0.1.9] - 2022-03-25
|
19
|
+
|
20
|
+
- Adding platformer support
|
21
|
+
- Jump
|
22
|
+
- Gravity
|
23
|
+
- Music background support
|
data/README.md
CHANGED
@@ -116,12 +116,13 @@ Managing game elements which have (optionally) image, movement and collision
|
|
116
116
|
- Easy to set an `image`
|
117
117
|
- Managing movement through `direction` and `speed`
|
118
118
|
- Built-in movement control through cursors
|
119
|
-
- Collision detection, OnCollision callback
|
120
|
-
- Jump
|
121
|
-
- Gravity
|
119
|
+
- Collision detection, OnCollision callback, Collision matrix
|
120
|
+
- Jump
|
121
|
+
- Gravity
|
122
122
|
- Animations (TODO)
|
123
123
|
- Possibility to extend Actor class or instantiate it directly for simple characters
|
124
124
|
- Allowing magic instance properties (Like in OpenStruct). So programmer can do `actor.stuff = 1` and it is valid (TODO)
|
125
|
+
- Alignment "center" and "top-left" (TODO)
|
125
126
|
|
126
127
|
### Clock
|
127
128
|
|
@@ -196,7 +197,9 @@ Move the core functions to the top level hierarchy so I don't need to create a `
|
|
196
197
|
|
197
198
|
### Sound
|
198
199
|
|
199
|
-
Direct and easy way to play a sound
|
200
|
+
- Direct and easy way to play a sound
|
201
|
+
- Direct and easy way to play a background music
|
202
|
+
|
200
203
|
|
201
204
|
### Background
|
202
205
|
|
@@ -219,12 +222,13 @@ Easy access to keyboard and mouse inputs on any part of the code. Specially in t
|
|
219
222
|
- Remove "on_space_bar" when changing scene (TODO)
|
220
223
|
- Detect when key/mouse button is pressed in the actual frame in any part of the code (TODO)
|
221
224
|
|
222
|
-
###
|
225
|
+
### Tilemap (TODO)
|
223
226
|
|
224
227
|
For easy creation of:
|
225
228
|
|
226
|
-
- Top-down map levels
|
229
|
+
- Top-down map levels
|
227
230
|
- Platformer map levels (TODO)
|
231
|
+
- Allow specific map keys like a=>actor_1, b=>actor_2 (TODO)
|
228
232
|
|
229
233
|
### Tweens (TODO)
|
230
234
|
|
@@ -301,6 +305,7 @@ player.solid = true
|
|
301
305
|
player.speed = 200
|
302
306
|
player.layer = 1
|
303
307
|
player.move_with_cursors
|
308
|
+
player.collision_with = ["enemy", "bullets"] # default "all"
|
304
309
|
|
305
310
|
player.on_collision do |other|
|
306
311
|
if other.name == "enemy"
|
@@ -330,6 +335,7 @@ class Player < Actor
|
|
330
335
|
@speed = 200
|
331
336
|
@layer = 1
|
332
337
|
@direction = Coordinates.zero
|
338
|
+
@collision_with = ["enemy", "bullets"] # default "all"
|
333
339
|
move_with_cursors
|
334
340
|
end
|
335
341
|
|
@@ -351,6 +357,25 @@ class Player < Actor
|
|
351
357
|
end
|
352
358
|
```
|
353
359
|
|
360
|
+
Actor settings for a platformer:
|
361
|
+
|
362
|
+
```ruby
|
363
|
+
player = Actor.new("warrior") # ./images/warrior.png
|
364
|
+
player.solid = true
|
365
|
+
player.jump = 150
|
366
|
+
player.gravity = 200
|
367
|
+
player.move_with_cursors(left: true, right: true, up: false, down: false, jump: true)
|
368
|
+
|
369
|
+
player.on_start_jumping do
|
370
|
+
Sound.play("jump")
|
371
|
+
player.image = "warrior_jump")
|
372
|
+
end
|
373
|
+
|
374
|
+
player.on_start_falling do
|
375
|
+
player.image = "warrior")
|
376
|
+
end
|
377
|
+
```
|
378
|
+
|
354
379
|
### Clock
|
355
380
|
|
356
381
|
```ruby
|
@@ -397,18 +422,43 @@ end
|
|
397
422
|
|
398
423
|
### Sound
|
399
424
|
|
425
|
+
Plays only once:
|
426
|
+
|
400
427
|
```ruby
|
401
428
|
Sound.play("shoot") # ./sounds/shoot.wav
|
402
429
|
```
|
403
430
|
|
431
|
+
Plays in loop:
|
432
|
+
|
433
|
+
```ruby
|
434
|
+
Music.play("music") # ./musics/music.mp3
|
435
|
+
Music.volume = 0.5
|
436
|
+
Music.stop
|
437
|
+
```
|
438
|
+
|
439
|
+
### Tilemap
|
440
|
+
|
441
|
+
```ruby
|
442
|
+
# ./maps/sky.txt
|
443
|
+
#0 0 0
|
444
|
+
# 1 0
|
445
|
+
#
|
446
|
+
#0 0 0
|
447
|
+
|
448
|
+
planet = Actor.new("planet")
|
449
|
+
star = Actor.new("star")
|
450
|
+
map = Tilemap.new(map_name: "sky", tiles: [planet, star], tile_size: 30)
|
451
|
+
map.spawn
|
452
|
+
```
|
404
453
|
|
405
454
|
### UI
|
406
455
|
|
407
456
|
#### HUD Text
|
408
457
|
|
409
458
|
```ruby
|
410
|
-
timer = HudText.new(position: Coordinates.new(
|
459
|
+
timer = HudText.new(position: Coordinates.new(SCREEN_WIDTH / 2, 10))
|
411
460
|
timer.text = 0
|
461
|
+
timer.alignment = "center"
|
412
462
|
timer.size = "big"
|
413
463
|
|
414
464
|
Clock.new { timer.text += 1 }.repeat(seconds: 1)
|
data/lib/fantasy/actor.rb
CHANGED
@@ -1,26 +1,40 @@
|
|
1
1
|
class Actor
|
2
2
|
include MoveByCursor
|
3
|
+
include MoveByDirection
|
4
|
+
include Mover
|
5
|
+
include Gravitier
|
6
|
+
include Jumper
|
3
7
|
|
4
8
|
attr_reader :image, :moving_with_cursors
|
5
|
-
attr_accessor :image_name, :position, :direction, :speed, :solid, :scale, :name, :layer
|
9
|
+
attr_accessor :image_name, :position, :direction, :speed, :jump, :gravity, :solid, :scale, :name, :layer
|
10
|
+
attr_accessor :collision_with
|
6
11
|
|
7
12
|
def initialize(image_name)
|
8
13
|
@image_name = image_name
|
9
14
|
@image = Image.new(image_name)
|
10
15
|
@name = image_name
|
11
|
-
@position = Coordinates.
|
12
|
-
@direction = Coordinates.
|
16
|
+
@position = Coordinates.zero
|
17
|
+
@direction = Coordinates.zero
|
13
18
|
@speed = 0
|
14
19
|
@scale = 1
|
15
|
-
|
20
|
+
|
16
21
|
@moving_with_cursors = false
|
17
22
|
@solid = false
|
18
23
|
@draggable_on_debug = true
|
19
24
|
@dragging = false
|
20
25
|
@dragging_offset = nil
|
21
26
|
@layer = 0
|
27
|
+
@gravity = 0
|
28
|
+
@jump = 0
|
29
|
+
@collision_with = "all"
|
30
|
+
|
31
|
+
@on_floor = false
|
22
32
|
|
33
|
+
@on_after_move_callback = nil
|
23
34
|
@on_collision_callback = nil
|
35
|
+
@on_destroy_callback = nil
|
36
|
+
@on_start_jumping_callback = nil
|
37
|
+
@on_start_falling_callback = nil
|
24
38
|
|
25
39
|
Global.actors << self
|
26
40
|
end
|
@@ -30,20 +44,16 @@ class Actor
|
|
30
44
|
end
|
31
45
|
|
32
46
|
def width
|
33
|
-
@image.width
|
47
|
+
@image.width * @scale
|
34
48
|
end
|
35
49
|
|
36
50
|
def height
|
37
|
-
@image.height
|
38
|
-
end
|
39
|
-
|
40
|
-
def move_with_cursors
|
41
|
-
@moving_with_cursors = true
|
51
|
+
@image.height * @scale
|
42
52
|
end
|
43
53
|
|
44
54
|
def direction=(value)
|
45
55
|
@direction = value
|
46
|
-
@direction = @direction.normalize
|
56
|
+
@direction = @direction.normalize unless @direction.zero?
|
47
57
|
end
|
48
58
|
|
49
59
|
def draw
|
@@ -54,13 +64,32 @@ class Actor
|
|
54
64
|
|
55
65
|
def draw_debug
|
56
66
|
Utils.draw_frame(position_in_camera.x, position_in_camera.y, width, height, 1, Gosu::Color::RED) if solid
|
57
|
-
Global.
|
67
|
+
Global.pixel_fonts["medium"].draw_text("#{@position.x.floor},#{@position.y.floor}", position_in_camera.x, position_in_camera.y - 20, 1)
|
58
68
|
end
|
59
69
|
|
60
70
|
def position_in_camera
|
61
71
|
@position - Global.camera.position
|
62
72
|
end
|
63
73
|
|
74
|
+
# TODO: make this work optimized
|
75
|
+
# def position_top_left
|
76
|
+
# @position - position_delta
|
77
|
+
# end
|
78
|
+
|
79
|
+
# def position_delta
|
80
|
+
# case @alignment
|
81
|
+
# when "top-left"
|
82
|
+
# Coordinates.zero
|
83
|
+
# when "center"
|
84
|
+
# Coordinates.new(width/2, height/2)
|
85
|
+
# else
|
86
|
+
# raise "Actor.alignment value not valid '#{@alignment}'. Valid values: 'top-left, center'"
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
|
90
|
+
# TODO: I made more of this code while I was with Covid
|
91
|
+
# It looks horrible and it is crap
|
92
|
+
# I'll improve it some day :)
|
64
93
|
def move
|
65
94
|
mouse_position = Global.mouse_position + Global.camera.position
|
66
95
|
|
@@ -76,30 +105,87 @@ class Actor
|
|
76
105
|
if @dragging
|
77
106
|
@position = mouse_position - @dragging_offset
|
78
107
|
else
|
79
|
-
|
108
|
+
# Direction moving
|
109
|
+
unless @direction.zero?
|
110
|
+
@velocity = Coordinates.zero
|
111
|
+
last_position = @position
|
112
|
+
add_forces_by_direction
|
113
|
+
apply_forces(max_speed: @speed)
|
114
|
+
|
115
|
+
# Check collision after cursor moving
|
116
|
+
if @solid && @position != last_position
|
117
|
+
manage_collisions(last_position)
|
118
|
+
end
|
119
|
+
end
|
80
120
|
|
81
|
-
|
82
|
-
|
83
|
-
|
121
|
+
# Cursors moving
|
122
|
+
@velocity = Coordinates.zero
|
123
|
+
last_position = @position
|
124
|
+
add_forces_by_cursors
|
125
|
+
apply_forces(max_speed: @speed)
|
84
126
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
127
|
+
# Check collision after cursor moving
|
128
|
+
if @solid && @position != last_position
|
129
|
+
manage_collisions(last_position)
|
130
|
+
end
|
90
131
|
|
91
|
-
|
132
|
+
# Jump moving
|
133
|
+
unless @jump.zero?
|
134
|
+
@velocity = Coordinates.zero
|
135
|
+
last_position = @position
|
136
|
+
add_force_by_jump
|
137
|
+
apply_forces(max_speed: @speed)
|
138
|
+
|
139
|
+
# Check collision after jump moving
|
140
|
+
if @solid && @position != last_position
|
141
|
+
if manage_collisions(last_position)
|
142
|
+
@jumping = false
|
143
|
+
end
|
92
144
|
end
|
93
145
|
end
|
146
|
+
|
147
|
+
# Gravity moving
|
148
|
+
if !@gravity.zero? && !@jumping
|
149
|
+
@velocity = Coordinates.zero
|
150
|
+
last_position = @position
|
151
|
+
add_force_by_gravity
|
152
|
+
apply_forces(max_speed: @gravity)
|
153
|
+
|
154
|
+
# Check collision after gravity moving
|
155
|
+
if @solid && @position != last_position
|
156
|
+
@on_floor = false
|
157
|
+
manage_collisions(last_position)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
on_after_move_do
|
163
|
+
end
|
164
|
+
|
165
|
+
def manage_collisions(last_position)
|
166
|
+
collisions.each do |other|
|
167
|
+
on_collision_do(other)
|
168
|
+
other.on_collision_do(self)
|
169
|
+
|
170
|
+
if other.position.y > (last_position.y + height)
|
171
|
+
@on_floor = true
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
if collisions.any? # we don't cache collisions because position may be changed on collision callback
|
176
|
+
@position = last_position
|
177
|
+
|
178
|
+
return true
|
94
179
|
end
|
95
180
|
|
96
|
-
|
181
|
+
false
|
97
182
|
end
|
98
183
|
|
99
184
|
def solid?
|
100
185
|
@solid
|
101
186
|
end
|
102
187
|
|
188
|
+
# Set callbacks
|
103
189
|
def on_after_move(&block)
|
104
190
|
@on_after_move_callback = block
|
105
191
|
end
|
@@ -112,18 +198,51 @@ class Actor
|
|
112
198
|
@on_destroy_callback = block
|
113
199
|
end
|
114
200
|
|
115
|
-
def
|
116
|
-
@
|
201
|
+
def on_start_jumping(&block)
|
202
|
+
@on_start_jumping_callback = block
|
117
203
|
end
|
118
204
|
|
205
|
+
def on_start_falling(&block)
|
206
|
+
@on_start_falling_callback = block
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
# Execute callbacks
|
211
|
+
def on_after_move_do
|
212
|
+
instance_exec(&@on_after_move_callback) unless @on_after_move_callback.nil?
|
213
|
+
end
|
214
|
+
|
215
|
+
def on_collision_do(other)
|
216
|
+
instance_exec(other, &@on_collision_callback) unless @on_collision_callback.nil?
|
217
|
+
end
|
218
|
+
|
219
|
+
def on_destroy_do
|
220
|
+
instance_exec(&@on_destroy_callback) unless @on_destroy_callback.nil?
|
221
|
+
end
|
222
|
+
|
223
|
+
def on_start_jumping_do
|
224
|
+
instance_exec(&@on_start_jumping_callback) unless @on_start_jumping_callback.nil?
|
225
|
+
end
|
226
|
+
|
227
|
+
def on_start_falling_do
|
228
|
+
instance_exec(&@on_start_falling_callback) unless @on_start_falling_callback.nil?
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
|
119
233
|
def collisions
|
120
|
-
Global.actors.reject { |e| e == self }.select { |e| e.solid? }.select do |
|
121
|
-
|
234
|
+
Global.actors.reject { |e| e == self }.select { |e| e.solid? }.select do |other|
|
235
|
+
if(
|
236
|
+
(@collision_with == "all" || @collision_with.include?(other.name)) &&
|
237
|
+
(other.collision_with == "all" || other.collision_with.include?(self.name))
|
238
|
+
)
|
239
|
+
Utils.collision? self, other
|
240
|
+
end
|
122
241
|
end
|
123
242
|
end
|
124
243
|
|
125
244
|
def destroy
|
126
|
-
|
245
|
+
on_destroy_do
|
127
246
|
Global.actors.delete(self)
|
128
247
|
end
|
129
248
|
|
@@ -133,15 +252,21 @@ class Actor
|
|
133
252
|
actor.name = @name
|
134
253
|
actor.position = @position.clone
|
135
254
|
actor.direction = @direction.clone
|
255
|
+
|
136
256
|
actor.speed = @speed
|
137
257
|
actor.scale = @scale
|
138
258
|
actor.moving_with_cursors if @moving_with_cursors
|
139
259
|
actor.solid = @solid
|
140
260
|
actor.layer = @layer
|
261
|
+
actor.gravity = @gravity
|
262
|
+
actor.jump = @jump
|
263
|
+
actor.collision_with = @collision_with
|
141
264
|
|
142
265
|
actor.on_after_move_callback = @on_after_move_callback
|
143
266
|
actor.on_collision_callback = @on_collision_callback
|
144
267
|
actor.on_destroy_callback = @on_destroy_callback
|
268
|
+
actor.on_start_jumping = @on_start_jumping_callback
|
269
|
+
actor.on_start_falling = @on_start_falling_callback
|
145
270
|
|
146
271
|
actor
|
147
272
|
end
|
@@ -159,4 +284,12 @@ class Actor
|
|
159
284
|
def on_destroy_callback=(block)
|
160
285
|
@on_destroy_callback = block
|
161
286
|
end
|
287
|
+
|
288
|
+
def on_start_jumping=(block)
|
289
|
+
@on_start_jumping_callback = block
|
290
|
+
end
|
291
|
+
|
292
|
+
def on_start_falling=(block)
|
293
|
+
@on_start_falling_callback = block
|
294
|
+
end
|
162
295
|
end
|
data/lib/fantasy/clock.rb
CHANGED
data/lib/fantasy/coordinates.rb
CHANGED
data/lib/fantasy/global.rb
CHANGED
@@ -15,7 +15,7 @@ module Global
|
|
15
15
|
|
16
16
|
attr_accessor :game
|
17
17
|
attr_reader :frame_time # delta_time
|
18
|
-
attr_reader :
|
18
|
+
attr_reader :pixel_fonts
|
19
19
|
attr_reader :references
|
20
20
|
attr_reader :camera
|
21
21
|
attr_reader :game_state
|
@@ -30,12 +30,20 @@ module Global
|
|
30
30
|
@clocks = []
|
31
31
|
@last_frame_at = Time.now
|
32
32
|
@debug = false
|
33
|
-
|
33
|
+
|
34
|
+
@pixel_fonts = {}
|
35
|
+
@pixel_fonts["small"] = Gosu::Font.new(20, { name: "#{__dir__}/../../fonts/VT323-Regular.ttf" } )
|
36
|
+
@pixel_fonts["medium"] = Gosu::Font.new(40, { name: "#{__dir__}/../../fonts/VT323-Regular.ttf" } )
|
37
|
+
@pixel_fonts["big"] = Gosu::Font.new(60, { name: "#{__dir__}/../../fonts/VT323-Regular.ttf" } )
|
38
|
+
@pixel_fonts["huge"] = Gosu::Font.new(100, { name: "#{__dir__}/../../fonts/VT323-Regular.ttf" } )
|
39
|
+
|
34
40
|
@d_key_pressed = false
|
35
41
|
@references = OpenStruct.new
|
36
42
|
@camera = Camera.new(position: Coordinates.zero)
|
37
43
|
@game_state = Global.presentation_proc.nil? ? "game" : "presentation"
|
38
|
-
@
|
44
|
+
@scene_started_at = Time.now
|
45
|
+
|
46
|
+
@background = Color.new(r: 0, g: 0, b: 0)
|
39
47
|
|
40
48
|
if @presentation_proc.nil?
|
41
49
|
on_presentation { Global.default_on_presentation }
|
@@ -102,12 +110,28 @@ module Global
|
|
102
110
|
end
|
103
111
|
|
104
112
|
def clear_state_elements
|
113
|
+
@scene_started_at = Time.now
|
105
114
|
@actors.clear
|
106
115
|
@hud_texts.clear
|
107
116
|
@hud_images.clear
|
108
117
|
@backgrounds.clear
|
109
118
|
@tile_maps.clear
|
110
|
-
@
|
119
|
+
@camera.position = Coordinates.zero
|
120
|
+
|
121
|
+
@clocks.reject(&:persistent?).each do |clock|
|
122
|
+
clock.stop unless clock.thread == Thread.current # no stop current Thread
|
123
|
+
end
|
124
|
+
|
125
|
+
# clear callbacks
|
126
|
+
@button_proc = nil
|
127
|
+
@space_bar_proc = nil
|
128
|
+
@cursor_up_proc = nil
|
129
|
+
@cursor_down_proc = nil
|
130
|
+
@cursor_left_proc = nil
|
131
|
+
@cursor_right_proc = nil
|
132
|
+
@mouse_button_left_proc = nil
|
133
|
+
@mouse_button_right_proc = nil
|
134
|
+
|
111
135
|
@background = Color.new(r: 0, g: 0, b: 0)
|
112
136
|
end
|
113
137
|
|
@@ -120,8 +144,8 @@ module Global
|
|
120
144
|
Image.preload_images
|
121
145
|
end
|
122
146
|
|
123
|
-
def
|
124
|
-
Time.now - @
|
147
|
+
def seconds_in_scene
|
148
|
+
Time.now - @scene_started_at
|
125
149
|
end
|
126
150
|
end
|
127
151
|
end
|
data/lib/fantasy/hud_image.rb
CHANGED
@@ -37,7 +37,7 @@ class HudImage
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def draw_debug
|
40
|
-
Global.
|
40
|
+
Global.pixel_fonts["medium"].draw_text("#{@position.x.floor},#{@position.y.floor}", @position.x, @position.y - 20, 1)
|
41
41
|
end
|
42
42
|
|
43
43
|
def destroy
|
data/lib/fantasy/hud_text.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class HudText
|
2
|
-
attr_accessor :text, :size, :color, :visible, :layer, :in_world
|
2
|
+
attr_accessor :text, :size, :color, :visible, :layer, :in_world, :position, :alignment
|
3
3
|
|
4
4
|
def initialize(position:, text: "")
|
5
5
|
@position = position
|
@@ -9,6 +9,7 @@ class HudText
|
|
9
9
|
@visible = true
|
10
10
|
@layer = 100
|
11
11
|
@in_world = false
|
12
|
+
@alignment = "top-left"
|
12
13
|
|
13
14
|
Global.hud_texts.push(self)
|
14
15
|
end
|
@@ -17,14 +18,35 @@ class HudText
|
|
17
18
|
|
18
19
|
def draw
|
19
20
|
if visible
|
20
|
-
|
21
|
-
|
21
|
+
font.draw_markup_rel(text, screen_position.x + shadow_offset, screen_position.y + shadow_offset, 1, position_rel.x, position_rel.y, 1, 1, Gosu::Color::BLACK)
|
22
|
+
font.draw_markup_rel(text, screen_position.x, screen_position.y, 1, position_rel.x, position_rel.y, 1, 1, color)
|
22
23
|
end
|
23
24
|
|
24
25
|
draw_debug if Global.debug
|
25
26
|
end
|
26
27
|
|
27
|
-
def
|
28
|
+
def font
|
29
|
+
found_font = Global.pixel_fonts[@size]
|
30
|
+
if found_font.nil?
|
31
|
+
raise "HudText.size value not valid '#{@size}'. Valid values: 'small, medium, big, huge'"
|
32
|
+
end
|
33
|
+
found_font
|
34
|
+
end
|
35
|
+
|
36
|
+
def position_rel
|
37
|
+
case @alignment
|
38
|
+
when "top-left"
|
39
|
+
Coordinates.new(0, 0)
|
40
|
+
when "top-right"
|
41
|
+
Coordinates.new(1, 0)
|
42
|
+
when "center"
|
43
|
+
Coordinates.new(0.5, 0.5)
|
44
|
+
else
|
45
|
+
raise "HudText.alignment value not valid '#{@alignment}'. Valid values: 'top-left, top-right, center'"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def shadow_offset
|
28
50
|
case @size
|
29
51
|
when "small"
|
30
52
|
1
|
@@ -35,7 +57,7 @@ class HudText
|
|
35
57
|
when "huge"
|
36
58
|
4
|
37
59
|
else
|
38
|
-
raise "HudText.size not valid '#{@size}'. Valid sizes: 'small, medium, big, huge'"
|
60
|
+
raise "HudText.size value not valid '#{@size}'. Valid sizes: 'small, medium, big, huge'"
|
39
61
|
end
|
40
62
|
end
|
41
63
|
|
@@ -52,6 +74,6 @@ class HudText
|
|
52
74
|
end
|
53
75
|
|
54
76
|
def draw_debug
|
55
|
-
Global.
|
77
|
+
Global.pixel_fonts["medium"].draw_text("#{@position.x.floor},#{@position.y.floor}", screen_position.x, screen_position.y, 1)
|
56
78
|
end
|
57
79
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Jumper
|
2
|
+
def add_force_by_jump
|
3
|
+
if Gosu.button_down?(Gosu::KB_SPACE) && @move_with_cursors_jump && !@jumping && @on_floor
|
4
|
+
execute_jump
|
5
|
+
end
|
6
|
+
|
7
|
+
if @jumping
|
8
|
+
continue_jump
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute_jump
|
13
|
+
@jumping = true
|
14
|
+
@on_floor = false
|
15
|
+
@final_vertical_position = @position.y - @jump
|
16
|
+
|
17
|
+
on_start_jumping_do
|
18
|
+
end
|
19
|
+
|
20
|
+
def continue_jump
|
21
|
+
add_force(Coordinates.up * @jump)
|
22
|
+
|
23
|
+
if(@position.y <= @final_vertical_position)
|
24
|
+
@position.y = @final_vertical_position
|
25
|
+
@jumping = false
|
26
|
+
|
27
|
+
on_start_falling_do
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,15 +1,26 @@
|
|
1
1
|
module MoveByCursor
|
2
|
-
def
|
3
|
-
if Gosu.button_down?(Gosu::KB_DOWN)
|
4
|
-
|
5
|
-
elsif Gosu.button_down?(Gosu::KB_UP)
|
6
|
-
|
7
|
-
elsif Gosu.button_down?(Gosu::KB_RIGHT)
|
8
|
-
|
9
|
-
elsif Gosu.button_down?(Gosu::KB_LEFT)
|
10
|
-
|
2
|
+
def add_forces_by_cursors
|
3
|
+
if Gosu.button_down?(Gosu::KB_DOWN) && @move_with_cursors_down
|
4
|
+
add_force(Coordinates.down * @speed)
|
5
|
+
elsif Gosu.button_down?(Gosu::KB_UP) && @move_with_cursors_up
|
6
|
+
add_force(Coordinates.up * @speed)
|
7
|
+
elsif Gosu.button_down?(Gosu::KB_RIGHT) && @move_with_cursors_right
|
8
|
+
add_force(Coordinates.right * @speed)
|
9
|
+
elsif Gosu.button_down?(Gosu::KB_LEFT) && @move_with_cursors_left
|
10
|
+
add_force(Coordinates.left * @speed)
|
11
11
|
else
|
12
|
-
@
|
12
|
+
# @velocity.x = 0
|
13
13
|
end
|
14
|
+
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def move_with_cursors(down: true, up: true, left: true, right: true, jump: false)
|
19
|
+
puts "#{@name}: move_with_cursors(down: #{down}, up: #{up}, left: #{left}, right: #{right}), jump: #{jump}"
|
20
|
+
@move_with_cursors_down = down
|
21
|
+
@move_with_cursors_up = up
|
22
|
+
@move_with_cursors_left = left
|
23
|
+
@move_with_cursors_right = right
|
24
|
+
@move_with_cursors_jump = jump
|
14
25
|
end
|
15
26
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mover
|
2
|
+
def add_force(force)
|
3
|
+
@acceleration ||= Coordinates.zero
|
4
|
+
@acceleration += force
|
5
|
+
end
|
6
|
+
|
7
|
+
def apply_forces(max_speed:)
|
8
|
+
@acceleration ||= Coordinates.zero
|
9
|
+
@velocity ||= Coordinates.zero
|
10
|
+
|
11
|
+
@velocity += @acceleration
|
12
|
+
|
13
|
+
unless @velocity.length.zero?
|
14
|
+
@velocity = @velocity.normalize * max_speed * Global.frame_time
|
15
|
+
@position += @velocity
|
16
|
+
end
|
17
|
+
|
18
|
+
@acceleration = Coordinates.zero
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Music
|
2
|
+
class << self
|
3
|
+
@@musics = {}
|
4
|
+
@@actual_song = nil
|
5
|
+
|
6
|
+
def play(music_name)
|
7
|
+
stop
|
8
|
+
|
9
|
+
@@actual_song = locate_music(music_name)
|
10
|
+
@@actual_song.play(true)
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop
|
14
|
+
@@actual_song.stop unless @@actual_song.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def volume
|
18
|
+
@@actual_song&.volume
|
19
|
+
end
|
20
|
+
|
21
|
+
def volume=(value)
|
22
|
+
@@actual_song.volume = value unless @@actual_song.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def locate_music(music_name)
|
26
|
+
return @@musics[music_name] if @@musics[music_name]
|
27
|
+
|
28
|
+
puts "Initialize Music: '#{music_name}'"
|
29
|
+
|
30
|
+
file_name = Dir.entries(base_path).find { |e| e =~ /^#{music_name}($|\.)/ }
|
31
|
+
|
32
|
+
raise "Music file not found with name '#{music_name}'" if file_name.nil?
|
33
|
+
|
34
|
+
@@musics[music_name] = Gosu::Song.new("#{base_path}/#{file_name}")
|
35
|
+
|
36
|
+
return @@musics[music_name]
|
37
|
+
end
|
38
|
+
|
39
|
+
def preload_musics
|
40
|
+
Dir.each_child(base_path) do |file_name|
|
41
|
+
locate_music(file_name) unless file_name.start_with?(".")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def base_path
|
46
|
+
"#{Dir.pwd}/musics"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class
|
1
|
+
class Tilemap
|
2
2
|
attr_accessor :position
|
3
3
|
|
4
4
|
def initialize(map_name:, tiles:, tile_size: nil, tile_width: nil, tile_height: nil)
|
@@ -13,7 +13,7 @@ class TileMap
|
|
13
13
|
@tiles = tiles
|
14
14
|
@position = Coordinates.zero
|
15
15
|
|
16
|
-
@grid =
|
16
|
+
@grid = Tilemap.load_grid(@map_name)
|
17
17
|
end
|
18
18
|
|
19
19
|
def width
|
@@ -32,7 +32,13 @@ class TileMap
|
|
32
32
|
|
33
33
|
line.each do |tile_index|
|
34
34
|
if !tile_index.nil?
|
35
|
-
|
35
|
+
actor_template = @tiles[tile_index]
|
36
|
+
|
37
|
+
if actor_template.nil?
|
38
|
+
raise "Tilemap config error. Not found Tile for index '#{tile_index}'"
|
39
|
+
end
|
40
|
+
|
41
|
+
actor = actor_template.clone
|
36
42
|
actor.position.x = @position.x + (tile_position.x * @tile_width)
|
37
43
|
actor.position.y = @position.y + (tile_position.y * @tile_height)
|
38
44
|
end
|
@@ -50,7 +56,7 @@ class TileMap
|
|
50
56
|
@@maps = {}
|
51
57
|
|
52
58
|
def load_grid(map_name)
|
53
|
-
File.readlines(
|
59
|
+
File.readlines(Tilemap.locate_map(map_name), chomp: true).map do |line|
|
54
60
|
line.each_char.map do |char|
|
55
61
|
char == " " ? nil : char.to_i
|
56
62
|
end
|
data/lib/fantasy/utils.rb
CHANGED
@@ -27,4 +27,9 @@ module Utils
|
|
27
27
|
Gosu.draw_rect(x, y + (height - stroke), width, stroke, color)
|
28
28
|
Gosu.draw_rect(x, y, stroke, height, color)
|
29
29
|
end
|
30
|
+
|
31
|
+
def self.remap(value:, from_ini:, from_end:, to_ini:, to_end:)
|
32
|
+
result = to_ini + (value - from_ini) * (to_end - to_ini) / (from_end - from_ini);
|
33
|
+
result
|
34
|
+
end
|
30
35
|
end
|
data/lib/fantasy/version.rb
CHANGED
data/lib/fantasy.rb
CHANGED
@@ -2,12 +2,17 @@
|
|
2
2
|
require "gosu"
|
3
3
|
|
4
4
|
require_relative "fantasy/version"
|
5
|
+
|
6
|
+
require_relative "fantasy/coordinates"
|
5
7
|
require_relative "fantasy/includes/move_by_cursors"
|
8
|
+
require_relative "fantasy/includes/move_by_direction"
|
9
|
+
require_relative "fantasy/includes/mover"
|
10
|
+
require_relative "fantasy/includes/gravitier"
|
11
|
+
require_relative "fantasy/includes/jumper"
|
6
12
|
require_relative "fantasy/tween"
|
7
13
|
require_relative "fantasy/draggable"
|
8
14
|
require_relative "fantasy/color"
|
9
15
|
require_relative "fantasy/actor"
|
10
|
-
require_relative "fantasy/coordinates"
|
11
16
|
require_relative "fantasy/utils"
|
12
17
|
require_relative "fantasy/global"
|
13
18
|
require_relative "fantasy/clock"
|
@@ -16,7 +21,8 @@ require_relative "fantasy/hud_text"
|
|
16
21
|
require_relative "fantasy/hud_image"
|
17
22
|
require_relative "fantasy/background"
|
18
23
|
require_relative "fantasy/sound"
|
24
|
+
require_relative "fantasy/music"
|
19
25
|
require_relative "fantasy/camera"
|
20
26
|
require_relative "fantasy/image"
|
21
|
-
require_relative "fantasy/
|
27
|
+
require_relative "fantasy/tilemap"
|
22
28
|
require_relative "fantasy/base"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fantasy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fernando Guillen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03-
|
11
|
+
date: 2022-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gosu
|
@@ -69,10 +69,15 @@ files:
|
|
69
69
|
- lib/fantasy/hud_image.rb
|
70
70
|
- lib/fantasy/hud_text.rb
|
71
71
|
- lib/fantasy/image.rb
|
72
|
+
- lib/fantasy/includes/gravitier.rb
|
73
|
+
- lib/fantasy/includes/jumper.rb
|
72
74
|
- lib/fantasy/includes/move_by_cursors.rb
|
75
|
+
- lib/fantasy/includes/move_by_direction.rb
|
76
|
+
- lib/fantasy/includes/mover.rb
|
73
77
|
- lib/fantasy/loop.rb
|
78
|
+
- lib/fantasy/music.rb
|
74
79
|
- lib/fantasy/sound.rb
|
75
|
-
- lib/fantasy/
|
80
|
+
- lib/fantasy/tilemap.rb
|
76
81
|
- lib/fantasy/tween.rb
|
77
82
|
- lib/fantasy/utils.rb
|
78
83
|
- lib/fantasy/version.rb
|