/* * $Id: legoman.cpp,v 1.26 2002/07/22 12:07:36 msell Exp $ * * * $Log: legoman.cpp,v $ * Revision 1.26 2002/07/22 12:07:36 msell * Pää kiinni * * Revision 1.25 2002/07/22 01:14:14 msell * Lopetussysteemi * * Revision 1.24 2002/07/21 22:50:39 msell * no message * * Revision 1.23 2002/07/21 20:14:28 msell * no message * * Revision 1.22 2002/07/21 16:37:00 msell * no message * * Revision 1.21 2002/07/21 15:12:16 msell * Äänet enabloitu :) * * Revision 1.20 2002/07/21 15:03:12 msell * Äänet disabloitu * * Revision 1.19 2002/07/19 18:59:46 msell * Alkuhommaa ja säätöä * * Revision 1.18 2002/07/18 23:05:31 msell * Partikkelit ja kakkospelaajan liike * * Revision 1.17 2002/07/17 22:45:54 msell * Ääniä vähän * * Revision 1.16 2002/07/16 19:52:09 jkaarlas * kämmenet hienosäädetty * * Revision 1.15 2002/07/16 07:27:32 jkaarlas * nyt latautuu kämmen. paikka ja väri pitää vielä säätää * * Revision 1.14 2002/07/16 00:42:43 msell * Uusia skyboxeja ja areenan säätöä * * Revision 1.13 2002/07/15 22:03:23 msell * MultiAppearance * * Revision 1.12 2002/07/15 15:22:08 msell * Parantelua * * Revision 1.11 2002/07/14 21:40:43 msell * Conflictit pois, liikkumiset (hyppy, kävely, lyönti), uusi areena * * Revision 1.10 2002/07/14 21:22:39 jkaarlas * skybox ja ukkojen säätö * * Revision 1.9 2002/07/11 18:33:58 jkaarlas * mallit paikoillaan, vaatii säätöä * * Revision 1.8 2002/07/10 22:22:53 msell * Cartoon-rendaus * * Revision 1.7 2002/07/10 21:17:02 msell * Ukon geometrian viilausta * * Revision 1.6 2002/07/10 17:13:44 msell * Törmäystarkastelun parantelua * * Revision 1.5 2002/07/08 22:53:38 msell * Säätöä * * Revision 1.4 2002/07/08 18:28:47 msell * Törmäystä ja ukkoja * * Revision 1.3 2002/07/07 23:21:11 msell * Pientä parantelua * * Revision 1.2 2002/07/07 23:05:22 msell * Osien liimaaminen toisiinsa (kesken) * * Revision 1.1 2002/07/07 17:53:21 msell * Legoukon alku * * * * $Date: 2002/07/22 12:07:36 $ * */ #include "main.h" #include #include "legoman.h" #include "object.h" #include "sphere.h" #include "world.h" #include "legoblocks.h" #include "vector.h" #include "collision.h" #include "objectfactory.h" #include "utils.h" #include "particle.h" #include "fight.h" #include "glapi.h" BodyPart::BodyPart(Legoman *parent, float strength){ this->parent = parent; this->strength = strength; reset(); } void BodyPart::reset(void){ this->energy = 1; this->attached = true; this->immortal = 0; vectorSet(position, 0, 0, 0); vectorSet(momentum, 0, 0, 0); matrixIdentity(rotation); vectorSet(angularmomentum, 0, 0, 0); } void BodyPart::move(void){ if (immortal > 0) immortal--; Object::move(); } void BodyPart::hitForce(float speed, float *speed2, Object *source){ if (parent->isHarmfulObject(source)){ float tolerance = 0.3; if (speed > tolerance){ Sound *sound; sound = hitsound1; float volume = (speed-tolerance)*0.4; if (volume > 1) volume = 1; volume = 1; sound->setVolume(volume); sound->play(30 + random(120)); int i; for (i = 0; i < (int)(speed-0.5); i++){ float vel[3] = {randomf(2)-1, randomf(3), randomf(2)-1}; vectorAdd(vel, speed2); createBlood(position, vel); } //makeDamage(0.1); if (this == parent->head && source == parent->opponent->head){ speed *= 0.1; } makeDamage(speed*0.1); } } else{ Object::hitForce(speed, speed2, source); } } void BodyPart::makeDamage(float amount){ if (strength == 0) return; if (energy == 0) return; if (!parent->opponent->isAlive()) return; if (immortal > 0) return; energy -= amount/strength; if (energy < 0) energy = 0; if (energy == 0){ parent->releasePart(this); } immortal = 30; } Sensor::Sensor(){ } void Sensor::attach(Object *object, float *relativeposition){ vectorCopy(this->relativeposition, relativeposition); this->object = object; update(); update(); update(); update(); } void Sensor::attach(Object *object){ float position[3] = {0, 0, 0}; attach(object, position); } void Sensor::update(void){ vectorCopy(oldposition, position); vectorCopy(oldvelocity, velocity); object->transformPoint(position, relativeposition); vectorSub(velocity, position, oldposition); vectorSub(acceleration, velocity, oldvelocity); //printf("V: %f, %f, %f\n", velocity[0], velocity[1], velocity[2]); } void Sensor::getPosition(float *target){ vectorCopy(target, position); } void Sensor::getVelocity(float *target){ vectorCopy(target, velocity); } void Sensor::getAcceleration(float *target){ vectorCopy(target, acceleration); } //float rightHandOffset[3] = {-0.60, 0.45, 0.0}; float rightHandOffset[3] = {-0.40, 0.45, 0.0}; //float leftHandOffset[3] = {0.60, 0.46, 0.0}; float leftHandOffset[3] = {0.40, 0.46, 0.0}; //float leftPalmOffset[3] = {0.28, -0.3, -0.38}; float leftPalmOffset[3] = {0.08, -0.3, -0.38}; //float rightPalmOffset[3] = {-0.30, -0.3, -0.38}; float rightPalmOffset[3] = {-0.10, -0.3, -0.38}; float waistOffset[3] = {0.0, 0.2, 0.0}; float rightLegOffset[3] = {-0.15, 0.4, 0.0}; float leftLegOffset[3] = {0.1, 0.4, 0.0}; Legoman::Legoman(int side){ this->side = side; int collisiongroup, collisiongrouphand; if (side == PLAYER1){ collisiongroup = COLLISIONGROUP_MAN1; collisiongrouphand = COLLISIONGROUP_MAN1HAND; } if (side == PLAYER2){ collisiongroup = COLLISIONGROUP_MAN2; collisiongrouphand = COLLISIONGROUP_MAN2HAND; } float torsocolor[3], legcolor[3]; if (side == PLAYER1){ vectorSet(torsocolor, 1, 0, 0); vectorSet(legcolor, 0, 0, 1); } else if (side == PLAYER2){ vectorSet(torsocolor, 0, 0, 1); vectorSet(legcolor, 1, 0, 0); } //Legs Mesh* geomLegMesh = createBox(-0.45, 0.45, -BLOCKHEIGHT*LEGHEIGHT/2.0, BLOCKHEIGHT*LEGHEIGHT/2.0, -0.5, 0.5); float tmpScale = 1.0; //Left leg { leftleg = new BodyPart(this, 8); Mesh* leftLegMesh = loadAscModel((char*)LEFTLEGASC, MODELSCALE, leftLegOffset); MeshShape *leftLegGeom = new MeshShape(leftleg, geomLegMesh); leftleg->geometry = leftLegGeom; leftleg->appearance = new MeshAppearance(leftLegMesh); //leftleg->appearance = new MeshAppearance(geomLegMesh); leftleg->appearance->material.setColor(legcolor[0], legcolor[1], legcolor[2], 1); vectorSet(leftleg->position, -0.6, BLOCKHEIGHT*(LEGHEIGHT/2.0), 0); leftleg->setGravity(true); leftleg->setMass(LEGHEIGHT/3.0); leftleg->setCollisionGroup(collisiongroup); } //Right leg { rightleg = new BodyPart(this, 8); Mesh* rightLegMesh = loadAscModel((char*)RIGHTLEGASC, MODELSCALE, rightLegOffset); MeshShape *rightLegGeom = new MeshShape(rightleg, geomLegMesh); rightleg->geometry = rightLegGeom; rightleg->appearance = new MeshAppearance(rightLegMesh); //rightleg->appearance = new MeshAppearance(geomLegMesh); rightleg->appearance->material.setColor(legcolor[0], legcolor[1], legcolor[2], 1); vectorSet(rightleg->position, 0.6, BLOCKHEIGHT*(LEGHEIGHT/2.0), 0); rightleg->setGravity(true); rightleg->setMass(LEGHEIGHT/3.0); rightleg->setCollisionGroup(collisiongroup); } //Waist { waist = new BodyPart(this, 0); Mesh* waistMesh = loadAscModel((char*)WAISTASC, MODELSCALE, waistOffset); MeshAppearance* waistappearance = new MeshAppearance(waistMesh); waistappearance->material.setColor(0, 1, 0, 1); Mesh *waistGeomMesh = createBox(-1 + 0.1, 1 - 0.1, 0, BLOCKHEIGHT*WAISTHEIGHT/2.0, 0.1, 0.4); MeshShape *waistgeometry = new MeshShape(waist, waistGeomMesh); waist->geometry = waistgeometry; waist->appearance = waistappearance; //waist->appearance = new MeshAppearance(waistGeomMesh); vectorSet(waist->position, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT/2.0), 0); waist->setGravity(true); waist->setMass(2*WAISTHEIGHT/3.0); waist->setCollisionGroup(collisiongroup); } //Torso { torso = new BodyPart(this, 4); Mesh* torsoMesh = loadAscModel((char*)TORSOASC, TORSOSCALE); //int i; //for (i = 0; i < torsoMesh->polygoncount; i++) torsoMesh->polygons[i].smooth = false; MeshAppearance* torsoAppearance = new MeshAppearance(torsoMesh); torsoAppearance->material.setColor(torsocolor[0], torsocolor[1], torsocolor[2], 1); Mesh *torsoGeomMesh = createBox(-1, 1, -BLOCKHEIGHT*TORSOHEIGHT/2.0, BLOCKHEIGHT*TORSOHEIGHT/2.0, -0.5, 0.5); MeshShape *torsogeometry = new MeshShape(torso, torsoGeomMesh); torso->geometry = torsogeometry; torso->appearance = torsoAppearance; //torso->appearance = new MeshAppearance(torsoGeomMesh); vectorSet(torso->position, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT/2.0), 0); torso->setGravity(true); torso->setMass(2*TORSOHEIGHT/3.0); torso->setCollisionGroup(collisiongroup); } //Hands //Mesh *handMeshGeom = createBox(-0.4, 0.4, -BLOCKHEIGHT*HANDHEIGHT/2.0, BLOCKHEIGHT*HANDHEIGHT/2.0, -0.5, 0.5); Mesh *handMeshGeom = createBox(-0.2, 0.2, -BLOCKHEIGHT*HANDHEIGHT/2.0, BLOCKHEIGHT*HANDHEIGHT/2.0, -0.5, 0.5); //Left hand { lefthand = new BodyPart(this, 5); Mesh* leftHandMesh = loadAscModel((char*)LEFTARMASC, MODELSCALE, leftHandOffset); Mesh* leftPalmMesh = loadAscModel((char*)LEFTPALMASC, MODELSCALE, leftPalmOffset); MultiAppearance *a = new MultiAppearance(); Appearance *arm = new MeshAppearance(leftHandMesh); Appearance *palm = new MeshAppearance(leftPalmMesh); arm->material.setColor(torsocolor[0], torsocolor[1], torsocolor[2], 1); palm->material.setColor(1, 1, 0, 1); a->addAppearance(arm); a->addAppearance(palm); MeshShape *lefthandgeometry = new MeshShape(lefthand, handMeshGeom); lefthand->geometry = lefthandgeometry; lefthand->appearance = a;//new MeshAppearance(leftHandMesh); //lefthand->appearance = new MeshAppearance(handMeshGeom); //lefthand->appearance->material.setColor(1, 0, 0, 1); vectorSet(lefthand->position, -1.3, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT - HANDHEIGHT/2.0), 0); lefthand->setGravity(true); lefthand->setMass(HANDHEIGHT/3.0); lefthand->setCollisionGroup(collisiongrouphand); } //Right hand { righthand = new BodyPart(this, 5); Mesh* rightHandMesh = loadAscModel((char*)RIGHTARMASC, MODELSCALE, rightHandOffset); Mesh* rightPalmMesh = loadAscModel((char*)RIGHTPALMASC, MODELSCALE, rightPalmOffset); MultiAppearance *a = new MultiAppearance(); Appearance *arm = new MeshAppearance(rightHandMesh); arm->material.setColor(torsocolor[0], torsocolor[1], torsocolor[2], 1); Appearance *palm = new MeshAppearance(rightPalmMesh); palm->material.setColor(1, 1, 0, 1); a->addAppearance(arm); a->addAppearance(palm); MeshShape *righthandgeometry = new MeshShape(righthand, handMeshGeom); righthand->geometry = righthandgeometry; righthand->appearance = a; //righthand->appearance = new MeshAppearance(handMeshGeom); vectorSet(righthand->position, 1.3, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT - HANDHEIGHT/2.0), 0); righthand->setGravity(true); righthand->setMass(HANDHEIGHT/3.0); righthand->setCollisionGroup(collisiongrouphand); } //Head { head = new BodyPart(this, 2); Appearance *headappearance = new HeadAppearance(); float r = BLOCKHEIGHT*HEADHEIGHT/2; /*SphereAppearance *headappearance = new SphereAppearance(); headappearance->setRadius(r); headappearance->material.setColor(1, 1, 0, 1);*/ SphereShape *headgeometry = new SphereShape(head); headgeometry->setRadius(r); head->geometry = headgeometry; head->appearance = headappearance; vectorSet(head->position, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT + HEADHEIGHT/2 + 0.5), 0); head->setGravity(true); head->setMass(4.0/3*PI*r*r*r); head->setCollisionGroup(collisiongroup); } headsensor = new Sensor(); torsosensor = new Sensor(); headvisual = new DamageVisual(head, damageHead, false, -0.5, -2, 0.5, -1); torsovisual = new DamageVisual(torso, damageTorso, false, -0.5, -1, 0.5, 0); lefthandvisual = new DamageVisual(lefthand, damageHand, true, 0.4, -1, 0.9, 0); righthandvisual = new DamageVisual(righthand, damageHand, true, -0.4, -1, -0.9, 0); leftlegvisual = new DamageVisual(leftleg, damageLeg, true, 0, 0, 0.5, 1); rightlegvisual = new DamageVisual(rightleg, damageLeg, true, -0, 0, -0.5, 1); harmfulobjects = NULL; walkphase = 0; jumpphase = 0; hitside = 0; alive = true; } void Legoman::insertToWorld(World *world){ this->world = world; world->addChild(rightleg); world->addChild(leftleg); world->addChild(waist); world->addChild(torso); world->addChild(lefthand); world->addChild(righthand); world->addChild(head); float linkpoint[3]; vectorSet(linkpoint, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT + HEADHEIGHT), 0); headlinks[0] = world->addLink(head, torso, linkpoint); vectorSet(linkpoint, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT), 0); headlinks[1] = world->addLink(head, torso, linkpoint); vectorSet(linkpoint, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT + HEADHEIGHT*0.5), 1); headlinks[2] = world->addLink(head, torso, linkpoint); head->attached = true; vectorSet(linkpoint, -1, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT) - 0.5, 0); lefthandlinks[0] = world->addLink(torso, lefthand, linkpoint); vectorSet(linkpoint, -2, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT) - 0.5, 0); lefthandlinks[1] = world->addLink(torso, lefthand, linkpoint); lefthand->attached = true; vectorSet(linkpoint, 1, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT) - 0.5, 0); righthandlinks[0] = world->addLink(torso, righthand, linkpoint); vectorSet(linkpoint, 2, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT) - 0.5, 0); righthandlinks[1] = world->addLink(torso, righthand, linkpoint); righthand->attached = true; vectorSet(linkpoint, -1, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT), -0.5); world->addLink(torso, waist, linkpoint); vectorSet(linkpoint, 1, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT), -0.5); world->addLink(torso, waist, linkpoint); vectorSet(linkpoint, -1, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT), 0.5); world->addLink(torso, waist, linkpoint); vectorSet(linkpoint, 1, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT), 0.5); world->addLink(torso, waist, linkpoint); waist->attached = true; vectorSet(linkpoint, -1, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT)-0.5, 0); leftleglinks[0] = world->addLink(waist, leftleg, linkpoint); vectorSet(linkpoint, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT)-0.5, 0); leftleglinks[1] = world->addLink(waist, leftleg, linkpoint); lll = leftleglinks[1]; leftleg->attached = true; vectorSet(linkpoint, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT)-0.5, 0); rightleglinks[0] = world->addLink(waist, rightleg, linkpoint); vectorSet(linkpoint, 1, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT)-0.5, 0); rightleglinks[1] = world->addLink(waist, rightleg, linkpoint); rll = rightleglinks[0]; rightleg->attached = true; leftleglinks[2] = world->addLink(waist, leftleg, NULL); leftleglink = leftleglinks[2]; leftleglink->enabled = false; rightleglinks[2] = world->addLink(waist, rightleg, NULL); rightleglink = rightleglinks[2]; rightleglink->enabled = false; lefthandlinks[2] = world->addLink(torso, lefthand, NULL); lefthandlink = lefthandlinks[2]; lefthandlink->enabled = false; righthandlinks[2] = world->addLink(torso, righthand, NULL); righthandlink = righthandlinks[2]; righthandlink->enabled = false; } void Legoman::heal(void){ headlinks[0]->enabled = true; headlinks[1]->enabled = true; headlinks[2]->enabled = true; lefthandlinks[0]->enabled = true; lefthandlinks[1]->enabled = true; lefthandlinks[2]->enabled = true; righthandlinks[0]->enabled = true; righthandlinks[1]->enabled = true; righthandlinks[2]->enabled = true; leftleglinks[0]->enabled = true; leftleglinks[1]->enabled = true; leftleglinks[2]->enabled = true; rightleglinks[0]->enabled = true; rightleglinks[1]->enabled = true; rightleglinks[2]->enabled = true; leftleglink->enabled = false; rightleglink->enabled = false; lefthandlink->enabled = false; righthandlink->enabled = false; leftleg->reset(); rightleg->reset(); waist->reset(); torso->reset(); lefthand->reset(); righthand->reset(); head->reset(); vectorSet(leftleg->position, -0.6, BLOCKHEIGHT*(LEGHEIGHT/2.0), 0); vectorSet(rightleg->position, 0.6, BLOCKHEIGHT*(LEGHEIGHT/2.0), 0); vectorSet(waist->position, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT/2.0), 0); vectorSet(torso->position, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT/2.0), 0); vectorSet(lefthand->position, -1.3, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT - HANDHEIGHT/2.0), 0); vectorSet(righthand->position, 1.3, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT - HANDHEIGHT/2.0), 0); vectorSet(head->position, 0, BLOCKHEIGHT*(LEGHEIGHT + WAISTHEIGHT + TORSOHEIGHT + HEADHEIGHT/2 + 0.5), 0); headsensor->attach(head); torsosensor->attach(torso); alive = true; } void Legoman::lockPart(int part){ if (part & LEFTLEG && leftleg->energy > 0){ float linkpoint[3]; vectorScale(linkpoint, &leftleg->rotation[3], -1); //vectorAdd(linkpoint, leftleg->position); vectorAdd(linkpoint, waist->position); vectorAdd(linkpoint, lll->point1); world->renewLink(leftleglink, linkpoint); } if (part & RIGHTLEG && rightleg->energy > 0){ float linkpoint[3]; vectorScale(linkpoint, &rightleg->rotation[3], -1); //vectorAdd(linkpoint, rightleg->position); vectorAdd(linkpoint, waist->position); vectorAdd(linkpoint, rll->point1); world->renewLink(rightleglink, linkpoint); } if (part & LEFTHAND && lefthand->energy > 0){ float linkpoint[3]; vectorScale(linkpoint, &lefthand->rotation[3], -1); vectorAdd(linkpoint, lefthand->position); world->renewLink(lefthandlink, linkpoint); } if (part & RIGHTHAND && righthand->energy > 0){ float linkpoint[3]; vectorScale(linkpoint, &righthand->rotation[3], -1); vectorAdd(linkpoint, righthand->position); world->renewLink(righthandlink, linkpoint); } headsensor->attach(head); torsosensor->attach(torso); } void Legoman::addHarmfulObject(Object *object){ objectlist *node = new objectlist(); node->object = object; node->next = harmfulobjects; harmfulobjects = node; } bool Legoman::isHarmfulObject(Object *object){ objectlist *node = harmfulobjects; while (node != NULL){ if (node->object == object) return true; node = node->next; } return false; } float Legoman::getInvMass(void){ float mass = torso->getMass() + waist->getMass(); if (head->attached) mass += head->getMass(); if (lefthand->attached) mass += lefthand->getMass(); if (righthand->attached) mass += righthand->getMass(); if (leftleg->attached) mass += leftleg->getMass(); if (rightleg->attached) mass += rightleg->getMass(); return 1.0/mass; } void Legoman::addOpponent(Legoman *opponent){ this->opponent = opponent; opponent->addHarmfulObject(head); opponent->addHarmfulObject(lefthand); opponent->addHarmfulObject(righthand); opponent->addHarmfulObject(leftleg); opponent->addHarmfulObject(rightleg); } void Legoman::unlockPart(int part){ if (part & LEFTLEG){ leftleglink->enabled = false; } if (part & RIGHTLEG){ rightleglink->enabled = false; } if (part & LEFTHAND){ lefthandlink->enabled = false; } if (part & RIGHTHAND){ righthandlink->enabled = false; } } void Legoman::move(float *movement){ vectorAdd(leftleg->position, movement); vectorAdd(rightleg->position, movement); vectorAdd(waist->position, movement); vectorAdd(torso->position, movement); vectorAdd(lefthand->position, movement); vectorAdd(righthand->position, movement); vectorAdd(head->position, movement); } #define LEGSPEED 0.03 #define BALANCEANGLE (PI/12) void Legoman::balance(void){ if (!alive || !head->attached) return; float headpos[3], torsopos[3]; headsensor->getPosition(headpos); torsosensor->getPosition(torsopos); float posdiff[3]; vectorSub(posdiff, headpos, torsopos); float posdifflen = vectorLength(posdiff); float angle = acos(posdiff[1]/posdifflen); float headtarget[3]; vectorSet(headtarget, 0, posdifflen, 0); vectorAdd(headtarget, torsopos); float force[3]; vectorSub(force, headtarget, headpos); float headvel[3], torsovel[3]; headsensor->getVelocity(headvel); torsosensor->getVelocity(torsovel); float veldiff[3]; vectorSub(veldiff, headvel, torsovel); vectorScale(veldiff, 50); vectorSaturate(veldiff, 0, 10); vectorSub(force, veldiff); if (angle < BALANCEANGLE){ vectorScale(force, pow(1-angle/BALANCEANGLE, 0.1)); vectorScale(force, 100); head->addExternalForce(force); } if (walkdelay == 0){ if (walkphase > 0){ walkphase --; updateLegs(); } } vectorScale(lefthand->angularmomentum, 0.98); vectorScale(righthand->angularmomentum, 0.98); } void Legoman::update(void){ if (walkdelay > 0){ walkdelay--; } /*if (jumpphase > 0){ jumpphase--; }*/ if (torso->momentum[1] < 0 && isOnGround()){ jumpphase--; if (jumpphase == 0) jumpenabled = true; } if (hitside < 10) hitside += 2; //hitside = -hitside; /*if (hitside > 0){ hitside = -hitside; }/* else{ hitside = 0; }*/ if (alive){ if (head->position[1] < 0){// && torso->momentum[1] < 0){ fallOff(); } headsensor->update(); torsosensor->update(); balance(); } } void Legoman::updateLegs(void){ float temp[3]; float angle; walkphase = sfmod(walkphase, PI/LEGSPEED); //Left leg angle = sfmod(walkphase*LEGSPEED, PI); if (angle > PI/4) angle = PI/2 - angle; if (angle < -PI/4) angle = -PI/2 - angle; vectorSet(temp, 0, -cos(angle), -sin(angle)); vectorAdd(temp, lll->point1); vectorCopy(leftleglink->point1, temp); //Right leg angle = sfmod(walkphase*LEGSPEED + PI/2, PI); if (angle > PI/4) angle = PI/2 - angle; if (angle < -PI/4) angle = -PI/2 - angle; vectorSet(temp, 0, -cos(angle), -sin(angle)); vectorAdd(temp, rll->point1); vectorCopy(rightleglink->point1, temp); } void Legoman::walk(float amount){ walkdelay = 20; float sign; if (amount > 0) sign = 1; else sign = -1; walkphase += sign; updateLegs(); if (!isStanding()) return; float movement[3]; float xdir[3], ydir[3], zdir[3]; //vectorScale(ydir, &torso->rotation[3], 1); vectorSet(ydir, 0, 1, 0); vectorScale(zdir, &torso->rotation[6], -1); vectorCross(xdir, ydir, zdir); vectorNormalize(xdir); //vectorScale(xdir, &torso->rotation[0], 1); float oldmomentum[3]; vectorCopy(oldmomentum, torso->momentum); float xmove[3], ymove[3], zmove[3]; vectorProject(xmove, oldmomentum, xdir); vectorProject(ymove, oldmomentum, ydir); vectorProject(zmove, oldmomentum, zdir); vectorScale(xmove, 0.5); float wh = waist->position[1]; if (wh < WAISTHEIGHT + 1.0){ float hd = WAISTHEIGHT + 1.0 - wh; vectorScale(ymove, ydir, hd*10); } float newz[3]; vectorScale(newz, zdir, 6*sign); float ztemp[3]; vectorProject(ztemp, newz, ydir); vectorSub(newz, ztemp); vectorScale(newz, 0.8); vectorScale(zmove, 0.2); vectorAdd(zmove, newz); vectorCopy(movement, xmove); vectorAdd(movement, ymove); vectorAdd(movement, zmove); //if (isStanding() && isOnGround()) vectorCopy(torso->momentum, movement); vectorScale(movement, torso->invmass*waist->getMass()); vectorCopy(waist->momentum, movement); /*float speed = vectorDot(oldmomentum, movement); float speedadd = 1; float maxspeed = 5; /*speed += speedadd; if (speed > maxspeed) speed = maxspeed; if (speed + speedadd > maxspeed){ speedadd = maxspeed - speed; } vectorScale(movement, speedadd); if (waist->position[1] < WAISTHEIGHT + 1.0){ movement[1] = 3; } vectorAdd(torso->momentum, movement);*/ /*float proj[3]; vectorProject(proj, oldmomentum, movement); float len = vectorLength(proj); vectorAdd(movement, proj); vectorSaturate(movement, 0, movement[1] = 300; //torso->addExternalForce(movement); }*/ /*float linkpoint[3]; vectorScale(linkpoint, &leftleg->rotation[3], -1); vectorAdd(linkpoint, leftleg->position);*/ /*float movement[3]; float temp[3]; vectorScale(temp, &torso->rotation[3], amount*0.1); vectorScale(movement, &torso->rotation[6], amount); vectorAdd(movement, temp); if (walkphase == 0){ walkphase = 40; vectorAdd(leftleg->momentum, movement); } if (walkphase == 20){ walkphase = 19; vectorAdd(rightleg->momentum, movement); }*/ /*float axis[3]; vectorScale(axis, &leftleg->rotation[0], amount); if (walkphase == 0){ //walkphase = 40; vectorAdd(leftleg->angularmomentum, axis); vectorAdd(rightleg->angularmomentum, axis); }*/ /*if (walkphase == 0){ walkphase = 1; vectorAdd(rightleg->momentum, movement); }*/ /*float axis[3]; float movement[3]; if (walkphase == 0){ unlockPart(LEFTLEG); vectorScale(axis, &leftleg->rotation[0], 5); vectorAdd(leftleg->angularmomentum, axis); float temp[3]; vectorScale(temp, &torso->rotation[6], -10); vectorScale(movement, &torso->rotation[3], 5); vectorAdd(movement, temp); vectorAdd(torso->momentum, movement); vectorAdd(leftleg->momentum, movement); walkphase = 40; }*/ } void Legoman::turn(float amount){ float axis[3]; if (isStanding()){ vectorScale(axis, &torso->rotation[3], amount); vectorCopy(torso->angularmomentum, axis); } else{ vectorScale(axis, &torso->rotation[3], amount*0.3); vectorAdd(torso->angularmomentum, axis); } } void Legoman::hit(void){ if (!lefthand->attached && !righthand->attached) return; /*float leftdot = vectorDot(&lefthand->rotation[3], &torso->rotation[6]); float rightdot = vectorDot(&righthand->rotation[3], &torso->rotation[6]); if (leftdot < rightdot){ hitside = LEFTHAND; } else{ hitside = RIGHTHAND; }*/ if (hitside >= 10) hitside -= 9; else hitside -= 2; if ((hitside & 1) && !lefthand->attached) hitside++; if (!(hitside & 1) && !righthand->attached) hitside++; float axis[3]; if (hitside & 1){ vectorScale(axis, &lefthand->rotation[0], 20); vectorCopy(lefthand->angularmomentum, axis); } else{ vectorScale(axis, &righthand->rotation[0], 20); vectorCopy(righthand->angularmomentum, axis); } } void Legoman::jump(void){ if (!leftleg->attached && !rightleg->attached) return; if (jumpenabled){// == 0 && isOnGround()){ float r = BLOCKHEIGHT*HEADHEIGHT/2; float strength = (2*LEGHEIGHT + 2*WAISTHEIGHT + 2*TORSOHEIGHT + 2*HANDHEIGHT + 4.0*PI*r*r*r)/3.0*getInvMass(); float jumpvector[3] = {0, 100.0/strength, 0}; //vectorCopy(torso->momentum, jumpvector); torso->momentum[1] = jumpvector[1]; head->momentum[1] = 0;// jumpvector[1]; waist->momentum[1] = 0;// jumpvector[1]; leftleg->momentum[1] = 0;// jumpvector[1]; rightleg->momentum[1] = 0;// jumpvector[1]; lefthand->momentum[1] = 0;// jumpvector[1]; righthand->momentum[1] = 0;// jumpvector[1]; //vectorSet(head->momentum, 0, 0, 0); //jumpphase = 150; jumpsound->play(); jumpenabled = false; } jumpphase = 2; } bool Legoman::isOnGround(void){ //if (!isStanding()) return false; float wh = waist->position[1]; if (wh > WAISTHEIGHT + 1.5) return false; if (fabs(torso->momentum[1]) > 10) return false; //if (fabs(head->momentum[1]) > 10) return false; //if (fabs(waist->momentum[1]) > 3) return false; return true; } bool Legoman::isStanding(void){ if (!leftleg->attached && !rightleg->attached) return false; float headpos[3], torsopos[3]; headsensor->getPosition(headpos); torsosensor->getPosition(torsopos); float posdiff[3]; vectorSub(posdiff, headpos, torsopos); float posdifflen = vectorLength(posdiff); float angle = acos(posdiff[1]/posdifflen); if (angle < BALANCEANGLE) return true; else return false; } void Legoman::fallOff(void){ if (dead) return; if (rand()&1) fallsound1->play(); else fallsound2->play(); die(); head->energy = 0; torso->energy = 0; lefthand->energy = 0; righthand->energy = 0; waist->energy = 0; leftleg->energy = 0; rightleg->energy = 0; } void Legoman::releasePart(BodyPart *part){ if (dead) return; if (part == head){ headlinks[0]->enabled = false; headlinks[1]->enabled = false; headlinks[2]->enabled = false; head->attached = false; //float move[3]; //vectorScale(move, &head->rotation[3], 1); //vectorAdd(head->position, move); die(); } else if (part == lefthand){ lefthandlinks[0]->enabled = false; lefthandlinks[1]->enabled = false; lefthandlinks[2]->enabled = false; lefthand->attached = false; } else if (part == righthand){ righthandlinks[0]->enabled = false; righthandlinks[1]->enabled = false; righthandlinks[2]->enabled = false; righthand->attached = false; } else if (part == leftleg){ leftleglinks[0]->enabled = false; leftleglinks[1]->enabled = false; leftleglinks[2]->enabled = false; leftleg->attached = false; } else if (part == rightleg){ rightleglinks[0]->enabled = false; rightleglinks[1]->enabled = false; rightleglinks[2]->enabled = false; rightleg->attached = false; } else if (part == torso){ die(); } if (!lefthand->attached && !righthand->attached && !leftleg->attached && !rightleg->attached) die(); } void Legoman::die(void){ if (dead) return; alive = false; lll->enabled = false; rll->enabled = false; gameOver(this); } bool Legoman::isAlive(void){ return alive; } Legoman *Legoman::getOpponent(void){ return opponent; } void Legoman::drawVisuals(void){ headvisual->draw(); torsovisual->draw(); lefthandvisual->draw(); righthandvisual->draw(); leftlegvisual->draw(); rightlegvisual->draw(); } DamageVisual::DamageVisual(BodyPart *object, Texture *texture, bool mirror, float x1, float y1, float x2, float y2){ this->object = object; this->texture = texture; this->x1 = x1; this->y1 = y1; this->x2 = x2; this->y2 = y2; float d = 3.0/512; if (mirror){ this->tx1 = 1-d; this->tx2 = 0+d+0.01; } else{ this->tx1 = 0+d+0.01; this->tx2 = 1-d; } this->ty1 = 0+d; this->ty2 = 1-d; } void DamageVisual::draw(void){ float energy = object->energy; texture->enable(); glBegin(GL_QUADS); if (energy > 0) glColor3f(1-energy, energy, 0); else glColor3f(0.3, 0.3, 0.3); glTexCoord2f(tx1, ty1); glVertex2f(x1, y1); glTexCoord2f(tx1, ty2); glVertex2f(x1, y2); glTexCoord2f(tx2, ty2); glVertex2f(x2, y2); glTexCoord2f(tx2, ty1); glVertex2f(x2, y1); glEnd(); }