void particlesPhysicsTick( float dt ) { int i; float fadeAmt; /* update the positions of all the particles */ for( i = 0; i <= lastParticle; ++i ) { particles[i].lifeElapsed += dt; fadeAmt = inverseLerp( particles[i].fadeStart, particles[i].lifeTime, particles[i].lifeElapsed ); particles[i].futureColor.a = lerp( 1.0f, 0.0f, fadeAmt ); particles[i].futureScale = lerp( 1.0f, 0.0f, fadeAmt ); particles[i].currRenderPos = particles[i].futureRenderPos; vec2_AddScaled( &particles[i].velocity, &particles[i].gravity, dt, &particles[i].velocity ); vec2_AddScaled( &particles[i].futureRenderPos, &particles[i].velocity, dt, &particles[i].futureRenderPos ); } /* destroy all the dead particles, we won't worry about preserving order but should do some tests to see if doing so will make it more efficient */ for( i = 0; i <= lastParticle; ++i ) { if( particles[i].lifeElapsed >= particles[i].lifeTime ) { particles[i] = particles[lastParticle]; --lastParticle; --i; } } }
void steering_Arrive( Vector2* pos, Vector2* target, float innerRadius, float outerRadius, Vector2* out ) { assert( pos != NULL ); assert( target != NULL ); assert( out != NULL ); assert( innerRadius <= outerRadius ); vec2_Subtract( target, pos, out ); float dist = vec2_Normalize( out ); float speed = inverseLerp( innerRadius, outerRadius, dist ); vec2_Scale( out, speed, out ); }
// stereo LRLRLR order void mixerCallback( void* userdata, Uint8* streamData, int len ) { memset( streamData, len, workingSilence ); memset( workingBuffer, 0, workingBufferSize ); if( workingBuffer == NULL ) { return; } int numSamples = ( len / WORKING_CHANNELS ) / ( ( SDL_AUDIO_MASK_BITSIZE & WORKING_FORMAT ) / 8 ); #if 0 int soundFreq = 440; // wave length float step = 1.0f / WORKING_RATE; // for testing audio output for( int s = 0; s < numSamples; ++s ) { int streamIdx = ( s * WORKING_CHANNELS ); testTimePassed += 1.0f / WORKING_RATE; float v = sinf( testTimePassed * soundFreq * M_TWO_PI_F ); workingBuffer[streamIdx] = v * 0.1f; workingBuffer[streamIdx+1] = v * 0.1f; } #else // advance each playing sound for( EntityID id = idSet_GetFirstValidID( &playingIDSet ); id != INVALID_ENTITY_ID; id = idSet_GetNextValidID( &playingIDSet, id ) ) { int i = idSet_GetIndex( id ); Sound* snd = &( playingSounds[i] ); Sample* sample = &( samples[snd->sample] ); // for right now lets assume the pitch will stay the same, when we get it working it'll just involve // changing the speed at which we move through the array bool soundDone = false; float volume = snd->volume * sbSoundGroups[snd->group].volume * masterVolume; for( int s = 0; ( s < numSamples ) && !soundDone; ++s ) { int streamIdx = ( s * WORKING_CHANNELS ); // we're assuming stereo output here if( sample->numChannels == 1 ) { float data = sample->data[(int)snd->pos] * volume; /* left */ workingBuffer[streamIdx] += data * inverseLerp( 1.0f, 0.0f, snd->pan ); /* right */ workingBuffer[streamIdx+1] += data * inverseLerp( -1.0f, 0.0f, snd->pan ); snd->pos += snd->pitch; } else { // if the sample is stereo then we ignore panning // NOTE: Pitch change doesn't work with stereo samples yet workingBuffer[streamIdx] += sample->data[(int)snd->pos] * volume; workingBuffer[streamIdx+1] += sample->data[(int)snd->pos+1] * volume; snd->pos += 2.0f; } if( snd->pos >= sample->numSamples ) { if( sample->loops ) { snd->pos -= (float)sample->numSamples; } else { soundDone = true; } } } if( soundDone ) { idSet_ReleaseID( &playingIDSet, id ); // this doesn't invalidate the id for the loop } } for( int i = 0; i < MAX_STREAMING_SOUNDS; ++i ) { if( !streamingSounds[i].playing ) continue; StreamingSound* stream = &( streamingSounds[i] ); bool soundDone = false; float volume = stream->volume * sbSoundGroups[stream->group].volume * masterVolume; // if the next buffer fill would be past what we have loaded then load some more // note: the SDL_AudioStreamAvailable return value is in bytes while( ( SDL_AudioStreamAvailable( stream->sdlStream ) < len ) && !( stream->readDone ) ) { int read = 0; int request = STREAM_READ_BUFFER_SIZE / sizeof( short ); size_t test = ARRAY_SIZE( streamReadBuffer ); // returns the number of samples stored per channel int samplesPerChannel = stb_vorbis_get_samples_short_interleaved( stream->access, stream->access->channels, streamReadBuffer, request ); read = samplesPerChannel * sizeof( short ); SDL_AudioStreamPut( stream->sdlStream, streamReadBuffer, samplesPerChannel * stream->channels * sizeof( short ) ); // reached the end of the file, are we looping? if( read != request ) { if( stream->loops ) { stb_vorbis_seek_start( stream->access ); } else { stream->readDone = true; SDL_AudioStreamFlush( stream->sdlStream ); } } } // read data from the audio stream until there is no more left or the end of the buffer to fill int bytesToStream = numSamples * stream->channels * sizeof( sbStreamWorkingBuffer[0] ); sb_Reserve( sbStreamWorkingBuffer, (size_t)bytesToStream ); int gotten = SDL_AudioStreamGet( stream->sdlStream, sbStreamWorkingBuffer, bytesToStream ); if( gotten < 0 ) { llog( LOG_ERROR, "Error reading from sdlStream: %s", SDL_GetError( ) ); stream->playing = false; continue; } else if( gotten == 0 ) { // end of stream stream->playing = false; } int samplesGotten = gotten / ( stream->channels * sizeof( sbStreamWorkingBuffer[0] ) ); for( int s = 0; s < samplesGotten; ++s ) { // then just mix those samples int streamIdx = ( s * WORKING_CHANNELS ); int workingIdx = ( s * stream->channels ); // we're assuming stereo output here if( stream->access->channels == 1 ) { float data = sbStreamWorkingBuffer[workingIdx] * volume; workingBuffer[streamIdx] += data * inverseLerp( 1.0f, 0.0f, stream->pan ); // left workingBuffer[streamIdx+1] += data * inverseLerp( -1.0f, 0.0f, stream->pan ); // right } else { // if the sample is stereo then we ignore panning workingBuffer[streamIdx] += sbStreamWorkingBuffer[workingIdx] * volume; workingBuffer[streamIdx+1] += sbStreamWorkingBuffer[workingIdx + 1] * volume; } } } #endif memcpy( streamData, workingBuffer, len ); }
/** * Draws a graph representing fpsqueue to the screen at (xpos, ypos) (the bottom left corner). * Lots of magic numbers, but it looks good for now. */ void FpsGraph::Draw(float x, float y, float w, float h, std::string label) { float baseY = y + h; //Bottom of the graph float displayedFPS = 0.0f; if (fpsqueue.size() > 0) displayedFPS = fpsqueue.at(0); //Draw label if (label.empty()) { label = "FPS"; } ofSetColor(255, 255, 255); ofDrawBitmapString(label, x - 1, y - 7); //Draw background box ofSetColor(0, 0, 0); ofRect(x, y, w, h); //Draw graph ofSetHexColor(0x43A047); ofPolyline graphLine; for (int i = queueSize - 1; i>= 0; i--) { float fps = fpsqueue.at(i); float innerX = inverseLerp(0, queueSize - 1, i) * w; float innerY = inverseLerp(lowerFpsLine, upperFpsLine, fps) * h; //if (fillGraph) graphLine.addVertex(x + innerX, y + 0); graphLine.addVertex(x + w - innerX, baseY - innerY); } if (fillGraph) { //Add closing vertices along bottom of graph graphLine.addVertex(x + w, baseY); graphLine.addVertex(x, baseY); //Close //graphLine.close(); //graphLine.draw(); //OpenGL method (faster) ofBeginShape(); for (int i = 0; i < graphLine.getVertices().size(); i++) { ofVertex(graphLine.getVertices().at(i).x, graphLine.getVertices().at(i).y); } ofEndShape(); } else { graphLine.draw(); } //Draw target line ofSetColor(255, 0, 0); ofPolyline targetLine; float targetLineInnerY = inverseLerp(lowerFpsLine, upperFpsLine, targetFps) * h; targetLine.addVertex(x, baseY - targetLineInnerY); targetLine.addVertex(x + w, baseY - targetLineInnerY); targetLine.draw(); //Draw target line FPS ofDrawBitmapString(ofToString(targetFps, 0), x + 3, baseY - targetLineInnerY + 12); //Draw FPS string ofSetColor(255, 255, 255); if (displayedFPS < targetFps) ofSetColor(255, 0, 0); ofDrawBitmapString(ofToString(displayedFPS, 0), x + 3, y + 10); //Draw border box ofSetColor(255); ofPolyline rect; rect.addVertex(x, y); rect.addVertex(x + w, y); rect.addVertex(x + w, y + h); rect.addVertex(x, y + h); rect.addVertex(x, y); //Close rect.draw(); ofSetColor(255); }