Project 1 – Gauntlet
Schotter
LibCinder Implementation
Processing/Processing.js Implementation
Text Rain
#include "cinder/app/AppBasic.h" #include "cinder/gl/gl.h" #include "cinder/Text.h" #include "cinder/gl/GlslProg.h" #include "cinder/gl/Texture.h" #include "cinder/Rand.h" #include "cinder/Capture.h" #include "Kinect.h" using namespace ci; using namespace ci::app; using namespace std; /*************************** Messy, but -probably- works ****************************/ class Letter { public: static std::map<char, gl::Texture> textureForCharacter; static std::map<char, float> baselineOffsetForCharacter; static float fontSize; static bool texturesGenerated; Vec2f mPosition; Vec2f mVelocity; Vec2f mAcceleration; char mLetter; Letter(char letter, Vec2f position) { mAcceleration = Vec2f(0, 0.01); mPosition = position; mVelocity = Vec2f(0, 0); mLetter = letter; if (!texturesGenerated) { for(char character = 'A'; character < 'Z'; character++) { float baselineOffset = 0; std::string str(1, character); textureForCharacter[character] = gl::Texture( renderString( str, Font("Arial", fontSize), Color::white(), &baselineOffset ) ); baselineOffsetForCharacter[character] = baselineOffset; } texturesGenerated = true; } } void update() { mVelocity += mAcceleration; mPosition += mVelocity; } void draw() { float brightness = 1 - (mPosition.y / getWindowHeight()); gl::color(Color(1, brightness, brightness )); gl::draw( textureForCharacter[mLetter], mPosition - Vec2f( 0, baselineOffsetForCharacter[mLetter] ) ); } Area frame() { return Area(mPosition + Vec2f(0, baselineOffsetForCharacter[mLetter]), textureForCharacter[mLetter].getSize()); } void detectCollisions(const Surface8u &background) { const Area clippedFrame( frame().getClipBy( background.getBounds() ) ); if (clippedFrame.getWidth() <= 0 || clippedFrame.getHeight() <= 0) return; float sum = 0; // probably bad. hm. uint8_t inc = background.getPixelInc(); const uint8_t *line = background.getData( clippedFrame.getUL() ); for( int32_t y = clippedFrame.y1; y < clippedFrame.y2; ++y ) { const uint8_t *pixel = line; for( int32_t x = clippedFrame.x1; x < clippedFrame.x2; ++x ) { if(*pixel > 150) { sum++; } pixel += inc; } line += background.getRowBytes(); } if (sum > 10 && mVelocity.y > 0) { mVelocity.y = 0; } if(sum > 20) { mVelocity.y -= sum * 0.0004; } // mVelocity -= percent * 5; } }; bool Letter::texturesGenerated = false; std::map<char, float> Letter::baselineOffsetForCharacter; std::map<char, gl::Texture> Letter::textureForCharacter; float Letter::fontSize = 18; class TextRainApp : public AppBasic { public: void setup(); void mouseDown( MouseEvent event ); void update(); void draw(); private: std::vector<Letter> letters; void emitRandomLetter(); float mLastEmitTime; float mEmitInterval; float lastEmitLocation; int lastEmitCharacterIndex; Kinect mKinect; gl::Texture mColorTexture, mDepthTexture; Surface8u mDepthSurface; }; void TextRainApp::setup() { setFrameRate(30); mEmitInterval = 1; mLastEmitTime = -mEmitInterval; lastEmitCharacterIndex = 0; lastEmitLocation = 0; mKinect = Kinect( Kinect::Device() ); // the default Device implies the first Kinect connected gl::enableAdditiveBlending(); } void TextRainApp::mouseDown( MouseEvent event ) { } void TextRainApp::emitRandomLetter() { // char character = (char) Rand::randInt(97, 122); string poem = ("A ONE THAT IS NOT COLD IS SCARECLY A ONE AT ALL"); lastEmitCharacterIndex += Rand::randInt(poem.length()); char character = poem[lastEmitCharacterIndex % poem.length()]; if(character == ' ') return; float horizontalEmitLocation = ((float)(lastEmitCharacterIndex % poem.length()) / poem.length()) * getWindowWidth(); Vec2f startPosition = Vec2f(horizontalEmitLocation, -18); lastEmitLocation = horizontalEmitLocation; Letter letter(character, startPosition); letters.push_back(letter); } void TextRainApp::update() { if ((getElapsedSeconds() - mLastEmitTime) > mEmitInterval) { emitRandomLetter(); mLastEmitTime = getElapsedSeconds(); } if( mKinect.checkNewDepthFrame() ) { mDepthTexture = mKinect.getDepthImage(); mDepthSurface = Surface8u( mKinect.getDepthImage() ); } if( mKinect.checkNewColorFrame() ) mColorTexture = mKinect.getColorImage(); } void TextRainApp::draw() { // clear out the window with black gl::clear( Color( 0, 0, 0 ) ); gl::color(Color::white()); if (mColorTexture) { gl::draw(mColorTexture); } for (vector<Letter>::iterator iter = letters.begin(); iter != letters.end();) { iter->update(); iter->draw(); if (mDepthSurface) { iter->detectCollisions(mDepthSurface); } if (iter->mPosition.y > getWindowHeight() || iter->mPosition.y < -1000) { iter = letters.erase(iter); } else { iter = ++iter; } } } CINDER_APP_BASIC( TextRainApp, RendererGl ) |