yeah 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|