road_to_rubykaigi 0.1.0

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 (37) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.standard.yml +18 -0
  4. data/CHANGELOG.md +3 -0
  5. data/CODE_OF_CONDUCT.md +132 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +49 -0
  8. data/Rakefile +10 -0
  9. data/bin/road_to_rubykaigi +5 -0
  10. data/lib/road_to_rubykaigi/ansi.rb +22 -0
  11. data/lib/road_to_rubykaigi/fireworks.rb +63 -0
  12. data/lib/road_to_rubykaigi/game.rb +97 -0
  13. data/lib/road_to_rubykaigi/graphics/fireworks.rb +16 -0
  14. data/lib/road_to_rubykaigi/graphics/fireworks.txt +369 -0
  15. data/lib/road_to_rubykaigi/graphics/map.rb +11 -0
  16. data/lib/road_to_rubykaigi/graphics/map.txt +30 -0
  17. data/lib/road_to_rubykaigi/graphics/mask.rb +11 -0
  18. data/lib/road_to_rubykaigi/graphics/mask.txt +30 -0
  19. data/lib/road_to_rubykaigi/graphics/player.rb +81 -0
  20. data/lib/road_to_rubykaigi/manager/collision_manager.rb +133 -0
  21. data/lib/road_to_rubykaigi/manager/drawing_manager.rb +48 -0
  22. data/lib/road_to_rubykaigi/manager/game_manager.rb +55 -0
  23. data/lib/road_to_rubykaigi/manager/update_manager.rb +27 -0
  24. data/lib/road_to_rubykaigi/map.rb +120 -0
  25. data/lib/road_to_rubykaigi/opening_screen.rb +56 -0
  26. data/lib/road_to_rubykaigi/score_board.rb +17 -0
  27. data/lib/road_to_rubykaigi/sprite/attack.rb +72 -0
  28. data/lib/road_to_rubykaigi/sprite/bonus.rb +127 -0
  29. data/lib/road_to_rubykaigi/sprite/deadline.rb +57 -0
  30. data/lib/road_to_rubykaigi/sprite/effect.rb +88 -0
  31. data/lib/road_to_rubykaigi/sprite/enemy.rb +178 -0
  32. data/lib/road_to_rubykaigi/sprite/player.rb +178 -0
  33. data/lib/road_to_rubykaigi/sprite/sprite.rb +22 -0
  34. data/lib/road_to_rubykaigi/version.rb +5 -0
  35. data/lib/road_to_rubykaigi.rb +46 -0
  36. data/sig/road_to_rubykaigi.rbs +4 -0
  37. metadata +82 -0
@@ -0,0 +1,57 @@
1
+ module RoadToRubykaigi
2
+ module Sprite
3
+ class Deadline < Sprite
4
+ DEADLINE_SPEED = 0.3
5
+ DEADLINE_START_X = 18
6
+
7
+ attr_reader :x, :y, :width, :height
8
+
9
+ def find
10
+ yield self || nil
11
+ end
12
+
13
+ def update
14
+ return unless active?
15
+ now = Time.now
16
+ if (now - @last_update) > DEADLINE_SPEED
17
+ @x += 1
18
+ @last_update = now
19
+ end
20
+ end
21
+
22
+ def build_buffer(offset_x:)
23
+ buffer = Array.new(Map::VIEWPORT_HEIGHT) { Array.new(Map::VIEWPORT_WIDTH) { "" } }
24
+ relative_x = @x - offset_x - 1
25
+ relative_y = @y - 1
26
+ @height.times do |i|
27
+ next if relative_x < 1
28
+ buffer[relative_y+i][relative_x] = ANSI::RED + "#" + ANSI::DEFAULT_TEXT_COLOR
29
+ end
30
+ buffer
31
+ end
32
+
33
+ def bounding_box
34
+ { x: @x, y: @y, width: @width, height: @height }
35
+ end
36
+
37
+ def activate(player_x:)
38
+ @waiting = false if player_x > DEADLINE_START_X
39
+ end
40
+
41
+ private
42
+
43
+ def initialize(map_height)
44
+ @x = 2
45
+ @y = 1
46
+ @width = 1
47
+ @height = map_height
48
+ @last_update = Time.now
49
+ @waiting = true
50
+ end
51
+
52
+ def active?
53
+ !@waiting
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,88 @@
1
+ module RoadToRubykaigi
2
+ module Sprite
3
+ class Effects
4
+ def update
5
+ @effects.reject!(&:expired?)
6
+ end
7
+
8
+ def heart(x, y)
9
+ @effects << HeartEffect.new(x, y)
10
+ end
11
+
12
+ def note(x, y)
13
+ @effects << NoteEffect.new(x, y)
14
+ end
15
+
16
+ def lightning(x, y)
17
+ @effects << LightningEffect.new(x, y)
18
+ end
19
+
20
+ def build_buffer(offset_x:)
21
+ buffer = Array.new(Map::VIEWPORT_HEIGHT) { Array.new(Map::VIEWPORT_WIDTH) { "" } }
22
+ @effects.each do |effect|
23
+ bounding_box = effect.bounding_box
24
+ relative_x = bounding_box[:x] - offset_x - 1
25
+ relative_y = bounding_box[:y] - 1
26
+ next if relative_x < 1
27
+ buffer[relative_y][relative_x] = effect.character
28
+ end
29
+ buffer
30
+ end
31
+
32
+ def to_a
33
+ @effects.to_a
34
+ end
35
+
36
+ private
37
+
38
+ def initialize
39
+ @effects = []
40
+ end
41
+ end
42
+
43
+ class Effect < Sprite
44
+ def update
45
+ elapsed = Time.now - @start_time
46
+ @y = (@y - elapsed).to_i
47
+ end
48
+
49
+ def character
50
+ self.class::SYMBOL
51
+ end
52
+
53
+ def expired?
54
+ (Time.now - @start_time) >= self.class::DURATION
55
+ end
56
+
57
+ def bounding_box
58
+ { x: @x, y: @y, width: 1, height: 1 }
59
+ end
60
+
61
+ private
62
+
63
+ def initialize(x, y)
64
+ @x = x
65
+ @y = y
66
+ @start_time = Time.now
67
+ end
68
+ end
69
+
70
+ class HeartEffect < Effect
71
+ DURATION = 1.0
72
+ SYMBOL = ANSI::RED + "♥" + ANSI::DEFAULT_TEXT_COLOR
73
+ end
74
+
75
+ class NoteEffect < Effect
76
+ DURATION = 1.0
77
+ SYMBOL = ANSI::BLUE + "♪" + ANSI::DEFAULT_TEXT_COLOR
78
+ end
79
+
80
+ class LightningEffect < Effect
81
+ DURATION = 0.3
82
+ SYMBOL = ANSI::YELLOW + "⚡︎" + ANSI::DEFAULT_TEXT_COLOR
83
+
84
+ def update
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,178 @@
1
+ require "forwardable"
2
+
3
+ module RoadToRubykaigi
4
+ module Sprite
5
+ class Enemies
6
+ extend Forwardable
7
+ def_delegators :@enemies, :to_a, :find, :delete, :each
8
+ ENEMIES_DATA = {
9
+ FixedPatrol: [
10
+ { x: 55, y: 6, left_bound: 0, right_bound: 0, speed: 0, character: :ladybug },
11
+ { x: 125, y: 8, left_bound: 0, right_bound: 0, speed: 0, character: :ladybug },
12
+ { x: 293, y: 23, left_bound: 0, right_bound: 0, speed: 0, character: :spider },
13
+ ],
14
+ HorizontalPatrol: [
15
+ { x: 123, y: 26, left_bound: 114, right_bound: 123, speed: 1.5, character: :bee },
16
+ { x: 171, y: 26, left_bound: 162, right_bound: 171, speed: 1.5, character: :bee },
17
+ { x: 278, y: 15, left_bound: 270, right_bound: 278, speed: 1.5, character: :bug },
18
+ { x: 291, y: 15, left_bound: 283, right_bound: 291, speed: 1.5, character: :bug },
19
+ { x: 302, y: 15, left_bound: 297, right_bound: 302, speed: 1.5, character: :bug },
20
+ ],
21
+ ScreenEntryPatrol: [
22
+ { x: 63, y: 27, left_bound: 0, right_bound: 63, speed: 4.0, character: :bug },
23
+ { x: 76, y: 27, left_bound: 0, right_bound: 76, speed: 4.0, character: :bug },
24
+ { x: 87, y: 27, left_bound: 0, right_bound: 76, speed: 4.0, character: :bug },
25
+ { x: 221, y: 23, left_bound: 0, right_bound: 151, speed: 6.0, character: :bee },
26
+ { x: 240, y: 19, left_bound: 0, right_bound: 170, speed: 6.0, character: :bee },
27
+ { x: 256, y: 16, left_bound: 0, right_bound: 186, speed: 6.0, character: :bee },
28
+ ],
29
+ }
30
+
31
+ def build_buffer(offset_x:)
32
+ buffer = Array.new(Map::VIEWPORT_HEIGHT) { Array.new(Map::VIEWPORT_WIDTH) { "" } }
33
+ @enemies.each do |enemy|
34
+ bounding_box = enemy.bounding_box
35
+ relative_x = bounding_box[:x] - offset_x - 1
36
+ relative_y = bounding_box[:y] - 1
37
+ next if relative_x < 1
38
+ enemy.characters.each_with_index do |character, j|
39
+ next if relative_x + j >= Map::VIEWPORT_WIDTH - 1
40
+ buffer[relative_y][relative_x+j] = character
41
+ end
42
+ end
43
+ buffer
44
+ end
45
+
46
+ def update
47
+ if activated?
48
+ @enemies.each(&:update)
49
+ else
50
+ @enemies.each(&:reset_last_update_time)
51
+ end
52
+ end
53
+
54
+ def activate
55
+ @waiting = false
56
+ end
57
+
58
+ private
59
+
60
+ def initialize
61
+ @enemies = ENEMIES_DATA.map do |key, enemies|
62
+ strategy = RoadToRubykaigi::Sprite.const_get("#{key}Strategy")
63
+ enemies.map do |enemy|
64
+ Enemy.new(
65
+ enemy[:x],
66
+ enemy[:y],
67
+ enemy[:character],
68
+ strategy.new(
69
+ left_bound: enemy[:left_bound],
70
+ right_bound: enemy[:right_bound],
71
+ speed: enemy[:speed],
72
+ ),
73
+ )
74
+ end
75
+ end.flatten
76
+ @waiting = true
77
+ end
78
+
79
+ def activated?
80
+ !@waiting
81
+ end
82
+ end
83
+
84
+ class Enemy < Sprite
85
+ CHARACTER = {
86
+ bee: "🐝",
87
+ bug: "🐛",
88
+ ladybug: "🐞",
89
+ spider: "🕷️",
90
+ }
91
+ RIGHT = 1
92
+ LEFT = -1
93
+ attr_accessor :x
94
+ attr_reader :y, :direction
95
+
96
+ def bounding_box
97
+ { x: @x, y: @y, width: width, height: height }
98
+ end
99
+
100
+ def characters
101
+ super { [CHARACTER[@character]] }
102
+ end
103
+
104
+ def update
105
+ elapsed_time = Time.now - @last_update_time
106
+ @last_update_time = Time.now
107
+ @strategy.update(self, elapsed_time)
108
+ end
109
+
110
+ def reset_last_update_time
111
+ @last_update_time = Time.now
112
+ end
113
+
114
+ def width
115
+ 2
116
+ end
117
+
118
+ def height
119
+ 1
120
+ end
121
+
122
+ def reverse_direction
123
+ @direction *= -1
124
+ end
125
+
126
+ def activate_with_offset(offset_x)
127
+ if !@active && @x <= (offset_x + Map::VIEWPORT_WIDTH)
128
+ @active = true
129
+ end
130
+ end
131
+
132
+ def active?
133
+ @active
134
+ end
135
+
136
+ private
137
+
138
+ def initialize(x, y, character, strategy)
139
+ @x = x
140
+ @y = y
141
+ @character = character
142
+ @direction = LEFT
143
+ @strategy = strategy
144
+ @active = !strategy.is_a?(ScreenEntryPatrolStrategy)
145
+ @last_update_time = Time.now
146
+ end
147
+ end
148
+
149
+ class PatrolStrategy
150
+ def initialize(left_bound:, right_bound:, speed:)
151
+ @left_bound = left_bound
152
+ @right_bound = right_bound
153
+ @speed = speed
154
+ end
155
+
156
+ def update(enemy, elapsed_time)
157
+ end
158
+ end
159
+
160
+ class FixedPatrolStrategy < PatrolStrategy
161
+ end
162
+
163
+ class HorizontalPatrolStrategy < PatrolStrategy
164
+ def update(enemy, elapsed_time)
165
+ enemy.x += @speed * elapsed_time * enemy.direction
166
+ enemy.x = enemy.x.clamp(@left_bound, @right_bound)
167
+ enemy.reverse_direction if enemy.x == @left_bound || enemy.x == @right_bound
168
+ end
169
+ end
170
+
171
+ class ScreenEntryPatrolStrategy < PatrolStrategy
172
+ def update(enemy, elapsed_time)
173
+ return unless enemy.active?
174
+ enemy.x += @speed * elapsed_time * enemy.direction
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,178 @@
1
+ module RoadToRubykaigi
2
+ module Sprite
3
+ class Player
4
+ attr_reader :x, :y
5
+ attr_accessor :vy
6
+
7
+ WALK_ACCEL = 15.0
8
+ WALK_MAX_SPEED = 20.0
9
+ WALK_FRICTION = 1.0
10
+
11
+ BASE_Y = 26
12
+ JUMP_INITIAL_VELOCITY = -40.0
13
+ JUMP_GRAVITY = 80.0
14
+
15
+ KEY_INPUT_THRESHOLD = 0.5
16
+ ANIMETION_FRAME_SECOND = 0.5
17
+ STUN_SECOND = 2.0
18
+
19
+ RIGHT = 1
20
+ LEFT = -1
21
+
22
+ def right
23
+ move(RIGHT)
24
+ end
25
+
26
+ def left
27
+ move(LEFT)
28
+ end
29
+
30
+ def jump
31
+ unless jumping?
32
+ @jumping = true
33
+ @vy = JUMP_INITIAL_VELOCITY
34
+ end
35
+ end
36
+
37
+ def land(land_y)
38
+ @y = land_y - height
39
+ @vy = 0
40
+ @jumping = false
41
+ # Not change stompable since stompable will not change from true
42
+ end
43
+
44
+ def fall
45
+ unless @jumping
46
+ @jumping = true
47
+ @vy = 0
48
+ @stompable = true
49
+ end
50
+ end
51
+
52
+ def stun
53
+ @stunned_until = Time.now + STUN_SECOND
54
+ end
55
+
56
+ def stunned?
57
+ Time.now < @stunned_until
58
+ end
59
+
60
+ def stompable?
61
+ @stompable
62
+ end
63
+
64
+ def update
65
+ return @coordinate_updated_time = Time.now if stunned?
66
+
67
+ now = Time.now
68
+ if (now - @animetion_updated_time) >= ANIMETION_FRAME_SECOND
69
+ @walking_frame = (@walking_frame + 1) % current_character.size
70
+ @animetion_updated_time = now
71
+ end
72
+
73
+ elapsed_time = now - @coordinate_updated_time
74
+ @coordinate_updated_time = now
75
+ if jumping?
76
+ @vy += JUMP_GRAVITY * elapsed_time
77
+ @y += @vy * elapsed_time
78
+ @stompable = @vy.positive?
79
+ if @y >= BASE_Y
80
+ @y = BASE_Y
81
+ @vy = 0
82
+ @jumping = false
83
+ end
84
+ else
85
+ @stompable = false
86
+ if current_direction == RIGHT
87
+ @vx -= friction * elapsed_time
88
+ @vx = [@vx, 0].max # vx must be positive
89
+ else
90
+ @vx += friction * elapsed_time
91
+ @vx = [@vx, 0].min # vx must be negative
92
+ end
93
+ end
94
+ @x += @vx * elapsed_time
95
+
96
+ @x = @x.round.to_i
97
+ @y = @y.round.to_i
98
+ end
99
+
100
+ def build_buffer(offset_x:)
101
+ buffer = Array.new(Map::VIEWPORT_HEIGHT) { Array.new(Map::VIEWPORT_WIDTH) { "" } }
102
+ relative_x = @x - offset_x - 1
103
+ relative_y = @y - 1
104
+ current_character[@walking_frame].each_with_index do |row, i|
105
+ row.each_with_index do |character, j|
106
+ buffer[relative_y+i][relative_x+j] = character
107
+ end
108
+ end
109
+ buffer
110
+ end
111
+
112
+ def enforce_boundary(map, offset_x:)
113
+ @x, @y = map.clamp_position(
114
+ dx: @vx.round.clamp(-1, 1) * -1,
115
+ dy: @vy.round.clamp(-1, 1) * -1,
116
+ **bounding_box
117
+ )
118
+ end
119
+
120
+ def bounding_box
121
+ { x: @x, y: @y, width: width, height: height }
122
+ end
123
+
124
+ def width
125
+ @width ||= current_character.first.map(&:size).max
126
+ end
127
+
128
+ def height
129
+ @height ||= current_character.first.size
130
+ end
131
+
132
+ private
133
+
134
+ def initialize(x = 10, y = BASE_Y)
135
+ @x = x
136
+ @y = y
137
+ @vx = 0.0
138
+ @vy = 0.0
139
+ @walking_frame = 0
140
+ @coordinate_updated_time = Time.now
141
+ @animetion_updated_time = Time.now
142
+ @key_input_time = Time.now
143
+ @jumping = false
144
+ @stompable = false
145
+ @stunned_until = Time.now
146
+ end
147
+
148
+ def move(dx)
149
+ unless current_direction == dx
150
+ @vx = 0
151
+ end
152
+ @vx += WALK_ACCEL * dx
153
+ @vx = @vx.clamp(-WALK_MAX_SPEED, WALK_MAX_SPEED)
154
+ end
155
+
156
+ def current_character
157
+ status = stunned? ? :stunned : :normal
158
+ Graphics::Player.character(status, current_direction)
159
+ end
160
+
161
+ def jumping?
162
+ @jumping
163
+ end
164
+
165
+ def friction
166
+ if (Time.now - @key_input_time) >= KEY_INPUT_THRESHOLD
167
+ WALK_MAX_SPEED
168
+ else
169
+ WALK_FRICTION
170
+ end
171
+ end
172
+
173
+ def current_direction
174
+ (@vx >= 0) ? RIGHT : LEFT
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,22 @@
1
+ module RoadToRubykaigi
2
+ module Sprite
3
+ class Sprite
4
+ def characters
5
+ yield.map do |character|
6
+ fullwidth?(character) ? [character, ANSI::NULL] : character
7
+ end.flatten
8
+ end
9
+
10
+ private
11
+
12
+ def fullwidth?(character)
13
+ code = character.ord
14
+ (0x1F300..0x1F5FF).cover?(code) ||
15
+ (0x1F600..0x1F64F).cover?(code) ||
16
+ (0x1F680..0x1F6FF).cover?(code) ||
17
+ (0x1F700..0x1F77F).cover?(code) ||
18
+ code == 0x2615
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RoadToRubykaigi
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,46 @@
1
+ require_relative "road_to_rubykaigi/version"
2
+ require_relative "road_to_rubykaigi/ansi"
3
+ require_relative "road_to_rubykaigi/fireworks"
4
+ require_relative "road_to_rubykaigi/game"
5
+ require_relative "road_to_rubykaigi/map"
6
+ require_relative "road_to_rubykaigi/opening_screen"
7
+ require_relative "road_to_rubykaigi/score_board"
8
+ require_relative "road_to_rubykaigi/manager/collision_manager"
9
+ require_relative "road_to_rubykaigi/manager/drawing_manager"
10
+ require_relative "road_to_rubykaigi/manager/game_manager"
11
+ require_relative "road_to_rubykaigi/manager/update_manager"
12
+ require_relative "road_to_rubykaigi/sprite/sprite"
13
+ require_relative "road_to_rubykaigi/sprite/attack"
14
+ require_relative "road_to_rubykaigi/sprite/bonus"
15
+ require_relative "road_to_rubykaigi/sprite/deadline"
16
+ require_relative "road_to_rubykaigi/sprite/effect"
17
+ require_relative "road_to_rubykaigi/sprite/enemy"
18
+ require_relative "road_to_rubykaigi/sprite/player"
19
+ require_relative "road_to_rubykaigi/graphics/fireworks"
20
+ require_relative "road_to_rubykaigi/graphics/mask"
21
+ require_relative "road_to_rubykaigi/graphics/map"
22
+ require_relative "road_to_rubykaigi/graphics/player"
23
+ require "io/console"
24
+
25
+ module RoadToRubykaigi
26
+ class Error < StandardError; end
27
+ END_POSITION = Map.new.height + 2
28
+
29
+ def self.start
30
+ ANSI.cursor_off
31
+ at_exit do
32
+ print "\e[#{END_POSITION};1H"
33
+ ANSI.cursor_on
34
+ end
35
+
36
+ OpeningScreen.new.display && Game.new.run
37
+ end
38
+
39
+ def self.debug
40
+ @debug ||= []
41
+ end
42
+
43
+ def self.debug_add(string)
44
+ @debug << "\e[#{END_POSITION+@debug.size};1H" + string
45
+ end
46
+ end
@@ -0,0 +1,4 @@
1
+ module RoadToRubykaigi
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: road_to_rubykaigi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - makicamel
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2025-02-27 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Road to RubyKaigi is a Ruby gem that delivers a nostalgic, text-based
13
+ action game experience. Dodge obstacles, overcome bugs, and beat the deadline to
14
+ reach RubyKaigi. All in your terminal.
15
+ email:
16
+ - unright@gmail.com
17
+ executables:
18
+ - road_to_rubykaigi
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".rspec"
23
+ - ".standard.yml"
24
+ - CHANGELOG.md
25
+ - CODE_OF_CONDUCT.md
26
+ - LICENSE.txt
27
+ - README.md
28
+ - Rakefile
29
+ - bin/road_to_rubykaigi
30
+ - lib/road_to_rubykaigi.rb
31
+ - lib/road_to_rubykaigi/ansi.rb
32
+ - lib/road_to_rubykaigi/fireworks.rb
33
+ - lib/road_to_rubykaigi/game.rb
34
+ - lib/road_to_rubykaigi/graphics/fireworks.rb
35
+ - lib/road_to_rubykaigi/graphics/fireworks.txt
36
+ - lib/road_to_rubykaigi/graphics/map.rb
37
+ - lib/road_to_rubykaigi/graphics/map.txt
38
+ - lib/road_to_rubykaigi/graphics/mask.rb
39
+ - lib/road_to_rubykaigi/graphics/mask.txt
40
+ - lib/road_to_rubykaigi/graphics/player.rb
41
+ - lib/road_to_rubykaigi/manager/collision_manager.rb
42
+ - lib/road_to_rubykaigi/manager/drawing_manager.rb
43
+ - lib/road_to_rubykaigi/manager/game_manager.rb
44
+ - lib/road_to_rubykaigi/manager/update_manager.rb
45
+ - lib/road_to_rubykaigi/map.rb
46
+ - lib/road_to_rubykaigi/opening_screen.rb
47
+ - lib/road_to_rubykaigi/score_board.rb
48
+ - lib/road_to_rubykaigi/sprite/attack.rb
49
+ - lib/road_to_rubykaigi/sprite/bonus.rb
50
+ - lib/road_to_rubykaigi/sprite/deadline.rb
51
+ - lib/road_to_rubykaigi/sprite/effect.rb
52
+ - lib/road_to_rubykaigi/sprite/enemy.rb
53
+ - lib/road_to_rubykaigi/sprite/player.rb
54
+ - lib/road_to_rubykaigi/sprite/sprite.rb
55
+ - lib/road_to_rubykaigi/version.rb
56
+ - sig/road_to_rubykaigi.rbs
57
+ homepage: https://github.com/makicamel/road_to_rubykaigi
58
+ licenses:
59
+ - MIT
60
+ metadata:
61
+ homepage_uri: https://github.com/makicamel/road_to_rubykaigi
62
+ source_code_uri: https://github.com/makicamel/road_to_rubykaigi
63
+ changelog_uri: https://github.com/makicamel/road_to_rubykaigi/blob/main/CHANGELOG.md
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 3.4.0
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubygems_version: 3.6.2
79
+ specification_version: 4
80
+ summary: A retro ASCII action game where Rubyist overcomes a looming deadline and
81
+ bugs on your way to RubyKaigi
82
+ test_files: []