#include "creature.h" //------------------------------------------------------------------ creature::creature(){ bWander = true; bDrunk = false; bIll = false; range = 40.0f; rangeAlpha = 0; awareness = 0.0f; awarenessAlpha = 0; enthusiasm = ofRandom(5, 25); foodDistance = 0.0f; wanderTimer = 0; engageTimer = 0; outfit.length = 60.0f; outfit.girth = 0.0f; outfit.girthMin = 2.0f; outfit.girthMax = 16.0f; outfit.gap = 12.0f; outfit.spread = 6.0f; outfit.alpha = 180; //catchUpSpeed = 0.005f; catchUpSpeed = 0.0f; angle = 0.0f; speedMin = 0.01f; speedMax = 0.32f; gasser.tank = 1.0f; gasser.burn = 0.001f; // was 0.0005 cycler.phase = 0.0f; cycler.stepper = 0.25f; cycler.cycleMin = 0.08f; cycler.cycleMax = 0.5f; cycler.intensity = 0.0f; cycler.intensityMin = 20.0f; cycler.intensityMax = 60.0f; // trail trail.maxNumPts = 15; trail.color.r = 255; trail.color.g = 255; trail.color.b = 255; trail.color.a = 200; trailTimer = 0; trailRate = 2; // debug bDebugInfo = bDebugRange = false; } //------------------------------------------------------------------ void creature::update() { gas(); condition(); ooomph(); cycle(); leaveTrail(); // not so much absolute as it is expected position(); } //------------------------------------------------------------------ void creature::draw() { // draw needs to show lines // trail can be used to modulate creature size. //trail.draw(); ofFill(); ofSetRectMode(OF_RECTMODE_CENTER); // center around the position ofSetColor(255, 255, 255); // this needs to be moved to update/something whater // logic doesn't belong here. float primary_rotation; float gap; float spread; if (!bIll) { primary_rotation = angle * RAD_TO_DEG; gap = outfit.gap; } else { primary_rotation = angle * RAD_TO_DEG + ofRandom(0, 5.0); gap = outfit.gap + ofRandom(0, 4.0); } if (bEngage) { spread = 0; gap = outfit.gap + ofRandom(10, 50); } else { spread = outfit.spread; gap = outfit.gap; } if (bDrunk) { gap = 0; spread = ofRandom(50, 200); } /* cout << endl << "draw--" << endl << "x: " << (int) pos.x << endl << "y: " << (int) pos.y << endl; */ // this is serious glPushMatrix(); glTranslatef(pos.x, pos.y, 0); glRotatef(primary_rotation, 0, 0, 1); ofEnableAlphaBlending(); // SIDE: A ofSetColor(255, 255, 255, outfit.alpha); glPushMatrix(); glRotatef((spread*(-1.0f)), 0, 0, 1); glPushMatrix(); glRotatef((cycler.sideA*(-1.0f)), 0, -1, 0); ofRect(0, (gap*(-1.0f)), outfit.length, outfit.girth); glPopMatrix(); glPopMatrix(); // SIDE: B ofSetColor(255, 255, 255, outfit.alpha); glPushMatrix(); glRotatef(spread, 0, 0, 1); glPushMatrix(); glRotatef(cycler.sideB, 0, 1, 0); ofRect(0, gap, outfit.length, outfit.girth); glPopMatrix(); glPopMatrix(); ofDisableAlphaBlending(); glPopMatrix(); drawTrail(); drawDebug(); } //------------------------------------------------------------------ void creature::leaveTrail(){ if (0 == trailTimer) { trail.addPoint( ofPoint(pos.x, pos.y, 0) ); } if (trailRate < trailTimer++) trailTimer = 0; } //------------------------------------------------------------------ void creature::drawTrail(){ ofEnableSmoothing(); if (!bEngage) { ofSetColor(255, 255, 255, ofRandom(100, 180)); glLineWidth(0.5); } else { ofSetColor(255, 255, 0, 255); glLineWidth(1.5); } ofNoFill(); ofBeginShape(); glLineWidth(0.5); for (int i = 0; i < trail.pts.size(); i++){ //int if ((trail.pts.size()-2) == i) { ofCurveVertex(pos.x, pos.y); } else { ofCurveVertex( trail.pts[i].x + ofRandom(-2,2)*i, trail.pts[i].y + ofRandom(-2,2)*i ); } } ofEndShape(false); ofDisableSmoothing(); } //------------------------------------------------------------------ void creature::gas(){ if (0 < gasser.tank) { // burn gas gasser.tank -= gasser.burn; if (0 > gasser.tank) gasser.tank = 0.0f; } // food = more gas if (bEngage) gasser.tank += 0.003f; // was 0.003 } //------------------------------------------------------------------ void creature::condition(){ float pct = gasser.tank; // fatness outfit.girth = (1.0f-pct) * outfit.girthMin + (pct) * outfit.girthMax; if (0.2 > pct) { bIll = true; } else { bIll = false; } // awareness awareness = ((1.0f - gasser.tank) * 220.0f) + (range+20.0f); if (bEngage) { awarenessAlpha = 5; } else { awarenessAlpha = 20; } // range if (bWander) { rangeAlpha = 100; } else { rangeAlpha = 200 + (int) ofRandom(0, 55); } // drunkenness - too much gas if (1.1 < pct) { bDrunk = true; } else { bDrunk = false; } // illness } //------------------------------------------------------------------ void creature::ooomph(){ float pct = gasser.tank; catchUpSpeed = (1.0f-pct) * speedMin + (pct) * speedMax; if (bWander) catchUpSpeed *= 0.75f; } //------------------------------------------------------------------ void creature::cycle(){ float pct = gasser.tank; cycler.stepper = pct * 20.0f; cycler.intensity = (1.0f-pct) * cycler.intensityMin + (pct) * cycler.intensityMax; cycler.phase += cycler.stepper * DEG_TO_RAD; cycler.sideA = sin(cycler.phase) * cycler.intensity; cycler.sideB = sin(cycler.phase - PI) * cycler.intensity; } //------------------------------------------------------------------ void creature::position(){ //cout << "in position" << endl; //cout << "wander: " << (bool) bWander << endl; if (bWander) { /************ * careless * ************/ if (0 == wanderTimer) { /* * wander needs to be addressed in degrees cyclically, or something, right now the randomization is in a box and it sucks. - if ill needs to wander to anywhere on screen. - drunk needs to spin. - ill needs to have a bigger number for catch up speed. */ float wander_severity = gasser.tank * 75.0f + 30.0f; float wander_angle = ofRandom(0, 360) * DEG_TO_RAD; // polar to rectangular coords nextPos.x = pos.x + (wander_severity * cos(wander_angle)); // x = r cos q(deg) nextPos.y = pos.y + (wander_severity * sin(wander_angle)); // y = r sin q(deg) // keep inside window if (0 > nextPos.x) { nextPos.x = fabs(nextPos.x) + pos.x; cout << "!! LEFT" << endl; } if (ofGetWidth() < nextPos.x) { nextPos.x = fabs(nextPos.x) - pos.x; cout << "!! RIGHT" << endl; } if (0 > nextPos.y) { nextPos.y = fabs(nextPos.y) + pos.y; cout << "!! TOP" << endl; } if (ofGetHeight() < nextPos.y) { nextPos.y = fabs(nextPos.y) - pos.y; cout << "!! BOTTOM" << endl; } /* cout << endl << "wander--" << endl << "x: " << (float) nextPos.x << endl << "y: " << (float) nextPos.y << endl; */ } if (enthusiasm < wanderTimer++) { wanderTimer = 0; enthusiasm = ofRandom(20, 40); } // hack catch up speed for now //catchUpSpeed = 0.05f; } else { /************** * determined * **************/ if (0 == engageTimer) { nextPos = foodPos; } if (enthusiasm < engageTimer++) { engageTimer = 0; enthusiasm = ofRandom(5, 20); } } // strut to next position strut(nextPos.x, nextPos.y); } //------------------------------------------------------------------ void creature::eatTarget(float x, float y, float foodRadius){ foodPos.x = x; foodPos.y = y; // find distance to food sqrt{(x2-x1)^2+(y2-y1)^2} foodDistance = powf((foodPos.x-pos.x), 2) + powf((foodPos.y-pos.y), 2); foodDistance = sqrt(foodDistance) - foodRadius; // compare distance to awareness // determine object state if (foodDistance <= awareness) { bWander = false; // compare distance to teeth range if (foodDistance <= range) { bEngage = true; } else { bEngage = false; } } else { bWander = true; bEngage = false; } } //------------------------------------------------------------------ void creature::strut(float catchX, float catchY){ //catchUpSpeed = 0.004f; prevPos = pos; pos.x = catchUpSpeed * catchX + (1-catchUpSpeed) * pos.x; pos.y = catchUpSpeed * catchY + (1-catchUpSpeed) * pos.y; angle = atan2(pos.y - prevPos.y, pos.x - prevPos.x); } //------------------------------------------------------------------ void creature::drawDebug(){ if (bDebugRange) { ofEnableSmoothing(); ofEnableAlphaBlending(); // show "awareness" ofSetCircleResolution(60); ofNoFill(); glLineWidth(1.0); ofSetColor(0, 222, 255, awarenessAlpha); ofCircle(pos.x, pos.y, awareness); ofSetCircleResolution(22); // show "teeth" range ofNoFill(); glLineWidth(1.0); ofSetColor(255, 0, 0, rangeAlpha); ofCircle(pos.x, pos.y, range); glLineWidth(1.0); ofDisableSmoothing(); ofDisableAlphaBlending(); } // show info if (bDebugInfo) { ofEnableAlphaBlending(); ofSetColor(255, 255, 255, 100); ofDrawBitmapString( "gas: " + ofToString(gasser.tank, 2) + "\n" + "catch: " + ofToString(catchUpSpeed, 5) + "\n" + "food m: " + ofToString(foodDistance, 1) , pos.x+40, pos.y-40 ); ofDisableAlphaBlending(); } }