shirokuro 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +0 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +21 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +21 -0
  8. data/Rakefile +8 -0
  9. data/examples/audio/main.rb +40 -0
  10. data/examples/audio/run.sh +2 -0
  11. data/examples/layers_and_sorting/main.rb +62 -0
  12. data/examples/layers_and_sorting/run.sh +2 -0
  13. data/examples/physx/main.rb +114 -0
  14. data/examples/physx/run.sh +2 -0
  15. data/examples/shared/content/audio/boing.ogg +0 -0
  16. data/examples/shared/content/audio/song_1.ogg +0 -0
  17. data/examples/shared/content/gfx/character_sprite.png +0 -0
  18. data/examples/shared/content/gfx/tileset.png +0 -0
  19. data/examples/shared/content/maps/stage2.json +299 -0
  20. data/examples/sprite/main.rb +43 -0
  21. data/examples/sprite/run.sh +2 -0
  22. data/examples/sprite_animation/main.rb +45 -0
  23. data/examples/sprite_animation/run.sh +2 -0
  24. data/examples/tmx_map/main.rb +70 -0
  25. data/examples/tmx_map/run.sh +2 -0
  26. data/lib/shirokuro.rb +42 -0
  27. data/lib/shirokuro/audio/audio_manager.rb +80 -0
  28. data/lib/shirokuro/content/content_manager.rb +58 -0
  29. data/lib/shirokuro/ecs/component.rb +37 -0
  30. data/lib/shirokuro/ecs/game_object.rb +58 -0
  31. data/lib/shirokuro/ecs/game_object_manager.rb +51 -0
  32. data/lib/shirokuro/ecs/id_generator.rb +10 -0
  33. data/lib/shirokuro/math/matrix.rb +72 -0
  34. data/lib/shirokuro/math/transform.rb +16 -0
  35. data/lib/shirokuro/math/vec2.rb +38 -0
  36. data/lib/shirokuro/physics/physics.rb +22 -0
  37. data/lib/shirokuro/standard_components/animations/animation.rb +30 -0
  38. data/lib/shirokuro/standard_components/animations/animation_component.rb +28 -0
  39. data/lib/shirokuro/standard_components/cameras/camera.rb +59 -0
  40. data/lib/shirokuro/standard_components/maps/map_component.rb +10 -0
  41. data/lib/shirokuro/standard_components/physics/box_collider.rb +40 -0
  42. data/lib/shirokuro/standard_components/physics/circle_collider.rb +29 -0
  43. data/lib/shirokuro/standard_components/physics/polygon_collider.rb +35 -0
  44. data/lib/shirokuro/standard_components/physics/rigid_body.rb +57 -0
  45. data/lib/shirokuro/standard_components/rendering/animation_sprite_renderer.rb +26 -0
  46. data/lib/shirokuro/standard_components/rendering/map_renderer.rb +36 -0
  47. data/lib/shirokuro/standard_components/rendering/shape_renderer.rb +95 -0
  48. data/lib/shirokuro/standard_components/rendering/sprite_renderer.rb +21 -0
  49. data/lib/shirokuro/standard_components/tmx/tmx_map.rb +20 -0
  50. data/lib/shirokuro/standard_components/tmx/tmx_map_layer.rb +38 -0
  51. data/lib/shirokuro/standard_components/tmx/tmx_map_layer_object.rb +17 -0
  52. data/lib/shirokuro/standard_components/transformation/rotation.rb +14 -0
  53. data/lib/shirokuro/version.rb +3 -0
  54. data/shirokuro.gemspec +30 -0
  55. data/spec/shirokuro/ecs/component_spec.rb +78 -0
  56. data/spec/shirokuro/ecs/game_object_manager_spec.rb +113 -0
  57. data/spec/shirokuro/ecs/game_object_spec.rb +110 -0
  58. data/spec/shirokuro/math/matrix_spec.rb +49 -0
  59. data/spec/shirokuro/math/transform_spec.rb +28 -0
  60. data/spec/shirokuro/math/vec2_spec.rb +49 -0
  61. data/spec/spec_helper.rb +12 -0
  62. metadata +223 -0
@@ -0,0 +1,51 @@
1
+ module SK
2
+ class GameObjectManager
3
+
4
+ attr_accessor :physics
5
+
6
+ def initialize
7
+ @id_generator = IdGenerator.new
8
+ @game_objects = []
9
+ @started = false
10
+
11
+ @physics = Physics.new
12
+ end
13
+
14
+ def create name
15
+ id = @id_generator.next()
16
+ game_object = GameObject.new(name, id)
17
+ game_object.instance_variable_set(:@manager, self)
18
+ @game_objects << game_object
19
+ if @started
20
+ game_object.start
21
+ end
22
+ game_object
23
+ end
24
+
25
+ def remove game_object
26
+ @game_objects.delete game_object
27
+ end
28
+
29
+ def start
30
+ @game_objects.each{ |x| x.start }
31
+ @started = true
32
+ end
33
+
34
+ def update dt
35
+ @physics.update dt
36
+ @game_objects.each{ |x| x.update dt}
37
+ end
38
+
39
+ def draw context
40
+ components = @game_objects.collect{|obj| obj.components }
41
+ .flatten.collect{|c| c }
42
+ .sort_by{ |c|
43
+ [c.layer, c.order_in_layer]
44
+ }
45
+
46
+ components.each do |component|
47
+ component.draw context
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,10 @@
1
+ class IdGenerator
2
+
3
+ def initialize
4
+ @current = 0
5
+ end
6
+
7
+ def next
8
+ @current += 1
9
+ end
10
+ end
@@ -0,0 +1,72 @@
1
+ module SK
2
+ class Matrix
3
+
4
+ attr_accessor :values
5
+
6
+ def initialize values = []
7
+ @values = values
8
+ end
9
+
10
+ def self.identity
11
+ Matrix.new([
12
+ 1.0, 0, 0, 0,
13
+ 0, 1.0, 0, 0,
14
+ 0, 0, 0, 0,
15
+ 0, 0, 0, 0
16
+ ])
17
+ end
18
+
19
+ def self.create_rotation angle
20
+ c = Math::cos(angle)
21
+ s = Math::sin(angle)
22
+
23
+ result = Matrix.new([
24
+ +c, +s, 0.0, 0.0,
25
+ -s, +c, 0.0, 0.0,
26
+ 0.0, 0.0, 1.0, 0.0,
27
+ 0.0, 0.0, 0.0, 1.0
28
+ ])
29
+ end
30
+
31
+ def self.create_translation(x, y)
32
+ Matrix.new([
33
+ 1, 0, 0, 0,
34
+ 0, 1, 0, 0,
35
+ 0, 0, 1, 0,
36
+ x, y, 0, 1
37
+ ])
38
+ end
39
+
40
+ def self.create_scale x, y
41
+ Matrix.new([
42
+ x, 0, 0, 0,
43
+ 0, y, 0, 0,
44
+ 0, 0, 1, 0,
45
+ 0, 0, 0, 1
46
+ ])
47
+ end
48
+
49
+ def decompose
50
+ position = Vec2.new(@values[12], @values[13])
51
+ # tan^-1(2/3) = tan^-1(-1/0)
52
+ rotation = Math::tan(-1.0 * (@values[0] / @values[1]))
53
+ scale = Vec2.new(@values[0], @values[5])
54
+ transform = Transform.new
55
+ transform.position.x = position.x
56
+ transform.position.y = position.y
57
+ transform.rotation = rotation
58
+ transform
59
+ end
60
+
61
+ def * (right)
62
+ result = []
63
+ 16.times do |i|
64
+ result[i] = 0;
65
+ 4.times do |j|
66
+ result[i] += @values[i / 4 * 4 + j] * right.values[i % 4 + j * 4]
67
+ end
68
+ end
69
+ return Matrix.new(result)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,16 @@
1
+ module SK
2
+ class Transform
3
+
4
+ attr_accessor :position, :rotation, :scale
5
+
6
+ def initialize
7
+ @position = Vec2.new
8
+ @scale = Vec2.new(1.0, 1.0)
9
+ @rotation = 0.0
10
+ end
11
+
12
+ # def matrix
13
+ # Matrix.new(4, 4)
14
+ # end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ module SK
2
+ class Vec2
3
+ attr_accessor :x, :y
4
+
5
+ def initialize x = 0.0, y = 0.0
6
+ @x = x
7
+ @y = y
8
+ end
9
+
10
+ def + other
11
+ if other.is_a?(Numeric)
12
+ return Vec2.new(@x + other, @y + other)
13
+ end
14
+ Vec2.new(@x + other.x, @y + other.y)
15
+ end
16
+
17
+ def - other
18
+ if other.is_a?(Numeric)
19
+ return Vec2.new(@x - other, @y - other)
20
+ end
21
+ Vec2.new(@x - other.x, @y - other.y)
22
+ end
23
+
24
+ def * other
25
+ if other.is_a?(Numeric)
26
+ return Vec2.new(@x * other, @y * other)
27
+ end
28
+ Vec2.new(@x * other.x, @y * other.y)
29
+ end
30
+
31
+ def / other
32
+ if other.is_a?(Numeric)
33
+ return Vec2.new(@x / other, @y / other)
34
+ end
35
+ Vec2.new(@x / other.x, @y / other.y)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ module SK
2
+ class Physics
3
+
4
+ attr_reader :space
5
+
6
+ def initialize
7
+ @space = CP::Space.new
8
+ @space.gravity.y = 100.0
9
+ @simulation_substeps = 6
10
+ end
11
+
12
+ def update dt
13
+ @simulation_substeps.times do
14
+ @space.step((1.0 / 30.0) / @simulation_substeps.to_f)
15
+ end
16
+
17
+ @space.instance_variable_get(:@bodies).each do |body|
18
+ body.reset_forces
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ module SK
2
+ class Animation
3
+ def initialize frames, interval
4
+ @frames = frames
5
+ @interval = interval
6
+ @current = 0.0
7
+ @current_frame = 0
8
+ end
9
+
10
+ def frame
11
+ @frames[@current_frame]
12
+ end
13
+
14
+ def reset
15
+ @current = 0.0
16
+ @current_frame = 0
17
+ end
18
+
19
+ def update dt
20
+ @current += dt
21
+ if @current > @interval
22
+ @current = 0.0
23
+ @current_frame += 1
24
+ if @current_frame > @frames.size - 1
25
+ reset
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ module SK
2
+ class AnimationComponent < Component
3
+
4
+ attr_accessor :animations, :current
5
+
6
+ def initialize animations
7
+ @animations = animations
8
+ @current = animations.keys.first
9
+ end
10
+
11
+ def set name
12
+ if name == @current
13
+ return
14
+ end
15
+ @current = name
16
+ @animations[@current].reset
17
+ end
18
+
19
+ def frame
20
+ @animations[@current].frame
21
+ end
22
+
23
+ def update dt
24
+ @animations[@current].update dt
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,59 @@
1
+ module SK
2
+ class Camera < Component
3
+
4
+ attr_accessor :speed
5
+
6
+ def initialize screen_size
7
+ @screen_size = screen_size / 2.0
8
+ @target = Vec2.new
9
+ @speed = 0.05
10
+ end
11
+
12
+ def x
13
+ -transform.position.x + (@screen_size.x / 2.0)
14
+ end
15
+
16
+ def y
17
+ -transform.position.y + (@screen_size.y / 2.0)
18
+ end
19
+
20
+ def move x, y
21
+ @target.x = x
22
+ @target.y = y
23
+ end
24
+
25
+ def move_by x, y
26
+ @target.x += x
27
+ @target.y += y
28
+ end
29
+
30
+ def zoom_by factor
31
+ transform.scale += factor
32
+ end
33
+
34
+ def set_zoom zoom
35
+ transform.scale.x = zoom
36
+ transform.scale.y = zoom
37
+ end
38
+
39
+ def lerp x, y, w
40
+ x + (y - x) * w
41
+ end
42
+
43
+ def update dt
44
+ # TODO: apply delta to smooth movement
45
+ transform.position.x = lerp(transform.position.x, @target.x, @speed)
46
+ transform.position.y = lerp(transform.position.y, @target.y, @speed)
47
+ end
48
+
49
+ def view window, &block
50
+ window.translate(@screen_size.x, @screen_size.y) do
51
+ window.scale(transform.scale.x, transform.scale.y) do
52
+ window.translate(-transform.position.x, -transform.position.y) do
53
+ block.call()
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ module SK
2
+ class MapComponent < Component
3
+
4
+ attr_accessor :map
5
+
6
+ def initialize map
7
+ @map = map
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,40 @@
1
+ module SK
2
+ class BoxCollider < Component
3
+
4
+ attr_accessor :width, :height, :friction, :restitution, :shape
5
+
6
+ def initialize width, height
7
+ @width = width
8
+ @height = height
9
+ @friction = 0.4
10
+ @restitution = 0.1
11
+ end
12
+
13
+ def start
14
+ rigid_body = get_component(RigidBody)
15
+
16
+ if rigid_body == nil
17
+ raise "RigidBody required for BoxCollider"
18
+ end
19
+
20
+ half_width = @width / 2.0
21
+ half_height = @height / 2.0
22
+
23
+ vertices = [
24
+ CP::Vec2.new(-half_width, -half_height),
25
+ CP::Vec2.new(-half_width, half_height),
26
+ CP::Vec2.new(half_width, half_height),
27
+ CP::Vec2.new(half_width, -half_height)
28
+ ]
29
+
30
+ @shape = CP::Shape::Poly.new(rigid_body.body, vertices, CP::Vec2.new(0, 0))
31
+ @shape.u = @friction
32
+ @shape.e = @restitution
33
+
34
+ # recalculate inertia
35
+ rigid_body.body.i = CP.moment_for_box(rigid_body.body.m, @width, @height)
36
+
37
+ physics.space.add_shape(@shape)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,29 @@
1
+ module SK
2
+ class CircleCollider < Component
3
+
4
+ attr_accessor :radius, :friction, :restitution, :shape
5
+
6
+ def initialize radius
7
+ @radius = radius
8
+ @friction = 0.4
9
+ @restitution = 0.1
10
+ end
11
+
12
+ def start
13
+ rigid_body = get_component(RigidBody)
14
+
15
+ if rigid_body == nil
16
+ raise "RigidBody required for BoxCollider"
17
+ end
18
+
19
+ @shape = CP::Shape::Circle.new(rigid_body.body, @radius, CP::Vec2.new(0, 0))
20
+ @shape.u = @friction
21
+ @shape.e = @restitution
22
+
23
+ # recalculate inertia
24
+ rigid_body.body.i = CP.moment_for_circle(rigid_body.body.m, @radius, @radius, CP::Vec2.new(0, 0))
25
+
26
+ physics.space.add_shape(@shape)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ module SK
2
+ class PolygonCollider < Component
3
+
4
+ attr_accessor :vertices, :friction, :restitution, :shape
5
+
6
+ def initialize vertices
7
+ @vertices = vertices
8
+ @friction = 0.4
9
+ @restitution = 0.1
10
+ end
11
+
12
+ def start
13
+ rigid_body = get_component(RigidBody)
14
+
15
+ if rigid_body == nil
16
+ raise "RigidBody required for BoxCollider"
17
+ end
18
+
19
+ unless CP::Shape::Poly.valid?(@vertices)
20
+ raise "Vertices does not form a valid polygon"
21
+ end
22
+
23
+ centroid = CP::centroid_for_poly(@vertices)
24
+
25
+ @shape = CP::Shape::Poly.new(rigid_body.body, vertices, centroid)
26
+ @shape.u = @friction
27
+ @shape.e = @restitution
28
+
29
+ # recalculate inertia
30
+ rigid_body.body.i = CP.moment_for_poly(rigid_body.body.m, @vertices, centroid)
31
+
32
+ physics.space.add_shape(@shape)
33
+ end
34
+ end
35
+ end