teien 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +11 -6
- data/bin/teien +16 -2
- data/lib/teien/ai.rb +27 -0
- data/lib/teien/animation.rb +34 -0
- data/lib/teien/animation_operator.rb +6 -0
- data/lib/teien/controller.rb +30 -0
- data/lib/teien/dispatcher.rb +22 -0
- data/lib/teien/event.rb +60 -0
- data/lib/teien/event_router.rb +118 -0
- data/lib/teien/garden.rb +60 -172
- data/lib/teien/garden_base.rb +117 -0
- data/lib/teien/garden_object.rb +119 -136
- data/lib/teien/model.rb +34 -0
- data/lib/teien/network.rb +108 -0
- data/lib/teien/object_info.rb +21 -0
- data/lib/teien/physics.rb +47 -39
- data/lib/teien/physics_object.rb +57 -0
- data/lib/teien/physics_object_factory.rb +170 -0
- data/lib/teien/proxy_garden.rb +118 -0
- data/lib/teien/remote_info.rb +20 -0
- data/lib/teien/sky_dome.rb +15 -0
- data/lib/teien/smooth_mover.rb +31 -42
- data/lib/teien/synchronizer.rb +26 -0
- data/lib/teien/tools.rb +30 -2
- data/lib/teien/user_interface.rb +58 -5
- data/lib/teien/version.rb +1 -1
- data/lib/teien/view.rb +52 -33
- data/lib/teien/view_object.rb +67 -0
- data/lib/teien/view_object_factory.rb +210 -0
- data/lib/teien.rb +62 -14
- data/sample/actor/app/ais/actor_ai.rb +112 -0
- data/sample/actor/app/controllers/actor_controller.rb +182 -0
- data/sample/actor/app/helpers/sinbad/sinbad.rb +176 -0
- data/sample/actor/app/helpers/sinbad/sinbad_state.rb +224 -0
- data/sample/actor/app/helpers/user_event.rb +75 -0
- data/sample/actor/app/models/actor_model.rb +108 -0
- data/sample/actor/config/plugins.cfg +19 -0
- data/sample/actor/config/resources.cfg +24 -0
- data/sample/hello_garden/app/controllers/hello_garden_controller.rb +90 -0
- data/sample/hello_garden/app/helpers/user_event.rb +12 -0
- data/sample/{standalone/hello_garden/hello_garden.rb → hello_garden/app/models/hello_garden_model.rb} +29 -83
- data/sample/{standalone/hello_garden → hello_garden/config}/plugins.cfg +0 -0
- data/sample/{standalone/hello_garden → hello_garden/config}/resources.cfg +0 -0
- data/sample/hello_garden/run +6 -0
- data/teien.gemspec +2 -1
- metadata +52 -15
- data/lib/teien/light_object.rb +0 -36
- data/lib/teien/object_factory.rb +0 -308
- data/sample/standalone/hello_garden/run +0 -5
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Teien
|
2
2
|
|
3
|
-
Teien will be a platform to make 3D
|
3
|
+
Teien will be a platform to make 3D worlds connected by network easily with Ruby.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -14,16 +14,21 @@ And then execute:
|
|
14
14
|
|
15
15
|
Or install it yourself as:
|
16
16
|
|
17
|
-
$ gem install
|
18
|
-
$ gem install ruby-
|
19
|
-
$ gem install
|
20
|
-
$ gem install
|
17
|
+
$ gem install eventmachine
|
18
|
+
$ gem install ruby-ogre
|
19
|
+
$ gem install ruby-bullet
|
20
|
+
$ gem install teienlib
|
21
|
+
$ rake build
|
22
|
+
$ gem install pkg/teien-<version>.gem
|
21
23
|
|
22
24
|
## Usage
|
23
25
|
|
24
26
|
Run a sample application.
|
25
27
|
|
26
|
-
$ /
|
28
|
+
$ mkdir mywork/
|
29
|
+
$ cp -r <gems>/teien-<version>/sample/ mywork/
|
30
|
+
$ cd mywork/sample/hello_garden/
|
31
|
+
$ ./run
|
27
32
|
|
28
33
|
## Contributing
|
29
34
|
|
data/bin/teien
CHANGED
@@ -45,5 +45,19 @@ end
|
|
45
45
|
$LOAD_PATH.push(libPath)
|
46
46
|
$LOAD_PATH.push("./")
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
require 'teien'
|
49
|
+
|
50
|
+
case ARGV[0]
|
51
|
+
when "server"
|
52
|
+
Teien::start_server_garden("0.0.0.0", 11922)
|
53
|
+
when "client"
|
54
|
+
ip = ARGV[1] ? ARGV[1] : "0.0.0.0"
|
55
|
+
port = ARGV[2] ? ARGV[2].to_i : 11922
|
56
|
+
Teien::start_client_garden(ip, port)
|
57
|
+
when "ai"
|
58
|
+
ip = ARGV[1] ? ARGV[1] : "0.0.0.0"
|
59
|
+
port = ARGV[2] ? ARGV[2].to_i : 11922
|
60
|
+
Teien::start_ai_garden(ip, port)
|
61
|
+
when "local"
|
62
|
+
Teien::start_local_garden()
|
63
|
+
end
|
data/lib/teien/ai.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'teien'
|
2
|
+
|
3
|
+
module Teien
|
4
|
+
|
5
|
+
class Ai
|
6
|
+
@@ais = Array.new
|
7
|
+
@@loaded_ais = Array.new
|
8
|
+
|
9
|
+
@garden = nil
|
10
|
+
|
11
|
+
def initialize(garden)
|
12
|
+
@garden = garden
|
13
|
+
@garden.register_receiver(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.inherited(klass)
|
17
|
+
@@ais.push(klass)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.load(garden)
|
21
|
+
@@ais.each {|ctl|
|
22
|
+
@@loaded_ais.push(ctl.new(garden))
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Teien
|
2
|
+
|
3
|
+
class Animation
|
4
|
+
attr_accessor :enable
|
5
|
+
attr_accessor :blend_mode
|
6
|
+
attr_accessor :operators
|
7
|
+
|
8
|
+
class Operator
|
9
|
+
attr_accessor :name
|
10
|
+
attr_accessor :speed
|
11
|
+
attr_accessor :loop
|
12
|
+
|
13
|
+
def initialize(name, speed, loop)
|
14
|
+
@name = name
|
15
|
+
@speed = speed
|
16
|
+
@loop = loop
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize()
|
21
|
+
@enable = false
|
22
|
+
@blend_mode = Ogre::ANIMBLEND_CUMULATIVE
|
23
|
+
@operators = Hash.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_operator(operator_name, animation_name, speed, loop)
|
27
|
+
unless @operators[operator_name]
|
28
|
+
@operators[operator_name] = Operator.new(animation_name, speed, loop)
|
29
|
+
end
|
30
|
+
return @operators[operator_name]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -3,6 +3,9 @@ class AnimationOperator
|
|
3
3
|
BL_MODE_CONCURRENT = 1 # cross fade, blend current animation out while blending next animation in.
|
4
4
|
BL_MODE_FIRSTFRAME = 2 # blend current animation to first frame of next animation, when done, start next animation.
|
5
5
|
|
6
|
+
attr_accessor :name
|
7
|
+
attr_accessor :loop
|
8
|
+
|
6
9
|
def initialize(entity)
|
7
10
|
@entity = entity
|
8
11
|
@state = nil
|
@@ -11,6 +14,8 @@ class AnimationOperator
|
|
11
14
|
@duration = 0.2
|
12
15
|
@timeLeft = 0
|
13
16
|
@complete = false
|
17
|
+
|
18
|
+
@name = nil
|
14
19
|
@loop = false
|
15
20
|
|
16
21
|
# @blender = Ogrelet::AnimationBlender.new(entity)
|
@@ -43,6 +48,7 @@ class AnimationOperator
|
|
43
48
|
end
|
44
49
|
|
45
50
|
def play(name, loop)
|
51
|
+
@name = name
|
46
52
|
@loop = loop
|
47
53
|
|
48
54
|
unless @state
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'teien'
|
2
|
+
|
3
|
+
module Teien
|
4
|
+
|
5
|
+
class Controller
|
6
|
+
@@controllers = Array.new
|
7
|
+
@@loaded_controllers = Array.new
|
8
|
+
|
9
|
+
@garden = nil
|
10
|
+
@ui = nil
|
11
|
+
|
12
|
+
def initialize(garden, ui)
|
13
|
+
@garden = garden
|
14
|
+
@garden.register_receiver(self)
|
15
|
+
@ui = ui
|
16
|
+
@ui.register_receiver(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.inherited(klass)
|
20
|
+
@@controllers.push(klass)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.load(garden, ui)
|
24
|
+
@@controllers.each {|ctl|
|
25
|
+
@@loaded_controllers.push(ctl.new(garden, ui))
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Teien
|
2
|
+
|
3
|
+
module Dispatcher
|
4
|
+
def initialize(*args, &block)
|
5
|
+
super
|
6
|
+
@receivers = Array.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def register_receiver(recv)
|
10
|
+
@receivers.push(recv)
|
11
|
+
end
|
12
|
+
|
13
|
+
def notify(method, *argv)
|
14
|
+
@receivers.each {|recv|
|
15
|
+
if (recv.respond_to?(method))
|
16
|
+
recv.method(method).call(*argv)
|
17
|
+
end
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/teien/event.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
module Event
|
2
|
+
|
3
|
+
# event
|
4
|
+
|
5
|
+
class ClientConnected
|
6
|
+
end
|
7
|
+
|
8
|
+
class ClientUnbinded
|
9
|
+
end
|
10
|
+
|
11
|
+
class SyncEnv
|
12
|
+
attr_accessor :gravity
|
13
|
+
attr_accessor :ambient_light_color
|
14
|
+
attr_accessor :sky_dome
|
15
|
+
|
16
|
+
def initialize(gravity, ambient_light_color, sky_dome)
|
17
|
+
@gravity = gravity
|
18
|
+
@ambient_light_color = ambient_light_color
|
19
|
+
@sky_dome = sky_dome
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class SyncObject
|
24
|
+
attr_accessor :id
|
25
|
+
attr_accessor :name
|
26
|
+
attr_accessor :mode
|
27
|
+
|
28
|
+
attr_accessor :object_info
|
29
|
+
attr_accessor :physics_info
|
30
|
+
attr_accessor :animation_info
|
31
|
+
|
32
|
+
attr_accessor :pos
|
33
|
+
attr_accessor :linear_vel
|
34
|
+
attr_accessor :angular_vel
|
35
|
+
attr_accessor :quat
|
36
|
+
attr_accessor :accel
|
37
|
+
|
38
|
+
|
39
|
+
def initialize(obj)
|
40
|
+
@id = obj.id
|
41
|
+
@name = obj.name
|
42
|
+
|
43
|
+
@object_info = obj.object_info
|
44
|
+
@physics_info = obj.physics_info
|
45
|
+
@animation_info = obj.animation_info
|
46
|
+
|
47
|
+
@pos = Vector3D.to_self(obj.get_position())
|
48
|
+
@linear_vel = Vector3D.to_self(obj.get_linear_velocity())
|
49
|
+
@angular_vel = Vector3D.to_self(obj.get_angular_velocity())
|
50
|
+
@quat = Quaternion.to_self(obj.get_rotation())
|
51
|
+
@accel = obj.get_acceleration()
|
52
|
+
end
|
53
|
+
|
54
|
+
def print
|
55
|
+
puts @name
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end # module Event
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require "eventmachine"
|
2
|
+
require "teien/event"
|
3
|
+
require "teien/network"
|
4
|
+
|
5
|
+
module Teien
|
6
|
+
|
7
|
+
##
|
8
|
+
# EventRouter routes events in this region and communicate with the other region routers.
|
9
|
+
#
|
10
|
+
# ====Usage
|
11
|
+
# 1. register a new event type name with registerEventType().
|
12
|
+
# 2. register a receiver object which receives the eventType with registerReceiver().
|
13
|
+
# The receiver object must have action(event) method.
|
14
|
+
# 3. call notify(event) which issues the event.
|
15
|
+
# The event must have eventType() method which returns event type name.
|
16
|
+
#
|
17
|
+
class EventRouter
|
18
|
+
attr_accessor :connected_regions
|
19
|
+
|
20
|
+
def initialize()
|
21
|
+
@connected_regions = Array.new
|
22
|
+
|
23
|
+
@event_type_receiver_hash = {} # event_type => receivers
|
24
|
+
|
25
|
+
@last_time = 0
|
26
|
+
@tick_event = Event::Tick.new(0)
|
27
|
+
register_event_type(Event::Tick)
|
28
|
+
end
|
29
|
+
|
30
|
+
def finalize()
|
31
|
+
end
|
32
|
+
|
33
|
+
# eventmachine
|
34
|
+
def send_all_regions(obj)
|
35
|
+
@connected_regions.each { |c|
|
36
|
+
c.send_object(obj)
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
# event_type: the class name of a event.
|
41
|
+
def register_event_type(event_type)
|
42
|
+
@event_type_receiver_hash[event_type] = Array.new
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
#
|
47
|
+
# The event receiver must have action(anEvent) method.
|
48
|
+
#
|
49
|
+
def register_receiver(event_name, receiver)
|
50
|
+
if (@event_type_receiver_hash.has_key?(event_name))
|
51
|
+
@event_type_receiver_hash[event_name].push(receiver)
|
52
|
+
else
|
53
|
+
print "No such event type(#{event_name}) in EventRouter.\n"
|
54
|
+
print "Use EventRouter::register_event_type(event_type) at first.\n"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# The event notified by this method must have a event_type attribute and
|
60
|
+
# the event_yype must be registered with register_event_type()
|
61
|
+
#
|
62
|
+
def notify(event)
|
63
|
+
if (@event_type_receiver_hash.has_key?(event.class))
|
64
|
+
@event_type_receiver_hash[event.class].each {|receiver|
|
65
|
+
receiver.receive_event(event)
|
66
|
+
}
|
67
|
+
else
|
68
|
+
print "No such event type(#{event.class}) in EventRouter.\n"
|
69
|
+
print "Use EventRouter::register_event_type(event_type) at first.\n"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def run()
|
74
|
+
EM.run do
|
75
|
+
Signal.trap("INT") { EM.stop; self.finalize() }
|
76
|
+
Signal.trap("TERM") { EM.stop; self.finalize() }
|
77
|
+
|
78
|
+
EM.add_periodic_timer(0) do
|
79
|
+
notify(@tick_event)
|
80
|
+
# update(delta)
|
81
|
+
end
|
82
|
+
|
83
|
+
# EM.start_server("0.0.0.0", 11922, ServerNetwork, @event_router)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# ip: string(ex. "0.0.0.0" means to accept all),
|
88
|
+
# port: num
|
89
|
+
def start_region(ip, port)
|
90
|
+
EM.run do
|
91
|
+
Signal.trap("INT") { EM.stop; self.finalize() }
|
92
|
+
Signal.trap("TERM") { EM.stop; self.finalize() }
|
93
|
+
|
94
|
+
EM.add_periodic_timer(0) do
|
95
|
+
notify(@tick_event)
|
96
|
+
end
|
97
|
+
|
98
|
+
EM.start_server(ip, port, Network, self)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def connect_to_region(ip, port)
|
103
|
+
EM.run do
|
104
|
+
# setting signals
|
105
|
+
Signal.trap("INT") { EM.stop; self.finalize() }
|
106
|
+
Signal.trap("TERM") { EM.stop; self.finalize() }
|
107
|
+
|
108
|
+
# main loop
|
109
|
+
EM.add_periodic_timer(0) do
|
110
|
+
notify(Event::Tick.new(@tick_event))
|
111
|
+
end
|
112
|
+
|
113
|
+
EM.connect('49.212.146.194', 11922, Network, self)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
data/lib/teien/garden.rb
CHANGED
@@ -1,203 +1,91 @@
|
|
1
|
-
require "teien/
|
2
|
-
require "teien/
|
3
|
-
require "teien/
|
4
|
-
require "teien/view.rb"
|
5
|
-
#require "teien/server_view.rb"
|
6
|
-
require "teien/physics.rb"
|
7
|
-
require "teien/user_interface.rb"
|
8
|
-
#require "teien/server_user_interface.rb"
|
1
|
+
require "teien/garden_base.rb"
|
2
|
+
require "teien/network.rb"
|
3
|
+
require "teien/event.rb"
|
9
4
|
|
10
5
|
module Teien
|
11
6
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
attr_accessor :physics
|
16
|
-
attr_accessor :resources_cfg
|
17
|
-
attr_accessor :plugins_cfg
|
18
|
-
attr_accessor :objects
|
19
|
-
attr_accessor :object_factory
|
20
|
-
attr_accessor :is_server
|
21
|
-
|
22
|
-
#
|
23
|
-
# _script_klass_:: : set a user define class.
|
24
|
-
#
|
25
|
-
def initialize(script_klass)
|
26
|
-
@view = nil
|
27
|
-
@physics = nil
|
28
|
-
@script_klass = script_klass
|
29
|
-
|
30
|
-
@resources_cfg = nil
|
31
|
-
@plugins_cfg = nil
|
32
|
-
@objects = {}
|
33
|
-
@object_num = 0
|
34
|
-
|
35
|
-
@object_factory = ObjectFactory.new(self)
|
36
|
-
|
37
|
-
@is_server = false
|
38
|
-
@debug_draw = false
|
39
|
-
@quit = false
|
40
|
-
end
|
41
|
-
|
42
|
-
#
|
43
|
-
# set a title name on the window title bar.
|
44
|
-
#
|
45
|
-
# _title_ :: : set a name(String).
|
46
|
-
#
|
47
|
-
def set_window_title(title)
|
48
|
-
@view.window_title = title unless @is_server
|
49
|
-
end
|
50
|
-
|
51
|
-
#
|
52
|
-
# set the gravity of the world.
|
53
|
-
#
|
54
|
-
# _grav_ :: : set a vector(Vector3D) as the gravity.
|
55
|
-
#
|
56
|
-
def set_gravity(grav)
|
57
|
-
@physics.set_gravity(grav)
|
58
|
-
end
|
59
|
-
|
60
|
-
#
|
61
|
-
# set the ambient light of the world.
|
62
|
-
#
|
63
|
-
# _color_:: : set a color(Color).
|
64
|
-
#
|
65
|
-
def set_ambient_light(color)
|
66
|
-
@view.scene_mgr.set_ambient_light(color)
|
67
|
-
end
|
68
|
-
|
69
|
-
def set_sky_dome(enable, materialName, curvature = 10, tiling = 8, distance = 4000)
|
70
|
-
@view.scene_mgr.set_sky_dome(enable, materialName, curvature, tiling, distance)
|
71
|
-
end
|
72
|
-
|
73
|
-
def set_debug_draw(bl)
|
74
|
-
if (bl)
|
75
|
-
@debug_draw = bl
|
76
|
-
@debug_drawer = Teienlib::DebugDrawer.new(@view.scene_mgr)
|
77
|
-
@physics.dynamicsWorld.set_debug_drawer(@debug_drawer)
|
78
|
-
end
|
7
|
+
class Garden < GardenBase
|
8
|
+
def initialize()
|
9
|
+
super
|
79
10
|
end
|
80
11
|
|
81
|
-
def
|
82
|
-
|
83
|
-
return ServerUserInterface.new(@view)
|
84
|
-
else
|
85
|
-
return UserInterface.new(@view)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def create_object(name, objectInfo, physicsInfo)
|
90
|
-
return @object_factory.create_object(name, objectInfo, physicsInfo)
|
91
|
-
end
|
92
|
-
|
93
|
-
def create_light(name)
|
94
|
-
return LightObject.new(self, name)
|
95
|
-
end
|
12
|
+
def run(ip = nil, port = 11922)
|
13
|
+
return false unless setup()
|
96
14
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
if
|
101
|
-
@
|
15
|
+
@last_time = 0
|
16
|
+
EM.run do
|
17
|
+
EM.add_periodic_timer(0.01) do
|
18
|
+
if @last_time == 0
|
19
|
+
@last_time = Time.now.to_f
|
102
20
|
else
|
103
|
-
|
21
|
+
now = Time.now.to_f
|
22
|
+
delta = now - @last_time
|
23
|
+
@last_time = now
|
24
|
+
|
25
|
+
unless update(delta)
|
26
|
+
EM.stop
|
27
|
+
self.finalize()
|
28
|
+
end
|
104
29
|
end
|
105
30
|
end
|
106
|
-
@objects[obj.name] = obj
|
107
|
-
obj.id = @object_num
|
108
|
-
@object_num += 1
|
109
|
-
else
|
110
|
-
raise RuntimeError, "There is a object with the same name (#{obj.name})"
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def check_collision(objectA, objectB)
|
115
|
-
result = @physics.contact_pair_test(objectA.rigid_body, objectB.rigid_body)
|
116
|
-
return result.isCollided
|
117
|
-
end
|
118
31
|
|
119
|
-
|
120
|
-
|
121
|
-
@view = ServerView.new(self)
|
122
|
-
else
|
123
|
-
@view = View.new(self)
|
124
|
-
end
|
125
|
-
|
126
|
-
@physics = Physics.new(self)
|
127
|
-
@script = @script_klass.new(self)
|
128
|
-
|
129
|
-
if @view.setup()
|
130
|
-
@view.start(@script)
|
131
|
-
@view.prepare_render_loop()
|
132
|
-
|
133
|
-
@physics.setup()
|
134
|
-
@script.setup()
|
135
|
-
|
136
|
-
return true
|
137
|
-
else
|
138
|
-
return false
|
139
|
-
end
|
140
|
-
end
|
32
|
+
Signal.trap("INT") { EM.stop; self.finalize() }
|
33
|
+
Signal.trap("TERM") { EM.stop; self.finalize() }
|
141
34
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
def run()
|
146
|
-
return false unless setup()
|
147
|
-
|
148
|
-
last_time = Time.now.to_f
|
149
|
-
while !@quit
|
150
|
-
now_time = Time.now.to_f
|
151
|
-
delta = now_time - last_time
|
152
|
-
last_time = now_time
|
153
|
-
break unless update(delta)
|
35
|
+
if (ip)
|
36
|
+
EM.start_server(ip, port, Network, self)
|
37
|
+
end
|
154
38
|
end
|
155
|
-
|
156
|
-
finalize()
|
39
|
+
end
|
157
40
|
|
41
|
+
def setup()
|
42
|
+
@physics.setup(self)
|
43
|
+
notify(:setup, self)
|
158
44
|
return true
|
159
45
|
end
|
160
46
|
|
161
|
-
|
162
47
|
def update(delta)
|
163
|
-
@physics.
|
164
|
-
|
165
|
-
|
48
|
+
@physics.update(delta)
|
49
|
+
@actors.each_value {|actor|
|
50
|
+
actor.update(delta)
|
51
|
+
}
|
52
|
+
notify(:update, delta)
|
53
|
+
return !@quit
|
166
54
|
end
|
167
55
|
|
168
|
-
#
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
56
|
+
# receive handler of Network.
|
57
|
+
def receive_event(event, from)
|
58
|
+
case event
|
59
|
+
when Event::ClientConnected
|
60
|
+
from.send_object(Event::SyncEnv.new(@gravity, @ambient_light_color, @sky_dome))
|
61
|
+
notify_objects(from)
|
62
|
+
end
|
63
|
+
notify(:receive_event, event, from)
|
64
|
+
end
|
177
65
|
|
178
|
-
|
66
|
+
def send_event(event, to = nil)
|
67
|
+
if (to)
|
68
|
+
to.send_object(event)
|
69
|
+
else
|
70
|
+
Network::send_all(event)
|
71
|
+
end
|
179
72
|
end
|
180
73
|
|
181
|
-
def
|
182
|
-
@
|
183
|
-
|
184
|
-
|
74
|
+
def notify_objects(to = nil)
|
75
|
+
@objects.each_value { |obj|
|
76
|
+
if to == nil
|
77
|
+
Network::send_all(Event::SyncObject.new(obj))
|
78
|
+
else
|
79
|
+
to.send_object(Event::SyncObject.new(obj))
|
80
|
+
end
|
81
|
+
}
|
185
82
|
end
|
186
83
|
|
187
|
-
# called by Garden class.
|
188
|
-
# clear all managers.
|
189
84
|
def finalize()
|
190
85
|
@physics.finalize()
|
191
|
-
@view.root.save_config()
|
192
|
-
@view.finalize()
|
193
86
|
@objects = {}
|
194
87
|
end
|
195
|
-
|
196
88
|
|
197
|
-
# quit the current running garden.
|
198
|
-
def quit()
|
199
|
-
@quit = true
|
200
|
-
end
|
201
89
|
end
|
202
90
|
|
203
|
-
end
|
91
|
+
end
|