OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef FLOCK_H_ | |
6 #define FLOCK_H_ | |
7 | |
8 #include <string> | |
9 #include <tr1/memory> | |
10 #include <vector> | |
11 | |
12 #include "boost/scoped_ptr.hpp" | |
13 #include "nacl_app/goose.h" | |
14 #include "nacl_app/locking_image_data.h" | |
15 #include "nacl_app/frame_counter.h" | |
16 #include "nacl_app/scoped_pixel_lock.h" | |
17 #include "nacl_app/sprite.h" | |
18 #include "nacl_app/vector2.h" | |
19 #include "ppapi/cpp/point.h" | |
20 #include "ppapi/cpp/rect.h" | |
21 #include "ppapi/cpp/size.h" | |
22 #include "threading/condition_lock.h" | |
23 #include "threading/pthread_ext.h" | |
24 | |
25 namespace flocking_geese { | |
26 // The main object that runs a simple flocking simulation. This object owns | |
27 // a flock of Geese. See: | |
28 // http://processingjs.org/learning/topic/flocking with references to | |
29 // http://harry.me/2011/02/17/neat-algorithms---flocking. | |
30 class Flock { | |
31 public: | |
32 // The possible simulation modes. | |
33 enum SimulationMode { | |
34 kRunning, // Running simulation ticks. | |
35 kRenderThrottle, // Waiting for the browser to catch up. | |
36 kPaused | |
37 }; | |
38 | |
39 Flock(); | |
40 virtual ~Flock(); | |
41 | |
42 // Start up the simulation thread. The simultion is started in paused | |
43 // mode, to get the simulation running you have to set the simulation | |
44 // mode to kRunning (see set_simulaiton_mode()); | |
45 void StartSimulation(); | |
46 | |
47 // Resize the simulation to |size|. The new dimensions are used as the | |
48 // boundaries for the geese. | |
49 void Resize(const pp::Size& size); | |
50 | |
51 // Create a flock of geese. The geese start at the given location with | |
52 // random velocities. Any previous geese are deleted and the simulation | |
53 // starts with an entirely new flock. | |
54 // @param size The size of the flock. | |
55 // @param initialLocation The initial location of each goose in the flock. | |
56 void ResetFlock(size_t size, const Vector2& initialLocation); | |
57 | |
58 // Run one tick of the simulation. This records the tick duration. | |
59 void SimulationTick(); | |
60 | |
61 // Render the flock into the shared pixel buffer. Clears the rendering | |
62 // throttle. | |
63 void Render(); | |
64 | |
65 // Sleep on the condition that the current simulation mode is not the | |
66 // paused mode. Returns the new run mode. | |
67 SimulationMode WaitForRunMode(); | |
68 | |
69 // Set the location of the attractor at the specified index. The array of | |
70 // attractors is expanded to include |index|. | |
71 void SetAttractorAtIndex(const Vector2& attractor, size_t index); | |
72 | |
73 SimulationMode simulation_mode() const { | |
74 return static_cast<SimulationMode>(simulation_mode_.condition_value()); | |
75 } | |
76 void set_simulation_mode(SimulationMode new_mode); | |
77 | |
78 double FrameRate() const { | |
79 return frame_counter_.frames_per_second(); | |
80 } | |
81 | |
82 void set_pixel_buffer( | |
83 const std::tr1::shared_ptr<LockingImageData>& pixel_buffer) { | |
84 shared_pixel_buffer_ = pixel_buffer; | |
85 } | |
86 | |
87 // Flock takes ownership of |goose_sprite|. The caller should not reference | |
88 // the pointer after this call. | |
89 void set_goose_sprite(Sprite* goose_sprite) { | |
90 goose_sprite_.reset(goose_sprite); | |
91 } | |
92 // Return |true| if the goose sprite data has been set. | |
93 bool has_goose_sprite() const { | |
94 return goose_sprite_ != NULL; | |
95 } | |
96 | |
97 pthread_mutex_t* simulation_mutex() { | |
98 return &flock_simulation_mutex_; | |
99 } | |
100 | |
101 // Set the condition lock to indicate whether the simulation thread is | |
102 // running. | |
103 bool is_simulation_running() const { | |
104 return sim_state_condition_.condition_value() != kSimulationStopped; | |
105 } | |
106 void set_is_simulation_running(bool flag) { | |
107 sim_state_condition_.Lock(); | |
108 sim_state_condition_.UnlockWithCondition( | |
109 flag ? kSimulationRunning : kSimulationStopped); | |
110 } | |
111 | |
112 // The simulation tick counter is locked by the simulation mode. | |
113 int32_t tick_counter() const { | |
114 return tick_counter_; | |
115 } | |
116 void set_tick_counter(int32_t count) { | |
117 tick_counter_ = count; | |
118 } | |
119 int32_t increment_tick_counter() { | |
120 return ++tick_counter_; | |
121 } | |
122 | |
123 private: | |
124 // The state of the main simulation thread. These are values that the | |
125 // simulation condition lock can have. | |
126 enum SimulationState { | |
127 kSimulationStopped, | |
128 kSimulationRunning | |
129 }; | |
130 | |
131 // The main simulation loop. This loop runs the Life simulation. |param| is | |
132 // a pointer to the Life instance. This routine is run on its own thread. | |
133 static void* FlockSimulation(void* param); | |
134 | |
135 // Thread support variables. | |
136 pthread_t flock_simulation_thread_; | |
137 pthread_mutex_t flock_simulation_mutex_; | |
138 threading::ConditionLock sim_state_condition_; | |
139 std::tr1::shared_ptr<LockingImageData> shared_pixel_buffer_; | |
140 | |
141 // Simulation variables. | |
142 pp::Rect flockBounds_; | |
143 threading::ConditionLock simulation_mode_; | |
144 std::vector<Goose> geese_; | |
145 std::vector<Vector2> attractors_; | |
146 FrameCounter frame_counter_; | |
147 int32_t tick_counter_; // Number of sim ticks between Render() calls. | |
148 | |
149 // Drawing support. | |
150 boost::scoped_ptr<Sprite> goose_sprite_; | |
151 }; | |
152 | |
153 } // namespace flocking_geese | |
154 | |
155 #endif // FLOCK_H_ | |
156 | |
OLD | NEW |