shirokuro 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.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
|