1
0
Fork 0
blockofighter/src/legoman.cpp

1111 lines
31 KiB
C++

/*
* $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 <math.h>
#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();
}