瀏覽代碼

Merge branch 'next' of https://github.com/blackberry-gaming/GamePlay into next-ablake

Adam Blake 14 年之前
父節點
當前提交
0b68e36d2f

+ 1 - 0
gameplay/gameplay.vcxproj

@@ -177,6 +177,7 @@
     <ClInclude Include="src\TextBox.h" />
     <ClInclude Include="src\Texture.h" />
     <ClInclude Include="src\Theme.h" />
+    <ClInclude Include="src\TimeListener.h" />
     <ClInclude Include="src\Touch.h" />
     <ClInclude Include="src\Transform.h" />
     <ClInclude Include="src\Vector2.h" />

+ 4 - 1
gameplay/gameplay.vcxproj.filters

@@ -524,6 +524,9 @@
     <ClInclude Include="src\PhysicsCharacter.h">
       <Filter>src</Filter>
     </ClInclude>
+    <ClInclude Include="src\TimeListener.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="res\shaders\bumped-specular.vsh">
@@ -658,4 +661,4 @@
       <Filter>src</Filter>
     </None>
   </ItemGroup>
-</Project>
+</Project>

+ 35 - 0
gameplay/src/Game.cpp

@@ -177,6 +177,9 @@ void Game::frame()
 
         // Update the scheduled and running animations.
         _animationController->update(elapsedTime);
+
+        // Fire time events to scheduled TimeListeners
+        fireTimeEvents(frameTime);
     
         // Update the physics.
         _physicsController->update(elapsedTime);
@@ -262,6 +265,13 @@ void Game::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactI
 {
 }
 
+void Game::schedule(long timeOffset, TimeListener* timeListener, void* cookie)
+{
+    assert(timeListener);
+    TimeEvent timeEvent(getGameTime() + timeOffset, timeListener, cookie);
+    _timeEvents.push(timeEvent);
+}
+
 bool Game::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
 {
     return false;
@@ -281,4 +291,29 @@ void Game::updateOnce()
     _audioController->update(elapsedTime);
 }
 
+void Game::fireTimeEvents(long frameTime)
+{
+    while (!_timeEvents.empty())
+    {
+        TimeEvent* timeEvent = &_timeEvents.top();
+        if (timeEvent->time > frameTime)
+        {
+            break;
+        }
+        timeEvent->listener->timeEvent(frameTime - timeEvent->time, timeEvent->cookie);
+        _timeEvents.pop();
+    }
+}
+
+Game::TimeEvent::TimeEvent(long time, TimeListener* timeListener, void* cookie)
+            : time(time), listener(timeListener), cookie(cookie)
+{
+}
+
+bool Game::TimeEvent::operator<(const TimeEvent& v) const
+{
+    // The first element of std::priority_queue is the greatest.
+    return time > v.time;
+}
+
 }

+ 42 - 0
gameplay/src/Game.h

@@ -1,6 +1,8 @@
 #ifndef GAME_H_
 #define GAME_H_
 
+#include <queue>
+
 #include "Keyboard.h"
 #include "Touch.h"
 #include "Mouse.h"
@@ -8,6 +10,7 @@
 #include "AnimationController.h"
 #include "PhysicsController.h"
 #include "Vector4.h"
+#include "TimeListener.h"
 
 namespace gameplay
 {
@@ -254,6 +257,16 @@ public:
      */
     inline void getAccelerometerValues(float* pitch, float* roll);
 
+    /**
+     * Schedules a time event to be sent to the given TimeListener a given of game milliseconds from now.
+     * Game time stops while the game is paused. A time offset of zero will fire the time event in the next frame.
+     * 
+     * @param timeOffset The number of game milliseconds in the future to schedule the event to be fired.
+     * @param timeListener The TimeListener that will receive the event.
+     * @param cookie The cookie data that the time event will contain.
+     */
+    void schedule(long timeOffset, TimeListener* timeListener, void* cookie = 0);
+
 protected:
 
     /**
@@ -310,6 +323,27 @@ protected:
 
 private:
 
+    /**
+     * TimeEvent represents the event that is sent to TimeListeners as a result of 
+     * calling Game::schedule().
+     */
+    class TimeEvent
+    {
+    public:
+
+        TimeEvent(long time, TimeListener* timeListener, void* cookie);
+        // The comparator is used to determine the order of time events in the priority queue.
+        bool operator<(const TimeEvent& v) const;
+        
+        /**
+         * The game time.
+         * @see Game::getGameTime()
+         */
+        long time;
+        TimeListener* listener;
+        void* cookie;
+    };
+
     /**
      * Constructor.
      *
@@ -327,6 +361,13 @@ private:
      */
     void shutdown();
 
+    /**
+     * Fires the time events that were scheduled to be called.
+     * 
+     * @param frameTime The current game frame time. Used to determine which time events need to be fired.
+     */
+    void fireTimeEvents(long frameTime);
+
     bool _initialized;                          // If game has initialized yet.
     State _state;                               // The game state.
     static long _pausedTimeLast;                // The last time paused.
@@ -342,6 +383,7 @@ private:
     AnimationController* _animationController;  // Controls the scheduling and running of animations.
     AudioController* _audioController;          // Controls audio sources that are playing in the game.
     PhysicsController* _physicsController;      // Controls the simulation of a physics scene and entities.
+    std::priority_queue<TimeEvent> _timeEvents; // Contains the scheduled time events.
 };
 
 }

+ 14 - 0
gameplay/src/PhysicsCharacter.cpp

@@ -147,6 +147,20 @@ void PhysicsCharacter::addAnimation(const char* name, AnimationClip* clip, float
     _animations[name] = a;
 }
 
+AnimationClip* PhysicsCharacter::getAnimation(const char* name)
+{
+    if (name)
+    {
+        // Lookup the specified animation
+        std::map<const char*, CharacterAnimation>::iterator aitr = _animations.find(name);
+        if (aitr != _animations.end())
+        {
+            return aitr->second.clip;
+        }
+    }
+    return NULL;
+}
+
 void PhysicsCharacter::play(const char* name, AnimationFlags flags, float speed, unsigned int blendDuration, unsigned int layer)
 {
     CharacterAnimation* animation = NULL;

+ 1 - 1
gameplay/src/PhysicsCharacter.h

@@ -111,7 +111,7 @@ public:
      *
      * @return The specified animation clip.
      */
-    AnimationClip* getAnimation(const char* name) const;
+    AnimationClip* getAnimation(const char* name);
 
     /**
      * Plays the specified animation.

+ 26 - 0
gameplay/src/TimeListener.h

@@ -0,0 +1,26 @@
+#ifndef TIMELISTENER_H_
+#define TIMELISTENER_H_
+
+namespace gameplay
+{
+
+/**
+ * The TimeListener interface allows a class to be scheduled and called at a later time using Game::schedule().
+ */
+class TimeListener
+{
+public:
+
+    /**
+     * Callback method that is called when the scheduled event is fired.
+     * 
+     * @param timeDiff The time difference between the current game time and the target time.
+     *                 The time differences will always be non-negative because scheduled events will not fire early.
+     * @param cookie The cookie data that was passed when the event was scheduled.
+     */
+    virtual void timeEvent(long timeDiff, void* cookie) = 0;
+};
+
+}
+
+#endif