shattered_pack 0.3.3 → 0.4

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.
Files changed (34) hide show
  1. data/lib/mock_objects/shattered_ogre/input.rb +6 -0
  2. data/lib/mock_objects/shattered_ogre/light.rb +4 -0
  3. data/lib/mock_objects/shattered_ogre/mesh.rb +17 -0
  4. data/lib/mock_objects/shattered_ogre/node.rb +17 -0
  5. data/lib/mock_objects/shattered_ogre/renderer.rb +11 -0
  6. data/lib/mock_objects/shattered_ogre/resource_handler.rb +9 -0
  7. data/lib/mock_objects/shattered_ogre/scene.rb +28 -0
  8. data/lib/mock_objects.rb +5 -0
  9. data/lib/shattered_controller/actor/actor.rb +14 -53
  10. data/lib/shattered_controller/runner.rb +10 -4
  11. data/lib/shattered_controller/state.rb +29 -4
  12. data/lib/shattered_controller.rb +3 -2
  13. data/lib/shattered_model/base.rb +81 -0
  14. data/lib/shattered_model.rb +2 -1
  15. data/lib/shattered_pack/base.rb +5 -3
  16. data/lib/shattered_pack/keyboard_input/key_converter.rb +51 -0
  17. data/lib/{shattered_controller → shattered_pack}/keyboard_input/keyboard_input.rb +6 -2
  18. data/lib/shattered_pack/pre_initialize/pre_initialize.rb +7 -5
  19. data/lib/shattered_pack/timer/timed_event.rb +36 -8
  20. data/lib/shattered_pack/timer/timer.rb +6 -11
  21. data/lib/shattered_pack.rb +2 -1
  22. data/lib/shattered_view/base.rb +23 -11
  23. data/lib/shattered_view/light.rb +5 -4
  24. data/lib/shattered_view/mesh/mesh.rb +22 -5
  25. data/lib/shattered_view/node.rb +0 -8
  26. data/lib/shattered_view/overlay.rb +20 -0
  27. data/lib/shattered_view/rmaterial.rb +2 -2
  28. data/lib/shattered_view/runner.rb +6 -6
  29. data/lib/shattered_view/vector.rb +18 -2
  30. data/lib/shattered_view.rb +3 -2
  31. metadata +13 -6
  32. data/lib/shattered_controller/base.rb +0 -108
  33. data/lib/shattered_controller/keyboard_input/key_converter.rb +0 -43
  34. data/lib/shattered_controller/mock_camera.rb +0 -9
@@ -0,0 +1,6 @@
1
+ module ShatteredOgre
2
+ class Input
3
+ def initialize
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ module ShatteredOgre
2
+ class Light
3
+ end
4
+ end
@@ -0,0 +1,17 @@
1
+ module ShatteredOgre # :nodoc:all
2
+ class Mesh
3
+ def initialize(file_name)
4
+ end
5
+ def getPosition
6
+ v(0,0,0)
7
+ end
8
+ def setPosition(x)
9
+ end
10
+ def getNumberOfAnimations
11
+ 0
12
+ end
13
+ def setMaterial(material)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module ShatteredOgre #:nodoc:all
2
+ class Node
3
+ def attachTo(object)
4
+ end
5
+ def createChildNode()
6
+ end
7
+ def setPosition(v)
8
+ end
9
+ def scale(amount)
10
+ end
11
+ def setVisible(vis)
12
+ end
13
+ def rotate(axis, amount)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module ShatteredOgre
2
+ class Renderer
3
+ def initialize
4
+ end
5
+ def failed
6
+ false
7
+ end
8
+ def nextFrame
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module ShatteredOgre
2
+ class ResourceHandler
3
+ def self.getSingleton
4
+ @@resource_handler ||= ResourceHandler.new
5
+ end
6
+ def addCustomMaterial(name, material)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,28 @@
1
+ module ShatteredOgre
2
+ class Scene
3
+ def initialize(*args)
4
+ end
5
+ def createMesh(*args)
6
+ Mesh.new("fake")
7
+ end
8
+ def self.getSingleton
9
+ new
10
+ end
11
+ def createSceneNode
12
+ Node.new
13
+ end
14
+ def getRootSceneNode
15
+ Node.new
16
+ end
17
+ def createLight
18
+ ShatteredOgre::Light.new
19
+ end
20
+ def hideOverlay(name)
21
+ end
22
+ def showOverlay(name)
23
+ end
24
+ def getCamera
25
+ Node.new
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ path = File.dirname(__FILE__) + "/mock_objects/shattered_ogre"
2
+ Dir.foreach(path) do |mock_object|
3
+ path_to_mock = "#{path}/#{mock_object}"
4
+ require path_to_mock if mock_object.ends_with? ".rb"
5
+ end
@@ -38,70 +38,31 @@ module ShatteredController
38
38
  #
39
39
  # See ShatteredController::Base for more detail.
40
40
  def actor( name, options = {} )
41
- before_init_call( :actor, name, options )
41
+ before_init_call( :actor, name, options, true )
42
42
  end
43
43
 
44
44
  end
45
45
  module InstanceMethods
46
-
47
- # This returns all of the actors created by this controller.
48
- def actors
49
- return @actors || []
50
- end
46
+
47
+ private
51
48
 
52
49
  # Same as ShatteredController::Actor::ClassMethods#actor
53
50
  #
54
51
  # Returns a newly created actor
55
- def actor(name=nil, options={})
56
- raise Error, "actor needs a name" if name.nil?
57
- actor = Actor.new(name,load_actor_classes(name))
58
-
52
+ def actor(name, options={}, created_by_meta_function=false )
53
+ unless created_by_meta_function
54
+ raise Error, "Use #{name.to_s.camelize}.new instead of actor :#{name} at the instance level"
55
+ end
56
+ begin
57
+ actor = eval(name.to_s.camelize).new(options)
58
+ rescue NameError
59
+ raise Error, "Actor #{name.to_s.camelize} is not defined."
60
+ end
59
61
  attr_reader(name.to_sym, actor)
60
- call_object_function_for_each_key( name.to_sym, options )
61
-
62
- @actors ||= []
63
- @actors << actor
62
+
64
63
  return actor
65
64
  end
66
-
67
- private
68
-
69
- def load_actor_classes(name)
70
- actor_options={}
71
- ['model', 'view', 'controller'].each do |type|
72
- evaled_class = nil
73
- begin
74
- evaled_class = eval("#{name.to_s.camelize}#{type.camelize}")
75
- rescue NameError
76
- next
77
- end
78
- actor_options[type.to_sym] = evaled_class.new
79
- end
80
- raise Error, "No Model, View, or Controller defined for Actor #{name}." if actor_options.empty?
81
- return actor_options
82
- end
83
-
84
- end
85
-
86
- # An actor is a delegator to a controller game object.
87
- class Actor #:nodoc:all
88
- attr_reader :controller
89
- def initialize( name, options = {} )
90
- @actor_name = name
91
- @controller = (options[:controller] || ShatteredController::Base.new)
92
- @controller.model = options[:model]
93
- @controller.view = options[:view]
94
- @controller.view.model = options[:model] unless @controller.view.nil?
95
-
96
- if options[:view].nil? && options[:model].nil? && @controller.nil? && !options[:testing]
97
- raise NameError, "No model view or controller found for actor #{name}"
98
- end
99
- end
100
-
101
- # Delegate to controller
102
- def method_missing(name, *args, &block)
103
- @controller.send(name, *args, &block)
104
- end
65
+
105
66
  end
106
67
  end
107
68
  end
@@ -5,28 +5,34 @@ module ShatteredController
5
5
  class Runner #:nodoc:
6
6
  def initialize( options = {} )
7
7
  @@environment ||= options
8
- @@environment[:input] = ShatteredController::KeyConverter.new(@@environment[:input])
8
+ @@environment[:input] = ShatteredPack::KeyConverter.new(@@environment[:input])
9
9
  end
10
+
10
11
  #Every time this exits, a game dies.
11
- def start_game
12
+ def start_game(env)
13
+ @@environment = env
12
14
  each_frame do |time_elapsed|
13
15
  @@environment[:state].update_timers(time_elapsed)
14
16
  @@environment[:input].flush
17
+ @@environment[:renderer].quit if @@environment[:quit]
15
18
  end
16
19
  end
20
+
17
21
  def each_frame
18
22
  yield @@environment[:renderer].timeSinceLastFrame while @@environment[:renderer].nextFrame
19
23
  end
24
+
20
25
  def self.environment
21
26
  begin
22
27
  return @@environment
23
28
  rescue NameError
24
- return mock_environment
29
+ return @@environment = mock_environment
25
30
  end
26
31
  end
32
+
27
33
  def self.mock_environment
28
34
  retv = {}
29
- retv[:camera] = MockCamera.new
35
+ retv[:camera] = ShatteredView::Node.new
30
36
  return retv
31
37
  end
32
38
  end
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__)+'/actor/actor'
2
+
1
3
  module ShatteredController
2
4
  def self.append_features(base)
3
5
  super
@@ -30,30 +32,53 @@ module ShatteredController
30
32
  # This blurs the lines between view and controller.
31
33
  # Valid types are [:box]
32
34
  def sky(type, options = {})
33
- before_init_set( "self", { :"sky" => [type, options[:material]] })
35
+ before_init_set( "self", { :sky => [type, options[:material]] })
34
36
  end
35
37
  end
36
38
  # State is the entry point for your shattered game.
37
39
  #
38
40
  # States define the actors, communications between the actors, and control the camera.
39
41
  # You can choose your starting state in config/environment.rb
40
- class State < ShatteredController::Base
42
+ class State < ShatteredPack::Base
41
43
  before_init_call :activate_state
44
+ attr_reader :actors
45
+
42
46
  def activate_state #:nodoc:
43
47
  ShatteredPack::Configuration.environment[:state] = self
48
+ @actors = []
49
+ end
50
+
51
+ # This is called to the State every frame by the main game loop. All update events are now
52
+ # run through Timers.
53
+ def update_timers(time_elapsed) #:nodoc:
54
+ actors.each { |actor| actor.update_timer(time_elapsed) }
55
+ self.time_elapsed = time_elapsed
56
+ timer.update(time_elapsed)
44
57
  end
45
58
 
46
59
  # Returns the camera used in the state. See ShatteredController::ClassMethods#camera
47
60
  def camera(*args)
48
61
  if args.length == 0
49
- return @camera ||= Runner.environment[:camera]
50
- end
62
+ return @camera ||= Runner.environment[:camera]
63
+ end
51
64
  call_object_function_for_each_key(:camera, args[0])
52
65
  end
53
66
 
54
67
  def sky=(type, material) #:nodoc:
55
68
  Runner.environment[:scene].send("setSky#{type.to_s.capitalize}",material)
56
69
  end
70
+
71
+ def quit
72
+ Runner.environment[:quit]=true
73
+ end
74
+ end
75
+
76
+ class Error < StandardError # :nodoc:
57
77
  end
58
78
  end
59
79
 
80
+
81
+ ShatteredController::State.class_eval do
82
+ include ShatteredController::Actor
83
+ end
84
+
@@ -1,3 +1,4 @@
1
- %w(runner base state mock_camera).each do |dependency|
2
- require "shattered_controller/#{dependency}"
1
+ %w(runner state).each do |dependency|
2
+ dependency = "shattered_controller/#{dependency}"
3
+ require dependency
3
4
  end
@@ -12,7 +12,86 @@ module ShatteredModel #:nodoc:
12
12
  #
13
13
  # Models are useful for unit tests and for making game rules.
14
14
  # They are where all logic (AI/collisions/etc) go.
15
+ #
16
+ # They can also specify keyboard input.
15
17
  class Base < ShatteredPack::Base
18
+ attr_accessor :view
19
+ before_init_call :setup_view
20
+ before_init_call :register_with_state
21
+
22
+ private
23
+
24
+ # Registers an actor with a state, Called when the model is created
25
+ def register_with_state
26
+ return if state.nil?
27
+ state.actors << self
28
+ end
29
+
30
+
31
+ # Creates a view object and ties it directly into the model through method redefiniton
32
+ def setup_view
33
+ @view = eval("#{self.class}View").new if eval("defined? #{self.class}View")
34
+
35
+ methods.each do |method|
36
+ next if( method =~ /^model_/ || Base.instance_methods.include?(method))
37
+ redefine_method_for_view(method)
38
+ end
39
+
40
+ @view.model = self if @view
41
+ end
42
+
43
+ # Uses meta-programming to redefine methods to also call view methods
44
+ # old methods are aliased to model_#{method}
45
+ def redefine_method_for_view(method)
46
+ self.class.instance_eval do
47
+ @@model_method ||= {}
48
+
49
+ module_eval <<-EOF
50
+ unless @@model_method[:#{method}]
51
+ @@model_method[:#{method}] = instance_method(:#{method})
52
+ def #{method}(*args, &block)
53
+ retv = @@model_method[:#{method}].bind(self).call(*args, &block)
54
+ view.send(:#{method},*args, &block) if (!view.nil? && view.class.method_defined?(:#{method}))
55
+ return retv
56
+ end
57
+ end
58
+ EOF
59
+ # We cannot use this method because we will lose the power of blocks inside our code.
60
+ # This should be fixed in Ruby 1.9, but for now we use eval (evil) and string interpolation
61
+ # define_method(method) do |*args|
62
+ # retv = model_method.bind(self).call(*args)
63
+ # view.send(method,*args) if (!view.nil? && view.class.method_defined?(method))
64
+ # return retv
65
+ # end
66
+ end
67
+ end
68
+
69
+ public
70
+
71
+ # Propogates events to view as well.
72
+ def update_timer(time_elapsed)#:nodoc:
73
+ return if @timer == :unloaded
74
+ [self, view].each do |base|
75
+ next if base.nil?
76
+ base.time_elapsed = time_elapsed
77
+ base.timer.update(time_elapsed)
78
+ end
79
+ end
80
+
81
+ # Unloading a controller will completely unload an object from the scene.
82
+ def unload!
83
+ super
84
+ @disabled = true
85
+ @timer=:unloaded
86
+ @view.send(:unload!) if @view
87
+ self.view = nil
88
+ end
89
+
90
+ # An object is disabled when it has been unloaded.
91
+ def disabled?
92
+ super
93
+ end
94
+
16
95
  def fuzzy_logic=(file) #:nodoc:
17
96
  @fuzzy_logic = FuzzyLogic.new
18
97
  @fuzzy_logic.parse_fuzzy_file(File.dirname(__FILE__)+"/#{file}")
@@ -20,5 +99,7 @@ module ShatteredModel #:nodoc:
20
99
  def update_fuzzy_logic #:nodoc:
21
100
  @fuzzy_logic.update(self)
22
101
  end
102
+
23
103
  end
24
104
  end
105
+
@@ -1,3 +1,4 @@
1
1
  %w(base fuzzy_logic linear_interpolator).each do |dependency|
2
- require "shattered_model/#{dependency}"
2
+ dependency = "shattered_model/#{dependency}"
3
+ require dependency
3
4
  end
@@ -4,6 +4,7 @@ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname
4
4
 
5
5
  require 'timer/timer'
6
6
  require 'pre_initialize/pre_initialize'
7
+ require 'keyboard_input/keyboard_input'
7
8
 
8
9
  module ShatteredPack #:nodoc:
9
10
 
@@ -12,10 +13,10 @@ module ShatteredPack #:nodoc:
12
13
  alias_method :per_second, :time_elapsed
13
14
 
14
15
  # This is overwritten to allow for a pre_initialize before initialize
15
- def self.new(*options) #:nodoc
16
+ def self.new(options={}) #:nodoc
16
17
  new_base = allocate
17
- new_base.pre_initialize
18
- new_base.send(:initialize, *options)
18
+ new_base.pre_initialize(options)
19
+ new_base.send(:initialize)
19
20
  return new_base
20
21
  end
21
22
 
@@ -124,4 +125,5 @@ end
124
125
  ShatteredPack::Base.class_eval do
125
126
  include ShatteredPack::Timer
126
127
  include ShatteredPack::PreInitialize
128
+ include ShatteredPack::KeyboardInput
127
129
  end
@@ -0,0 +1,51 @@
1
+ module ShatteredPack
2
+ # This is a wrapper around Ogre's input listener.
3
+ # It allows us to query the status of each device every frame.
4
+ class KeyConverter #:nodoc:
5
+
6
+ def initialize( ogre_input )
7
+ @ogre_input = ogre_input
8
+ end
9
+
10
+ def key_event?( type, key_symbol )
11
+ ogre_key_method = "isKey#{type.to_s.capitalize}".to_sym
12
+ return @ogre_input.send(ogre_key_method, self.class.convert(key_symbol))
13
+ end
14
+
15
+ def flush
16
+ @ogre_input.flush
17
+ end
18
+
19
+ def self.back_conversions
20
+ @@back_conversions ||= conversions.invert
21
+ end
22
+
23
+ def self.conversions
24
+ begin
25
+ return @@conversions
26
+ rescue NameError
27
+ end
28
+ @@conversions = {}
29
+ ShatteredOgre.constants.each do |constant|
30
+ kc_evaled = eval("ShatteredOgre::#{constant}")
31
+ @@conversions[kc_evaled] = symbolize(constant[3..-1].downcase) if constant.to_s =~ /^KC_/
32
+ end
33
+ return @@conversions
34
+ end
35
+
36
+ def self.convert( kc_character )
37
+ return self.conversions[kc_character] if kc_character.is_a? Fixnum
38
+ return self.back_conversions[kc_character]
39
+ end
40
+
41
+ private
42
+
43
+ def self.symbolize( name )
44
+ exceptions = { 'pgdown' => :page_down,
45
+ 'pgup' => :page_up }
46
+ return name.to_sym if exceptions[name] == nil
47
+ return exceptions[name]
48
+ end
49
+ end
50
+
51
+ end
@@ -3,7 +3,7 @@ $:.unshift(File.dirname(__FILE__)) unless
3
3
 
4
4
  require 'key_converter'
5
5
 
6
- module ShatteredController
6
+ module ShatteredPack
7
7
  module KeyboardInput #:nodoc:
8
8
  def self.append_features(base)
9
9
  super
@@ -36,7 +36,7 @@ module ShatteredController
36
36
  end
37
37
 
38
38
  module InstanceMethods
39
- def pre_initialize
39
+ def pre_initialize(options)
40
40
  # update our keyboard input
41
41
  timer.every(:frame) do |time_elapsed|
42
42
  update_input(time_elapsed, ShatteredController::Runner.environment[:input])
@@ -72,20 +72,24 @@ module ShatteredController
72
72
  return [action, []] unless action.is_a? Hash
73
73
  return [action.keys[0], action.values[0]]
74
74
  end
75
+
75
76
  # See KeyboardInput::key
76
77
  def key(actions={})
77
78
  reaction, keys = reaction_from(actions)
78
79
  action, params = action_from(actions)
79
80
  keys.each { |key| key_actions << [reaction, key.to_sym, action, params ] }
80
81
  end
82
+
81
83
  # Update_key will send each of the events to the actor object for whatever key options
82
84
  # are defined.
83
85
  def key_action(reaction, action, time_elapsed, params) #:nodoc:
84
86
  send(action, *params)
85
87
  end
88
+
86
89
  def key_actions #:nodoc:
87
90
  @key_actions ||= []
88
91
  end
92
+
89
93
  # update_input takes the input object, and sends the actor every key event this frame.
90
94
  def update_input(time_elapsed, input) #:nodoc:
91
95
  key_actions.each do |reaction, key, action, params|
@@ -44,9 +44,11 @@ module ShatteredPack
44
44
  # This function is called after an object is allocated, but before it's initialized.
45
45
  #
46
46
  # See ShatteredPack::ClassMethods#before_init_call for usage.
47
- def pre_initialize #:nodoc:
47
+ def pre_initialize(options) #:nodoc:
48
48
  pre_initialize_set
49
49
  pre_initialize_call
50
+ # Set the options for new(...) without evaluating symbols
51
+ call_object_function_for_each_key("self",options, false)
50
52
  end
51
53
 
52
54
  # Used in pre_initialize
@@ -72,15 +74,15 @@ module ShatteredPack
72
74
  end
73
75
  end
74
76
 
75
- def call_object_function_for_each_key( actor, options )
77
+ def call_object_function_for_each_key( actor, options, evaluate_symbols=true )
76
78
  options.each_pair do |action, params|
77
- call_object_function actor, "#{action}=", params
79
+ call_object_function actor, "#{action}=", params, evaluate_symbols
78
80
  end
79
81
  end
80
82
 
81
- def call_object_function(actor, action, params)
83
+ def call_object_function(actor, action, params, evaluate_symbols=true)
82
84
  begin
83
- if params.is_a? Symbol #|| (params.length == 1 && params[0].is_a?(Symbol)) this will allow substitution in before_init_call. This may not be intended behavior.
85
+ if params.is_a?(Symbol) && evaluate_symbols
84
86
  params = eval(params.to_s)
85
87
  end
86
88
  rescue NameError
@@ -3,14 +3,19 @@ module ShatteredPack
3
3
 
4
4
  class Timer
5
5
  attr_reader :events_remaining
6
- def initialize
6
+ def initialize(context)
7
7
  @events_remaining = []
8
+ @context = context
8
9
  end
9
- def in(seconds, &block)
10
- @events_remaining << TimedEvent.new(seconds, &block)
10
+ def in(seconds, options = {}, &block)
11
+ event = TimedEvent.new(@context, seconds, options, &block)
12
+ @events_remaining << event
13
+ return event
11
14
  end
12
- def every(seconds, &block)
13
- @events_remaining << ContinuousTimedEvent.new(seconds,&block)
15
+ def every(seconds, options = {}, &block)
16
+ event = ContinuousTimedEvent.new(@context, seconds, options, &block)
17
+ @events_remaining << event
18
+ return event
14
19
  end
15
20
  def update(time_elapsed)
16
21
  events_for_update = @events_remaining.dup
@@ -23,8 +28,10 @@ module ShatteredPack
23
28
 
24
29
  class TimedEvent
25
30
  attr_accessor :time_remaining
26
- def initialize(seconds, &block)
31
+ def initialize(context, seconds, options={}, &block)
32
+ @context=context
27
33
  @event = block
34
+ @options = options
28
35
  if(seconds != :frame)
29
36
  @time_remaining = seconds
30
37
  @initial_time = @time_remaining
@@ -34,7 +41,7 @@ module ShatteredPack
34
41
  end
35
42
  end
36
43
  def update(time_elapsed)
37
- return if processed?
44
+ return if processed? || stopped?
38
45
  @time_remaining -= time_elapsed
39
46
  if time_up?
40
47
  process_event
@@ -47,17 +54,38 @@ module ShatteredPack
47
54
  def reset
48
55
  @time_remaining = @initial_time
49
56
  end
57
+ # Stop the timer
58
+ def stop
59
+ @stopped = true
60
+ end
61
+ def stopped?
62
+ !@stopped.nil?
63
+ end
50
64
  private
51
65
  def process_event
52
- @event.call(@initial_time - @time_remaining)
66
+ @event.call(@initial_time - @time_remaining) if satisfies_condition?
53
67
  end
54
68
  def time_up?
55
69
  return @time_remaining <= 0
56
70
  end
71
+ def satisfies_condition?
72
+ return true if(@options[:if].nil? && @options[:unless].nil?)
73
+ unless @options[:if].nil?
74
+ result=@options[:if]
75
+ result=@context.send(result) if(result.is_a? Symbol)
76
+ return result
77
+ end
78
+ unless @options[:unless].nil?
79
+ result=@options[:unless]
80
+ result=@context.send(result) if(result.is_a? Symbol)
81
+ return !result
82
+ end
83
+ end
57
84
  end
58
85
 
59
86
  class ContinuousTimedEvent < TimedEvent
60
87
  def update(time_elapsed)
88
+ return if stopped?
61
89
  @time_remaining -= time_elapsed
62
90
  if(time_up?)
63
91
  process_event
@@ -35,22 +35,17 @@ module ShatteredPack
35
35
  end
36
36
  time = options[:in] || options[:every]
37
37
  action = options[:action]
38
- before_init_call(:timer_in, time, action) unless options[:in].nil?
39
- before_init_call(:timer_every, time, action) unless options[:every].nil?
38
+ before_init_call(:create_timer, :in, time, action, options) unless options[:in].nil?
39
+ before_init_call(:create_timer, :every, time, action, options) unless options[:every].nil?
40
40
  end
41
41
  end
42
42
  module InstanceMethods
43
43
  def timer
44
- @timer ||= Timer.new
44
+ @timer ||= Timer.new(self)
45
45
  end
46
46
  private
47
- def timer_in(time, action)
48
- timer.in(time) do |time_elapsed|
49
- timer_enactment(action, time_elapsed)
50
- end
51
- end
52
- def timer_every(time, action)
53
- timer.every(time) do |time_elapsed|
47
+ def create_timer(type, time, action, options)
48
+ timer.send(type, time, options) do |time_elapsed|
54
49
  timer_enactment(action, time_elapsed)
55
50
  end
56
51
  end
@@ -66,7 +61,7 @@ module ShatteredPack
66
61
  send(action.to_sym)
67
62
  end
68
63
  rescue ArgumentError => argument_error
69
- raise argument_error unless argument_error.message.to_sym == :"wrong number of arguments (0 for 1)"
64
+ raise argument_error unless argument_error.message.to_sym == "wrong number of arguments (0 for 1)".to_sym
70
65
  send(action.to_sym,time_elapsed)
71
66
  end
72
67
  end
@@ -1,7 +1,8 @@
1
1
  $: << File.expand_path(File.dirname(__FILE__))
2
2
 
3
3
  %w( base runner ).each do |component|
4
- require "shattered_pack/#{component}"
4
+ dependency = "shattered_pack/#{component}"
5
+ require dependency
5
6
  end
6
7
 
7
8
  require 'shattered_support'
@@ -42,10 +42,10 @@ module ShatteredView #:nodoc:
42
42
  # directions equally.
43
43
  # Example: light :fireplace, :position => [0,-5,20], :diffuse => [1,0.5,0.5], :specular => [1,0,0], :attenuation => [8000,0,4,0.3]
44
44
  # Parameters:
45
- # :position: the x,y,z position or vector position
46
- # :diffuse: the r,g,b value of the diffuse color
47
- # :specular: the r,g,b value of the specular color
48
- # :attenuation: arguments are range, constant, linear, quadratic
45
+ # position:: the x,y,z position or vector position
46
+ # diffuse:: the r,g,b value of the diffuse color
47
+ # specular:: the r,g,b value of the specular color
48
+ # attenuation:: arguments are range, constant, linear, quadratic
49
49
  # range is how far the light will extend
50
50
  # constant The constant factor in the attenuation formula: 1.0 means never attenuate, 0.0 is complete attenuation
51
51
  # linear The linear factor in the attenuation formula: 1 means attenuate evenly over the distance
@@ -53,18 +53,19 @@ module ShatteredView #:nodoc:
53
53
  #
54
54
  # Directional Light - this light is like the positional light, except instead of position it has only direction
55
55
  # Example: light :sun, :direction => [0,-1,-1], :diffuse => [1,1,1], :specular => [1,1,1]
56
- # :direction: the direction light emanates from
57
- # : other : same as point light above.
56
+ # direction:: the direction light emanates from
57
+ # other:: same as point light above.
58
58
  #
59
+ # Note: The following type of light is not currently implemented in shattered.
59
60
  # Spotlight - this light has both a direction and a position, as well as other factors.
60
61
  # Example: light :flashlight...
61
- # TODO: This type of light is not currently implemented in shattered.
62
62
 
63
63
  def light(name, options = {})
64
64
  before_init_set "self", {:new_light => [name]}
65
65
  before_init_set name, options
66
66
  end
67
67
 
68
+ # The following is not yet implemented:
68
69
  # Particle systems are defined in .particle files
69
70
  # - This works for first order particle systems --
70
71
  # - We need to look into second and third order particle systems
@@ -78,8 +79,12 @@ module ShatteredView #:nodoc:
78
79
  end
79
80
 
80
81
  class Base < ShatteredPack::Base
81
- attr_reader :meshes
82
- attr_accessor :model
82
+ attr_accessor :controller, :model
83
+ attr_reader :lights
84
+
85
+ def visible=(visible)
86
+ node.visible=(visible)
87
+ end
83
88
 
84
89
  def rotate(vector, amount)
85
90
  node.rotate(vector, amount)
@@ -107,13 +112,20 @@ module ShatteredView #:nodoc:
107
112
  end
108
113
 
109
114
  def new_light=(name)
110
- define_accessor("@lights", ShatteredView::Light.new, name)
115
+ #define_accessor("@lights", ShatteredView::Light.new, name)
116
+ @lights ||= {}
117
+ name = name.to_sym
118
+ @lights[name] = Light.new
119
+ self.class.send(:define_method, name) do
120
+ @lights[name]
121
+ end
111
122
  end
112
123
 
113
124
  def new_particle_system=(name, template)
114
125
  define_accessor("@particle_systems", ShatteredView::ParticleSystem.new(template), name)
115
126
  end
116
-
117
127
 
128
+
129
+
118
130
  #Return all of the children attached to this view's scene node
119
131
  def children
120
132
  node.children
@@ -1,11 +1,12 @@
1
1
  module ShatteredView
2
+
2
3
  class Light
3
4
  def light
4
- @light ||= Scene.getSingleton().createLight
5
+ @light ||= ShatteredOgre::Scene.getSingleton().createLight
5
6
  end
6
7
  def direction=(*direction)
7
8
  light.setType(ShatteredOgre::Light::LT_DIRECTIONAL)
8
- light.setDirection(direction.to_v)
9
+ light.setDirection(direction.to_v3)
9
10
  end
10
11
  def diffuse=(r,g,b)
11
12
  light.setDiffuseColour(r,g,b)
@@ -15,10 +16,10 @@ module ShatteredView
15
16
  end
16
17
  def position=(pos)
17
18
  light.setType(ShatteredOgre::Light::LT_POINT)
18
- light.setPosition(pos.to_v)
19
+ light.setPosition(pos.to_v3)
19
20
  end
20
21
  def ambient=(r,g,b)
21
- Scene.getSingleton().setAmbientLight(r,g,b);
22
+ ShatteredOgre::Scene.getSingleton().setAmbientLight(r,g,b);
22
23
  end
23
24
  def attenuation=(range, const, linear, quad)
24
25
  light.setType(ShatteredOgre::Light::LT_POINT)
@@ -35,6 +35,7 @@ module ShatteredView
35
35
  before_init_call( :mesh, file, options )
36
36
  end
37
37
 
38
+ # Note: The following is broken in 0.4
38
39
  # Animations declare helper functions for mesh animations.
39
40
  #
40
41
  # class AnimatedRubyView < ...
@@ -59,6 +60,14 @@ module ShatteredView
59
60
 
60
61
  module InstanceMethods
61
62
 
63
+ public
64
+
65
+ #TODO - Should it be a list like this, or a hash with the name as the index?
66
+ def meshes
67
+ # children.collect { |child| child if child.is_a? Mesh }
68
+ @meshes
69
+ end
70
+
62
71
  private
63
72
  def mesh(file, options={})
64
73
  mesh = Mesh.new(file)
@@ -68,10 +77,9 @@ module ShatteredView
68
77
  call_object_function_for_each_key(name, options)
69
78
  #keep track of the meshes we create
70
79
  mesh.attach_to(node)
71
- end
72
-
73
- def meshes
74
- children.collect { |child| child.is_a? Mesh }
80
+ @meshes ||= []
81
+ @meshes << mesh
82
+ mesh
75
83
  end
76
84
 
77
85
  def animation(name, options={})
@@ -83,7 +91,7 @@ module ShatteredView
83
91
  end
84
92
  end
85
93
  EOF
86
- call_object_function_for_each_key(:"#{mesh.name}.#{name}", options)
94
+ call_object_function_for_each_key("#{mesh.name}.#{name}".to_sym, options)
87
95
  end
88
96
  end
89
97
 
@@ -114,6 +122,15 @@ module ShatteredView
114
122
  return @animations[animation]
115
123
  end
116
124
 
125
+ #Set the material on this mesh. Accepts a string or a rmaterial
126
+ def material=( material )
127
+ if material.is_a? RMaterial
128
+ scene_node.generateTangents if material.tangent_space
129
+ material = material.name
130
+ end
131
+ scene_node.setMaterial(material.to_s)
132
+ end
133
+
117
134
  # Remove the Ogre Mesh from the scene
118
135
  def remove_from_scene
119
136
  scene_node.removeFromScene
@@ -90,14 +90,6 @@ module ShatteredView
90
90
  scene_node.scale amount
91
91
  end
92
92
 
93
- def material=( material )
94
- if material.is_a? RMaterial
95
- scene_node.generateTangents if material.tangent_space
96
- material = material.name
97
- end
98
- scene_node.setMaterial(material.to_s)
99
- end
100
-
101
93
  def visible=(visible)
102
94
  scene_node.setVisible(visible)
103
95
  end
@@ -0,0 +1,20 @@
1
+ module ShatteredView
2
+ class Overlay
3
+ attr_reader :name
4
+ def initialize(name)
5
+ @name = name
6
+ hide
7
+ end
8
+ def show
9
+ ShatteredOgre::Scene::getSingleton.showOverlay(name)
10
+ @visible = true
11
+ end
12
+ def hide
13
+ ShatteredOgre::Scene::getSingleton.hideOverlay(name)
14
+ @visible = false
15
+ end
16
+ def visible?
17
+ @visible
18
+ end
19
+ end
20
+ end
@@ -14,7 +14,7 @@ module ShatteredView
14
14
  ShatteredOgre::ResourceHandler.getSingleton.addCustomMaterial(name.to_s, result)
15
15
  end
16
16
  def create_ogre_material=(*args)
17
- load!("#{SHATTERED_ROOT}/media/templates/#{template}.rmaterial")
17
+ load!("#{SHATTERED_ROOT}/app/media/common/templates/#{template}.rmaterial")
18
18
  create_ogre_material!
19
19
  end
20
20
  def method_missing(name, *args)
@@ -22,7 +22,7 @@ module ShatteredView
22
22
  if name.to_s[-1].chr == "="
23
23
  name = name.to_s[0...-1].to_sym
24
24
  # Set the instance variable to the sent variable
25
- ivar = :"@#{ name }"
25
+ ivar = "@#{ name }".to_sym
26
26
  instance_variable_set(ivar, args[0])
27
27
  else
28
28
  begin
@@ -4,14 +4,14 @@ module ShatteredView
4
4
  class Runner #:nodoc:
5
5
  def initialize(options = {})
6
6
  generate_plugin_config
7
- Resources.instance.add_resource_paths("/app/views", "/media")
7
+ Resources.instance.add_resource_paths("/media", "/app/media", "/app/views")
8
8
  @renderer = ShatteredOgre::Renderer.new
9
9
  raise Error, "Renderer failed to initialize Ogre" if @renderer.failed
10
10
  @scene = ShatteredOgre::Scene.new(translate_to_scene_type(options[:scene_manager]))
11
11
  end
12
12
  def generate_plugin_config
13
- plugin_directory = SHATTERED_ROOT+"/config/"
14
- generated_plugin = plugin_directory+ "plugins."
13
+ plugin_directory = SHATTERED_ROOT+"/config/"
14
+ generated_plugin = plugin_directory+ "plugins."
15
15
  generator = plugin_directory + "ogre_plugins.rcfg"
16
16
  if PLATFORM =~ /mswin/
17
17
  generated_plugin += "win32"
@@ -22,13 +22,13 @@ module ShatteredView
22
22
  end
23
23
  process_plugin(generator, generated_plugin+".cfg")
24
24
  end
25
- def process_plugin(base, generate_to)
25
+ def process_plugin(base, generate_to)
26
26
  puts "Generating #{generate_to} from #{base}, #{File.exists?(base)}"
27
27
  return unless File.exists?(base)
28
28
  generated_banner = "\n\r//=== This file is generated. Modify the .rcfg instead. ===\n\r\n\r"
29
29
  to_write = generated_banner + ERB.new(File.open(base,"r").read).result + generated_banner
30
- output = File.open(generate_to, "w")
31
- output.syswrite(to_write)
30
+ output = File.open(generate_to, "w")
31
+ output.syswrite(to_write)
32
32
  output.close
33
33
  end
34
34
  def translate_to_scene_type( symbol )
@@ -36,6 +36,11 @@ class Symbol #:nodoc:
36
36
  def *(number)
37
37
  return to_v * number
38
38
  end
39
+
40
+ # Addition for vectors
41
+ def +(number)
42
+ return to_v + number
43
+ end
39
44
  end
40
45
 
41
46
  class Array #:nodoc:
@@ -223,18 +228,29 @@ class Vector
223
228
  # Equality test. This method will return true if all components of both vectors are
224
229
  # indentical.
225
230
  def ==(vector)
231
+ vector = vector.to_v if vector.is_a?(Symbol)
226
232
  vector.kind_of?(Vector) &&
227
233
  x == vector.x &&
228
234
  y == vector.y &&
229
235
  z == vector.z
230
236
  end
231
237
 
238
+ # Create a unique identifier based on x, y and z.
239
+ def hash
240
+ return self.to_a.hash
241
+ end
242
+
243
+ # Equality test for hash indexes.
244
+ def eql?(other)
245
+ return self.to_a.eql?(other.to_a)
246
+ end
247
+
232
248
  private
233
249
 
234
250
  def convert_args_to_vector(*args)
235
251
  args.flatten!
236
- if args.first.is_a? Vector
237
- args.first
252
+ if(args.first.is_a?(Vector) || args.first.is_a?(Symbol))
253
+ args.first.to_v
238
254
  else
239
255
  args.to_v
240
256
  end
@@ -2,6 +2,7 @@ require 'shattered_ogre'
2
2
  require 'shattered_pack'
3
3
  raise( ShatteredPack::Error, "Could not find ShatteredOgre (a ShatteredView dependency)" ) unless defined? ShatteredOgre
4
4
 
5
- %w(vector utilities node camera extensions runner rmaterial base resources).each do |dependency|
6
- require "shattered_view/#{dependency}"
5
+ %w(vector utilities node camera overlay light extensions runner rmaterial base resources).each do |dependency|
6
+ dependency = "shattered_view/#{dependency}"
7
+ require dependency
7
8
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: shattered_pack
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.3.3
7
- date: 2006-07-18 00:00:00 -06:00
6
+ version: "0.4"
7
+ date: 2006-09-10 00:00:00 -06:00
8
8
  summary: "Shattered Pack: The combination of model/view/controllers and the domain specific language for each."
9
9
  require_paths:
10
10
  - lib
@@ -28,22 +28,28 @@ cert_chain:
28
28
  authors: []
29
29
 
30
30
  files:
31
+ - lib/mock_objects.rb
31
32
  - lib/shattered_controller.rb
32
33
  - lib/shattered_model.rb
33
34
  - lib/shattered_pack.rb
34
35
  - lib/shattered_view.rb
35
- - lib/shattered_controller/base.rb
36
- - lib/shattered_controller/mock_camera.rb
36
+ - lib/mock_objects/shattered_ogre/input.rb
37
+ - lib/mock_objects/shattered_ogre/light.rb
38
+ - lib/mock_objects/shattered_ogre/mesh.rb
39
+ - lib/mock_objects/shattered_ogre/node.rb
40
+ - lib/mock_objects/shattered_ogre/renderer.rb
41
+ - lib/mock_objects/shattered_ogre/resource_handler.rb
42
+ - lib/mock_objects/shattered_ogre/scene.rb
37
43
  - lib/shattered_controller/runner.rb
38
44
  - lib/shattered_controller/state.rb
39
45
  - lib/shattered_controller/actor/actor.rb
40
- - lib/shattered_controller/keyboard_input/key_converter.rb
41
- - lib/shattered_controller/keyboard_input/keyboard_input.rb
42
46
  - lib/shattered_model/base.rb
43
47
  - lib/shattered_model/fuzzy_logic.rb
44
48
  - lib/shattered_model/linear_interpolator.rb
45
49
  - lib/shattered_pack/base.rb
46
50
  - lib/shattered_pack/runner.rb
51
+ - lib/shattered_pack/keyboard_input/key_converter.rb
52
+ - lib/shattered_pack/keyboard_input/keyboard_input.rb
47
53
  - lib/shattered_pack/pre_initialize/pre_initialize.rb
48
54
  - lib/shattered_pack/timer/timed_event.rb
49
55
  - lib/shattered_pack/timer/timer.rb
@@ -52,6 +58,7 @@ files:
52
58
  - lib/shattered_view/extensions.rb
53
59
  - lib/shattered_view/light.rb
54
60
  - lib/shattered_view/node.rb
61
+ - lib/shattered_view/overlay.rb
55
62
  - lib/shattered_view/resources.rb
56
63
  - lib/shattered_view/rmaterial.rb
57
64
  - lib/shattered_view/runner.rb
@@ -1,108 +0,0 @@
1
-
2
- $:.unshift(File.dirname(__FILE__)) unless
3
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
4
-
5
- require 'keyboard_input/keyboard_input'
6
- require 'actor/actor'
7
-
8
- module ShatteredController #:nodoc:
9
-
10
- # Controllers tie together the Model and View. They are the only objects that know
11
- # about both the model and the view, and as such have the responsibility of events.
12
- #
13
- # By default, when an unknown method is invoked on a controller object, it is delegated
14
- # to the model and the view. IE:
15
- #
16
- # class BulletController < ...
17
- # def known_method
18
- # puts "This will not be delegated to the " + model.inspect + " or the " + view.inspect
19
- # end
20
- # end
21
- #
22
- # class BattleState < ...
23
- # actor :bullet
24
- # def initialize
25
- # bullet.known_method # This is not delegated
26
- # bullet.unknown_method # This is delegated (and will throw an exception if unknown among the view/model)
27
- # end
28
- # end
29
- #
30
- # When obtaining a result from a delegated method, the result will be the a response in the following order
31
- # - Model (first)
32
- # - View (last)
33
- #
34
- # They are sorted so that you get the most useful response first.
35
- class Base < ShatteredPack::Base
36
- attr_accessor :model, :view
37
-
38
- before_init_call :disable_event
39
-
40
- def quit
41
- end
42
-
43
- # Controller delegates all unknown methods to the view and model.
44
- def method_missing(method_name, *args, &block)
45
- return if disabled?
46
- raise_no_method_error = true
47
- result = nil
48
- [view, model].each do |delegate|
49
- if delegate.class.method_defined?(method_name)
50
- result = delegate.send(method_name, *args, &block)
51
- raise_no_method_error = false
52
- end
53
- end
54
-
55
- raise NoMethodError, "Model, View, and Controller have no method defined named '#{method_name}'" if raise_no_method_error
56
- return result
57
- end
58
-
59
-
60
- def update_timer(time_elapsed)#:nodoc:
61
- return if @timer == :unloaded
62
- [self, model, view].each do |base|
63
- next if base.nil?
64
- base.time_elapsed = time_elapsed
65
- base.timer.update(time_elapsed)
66
- end
67
- end
68
-
69
- # This is called to the State every frame by the main game loop. All update events are now
70
- # run through Timers.
71
- def update_timers(time_elapsed) #:nodoc:
72
- update_timer(time_elapsed)
73
- actors.each { |actor| actor.update_timers(time_elapsed) }
74
- end
75
-
76
- # Unloading a controller will completely unload an object from the scene.
77
- def unload!
78
- super
79
- end
80
-
81
- # An object is disabled when it has been unloaded.
82
- def disabled?
83
- super
84
- end
85
-
86
- private
87
-
88
- def disable_event
89
- when_unloaded do
90
- @disabled = true
91
- @timer=:unloaded
92
- @model.send(:unload!) if @model
93
- @model = nil
94
- @view.send(:unload!) if @view
95
- @view = nil
96
- end
97
- end
98
- end
99
-
100
- class Error < StandardError #:nodoc:
101
- end
102
- end
103
-
104
- ShatteredController::Base.class_eval do
105
- include ShatteredController::KeyboardInput
106
- include ShatteredController::Actor
107
- end
108
-
@@ -1,43 +0,0 @@
1
- module ShatteredController
2
- # This is a wrapper around Ogre's input listener.
3
- # It allows us to query the status of each device every frame.
4
- class KeyConverter #:nodoc:
5
-
6
- def initialize( ogre_input )
7
- @ogre_input = ogre_input
8
- end
9
- def key_event?( type, key_symbol )
10
- return @ogre_input.send(:"isKey#{type.to_s.capitalize}", self.class.convert(key_symbol))
11
- end
12
- def flush
13
- @ogre_input.flush
14
- end
15
-
16
- def self.back_conversions
17
- @@back_conversions ||= conversions.invert
18
- end
19
- def self.conversions
20
- begin
21
- return @@conversions
22
- rescue NameError
23
- end
24
- @@conversions = {}
25
- ShatteredOgre.constants.each do |constant|
26
- kc_evaled = eval("ShatteredOgre::#{constant}")
27
- @@conversions[kc_evaled] = symbolize(constant[3..-1].downcase) if constant.to_s =~ /^KC_/
28
- end
29
- return @@conversions
30
- end
31
- def self.convert( kc_character )
32
- return self.conversions[kc_character] if kc_character.is_a? Fixnum
33
- return self.back_conversions[kc_character]
34
- end
35
- private
36
- def self.symbolize( name )
37
- exceptions = { 'pgdown' => :page_down,
38
- 'pgup' => :page_up }
39
- return name.to_sym if exceptions[name] == nil
40
- return exceptions[name]
41
- end
42
- end
43
- end
@@ -1,9 +0,0 @@
1
-
2
- module ShatteredController
3
- class MockCamera #:nodoc:
4
- attr_reader :position
5
- def position=(x,y,z)
6
- @position=[x,y,z]
7
- end
8
- end
9
- end