yeah 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +9 -0
- data/README.md +8 -95
- data/demo/happy_rectangle.rb +44 -0
- data/lib/yeah/color.rb +22 -0
- data/lib/yeah/desktop.rb +34 -0
- data/lib/yeah/entity.rb +7 -3
- data/lib/yeah/game.rb +20 -1
- data/lib/yeah/map.rb +7 -0
- data/lib/yeah/rectangle.rb +14 -0
- data/lib/yeah/surface.rb +59 -0
- data/lib/yeah.rb +5 -4
- data/spec/color_spec.rb +56 -0
- data/spec/desktop_spec.rb +123 -0
- data/spec/entity_spec.rb +32 -10
- data/spec/game_spec.rb +82 -11
- data/spec/map_spec.rb +20 -0
- data/spec/rectangle_spec.rb +71 -0
- data/spec/spec_helper.rb +8 -9
- data/spec/surface_spec.rb +141 -0
- data/spec/vector_spec.rb +6 -6
- data/spec/yeah_spec.rb +4 -4
- data/yeah-0.1.0.gem +0 -0
- metadata +15 -3
- data/yeah-0.0.2.gem +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d01dc8962df50d909356224581bb6c5e566991f5
|
4
|
+
data.tar.gz: 789fa6d989ad7422f05e1b13fd1c2bea2718c128
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0ae07e88b7f9334db886be3caf5497d95528bdeaa69eb82ed24a56885f04426088e1878758732afd0ca33d4d327a640fe30fa38ed156f7ff425591717600ef9
|
7
|
+
data.tar.gz: 82e2bdb785e40f172378eeafc06e6c091ec0769fd06e7e8cd64a1806270526e3d18f811e50720efadd816617f73875d6d9f8d62f1702ceea84c4131dd626959b
|
data/CHANGELOG.md
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -22,10 +22,13 @@ GEM
|
|
22
22
|
rb-kqueue (>= 0.2)
|
23
23
|
lumberjack (1.0.4)
|
24
24
|
method_source (0.8.1)
|
25
|
+
nice-ffi (0.4)
|
26
|
+
ffi (>= 0.5.0)
|
25
27
|
pry (0.9.12.2)
|
26
28
|
coderay (~> 1.0.5)
|
27
29
|
method_source (~> 0.8)
|
28
30
|
slop (~> 3.4)
|
31
|
+
rake (10.1.0)
|
29
32
|
rb-fsevent (0.9.3)
|
30
33
|
rb-inotify (0.9.0)
|
31
34
|
ffi (>= 0.5.0)
|
@@ -39,6 +42,11 @@ GEM
|
|
39
42
|
rspec-expectations (2.14.2)
|
40
43
|
diff-lcs (>= 1.1.3, < 2.0)
|
41
44
|
rspec-mocks (2.14.3)
|
45
|
+
ruby-sdl-ffi (0.4)
|
46
|
+
nice-ffi (>= 0.2)
|
47
|
+
rubygame (2.6.4)
|
48
|
+
rake (>= 0.7.0)
|
49
|
+
ruby-sdl-ffi (>= 0.1.0)
|
42
50
|
slop (3.4.5)
|
43
51
|
thor (0.18.1)
|
44
52
|
|
@@ -49,3 +57,4 @@ DEPENDENCIES
|
|
49
57
|
guard-rspec
|
50
58
|
libnotify
|
51
59
|
rspec
|
60
|
+
rubygame
|
data/README.md
CHANGED
@@ -1,99 +1,12 @@
|
|
1
1
|
Yeah
|
2
2
|
====
|
3
|
-
|
3
|
+
A Ruby video game framework that prioritizes happiness and agility over raw performance.
|
4
4
|
|
5
|
-
|
6
|
-
* Ruby is optimized for developer happiness, and this framework is, too. A happy developer is a productive developer, which translates into more games made and with greater passion.
|
7
|
-
* Ruby has great object-oriented syntax that makes a lot of sense for game constructs.
|
8
|
-
* Ruby's expressiveness reduces development time and makes it easier to experiment.
|
9
|
-
* Ruby supports operator overloading, which is very handy for the linear algebra that is typically abundant in game code.
|
10
|
-
* Code testing is wonderful and ubiquitous in the Ruby community, but the game development community has not embraced it. I hope this framework will help change that.
|
11
|
-
* [Rubygame](https://github.com/rubygame/rubygame/), [Opal](https://github.com/opal/opal), [Ruboto](https://github.com/ruboto/ruboto) and [MobiRuby](https://github.com/mobiruby/mobiruby-ios) would allow games to target the desktop, web, and mobile using the same codebase.
|
12
|
-
* The Ruby and game development communities are both particularly artistic as far as software development communities go.
|
5
|
+
> Premature optimization is the root of all evil. - Donald Knuth
|
13
6
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
```ruby
|
21
|
-
Vector[] #=> Vector[0, 0, 0]
|
22
|
-
v1 = Vector[2, 4, 16] #=> Vector[2, 4, 16]
|
23
|
-
v1[0] #=> 2
|
24
|
-
v1.height #=> 4
|
25
|
-
v1.z #=> 16
|
26
|
-
v2 = Vector[1.5, 2] * 2 #=> Vector[3, 4, 0]
|
27
|
-
v2.norm #=> 5
|
28
|
-
v2.magnitude #=> 5
|
29
|
-
v2.length #=> 5
|
30
|
-
v2.distance #=> 5
|
31
|
-
v2.speed #=> 5
|
32
|
-
```
|
33
|
-
|
34
|
-
### Entity
|
35
|
-
`Entity` instances are objects that behave in the context of a `Game` instance. Each has a `Vector` `position`, and may have a `Vector` `size` and `Visual` `visual`. An `Entity` instance has an `update` method which is continuously called by its `Game` instance. `Entity` is meant to be built upon.
|
36
|
-
|
37
|
-
```ruby
|
38
|
-
class Paddle < Entity
|
39
|
-
def initialize(*args)
|
40
|
-
super(*args) # attach to Game instance and set up position
|
41
|
-
@visual = Image.new("gfx/paddle.png")
|
42
|
-
@speed = 5
|
43
|
-
@velocity = Vector[]
|
44
|
-
end
|
45
|
-
|
46
|
-
def update
|
47
|
-
@velocity.reset # same as `@velocity = Vector[0, 0, 0]`
|
48
|
-
|
49
|
-
if pressing? :left || pressing? :a # if the left arrow key or A key is pressed...
|
50
|
-
@velocity.x -= @speed # increase @velocity to the left
|
51
|
-
end
|
52
|
-
|
53
|
-
if pressing? :right || pressing? :d # if right arrow or D is pressed...
|
54
|
-
@velocity.x += @speed # increase @velocity to the right
|
55
|
-
end
|
56
|
-
|
57
|
-
if touching? Wall # if next to or intersecting a Wall...
|
58
|
-
unintersect Wall # fancy function to unintersect from any Wall
|
59
|
-
@velocity.reset # all of our previous button pressing was for naught
|
60
|
-
end
|
61
|
-
|
62
|
-
@position += @velocity # move (or perhaps not)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
p = Paddle.new(20, 30) #=> Paddle at (20, 30, 0)
|
67
|
-
p.position #=> Vector[20, 30, 0]
|
68
|
-
p.y #=> 30 # method alias!
|
69
|
-
```
|
70
|
-
|
71
|
-
### Map
|
72
|
-
Maps are Ruby hashes that can be parsed from JSON. Upon loading a map into a `Game` instance, the game looks for an `entities` key with a value of a hash with keys that correspond to `Entity` subclass names. Each of these keys have a value that is an array of up to 3 numeric elements or an array of said arrays. These numeric arrays represent coordinates at which to instantiate said `Entity` subclasses. Maps can also contain arbitrary data.
|
73
|
-
|
74
|
-
```ruby
|
75
|
-
level4 = {
|
76
|
-
entities: {
|
77
|
-
Teal: [10, 10], # instantiate Entity subclass Teal at (10, 10, 0)
|
78
|
-
Behemoth: [ # instantiate Behemoth at three different coordinates
|
79
|
-
[50, 10],
|
80
|
-
[100, 10],
|
81
|
-
[150, 10]
|
82
|
-
]
|
83
|
-
},
|
84
|
-
name: "Level 4", # arbitrary data
|
85
|
-
time_limit: 300 # this too
|
86
|
-
}
|
87
|
-
```
|
88
|
-
|
89
|
-
### Game
|
90
|
-
A `Game` instance holds `Entity` instances in an `entities` array and runs their `update` methods on each frame. Assigning a map to `map` replaces `entities` with an array of new instances according to the map.
|
91
|
-
|
92
|
-
```ruby
|
93
|
-
g = Game.new #=> Game
|
94
|
-
g.entities #=> []
|
95
|
-
g.entities << Paddle.new #=> [Paddle]
|
96
|
-
g.entities #=> [Paddle]
|
97
|
-
g.map = level4
|
98
|
-
g.entities #=> [Teal, Behemoth, Behemoth, Behemoth]
|
99
|
-
```
|
7
|
+
Planned features
|
8
|
+
----------------
|
9
|
+
* An opinionated, modular API that makes common tasks easy and everything else possible.
|
10
|
+
* Command line initialization script to help one hit the ground running.
|
11
|
+
* Graphical tools for creating video game resources like sprites and maps.
|
12
|
+
* Multiple target platforms, starting with desktop and web.
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Happy Rectangle
|
4
|
+
# A barebones demo for Yeah.
|
5
|
+
|
6
|
+
lib = File.expand_path('../../lib/', __FILE__)
|
7
|
+
$:.unshift lib unless $:.include?(lib)
|
8
|
+
|
9
|
+
require 'yeah'
|
10
|
+
include Yeah
|
11
|
+
|
12
|
+
class HappyRectangle < Entity
|
13
|
+
def initialize(position)
|
14
|
+
super position
|
15
|
+
@visual = Rectangle.new(Vector[16, 24], Color[255, 255, 0, 255])
|
16
|
+
@updates = 0
|
17
|
+
@radius = 60
|
18
|
+
@center = (Game.new.resolution - @visual.size) / 2
|
19
|
+
end
|
20
|
+
|
21
|
+
def update
|
22
|
+
@updates += 1
|
23
|
+
@position.x = @center.x + (Math.cos(@updates) * @radius).floor
|
24
|
+
@position.y = @center.y + (Math.sin(@updates) * @radius).floor
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class HappyRectangleGame < Game
|
29
|
+
def initialize
|
30
|
+
super
|
31
|
+
@updates = 0
|
32
|
+
@entities << HappyRectangle.new(resolution/2)
|
33
|
+
end
|
34
|
+
|
35
|
+
def update
|
36
|
+
super
|
37
|
+
@updates += 1
|
38
|
+
puts "#{@updates}/60 updates."
|
39
|
+
abort if @updates == 60
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
g = HappyRectangleGame.new
|
44
|
+
g.start
|
data/lib/yeah/color.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
class Yeah::Color
|
2
|
+
attr_accessor :rgba_bytes
|
3
|
+
|
4
|
+
class << self
|
5
|
+
alias_method :[], :new
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(*arguments)
|
9
|
+
arguments = [0, 0, 0, 255] if arguments.empty?
|
10
|
+
|
11
|
+
case arguments[0]
|
12
|
+
when Numeric
|
13
|
+
@rgba_bytes = [*arguments]
|
14
|
+
when Array
|
15
|
+
@rgba_bytes = arguments[0]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def ==(other)
|
20
|
+
self.class == other.class && @rgba_bytes == other.rgba_bytes ? true : false
|
21
|
+
end
|
22
|
+
end
|
data/lib/yeah/desktop.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygame'
|
2
|
+
|
3
|
+
class Yeah::Desktop
|
4
|
+
attr_reader :screen, :resolution, :tickrate
|
5
|
+
|
6
|
+
def initialize(resolution=Vector[320, 240])
|
7
|
+
self.resolution = resolution
|
8
|
+
@clock = Rubygame::Clock.new
|
9
|
+
self.tickrate = 30
|
10
|
+
end
|
11
|
+
|
12
|
+
def resolution=(value)
|
13
|
+
@screen = Rubygame::Screen.new(value.components[0..1])
|
14
|
+
@resolution = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def render(surface)
|
18
|
+
struct = screen.send(:struct)
|
19
|
+
struct.pixels.write_string(surface.data(:bgra), surface.data.length)
|
20
|
+
screen.update
|
21
|
+
end
|
22
|
+
|
23
|
+
def tickrate=(value)
|
24
|
+
@clock.target_framerate = value
|
25
|
+
@tickrate = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def each_tick
|
29
|
+
loop do
|
30
|
+
yield
|
31
|
+
@clock.tick
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/yeah/entity.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
class Yeah::Entity
|
2
|
-
attr_accessor :position
|
2
|
+
attr_accessor :position, :visual
|
3
3
|
|
4
|
-
def initialize(
|
5
|
-
@position =
|
4
|
+
def initialize(position=Vector[])
|
5
|
+
@position = position
|
6
6
|
end
|
7
7
|
|
8
8
|
def x
|
@@ -28,4 +28,8 @@ class Yeah::Entity
|
|
28
28
|
def z=(value)
|
29
29
|
@position.z = value
|
30
30
|
end
|
31
|
+
|
32
|
+
def draw
|
33
|
+
visual.draw if visual
|
34
|
+
end
|
31
35
|
end
|
data/lib/yeah/game.rb
CHANGED
@@ -1,11 +1,30 @@
|
|
1
1
|
class Yeah::Game
|
2
|
-
attr_accessor :entities
|
2
|
+
attr_accessor :entities, :screen, :platform, :resolution
|
3
3
|
|
4
4
|
def initialize
|
5
|
+
@resolution = Vector[320, 240]
|
6
|
+
@screen = Surface.new(@resolution)
|
7
|
+
@platform = Desktop.new
|
5
8
|
@entities = []
|
6
9
|
end
|
7
10
|
|
8
11
|
def update
|
9
12
|
@entities.each { |e| e.update }
|
10
13
|
end
|
14
|
+
|
15
|
+
def draw
|
16
|
+
screen.fill(Color[0, 0, 0, 0])
|
17
|
+
@entities.each do |entity|
|
18
|
+
surface = entity.draw
|
19
|
+
screen.draw(surface, entity.position) unless surface.nil?
|
20
|
+
end
|
21
|
+
platform.render(screen)
|
22
|
+
end
|
23
|
+
|
24
|
+
def start
|
25
|
+
platform.each_tick do
|
26
|
+
update
|
27
|
+
draw
|
28
|
+
end
|
29
|
+
end
|
11
30
|
end
|
data/lib/yeah/map.rb
ADDED
data/lib/yeah/surface.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
class Yeah::Surface
|
2
|
+
attr_reader :size
|
3
|
+
attr_writer :data
|
4
|
+
|
5
|
+
def initialize(size=Vector[])
|
6
|
+
self.size = size
|
7
|
+
end
|
8
|
+
|
9
|
+
def size=(value)
|
10
|
+
@size = value
|
11
|
+
@data = "\x00" * 4 * size.x * size.y
|
12
|
+
end
|
13
|
+
|
14
|
+
def data(format=:rgba)
|
15
|
+
case format
|
16
|
+
when :rgba
|
17
|
+
@data
|
18
|
+
when :bgra
|
19
|
+
@data.scan(/.{4}/).map { |p| p[2] + p[1] + p[0] + p[3] }.join
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def color_at(position)
|
24
|
+
data_lines = data.scan(/.{#{size.x*4}}/)
|
25
|
+
line = data_lines[position.y]
|
26
|
+
color_string = line[position.x*4..position.x*4+3]
|
27
|
+
color_bytes = color_string.unpack('H*')[0].
|
28
|
+
scan(/.{2}/).map { |b| b.to_i(16) }
|
29
|
+
Color[*color_bytes]
|
30
|
+
end
|
31
|
+
|
32
|
+
def fill(color, position1=Vector[0, 0], position2=size-1)
|
33
|
+
color_byte_string = color.rgba_bytes.pack('C*')
|
34
|
+
data_lines = data.scan(/.{#{size.x*4}}/)
|
35
|
+
|
36
|
+
rect_width = (position2.x - position1.x).abs + 1
|
37
|
+
(position1.y..position2.y).each do |i|
|
38
|
+
line = data_lines[i]
|
39
|
+
color_bytes_row = color_byte_string * rect_width
|
40
|
+
line[position1.x*4...(position2.x+1)*4] = color_bytes_row
|
41
|
+
end
|
42
|
+
|
43
|
+
@data = data_lines.join
|
44
|
+
end
|
45
|
+
|
46
|
+
def draw(surface, position=Vector[0, 0])
|
47
|
+
data_lines = data.scan(/.{#{size.x*4}}/)
|
48
|
+
surface_data_lines = surface.data.scan(/.{#{surface.size.x*4}}/)
|
49
|
+
|
50
|
+
(position.y...position.y+surface.size.height).each_with_index do |y, i|
|
51
|
+
line = data_lines[y]
|
52
|
+
surface_line = surface_data_lines[i]
|
53
|
+
|
54
|
+
line[position.x*4...(position.x+surface.size.width)*4] = surface_line
|
55
|
+
end
|
56
|
+
|
57
|
+
@data = data_lines.join
|
58
|
+
end
|
59
|
+
end
|
data/lib/yeah.rb
CHANGED
data/spec/color_spec.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Color do
|
4
|
+
let(:klass) { described_class }
|
5
|
+
let(:instance) { klass.new }
|
6
|
+
|
7
|
+
it { klass.should be_kind_of Class }
|
8
|
+
|
9
|
+
[:new, :[]].each do |method_name|
|
10
|
+
describe "::#{method_name}" do
|
11
|
+
subject(:method) { klass.method(method_name) }
|
12
|
+
|
13
|
+
it { method.call.should be_instance_of klass }
|
14
|
+
it { method.call.rgba_bytes.should eq [0, 0, 0, 255] }
|
15
|
+
it { method.call([10, 20, 30, 40]).rgba_bytes.should eq [10, 20, 30, 40] }
|
16
|
+
it { method.call([55, 25, 55, 25]).rgba_bytes.should eq [55, 25, 55, 25] }
|
17
|
+
it { method.call(10, 20, 30, 40).rgba_bytes.should eq [10, 20, 30, 40] }
|
18
|
+
it { method.call(55, 25, 55, 25).rgba_bytes.should eq [55, 25, 55, 25] }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#==' do
|
23
|
+
subject(:method) { instance.method(:==).unbind }
|
24
|
+
|
25
|
+
it "is true for itself" do
|
26
|
+
color = klass[55, 54, 53, 52]
|
27
|
+
method.bind(color).call(color).should eq true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "is true for Color of same value" do
|
31
|
+
value = (1..4).map { Random.rand(255) }
|
32
|
+
method.bind(klass[value]).call(klass[value]).should eq true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "is false for Color of different value" do
|
36
|
+
value = (1..4).map { Random.rand(255) }
|
37
|
+
method.bind(klass[value]).call(klass[value.reverse]).should eq false
|
38
|
+
end
|
39
|
+
|
40
|
+
it "is false for nil" do
|
41
|
+
method.bind(klass[]).call(nil).should eq false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#rgba_bytes' do
|
46
|
+
subject(:rgba_bytes) { instance.rgba_bytes }
|
47
|
+
|
48
|
+
it { should eq [0, 0, 0, 255] }
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#rgba_bytes=' do
|
52
|
+
subject(:method) { instance.method(:rgba_bytes=) }
|
53
|
+
|
54
|
+
it_behaves_like 'writer', (1..4).map { Random.rand(255) }
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Desktop do
|
4
|
+
let(:klass) { described_class }
|
5
|
+
let(:instance) { klass.new }
|
6
|
+
|
7
|
+
it { klass.should be_instance_of Class }
|
8
|
+
|
9
|
+
describe '::new' do
|
10
|
+
subject(:method) { klass.method(:new) }
|
11
|
+
|
12
|
+
it { method.call.resolution.should eq Vector[320, 240] }
|
13
|
+
|
14
|
+
it "accepts Vector as resolution" do
|
15
|
+
vector = Vector[Random.rand(250), Random.rand(250)]
|
16
|
+
desktop = method.call(vector)
|
17
|
+
desktop.resolution.should eq vector
|
18
|
+
desktop.screen.size.should eq vector[0..1]
|
19
|
+
end
|
20
|
+
|
21
|
+
it { method.call.instance_variables.should include :@clock }
|
22
|
+
it do
|
23
|
+
clock = method.call.instance_variable_get(:@clock)
|
24
|
+
clock.should be_instance_of Rubygame::Clock
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#screen' do
|
29
|
+
subject { instance.screen }
|
30
|
+
|
31
|
+
it { should be_instance_of Rubygame::Screen }
|
32
|
+
its(:size) { should eq [320, 240] }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#resolution' do
|
36
|
+
subject { instance.resolution }
|
37
|
+
|
38
|
+
it { should eq Vector[320, 240] }
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#resolution=' do
|
42
|
+
subject(:method) { instance.method(:resolution=) }
|
43
|
+
|
44
|
+
it_behaves_like 'writer', Vector[Random.rand(250), Random.rand(250)]
|
45
|
+
|
46
|
+
it "changes screen size" do
|
47
|
+
resolution = Vector[Random.rand(250)+1, Random.rand(250)+1]
|
48
|
+
method.call(resolution)
|
49
|
+
instance.screen.size.should eq resolution.components[0..1]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#render' do
|
54
|
+
subject(:method) { instance.method(:render) }
|
55
|
+
|
56
|
+
it { expect { method.call }.to raise_error ArgumentError }
|
57
|
+
|
58
|
+
it "renders a Surface" do
|
59
|
+
surface = Surface.new(instance.resolution)
|
60
|
+
surface.fill(Color[255, 255, 0, 255], Vector[0, 0], Vector[1, 1])
|
61
|
+
|
62
|
+
screen_update_count = 0
|
63
|
+
allow(instance.screen).to receive(:update) { screen_update_count += 1 }
|
64
|
+
|
65
|
+
method.call(surface)
|
66
|
+
instance.screen.get_at([0, 0]).should eq [255, 255, 0, 255]
|
67
|
+
screen_update_count.should eq 1
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#each_tick' do
|
72
|
+
subject(:method) { instance.method(:each_tick) }
|
73
|
+
|
74
|
+
it { expect { method.call }.to raise_error LocalJumpError }
|
75
|
+
|
76
|
+
it "repeatedly calls passed block" do
|
77
|
+
call_count = 0
|
78
|
+
|
79
|
+
method.call do
|
80
|
+
call_count += 1
|
81
|
+
break if call_count == 5
|
82
|
+
end
|
83
|
+
|
84
|
+
call_count.should eq 5
|
85
|
+
end
|
86
|
+
|
87
|
+
it "calls Rubygame::Clock#tick per call" do
|
88
|
+
call_count = 0
|
89
|
+
tick_call_count = 0
|
90
|
+
allow(instance.instance_variable_get(:@clock)).to receive(:tick) do
|
91
|
+
tick_call_count += 1
|
92
|
+
end
|
93
|
+
|
94
|
+
method.call do
|
95
|
+
break if tick_call_count == 5
|
96
|
+
call_count += 1
|
97
|
+
end
|
98
|
+
|
99
|
+
call_count.should eq 5
|
100
|
+
tick_call_count.should eq 5
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#tickrate' do
|
105
|
+
subject { instance.tickrate }
|
106
|
+
|
107
|
+
its(:round) { should eq 30 }
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#tickrate=' do
|
111
|
+
subject(:method) { instance.method(:tickrate=) }
|
112
|
+
|
113
|
+
it_behaves_like 'writer', 60
|
114
|
+
|
115
|
+
it "sets @clock#target_framerate" do
|
116
|
+
tickrate = Random.rand(30) + 30
|
117
|
+
clock = instance.instance_variable_get(:@clock)
|
118
|
+
method.call(tickrate)
|
119
|
+
|
120
|
+
clock.target_framerate.round.should eq tickrate
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/spec/entity_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
let(:klass) {
|
3
|
+
describe Entity do
|
4
|
+
let(:klass) { described_class }
|
5
5
|
let(:instance) { klass.new }
|
6
6
|
|
7
7
|
it { klass.should be_instance_of Class }
|
@@ -10,23 +10,21 @@ describe Yeah::Entity do
|
|
10
10
|
subject(:method) { klass.method(:new) }
|
11
11
|
|
12
12
|
it { method.call.should be_instance_of klass }
|
13
|
-
it { method.call.position.should eq
|
14
|
-
it { method.call(2, 4, 8).position.should eq
|
13
|
+
it { method.call.position.should eq Vector[0, 0, 0] }
|
14
|
+
it { method.call(Vector[2, 4, 8]).position.should eq Vector[2, 4, 8] }
|
15
15
|
end
|
16
16
|
|
17
17
|
describe '#position' do
|
18
18
|
subject(:position) { instance.position }
|
19
19
|
|
20
|
-
it { should be_instance_of
|
20
|
+
it { should be_instance_of Vector }
|
21
21
|
it { position.components.should eq [0, 0, 0] }
|
22
22
|
end
|
23
23
|
|
24
24
|
describe '#position=' do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
instance.position.should eq vector
|
29
|
-
end
|
25
|
+
subject(:method) { instance.method(:position=) }
|
26
|
+
|
27
|
+
it_behaves_like 'writer', Vector[Random.rand(100)]
|
30
28
|
end
|
31
29
|
|
32
30
|
[:x, :y, :z].each do |method_name|
|
@@ -45,4 +43,28 @@ describe Yeah::Entity do
|
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
46
|
+
|
47
|
+
describe '#visual' do
|
48
|
+
subject { instance.visual }
|
49
|
+
|
50
|
+
it { should eq nil }
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#visual=' do
|
54
|
+
subject { instance.method(:visual=) }
|
55
|
+
|
56
|
+
it_behaves_like 'writer', Rectangle.new(Vector[50, 50])
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#draw' do
|
60
|
+
subject(:method) { instance.method(:draw) }
|
61
|
+
|
62
|
+
its(:call) { should eq nil }
|
63
|
+
|
64
|
+
it "calls #draw method of #visual if it exists" do
|
65
|
+
instance.visual = Rectangle.new
|
66
|
+
instance.visual.should receive(:draw)
|
67
|
+
method.call
|
68
|
+
end
|
69
|
+
end
|
48
70
|
end
|
data/spec/game_spec.rb
CHANGED
@@ -1,11 +1,29 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
let(:klass) {
|
3
|
+
describe Game do
|
4
|
+
let(:klass) { described_class }
|
5
5
|
let(:instance) { klass.new }
|
6
6
|
|
7
7
|
it { klass.should be_instance_of Class }
|
8
8
|
|
9
|
+
describe '#platform' do
|
10
|
+
subject { instance.platform }
|
11
|
+
|
12
|
+
it { should be_instance_of Desktop }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#resolution' do
|
16
|
+
subject { instance.resolution }
|
17
|
+
|
18
|
+
it { should eq Vector[320, 240] }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#resolution=' do
|
22
|
+
subject { instance.method(:resolution=) }
|
23
|
+
|
24
|
+
it_behaves_like 'writer', Vector[512, 384]
|
25
|
+
end
|
26
|
+
|
9
27
|
describe '#entities' do
|
10
28
|
subject(:entities) { instance.entities }
|
11
29
|
|
@@ -13,20 +31,73 @@ describe Yeah::Game do
|
|
13
31
|
end
|
14
32
|
|
15
33
|
describe '#entities=' do
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
instance.entities.should eq value
|
20
|
-
end
|
34
|
+
subject(:method) { instance.method(:entities=) }
|
35
|
+
|
36
|
+
it_behaves_like 'writer', [Entity.new(Random.rand(10))]
|
21
37
|
end
|
22
38
|
|
23
39
|
describe '#update' do
|
40
|
+
subject(:method) { instance.method(:update) }
|
41
|
+
|
24
42
|
it "calls #update of each element in #entities" do
|
25
|
-
instance.entities = (1..3).map {
|
26
|
-
|
27
|
-
|
43
|
+
instance.entities = (1..3).map { Entity.new }
|
44
|
+
instance.entities.each { |e| e.should receive(:update) }
|
45
|
+
method.call
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#draw' do
|
50
|
+
subject(:method) { instance.method(:draw) }
|
51
|
+
|
52
|
+
it "clears #screen" do
|
53
|
+
instance.screen.should receive(:fill).with(Color[0, 0, 0, 0])
|
54
|
+
method.call
|
55
|
+
end
|
56
|
+
|
57
|
+
it "calls #draw of each element in #entities" do
|
58
|
+
instance.entities = (1..3).map { Entity.new }
|
59
|
+
instance.entities.each { |e| e.should receive(:draw) }
|
60
|
+
method.call
|
61
|
+
end
|
62
|
+
|
63
|
+
it "draws entities on #screen" do
|
64
|
+
color = Color[0, 255, 0, 255]
|
65
|
+
entity = Entity.new
|
66
|
+
entity.visual = Rectangle.new(Vector[1, 1], color)
|
67
|
+
entity.position = Vector[Random.rand(10), Random.rand(10)]
|
68
|
+
instance.entities << entity
|
69
|
+
method.call
|
70
|
+
|
71
|
+
instance.screen.color_at(entity.position).should eq color
|
72
|
+
end
|
73
|
+
|
74
|
+
it "writes to #platform#screen#struct#pixels" do
|
75
|
+
pixels = instance.platform.screen.send(:struct).pixels
|
76
|
+
pixel_data = pixels.read_string(instance.screen.data.length)
|
77
|
+
pixel_data.should eq instance.screen.data
|
78
|
+
end
|
79
|
+
|
80
|
+
it "calls #platform#screen#update" do
|
81
|
+
instance.platform.screen.should receive(:update)
|
82
|
+
method.call
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#screen' do
|
87
|
+
subject(:screen) { instance.screen }
|
88
|
+
|
89
|
+
it { should be_instance_of Surface }
|
90
|
+
its(:size) { should eq instance.resolution }
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#start' do
|
94
|
+
subject(:method) { instance.method(:start) }
|
28
95
|
|
29
|
-
|
96
|
+
it "calls #platform#each_tick with a block with #update and #draw calls" do
|
97
|
+
instance.platform.instance_eval "def each_tick; yield; end"
|
98
|
+
instance.should receive(:update)
|
99
|
+
instance.should receive(:draw)
|
100
|
+
method.call
|
30
101
|
end
|
31
102
|
end
|
32
103
|
end
|
data/spec/map_spec.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Map do
|
4
|
+
let(:klass) { described_class }
|
5
|
+
let(:instance) { klass.new }
|
6
|
+
|
7
|
+
it { klass.should be_instance_of Class }
|
8
|
+
|
9
|
+
describe '#background' do
|
10
|
+
subject(:background) { instance.background }
|
11
|
+
|
12
|
+
it { should eq Color[] }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#background=' do
|
16
|
+
subject(:method) { instance.method(:background=) }
|
17
|
+
|
18
|
+
it_behaves_like 'writer', Color[*[Random.rand(255)]*4]
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rectangle do
|
4
|
+
let(:klass) { described_class }
|
5
|
+
let(:instance) { klass.new }
|
6
|
+
|
7
|
+
it { klass.should be_kind_of Class }
|
8
|
+
|
9
|
+
describe '::new' do
|
10
|
+
subject(:method) { klass.method(:new) }
|
11
|
+
|
12
|
+
it { method.call.should be_instance_of klass }
|
13
|
+
it { method.call.size.should eq Vector[] }
|
14
|
+
it { method.call.color.should eq Color[255, 255, 255, 255] }
|
15
|
+
|
16
|
+
it "assigns Vector first argument as #size" do
|
17
|
+
vector = Vector[Random.rand(40)]
|
18
|
+
method.call(vector).size.should eq vector
|
19
|
+
end
|
20
|
+
|
21
|
+
it "assigns second argument Color as #color" do
|
22
|
+
byte_array = (1..4).map { Random.rand(255) }
|
23
|
+
color = Color[*byte_array]
|
24
|
+
method.call(Vector[], color).color.should eq color
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#size' do
|
29
|
+
subject(:size) { instance.size }
|
30
|
+
|
31
|
+
it { should eq Vector[] }
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#size=' do
|
35
|
+
subject(:method) { instance.method(:size=) }
|
36
|
+
|
37
|
+
it_behaves_like 'writer', Vector[Random.rand(40)]
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#color' do
|
41
|
+
subject(:color) { instance.color }
|
42
|
+
|
43
|
+
it { should eq Color[255, 255, 255, 255] }
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#color=' do
|
47
|
+
subject(:method) { instance.method(:color=) }
|
48
|
+
|
49
|
+
it_behaves_like 'writer', Color[*[Random.rand(255)]*4]
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#draw' do
|
53
|
+
subject(:method) { instance.method(:draw) }
|
54
|
+
|
55
|
+
its(:call) { should be_instance_of Surface }
|
56
|
+
|
57
|
+
it "matches size" do
|
58
|
+
instance.size = Vector[Random.rand(49)+1, 50]
|
59
|
+
method.call.size.should eq instance.size
|
60
|
+
end
|
61
|
+
|
62
|
+
it "matches color" do
|
63
|
+
instance.size = Vector[10, 10]
|
64
|
+
instance.color = Color[*[Random.rand(255)]*4]
|
65
|
+
surface = method.call
|
66
|
+
surface.color_at(Vector[]).should eq instance.color
|
67
|
+
surface.color_at(instance.size/2).should eq instance.color
|
68
|
+
surface.color_at(instance.size-Vector[1, 1]).should eq instance.color
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
require 'yeah'
|
2
|
+
include Yeah
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
shared_examples 'writer' do |value|
|
5
|
+
it "assigns its reader" do
|
6
|
+
writer = subject
|
7
|
+
reader_name = writer.name[0..-2].to_sym
|
8
|
+
reader = writer.receiver.method(reader_name)
|
5
9
|
|
6
|
-
|
7
|
-
|
8
|
-
@update_count = 0
|
9
|
-
end
|
10
|
-
|
11
|
-
def update
|
12
|
-
@update_count += 1
|
10
|
+
writer.call(value)
|
11
|
+
reader.call.should eq value
|
13
12
|
end
|
14
13
|
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Surface do
|
4
|
+
let(:klass) { described_class }
|
5
|
+
let(:vector) { Vector[Random.rand(48)+2, Random.rand(48)+2] }
|
6
|
+
let(:instance) { klass.new(vector) }
|
7
|
+
|
8
|
+
describe '::new' do
|
9
|
+
subject(:method) { klass.method :new }
|
10
|
+
|
11
|
+
it { method.call.size.should eq Vector[] }
|
12
|
+
|
13
|
+
it "accepts a Vector size" do
|
14
|
+
surface = method.call(vector)
|
15
|
+
surface.size.should eq vector
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#size' do
|
20
|
+
subject { instance.size }
|
21
|
+
|
22
|
+
it { should eq vector }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#size=' do
|
26
|
+
subject(:method) { instance.method(:size=) }
|
27
|
+
|
28
|
+
it_behaves_like 'writer', Vector[20, 20]
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#data' do
|
32
|
+
subject(:method) { instance.method(:data) }
|
33
|
+
let(:data) { instance.data }
|
34
|
+
|
35
|
+
it "has length of #size.x * #size.y * 4" do
|
36
|
+
instance.size = instance.size * 2
|
37
|
+
expected_length = instance.size.x * instance.size.y * 4
|
38
|
+
data.length.should eq expected_length
|
39
|
+
end
|
40
|
+
|
41
|
+
it "is a series of \x00\x00\x00\x00 by default" do
|
42
|
+
pixels = data.unpack('H*')[0].scan(/.{8}/)
|
43
|
+
pixels.uniq.size.should eq 1
|
44
|
+
pixels.uniq.last.should eq "00000000"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "accepts format param" do
|
48
|
+
instance.data = "\x00\x11\x22\x33"
|
49
|
+
method.call(:rgba).should eq "\x00\x11\x22\x33"
|
50
|
+
method.call(:bgra).should eq "\x22\x11\x00\x33"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#data=' do
|
55
|
+
subject(:method) { instance.method(:data=) }
|
56
|
+
|
57
|
+
it "assigns hex data of length size.x * size.y * 4" do
|
58
|
+
data = "\xFF" * instance.size.x * instance.size.y * 4
|
59
|
+
method.call(data)
|
60
|
+
instance.data.should eq data
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#color_at' do
|
65
|
+
subject(:method) { instance.method(:color_at) }
|
66
|
+
|
67
|
+
it { expect { method.call }.to raise_error ArgumentError }
|
68
|
+
|
69
|
+
it "matches the color of the pixel at position" do
|
70
|
+
method.call(vector/2).should eq Color[0, 0, 0, 0]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#fill' do
|
75
|
+
subject(:method) { instance.method(:fill) }
|
76
|
+
let(:color2) { Color[0, 255, 0, 255] }
|
77
|
+
|
78
|
+
it { expect { method.call }.to raise_error ArgumentError }
|
79
|
+
|
80
|
+
it "changes color of rectangular area with position args" do
|
81
|
+
method.call(color2, Vector[], vector/2)
|
82
|
+
instance.color_at(Vector[]).should eq color2
|
83
|
+
instance.color_at(vector/2).should eq color2
|
84
|
+
instance.color_at(vector/2 + Vector[1, 0]).should eq Color[0, 0, 0, 0]
|
85
|
+
instance.color_at(vector/2 + Vector[0, 1]).should eq Color[0, 0, 0, 0]
|
86
|
+
instance.data.length.should eq instance.size.x * instance.size.y * 4
|
87
|
+
end
|
88
|
+
|
89
|
+
it "changes color of entire surface without position args" do
|
90
|
+
method.call(color2)
|
91
|
+
instance.color_at(Vector[]).should eq color2
|
92
|
+
instance.color_at(vector/2).should eq color2
|
93
|
+
instance.color_at(vector-1).should eq color2
|
94
|
+
instance.data.length.should eq instance.size.x * instance.size.y * 4
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#draw' do
|
99
|
+
subject(:method) { instance.method(:draw) }
|
100
|
+
let(:color) { Color[0, Random.rand(255), Random.rand(255), 255] }
|
101
|
+
|
102
|
+
it { expect { method.call }.to raise_error ArgumentError }
|
103
|
+
|
104
|
+
it "draws surface at position" do
|
105
|
+
surface = Surface.new(Vector[1, 1])
|
106
|
+
surface.fill(color)
|
107
|
+
surface2 = Surface.new(Vector[10, 10])
|
108
|
+
surface2.draw(surface, Vector[1, 1])
|
109
|
+
|
110
|
+
surface2.color_at(Vector[0, 0]).should eq Color[0, 0, 0, 0]
|
111
|
+
surface2.color_at(Vector[1, 1]).should eq color
|
112
|
+
surface2.color_at(Vector[2, 2]).should eq Color[0, 0, 0, 0]
|
113
|
+
end
|
114
|
+
|
115
|
+
it "draws surface at (0, 0) by default" do
|
116
|
+
surface = Surface.new(Vector[1, 1])
|
117
|
+
surface.fill(color)
|
118
|
+
surface2 = Surface.new(Vector[10, 10])
|
119
|
+
surface2.draw(surface)
|
120
|
+
|
121
|
+
surface2.color_at(Vector[0, 0]).should eq color
|
122
|
+
surface2.color_at(Vector[1, 1]).should eq Color[0, 0, 0, 0]
|
123
|
+
end
|
124
|
+
|
125
|
+
it "draws a rectangular area" do
|
126
|
+
surface = Surface.new(Vector[3, 3])
|
127
|
+
surface.fill(color)
|
128
|
+
surface2 = Surface.new(Vector[5, 5])
|
129
|
+
surface2.draw(surface, Vector[1, 1])
|
130
|
+
|
131
|
+
surface2.color_at(Vector[1, 1]).should eq color
|
132
|
+
surface2.color_at(Vector[1, 3]).should eq color
|
133
|
+
surface2.color_at(Vector[3, 1]).should eq color
|
134
|
+
surface2.color_at(Vector[3, 3]).should eq color
|
135
|
+
surface2.color_at(Vector[0, 3]).should eq Color[0, 0, 0, 0]
|
136
|
+
surface2.color_at(Vector[3, 0]).should eq Color[0, 0, 0, 0]
|
137
|
+
surface2.color_at(Vector[4, 3]).should eq Color[0, 0, 0, 0]
|
138
|
+
surface2.color_at(Vector[3, 4]).should eq Color[0, 0, 0, 0]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/spec/vector_spec.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
let(:klass) {
|
5
|
-
let(:arguments) { (1..3).map { Random.rand(100) } }
|
3
|
+
describe Vector do
|
4
|
+
let(:klass) { described_class }
|
5
|
+
let(:arguments) { (1..3).map { Random.rand(100)+1 } }
|
6
6
|
let(:instance) { klass.new(*arguments) }
|
7
7
|
|
8
8
|
it { klass.should be_instance_of Class }
|
@@ -104,10 +104,10 @@ describe Yeah::Vector do
|
|
104
104
|
|
105
105
|
it "subtracts Numeric" do
|
106
106
|
subtrahend = Random.rand(100)
|
107
|
-
difference = instance
|
107
|
+
difference = instance - subtrahend
|
108
108
|
|
109
109
|
difference.components.each_with_index do |component, i|
|
110
|
-
component.should eq instance.components[i]
|
110
|
+
component.should eq instance.components[i] - subtrahend
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
@@ -144,7 +144,7 @@ describe Yeah::Vector do
|
|
144
144
|
end
|
145
145
|
|
146
146
|
it "divides by Numeric" do
|
147
|
-
divisor = Random.rand(100)
|
147
|
+
divisor = Random.rand(100) + 1
|
148
148
|
quotient = instance / divisor
|
149
149
|
|
150
150
|
quotient.components.each_with_index do |component, i|
|
data/spec/yeah_spec.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Yeah do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
let(:modjul) { described_class }
|
5
|
+
|
6
|
+
it { modjul.should be_instance_of Module }
|
7
7
|
|
8
8
|
describe '::VERSION' do
|
9
|
-
subject {
|
9
|
+
subject { modjul::VERSION }
|
10
10
|
|
11
11
|
it { should be_instance_of String }
|
12
12
|
it { should match /[0-9]+\.[0-9]+\.[0-9]+/ }
|
data/yeah-0.1.0.gem
ADDED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yeah
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Artur Ostrega
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Programming video games should have a positive impact on your health!
|
14
14
|
email: skoofoo@gmail.com
|
@@ -18,18 +18,30 @@ extra_rdoc_files: []
|
|
18
18
|
files:
|
19
19
|
- Gemfile
|
20
20
|
- Guardfile
|
21
|
+
- lib/yeah/map.rb
|
21
22
|
- lib/yeah/game.rb
|
23
|
+
- lib/yeah/color.rb
|
24
|
+
- lib/yeah/surface.rb
|
22
25
|
- lib/yeah/vector.rb
|
26
|
+
- lib/yeah/desktop.rb
|
27
|
+
- lib/yeah/rectangle.rb
|
23
28
|
- lib/yeah/entity.rb
|
24
29
|
- lib/yeah.rb
|
25
30
|
- README.md
|
26
|
-
-
|
31
|
+
- CHANGELOG.md
|
27
32
|
- tmp/rspec_guard_result
|
28
33
|
- Gemfile.lock
|
29
34
|
- yeah.gemspec
|
30
35
|
- LICENSE.txt
|
36
|
+
- demo/happy_rectangle.rb
|
37
|
+
- yeah-0.1.0.gem
|
31
38
|
- spec/yeah_spec.rb
|
39
|
+
- spec/color_spec.rb
|
40
|
+
- spec/desktop_spec.rb
|
32
41
|
- spec/game_spec.rb
|
42
|
+
- spec/rectangle_spec.rb
|
43
|
+
- spec/surface_spec.rb
|
44
|
+
- spec/map_spec.rb
|
33
45
|
- spec/spec_helper.rb
|
34
46
|
- spec/entity_spec.rb
|
35
47
|
- spec/vector_spec.rb
|
data/yeah-0.0.2.gem
DELETED
Binary file
|