carpet_diem 0.0.1
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 +7 -0
- data/bin/carpet_diem +10 -0
- data/carpet_diem.gemspec +20 -0
- data/lib/carpet.rb +91 -0
- data/lib/endboss.rb +15 -0
- data/lib/lamp_with_genie.rb +122 -0
- data/lib/media/background.jpg +0 -0
- data/lib/media/carpet.png +0 -0
- data/lib/media/carpet_flipped.png +0 -0
- data/lib/media/endboss.png +0 -0
- data/lib/media/evil_genie.m4a +0 -0
- data/lib/media/evil_genie.png +0 -0
- data/lib/media/evil_genie_flipped.png +0 -0
- data/lib/media/good_genie.m4a +0 -0
- data/lib/media/good_genie.png +0 -0
- data/lib/media/good_genie_flipped.png +0 -0
- data/lib/media/lamp.m4a +0 -0
- data/lib/media/lamp.png +0 -0
- data/lib/media/lamp_flipped.png +0 -0
- data/lib/media/lamp_louder.m4a +0 -0
- data/lib/positionable.rb +23 -0
- data/lib/window.rb +85 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 95019d95a089eb8a906b5ed44c1124a65c95026d
|
4
|
+
data.tar.gz: d8bebff9b9676844f4b56aa84181f6af5bc0e696
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a40ef0bc567fb74965bb67f4c710787a3510b9569da9f7fafec849c2210eea79f04f4d8ce218338c1dab62117df7a8a97546cf59842f31ca52e6df37b409da27
|
7
|
+
data.tar.gz: 5420b642c8ed64ee1ab88aa94895c27607203c7e73689cb8b69fd1527f15d06a9f78cd0ddbec78dc80cd06e1015216ae188f1cc85f8b1a721d07d4236385fe4f
|
data/bin/carpet_diem
ADDED
data/carpet_diem.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'carpet_diem'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.licenses = ['MIT']
|
5
|
+
s.summary = "A Gosu game about a flying carpet"
|
6
|
+
s.description = "Be a flying carpet that hovers throught the clouds. On your way up you will encounter magic lamps. Rub them to see if a good or an evil genie is hidden inside, the one adding points to your score, the other being your worst enenmy!"
|
7
|
+
s.authors = ['Brigitte Markmann', 'Kathi Zwick']
|
8
|
+
s.email = ['bri.ma@gmx.de', 'ka.zwick@gmail.com']
|
9
|
+
s.files = %w(carpet_diem.gemspec)
|
10
|
+
s.files += Dir.glob('lib/**/*') + Dir.glob('bin/**/*.rb')
|
11
|
+
s.homepage = 'https://github.com/RapidRailsGirls/carpet-diem'
|
12
|
+
s.executables = %w[carpet_diem]
|
13
|
+
s.add_runtime_dependency 'gosu', '0.7.50'
|
14
|
+
s.add_runtime_dependency 'texplay'
|
15
|
+
s.add_runtime_dependency 'chingu'
|
16
|
+
|
17
|
+
s.add_development_dependency 'rspec'
|
18
|
+
s.add_development_dependency 'pry'
|
19
|
+
|
20
|
+
end
|
data/lib/carpet.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'texplay'
|
2
|
+
require 'chingu'
|
3
|
+
require_relative 'positionable'
|
4
|
+
|
5
|
+
class Carpet
|
6
|
+
include Positionable
|
7
|
+
CARPET_SPEED = 5
|
8
|
+
attr_reader :carpet_image
|
9
|
+
alias :image :carpet_image
|
10
|
+
undef :carpet_image
|
11
|
+
|
12
|
+
def initialize(window, carpet_image_file = 'lib/media/carpet.png', carpet_image_flipped_file = 'lib/media/carpet_flipped.png')
|
13
|
+
@carpet_image = @carpet_image_right = Gosu::Image.new(window, carpet_image_file)
|
14
|
+
@carpet_image_left = Gosu::Image.new(window, carpet_image_flipped_file)
|
15
|
+
@window = window
|
16
|
+
@x = window.width/2.0 - @carpet_image.width/2.0
|
17
|
+
@x += 1 if window.width.odd? && @carpet_image.width.odd?
|
18
|
+
@y = window.height/(18/13.0) - @carpet_image.height/2.0
|
19
|
+
end
|
20
|
+
|
21
|
+
def draw(counter, score)
|
22
|
+
if score > 3
|
23
|
+
@carpet_image.draw(@x, @y, 4)
|
24
|
+
elsif score > 0
|
25
|
+
@z = counter % 20 == 1 ? 1 : 4
|
26
|
+
@carpet_image.draw(@x, @y, @z)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def move_left
|
31
|
+
@x = [@x - CARPET_SPEED, 0 - @carpet_image.height / 4].max
|
32
|
+
@carpet_image = @carpet_image_left
|
33
|
+
end
|
34
|
+
|
35
|
+
def move_right
|
36
|
+
@x = [@x + CARPET_SPEED, @window.width - @carpet_image.height / 2].min
|
37
|
+
@carpet_image = @carpet_image_right
|
38
|
+
end
|
39
|
+
|
40
|
+
def collides_with?(object)
|
41
|
+
images_overlap?(object) && !opaque_overlapping_pixels(object).empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
def images_overlap?(object)
|
45
|
+
object.bottom > top &&
|
46
|
+
object.top < bottom &&
|
47
|
+
object.right > left &&
|
48
|
+
object.left < right
|
49
|
+
end
|
50
|
+
|
51
|
+
def opaque_overlapping_pixels(object)
|
52
|
+
overlapping_pixels(object).select do |x,y|
|
53
|
+
!@carpet_image.transparent_pixel?(x,y) && !object.image.transparent_pixel?(x,y)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def overlapping_pixels(object)
|
58
|
+
if left < object.left
|
59
|
+
box_left = object.left
|
60
|
+
if right < object.right
|
61
|
+
box_width = right - object.left
|
62
|
+
else
|
63
|
+
box_width = object.width
|
64
|
+
end
|
65
|
+
else
|
66
|
+
box_width = object.right - left
|
67
|
+
box_left = left
|
68
|
+
end
|
69
|
+
if top < object.top
|
70
|
+
box_top = object.top
|
71
|
+
if bottom < object.bottom
|
72
|
+
box_height = bottom - object.top
|
73
|
+
else
|
74
|
+
box_height = object.height
|
75
|
+
end
|
76
|
+
else
|
77
|
+
box_top = top
|
78
|
+
box_height = object.bottom - top
|
79
|
+
end
|
80
|
+
pixels(box_left, box_top, box_width, box_height)
|
81
|
+
end
|
82
|
+
|
83
|
+
def pixels(offset_x, offset_y, width, height)
|
84
|
+
height.round.times.flat_map do |y|
|
85
|
+
width.round.times.map do |x|
|
86
|
+
[(x + offset_x).to_i, (y + offset_y).to_i]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
data/lib/endboss.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class Endboss
|
2
|
+
|
3
|
+
def initialize(window)
|
4
|
+
@image = Gosu::Image.new(window, 'lib/media/endboss.png')
|
5
|
+
@x = window.width/2 - @image.width/2
|
6
|
+
@y = window.height
|
7
|
+
@scale = 0.0
|
8
|
+
end
|
9
|
+
|
10
|
+
def draw
|
11
|
+
@scale += 0.03 if @scale <= 1
|
12
|
+
@image.draw(@x, @y - 750 * @scale, 3, @scale, @scale)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require_relative 'positionable'
|
2
|
+
|
3
|
+
class LampWithGenie
|
4
|
+
attr_reader :lamp, :genie
|
5
|
+
|
6
|
+
class Lamp
|
7
|
+
include Positionable
|
8
|
+
attr_reader :image
|
9
|
+
|
10
|
+
def initialize(window, flipped)
|
11
|
+
if flipped
|
12
|
+
@image = Gosu::Image.new(window, 'lib/media/lamp_flipped.png')
|
13
|
+
else
|
14
|
+
@image = Gosu::Image.new(window, 'lib/media/lamp.png')
|
15
|
+
end
|
16
|
+
@sound = Gosu::Sample.new(window, 'lib/media/lamp.m4a')
|
17
|
+
@rubbed = false
|
18
|
+
@y = -@image.height
|
19
|
+
end
|
20
|
+
|
21
|
+
def draw
|
22
|
+
@image.draw(@x, @y, 2)
|
23
|
+
end
|
24
|
+
|
25
|
+
def rub!
|
26
|
+
return @rubbed if @rubbed
|
27
|
+
@rubbed = true
|
28
|
+
@sound.play
|
29
|
+
end
|
30
|
+
|
31
|
+
def rubbed?
|
32
|
+
@rubbed
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
class Genie
|
38
|
+
include Positionable
|
39
|
+
attr_reader :image
|
40
|
+
PADDING = 15
|
41
|
+
def initialize(window, flipped, lamp)
|
42
|
+
prefix = good? ? 'good' : 'evil'
|
43
|
+
suffix = '_flipped' if flipped
|
44
|
+
@image = Gosu::Image.new(window, "lib/media/#{prefix}_genie#{suffix}.png")
|
45
|
+
@sound = Gosu::Sample.new(window, "lib/media/#{prefix}_genie.m4a")
|
46
|
+
@lamp = lamp
|
47
|
+
@y = -@image.height
|
48
|
+
@flipped = flipped
|
49
|
+
@captured = false
|
50
|
+
@scale = 0.0
|
51
|
+
end
|
52
|
+
|
53
|
+
def draw
|
54
|
+
@image.draw(@x, @y, 3, @scale, @scale)
|
55
|
+
end
|
56
|
+
|
57
|
+
def update
|
58
|
+
@scale += 0.03 if @scale <= 1
|
59
|
+
if @flipped
|
60
|
+
@x = @lamp.x + width - PADDING
|
61
|
+
@y = @lamp.y - height * @scale
|
62
|
+
else
|
63
|
+
@x = (@lamp.x - (width + PADDING) * @scale)
|
64
|
+
@y = (@lamp.y - height * @scale)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def capture!
|
69
|
+
return @captured if @captured
|
70
|
+
@captured = true
|
71
|
+
@sound.play
|
72
|
+
end
|
73
|
+
|
74
|
+
def captured?
|
75
|
+
@captured
|
76
|
+
end
|
77
|
+
|
78
|
+
def good?
|
79
|
+
if defined? @good
|
80
|
+
return @good
|
81
|
+
else
|
82
|
+
@good = rand(2) == 0
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def evil?
|
87
|
+
!good?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def initialize(window)
|
92
|
+
flipped = rand(2) == 0
|
93
|
+
@lamp = Lamp.new(window, flipped)
|
94
|
+
@genie = Genie.new(window, flipped, @lamp)
|
95
|
+
x = if flipped
|
96
|
+
rand(0..(window.width - @genie.width - @lamp.width))
|
97
|
+
else
|
98
|
+
rand(@genie.width..(window.width - @lamp.width))
|
99
|
+
end
|
100
|
+
@lamp.x = x
|
101
|
+
@genie.x = flipped ? x + @lamp.width : x
|
102
|
+
@window = window
|
103
|
+
end
|
104
|
+
|
105
|
+
def scroll(speed)
|
106
|
+
@lamp.y += speed
|
107
|
+
@genie.y += speed
|
108
|
+
end
|
109
|
+
|
110
|
+
def draw
|
111
|
+
@lamp.draw
|
112
|
+
@genie.update && @genie.draw if @lamp.rubbed?
|
113
|
+
end
|
114
|
+
|
115
|
+
def off_screen?
|
116
|
+
if @lamp.rubbed?
|
117
|
+
@genie.y > @window.height
|
118
|
+
else
|
119
|
+
@lamp.y > @window.height
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/media/lamp.m4a
ADDED
Binary file
|
data/lib/media/lamp.png
ADDED
Binary file
|
Binary file
|
Binary file
|
data/lib/positionable.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Positionable
|
4
|
+
attr_accessor :x, :y
|
5
|
+
alias :top :y
|
6
|
+
alias :left :x
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :image, :height, :width
|
9
|
+
|
10
|
+
def bottom
|
11
|
+
y + height
|
12
|
+
end
|
13
|
+
|
14
|
+
def right
|
15
|
+
x + width
|
16
|
+
end
|
17
|
+
|
18
|
+
def image
|
19
|
+
raise NotImplementedError.new("Positionable objects must define a primary image")
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
data/lib/window.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
class Window < Gosu::Window
|
2
|
+
NUM_TILES = 6
|
3
|
+
TILE_COLS = 2
|
4
|
+
VELOCITY = 3
|
5
|
+
BLACK = Gosu::Color.argb(0xff000000)
|
6
|
+
|
7
|
+
module YAccessible
|
8
|
+
attr_writer :y
|
9
|
+
def y
|
10
|
+
@y.to_i
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
super(1200, 800, false)
|
16
|
+
@carpet = Carpet.new(self)
|
17
|
+
@backgrounds = NUM_TILES.times.collect do
|
18
|
+
Gosu::Image.new(self, 'lib/media/background.jpg', true).extend(YAccessible)
|
19
|
+
end
|
20
|
+
@font = Gosu::Font.new(self, Gosu::default_font_name, 60)
|
21
|
+
@yplus = -@backgrounds.last.height
|
22
|
+
@genielamps = []
|
23
|
+
@counter = 0
|
24
|
+
@score = 5
|
25
|
+
end
|
26
|
+
|
27
|
+
def draw
|
28
|
+
@carpet.draw(@counter, @score)
|
29
|
+
@font.draw("Score: #{@score}", 10, 10, 5, 1, 1, color = BLACK)
|
30
|
+
@backgrounds.each_with_index do | bg, index |
|
31
|
+
bg.y = (index / TILE_COLS) * bg.height + @yplus
|
32
|
+
bg.draw((index % TILE_COLS) * bg.width, bg.y, 1)
|
33
|
+
end
|
34
|
+
@genielamps.each {|genielamp| genielamp.draw}
|
35
|
+
@endboss.draw if @endboss
|
36
|
+
end
|
37
|
+
|
38
|
+
def update
|
39
|
+
@counter += 1
|
40
|
+
if button_down? Gosu::KbLeft
|
41
|
+
@carpet.move_left
|
42
|
+
end
|
43
|
+
if button_down? Gosu::KbRight
|
44
|
+
@carpet.move_right
|
45
|
+
end
|
46
|
+
scroll_background
|
47
|
+
unless @score == 0
|
48
|
+
if @counter % 120 == 1
|
49
|
+
@genielamps.push LampWithGenie.new(self)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
@endboss = Endboss.new(self) if @endboss.nil? && @genielamps.empty?
|
53
|
+
end
|
54
|
+
scroll_lamps
|
55
|
+
@genielamps.each do |genielamp|
|
56
|
+
if @score != 0 && !genielamp.lamp.rubbed? && @carpet.collides_with?(genielamp.lamp)
|
57
|
+
genielamp.lamp.rub!
|
58
|
+
end
|
59
|
+
if genielamp.lamp.rubbed? && !genielamp.genie.captured? && @carpet.collides_with?(genielamp.genie)
|
60
|
+
genielamp.genie.capture!
|
61
|
+
if genielamp.genie.good?
|
62
|
+
@score += 1
|
63
|
+
else
|
64
|
+
@score -= 1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@genielamps.reject!(&:off_screen?)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def scroll_background
|
72
|
+
bg = @backgrounds.last
|
73
|
+
if bg.y >= ((NUM_TILES / TILE_COLS) - 1) * bg.height - VELOCITY
|
74
|
+
@yplus = -bg.height
|
75
|
+
else
|
76
|
+
@yplus += VELOCITY - 1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def scroll_lamps
|
81
|
+
@genielamps.each do |genielamp|
|
82
|
+
@score == 0 ? genielamp.scroll(VELOCITY * 6) : genielamp.scroll(VELOCITY)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: carpet_diem
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brigitte Markmann
|
8
|
+
- Kathi Zwick
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-09-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: gosu
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 0.7.50
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.7.50
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: texplay
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: chingu
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: pry
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
description: Be a flying carpet that hovers throught the clouds. On your way up you
|
85
|
+
will encounter magic lamps. Rub them to see if a good or an evil genie is hidden
|
86
|
+
inside, the one adding points to your score, the other being your worst enenmy!
|
87
|
+
email:
|
88
|
+
- bri.ma@gmx.de
|
89
|
+
- ka.zwick@gmail.com
|
90
|
+
executables:
|
91
|
+
- carpet_diem
|
92
|
+
extensions: []
|
93
|
+
extra_rdoc_files: []
|
94
|
+
files:
|
95
|
+
- carpet_diem.gemspec
|
96
|
+
- lib/carpet.rb
|
97
|
+
- lib/endboss.rb
|
98
|
+
- lib/lamp_with_genie.rb
|
99
|
+
- lib/media/background.jpg
|
100
|
+
- lib/media/carpet.png
|
101
|
+
- lib/media/carpet_flipped.png
|
102
|
+
- lib/media/endboss.png
|
103
|
+
- lib/media/evil_genie.m4a
|
104
|
+
- lib/media/evil_genie.png
|
105
|
+
- lib/media/evil_genie_flipped.png
|
106
|
+
- lib/media/good_genie.m4a
|
107
|
+
- lib/media/good_genie.png
|
108
|
+
- lib/media/good_genie_flipped.png
|
109
|
+
- lib/media/lamp.m4a
|
110
|
+
- lib/media/lamp.png
|
111
|
+
- lib/media/lamp_flipped.png
|
112
|
+
- lib/media/lamp_louder.m4a
|
113
|
+
- lib/positionable.rb
|
114
|
+
- lib/window.rb
|
115
|
+
- bin/carpet_diem
|
116
|
+
homepage: https://github.com/RapidRailsGirls/carpet-diem
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.0.14
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: A Gosu game about a flying carpet
|
140
|
+
test_files: []
|