teien 0.0.2 → 0.0.3
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.
- 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
|