Mercurial > hg > beaglert
comparison projects/tank_wars/render.cpp @ 108:3068421c0737 ultra-staging
Merged default into ultra-staging
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Tue, 18 Aug 2015 00:35:15 +0100 |
parents | 3c3a1357657d |
children | 8d80eda512cd |
comparison
equal
deleted
inserted
replaced
54:d3f869b98147 | 108:3068421c0737 |
---|---|
4 * Created on: Oct 24, 2014 | 4 * Created on: Oct 24, 2014 |
5 * Author: parallels | 5 * Author: parallels |
6 */ | 6 */ |
7 | 7 |
8 | 8 |
9 #include "../../include/RTAudio.h" | 9 #include <BeagleRT.h> |
10 #include "../../include/Utilities.h" | 10 #include <Utilities.h> |
11 #include "game.h" | 11 #include "game.h" |
12 #include <rtdk.h> | 12 #include <rtdk.h> |
13 #include <cmath> | 13 #include <cmath> |
14 #include <cstdlib> | 14 #include <cstdlib> |
15 #include <time.h> | 15 #include <time.h> |
76 float gSoundProjectileOscillatorGain = 0.2; | 76 float gSoundProjectileOscillatorGain = 0.2; |
77 float gOscillatorPhaseScaler = 0; | 77 float gOscillatorPhaseScaler = 0; |
78 | 78 |
79 void screen_update(); | 79 void screen_update(); |
80 | 80 |
81 // initialise_render() is called once before the audio rendering starts. | 81 // setup() is called once before the audio rendering starts. |
82 // Use it to perform any initialisation and allocation which is dependent | 82 // Use it to perform any initialisation and allocation which is dependent |
83 // on the period size or sample rate. | 83 // on the period size or sample rate. |
84 // | 84 // |
85 // userData holds an opaque pointer to a data structure that was passed | 85 // userData holds an opaque pointer to a data structure that was passed |
86 // in from the call to initAudio(). | 86 // in from the call to initAudio(). |
87 // | 87 // |
88 // Return true on success; returning false halts the program. | 88 // Return true on success; returning false halts the program. |
89 | 89 |
90 bool initialise_render(int numAnalogChannels, int numDigitalChannels, int numAudioChannels, | 90 bool setup(BeagleRTContext *context, void *userData) |
91 int numAnalogFramesPerPeriod, | |
92 int numAudioFramesPerPeriod, | |
93 float analogSampleRate, float audioSampleRate, | |
94 void *userData) | |
95 { | 91 { |
96 srandom(time(NULL)); | 92 srandom(time(NULL)); |
97 | 93 |
98 // Verify we are running with matrix enabled | 94 // Verify we are running with matrix enabled |
99 if(numAnalogFramesPerPeriod == 0 || numAnalogChannels < 4) { | 95 if(context->analogFrames == 0 || context->analogChannels < 4) { |
100 rt_printf("Error: this example needs the matrix enabled with at least 4 channels\n"); | 96 rt_printf("Error: this example needs the matrix enabled with at least 4 channels\n"); |
101 return false; | 97 return false; |
102 } | 98 } |
103 | 99 |
104 // Initialise audio variables | 100 // Initialise audio variables |
105 gAudioFramesPerMatrixFrame = numAudioFramesPerPeriod / numAnalogFramesPerPeriod; | 101 gAudioFramesPerMatrixFrame = context->audioFrames / context->analogFrames; |
106 gOscillatorPhaseScaler = 2.0 * M_PI / audioSampleRate; | 102 gOscillatorPhaseScaler = 2.0 * M_PI / context->audioSampleRate; |
107 | 103 |
108 // Initialise the screen buffers | 104 // Initialise the screen buffers |
109 gScreenBufferMaxLength = 2 * analogSampleRate / gScreenFramesPerSecond; | 105 gScreenBufferMaxLength = 2 * context->analogSampleRate / gScreenFramesPerSecond; |
110 gScreenBuffer1 = new float[gScreenBufferMaxLength]; | 106 gScreenBuffer1 = new float[gScreenBufferMaxLength]; |
111 gScreenBuffer2 = new float[gScreenBufferMaxLength]; | 107 gScreenBuffer2 = new float[gScreenBufferMaxLength]; |
112 if(gScreenBuffer1 == 0 || gScreenBuffer2 == 0) { | 108 if(gScreenBuffer1 == 0 || gScreenBuffer2 == 0) { |
113 rt_printf("Error initialising screen buffers\n"); | 109 rt_printf("Error initialising screen buffers\n"); |
114 return false; | 110 return false; |
121 gScreenBufferNextUpdateLocation = 0; | 117 gScreenBufferNextUpdateLocation = 0; |
122 gScreenNextBufferReady = false; | 118 gScreenNextBufferReady = false; |
123 | 119 |
124 // Initialise the game | 120 // Initialise the game |
125 setupGame(gScreenWidth, gScreenHeight); | 121 setupGame(gScreenWidth, gScreenHeight); |
126 gGameFrameInterval = analogSampleRate / gGameFramesPerSecond; | 122 gGameFrameInterval = context->analogSampleRate / gGameFramesPerSecond; |
127 gSamplesUntilNextFrame = gGameFrameInterval; | 123 gSamplesUntilNextFrame = gGameFrameInterval; |
128 | 124 |
129 // Initialise auxiliary tasks | 125 // Initialise auxiliary tasks |
130 if((gScreenUpdateTask = createAuxiliaryTaskLoop(&screen_update, 90, | 126 if((gScreenUpdateTask = BeagleRT_createAuxiliaryTask(&screen_update, 90, |
131 "beaglert-screen-update")) == 0) | 127 "beaglert-screen-update")) == 0) |
132 return false; | 128 return false; |
133 | 129 |
134 return true; | 130 return true; |
135 } | 131 } |
136 | 132 |
157 // render() is called regularly at the highest priority by the audio engine. | 153 // render() is called regularly at the highest priority by the audio engine. |
158 // Input and output are given from the audio hardware and the other | 154 // Input and output are given from the audio hardware and the other |
159 // ADCs and DACs (if available). If only audio is available, numMatrixFrames | 155 // ADCs and DACs (if available). If only audio is available, numMatrixFrames |
160 // will be 0. | 156 // will be 0. |
161 | 157 |
162 void render(int numAnalogFrames, int numDigitalFrames, int numAudioFrames, float *audioIn, float *audioOut, | 158 void render(BeagleRTContext *context, void *userData) |
163 float *analogIn, float *analogOut, uint32_t *digital) | |
164 { | 159 { |
165 int audioIndex = 0; | 160 int audioIndex = 0; |
166 | 161 |
167 for(int n = 0; n < numAnalogFrames; n++) { | 162 for(unsigned int n = 0; n < context->analogFrames; n++) { |
168 for(int k = 0; k < gAudioFramesPerMatrixFrame; k++) { | 163 for(int k = 0; k < gAudioFramesPerMatrixFrame; k++) { |
169 // Render music and sound | 164 // Render music and sound |
170 float audioSample = 0; | 165 float audioSample = 0; |
171 | 166 |
172 // Music plays in a loop | 167 // Music plays in a loop |
191 1.0, 0, 300, 2000), 200, 6000); | 186 1.0, 0, 300, 2000), 200, 6000); |
192 if(gSoundProjectileOscillatorPhase > 2.0 * M_PI) | 187 if(gSoundProjectileOscillatorPhase > 2.0 * M_PI) |
193 gSoundProjectileOscillatorPhase -= 2.0 * M_PI; | 188 gSoundProjectileOscillatorPhase -= 2.0 * M_PI; |
194 } | 189 } |
195 | 190 |
196 audioOut[2*audioIndex] = audioOut[2*audioIndex + 1] = audioSample; | 191 context->audioOut[2*audioIndex] = context->audioOut[2*audioIndex + 1] = audioSample; |
197 audioIndex++; | 192 audioIndex++; |
198 } | 193 } |
199 | 194 |
200 // First-order lowpass filter to remove noise on launch FSR | 195 // First-order lowpass filter to remove noise on launch FSR |
201 float rawSample = AnalogRead(gInputLauncher, n); | 196 float rawSample = analogReadFrame(context, n, gInputLauncher); |
202 float launchSample = gLauncherFilterPole * gLauncherLastSample + | 197 float launchSample = gLauncherFilterPole * gLauncherLastSample + |
203 (1.0f - gLauncherFilterPole) * rawSample; | 198 (1.0f - gLauncherFilterPole) * rawSample; |
204 gLauncherLastSample = launchSample; | 199 gLauncherLastSample = launchSample; |
205 | 200 |
206 // Peak-detect on launch signal | 201 // Peak-detect on launch signal |
230 | 225 |
231 if(--gSamplesUntilNextFrame <= 0) { | 226 if(--gSamplesUntilNextFrame <= 0) { |
232 // Update game physics and cannon angles | 227 // Update game physics and cannon angles |
233 gSamplesUntilNextFrame = gGameFrameInterval; | 228 gSamplesUntilNextFrame = gGameFrameInterval; |
234 | 229 |
235 setTank1CannonAngle(map(AnalogRead(gInputTank1Angle, n), | 230 setTank1CannonAngle(map(analogReadFrame(context, n, gInputTank1Angle), |
236 0, 1.0, M_PI, 0)); | 231 0, 1.0, M_PI, 0)); |
237 setTank2CannonAngle(map(AnalogRead(gInputTank2Angle, n), | 232 setTank2CannonAngle(map(analogReadFrame(context, n, gInputTank2Angle), |
238 0, 1.0, M_PI, 0)); | 233 0, 1.0, M_PI, 0)); |
239 nextGameFrame(); | 234 nextGameFrame(); |
240 | 235 |
241 // Check for collision and start sound accordingly | 236 // Check for collision and start sound accordingly |
242 if(gameStatusCollisionOccurred()) { | 237 if(gameStatusCollisionOccurred()) { |
255 float x = gScreenBufferRead[gScreenBufferReadPointer++]; | 250 float x = gScreenBufferRead[gScreenBufferReadPointer++]; |
256 float y = gScreenBufferRead[gScreenBufferReadPointer++]; | 251 float y = gScreenBufferRead[gScreenBufferReadPointer++]; |
257 | 252 |
258 // Rescale screen coordinates to matrix ranges; invert the Y | 253 // Rescale screen coordinates to matrix ranges; invert the Y |
259 // coordinate to go from normal screen coordinates to scope coordinates | 254 // coordinate to go from normal screen coordinates to scope coordinates |
260 AnalogWriteFrame(gOutputX, n, constrain(map(x, 0, gScreenWidth, 0, 1.0), 0, 1.0)); | 255 analogWriteFrameOnce(context, n, gOutputX, constrain(map(x, 0, gScreenWidth, 0, 1.0), 0, 1.0)); |
261 AnalogWriteFrame(gOutputY, n, constrain(map(y, 0, gScreenHeight, 1.0, 0), 0, 1.0)); | 256 analogWriteFrameOnce(context, n, gOutputY, constrain(map(y, 0, gScreenHeight, 1.0, 0), 0, 1.0)); |
262 } | 257 } |
263 else { | 258 else { |
264 // Still not ready! Write 0 until something happens | 259 // Still not ready! Write 0 until something happens |
265 AnalogWriteFrame(gOutputX, n, 0); | 260 analogWriteFrameOnce(context, n, gOutputX, 0); |
266 AnalogWriteFrame(gOutputY, n, 0); | 261 analogWriteFrameOnce(context, n, gOutputY, 0); |
267 } | 262 } |
268 | 263 |
269 if(gameStatusWinner() != 0) { | 264 if(gameStatusWinner() != 0) { |
270 // Blink one LED to show who won | 265 // Blink one LED to show who won |
271 // Blink both LEDs when projectile is in motion | 266 // Blink both LEDs when projectile is in motion |
272 float val = (gSampleCounter % 4000 > 2000) ? 1.0 : 0; | 267 float val = (gSampleCounter % 4000 > 2000) ? 1.0 : 0; |
273 AnalogWriteFrame(gOutputPlayer1LED, n, gameStatusWinner() == 1 ? val : 0); | 268 analogWriteFrameOnce(context, n, gOutputPlayer1LED, gameStatusWinner() == 1 ? val : 0); |
274 AnalogWriteFrame(gOutputPlayer2LED, n, gameStatusWinner() == 2 ? val : 0); | 269 analogWriteFrameOnce(context, n, gOutputPlayer2LED, gameStatusWinner() == 2 ? val : 0); |
275 | 270 |
276 // After 5 seconds, restart the game | 271 // After 5 seconds, restart the game |
277 gSamplesSinceFinish++; | 272 gSamplesSinceFinish++; |
278 if(gSamplesSinceFinish > 22050*5) | 273 if(gSamplesSinceFinish > 22050*5) |
279 gGameShouldRestart = true; | 274 gGameShouldRestart = true; |
280 } | 275 } |
281 else if(gameStatusProjectileInMotion()) { | 276 else if(gameStatusProjectileInMotion()) { |
282 // Blink both LEDs when projectile is in motion | 277 // Blink both LEDs when projectile is in motion |
283 float val = (gSampleCounter % 2000 > 1000) ? 1.0 : 0; | 278 float val = (gSampleCounter % 2000 > 1000) ? 1.0 : 0; |
284 AnalogWriteFrame(gOutputPlayer1LED, n, val); | 279 analogWriteFrameOnce(context, n, gOutputPlayer1LED, val); |
285 AnalogWriteFrame(gOutputPlayer2LED, n, val); | 280 analogWriteFrameOnce(context, n, gOutputPlayer2LED, val); |
286 } | 281 } |
287 else if(gameStatusPlayer1Turn()) { | 282 else if(gameStatusPlayer1Turn()) { |
288 AnalogWriteFrame(gOutputPlayer1LED, n, 1.0); | 283 analogWriteFrameOnce(context, n, gOutputPlayer1LED, 1.0); |
289 AnalogWriteFrame(gOutputPlayer2LED, n, 0); | 284 analogWriteFrameOnce(context, n, gOutputPlayer2LED, 0); |
290 } | 285 } |
291 else { | 286 else { |
292 AnalogWriteFrame(gOutputPlayer2LED, n, 1.0); | 287 analogWriteFrameOnce(context, n, gOutputPlayer2LED, 1.0); |
293 AnalogWriteFrame(gOutputPlayer1LED, n, 0); | 288 analogWriteFrameOnce(context, n, gOutputPlayer1LED, 0); |
294 } | 289 } |
295 | 290 |
296 // Check if we have reached the point where we should next update | 291 // Check if we have reached the point where we should next update |
297 if(gScreenBufferReadPointer >= gScreenBufferNextUpdateLocation && | 292 if(gScreenBufferReadPointer >= gScreenBufferNextUpdateLocation && |
298 !gScreenNextBufferReady) { | 293 !gScreenNextBufferReady) { |
299 // Update the screen at lower priority than the audio thread | 294 // Update the screen at lower priority than the audio thread |
300 scheduleAuxiliaryTask(gScreenUpdateTask); | 295 BeagleRT_scheduleAuxiliaryTask(gScreenUpdateTask); |
301 } | 296 } |
302 | 297 |
303 gSampleCounter++; | 298 gSampleCounter++; |
304 } | 299 } |
305 } | 300 } |
318 | 313 |
319 // Flag it as ready to go | 314 // Flag it as ready to go |
320 gScreenNextBufferReady = true; | 315 gScreenNextBufferReady = true; |
321 } | 316 } |
322 | 317 |
323 // cleanup_render() is called once at the end, after the audio has stopped. | 318 // cleanup() is called once at the end, after the audio has stopped. |
324 // Release any resources that were allocated in initialise_render(). | 319 // Release any resources that were allocated in setup(). |
325 | 320 |
326 void cleanup_render() | 321 void cleanup(BeagleRTContext *context, void *userData) |
327 { | 322 { |
328 // Clean up the game state | 323 // Clean up the game state |
329 cleanupGame(); | 324 cleanupGame(); |
330 } | 325 } |