shirokuro 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +0 -0
- data/Gemfile +4 -0
- data/Guardfile +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +21 -0
- data/Rakefile +8 -0
- data/examples/audio/main.rb +40 -0
- data/examples/audio/run.sh +2 -0
- data/examples/layers_and_sorting/main.rb +62 -0
- data/examples/layers_and_sorting/run.sh +2 -0
- data/examples/physx/main.rb +114 -0
- data/examples/physx/run.sh +2 -0
- data/examples/shared/content/audio/boing.ogg +0 -0
- data/examples/shared/content/audio/song_1.ogg +0 -0
- data/examples/shared/content/gfx/character_sprite.png +0 -0
- data/examples/shared/content/gfx/tileset.png +0 -0
- data/examples/shared/content/maps/stage2.json +299 -0
- data/examples/sprite/main.rb +43 -0
- data/examples/sprite/run.sh +2 -0
- data/examples/sprite_animation/main.rb +45 -0
- data/examples/sprite_animation/run.sh +2 -0
- data/examples/tmx_map/main.rb +70 -0
- data/examples/tmx_map/run.sh +2 -0
- data/lib/shirokuro.rb +42 -0
- data/lib/shirokuro/audio/audio_manager.rb +80 -0
- data/lib/shirokuro/content/content_manager.rb +58 -0
- data/lib/shirokuro/ecs/component.rb +37 -0
- data/lib/shirokuro/ecs/game_object.rb +58 -0
- data/lib/shirokuro/ecs/game_object_manager.rb +51 -0
- data/lib/shirokuro/ecs/id_generator.rb +10 -0
- data/lib/shirokuro/math/matrix.rb +72 -0
- data/lib/shirokuro/math/transform.rb +16 -0
- data/lib/shirokuro/math/vec2.rb +38 -0
- data/lib/shirokuro/physics/physics.rb +22 -0
- data/lib/shirokuro/standard_components/animations/animation.rb +30 -0
- data/lib/shirokuro/standard_components/animations/animation_component.rb +28 -0
- data/lib/shirokuro/standard_components/cameras/camera.rb +59 -0
- data/lib/shirokuro/standard_components/maps/map_component.rb +10 -0
- data/lib/shirokuro/standard_components/physics/box_collider.rb +40 -0
- data/lib/shirokuro/standard_components/physics/circle_collider.rb +29 -0
- data/lib/shirokuro/standard_components/physics/polygon_collider.rb +35 -0
- data/lib/shirokuro/standard_components/physics/rigid_body.rb +57 -0
- data/lib/shirokuro/standard_components/rendering/animation_sprite_renderer.rb +26 -0
- data/lib/shirokuro/standard_components/rendering/map_renderer.rb +36 -0
- data/lib/shirokuro/standard_components/rendering/shape_renderer.rb +95 -0
- data/lib/shirokuro/standard_components/rendering/sprite_renderer.rb +21 -0
- data/lib/shirokuro/standard_components/tmx/tmx_map.rb +20 -0
- data/lib/shirokuro/standard_components/tmx/tmx_map_layer.rb +38 -0
- data/lib/shirokuro/standard_components/tmx/tmx_map_layer_object.rb +17 -0
- data/lib/shirokuro/standard_components/transformation/rotation.rb +14 -0
- data/lib/shirokuro/version.rb +3 -0
- data/shirokuro.gemspec +30 -0
- data/spec/shirokuro/ecs/component_spec.rb +78 -0
- data/spec/shirokuro/ecs/game_object_manager_spec.rb +113 -0
- data/spec/shirokuro/ecs/game_object_spec.rb +110 -0
- data/spec/shirokuro/math/matrix_spec.rb +49 -0
- data/spec/shirokuro/math/transform_spec.rb +28 -0
- data/spec/shirokuro/math/vec2_spec.rb +49 -0
- data/spec/spec_helper.rb +12 -0
- 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,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,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,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
|