1
0
Fork 0
blockofighter/src/legoman.cpp

1176 lines
33 KiB
C++

#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 "fonct.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);
vectorSet(velocity, 0, 0, 0);
vectorSet(angularvelocity, 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;
}
bool BodyPart::isInContact() {
if (!isAttached())
return false;
Object *obj = (Object *)this;
int collgroup = obj->getCollisionGroup();
for (int i = 0; i < contactcount; i++) {
if (contacts[i].object1 == obj) {
if (contacts[i].object2->getCollisionGroup() != collgroup)
return true;
} else if (contacts[i].object2 == obj) {
if (contacts[i].object1->getCollisionGroup() != collgroup)
return true;
}
}
return false;
}
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 = 0, collisiongrouphand = 0;
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);
// UNUSED//float tmpScale = 1.0;
// Left leg
{
leftleg = new BodyPart(this, 3);
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, 3);
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, 3);
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, 2);
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, 2);
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);
walkphase = 0;
jumpphase = 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()){
// if (torso->momentum[1] < 0 && (isStanding() || isOnGround())){
if (leftleg->isInContact() || rightleg->isInContact() ||
(torso->momentum[1] < 0 && isOnGround())) {
jumpphase--;
if (jumpphase == 0) {
jumpenabled = true;
leftleg->setGravity(true);
rightleg->setGravity(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 = (int)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 += (int)sign;
updateLegs();
if (hitcounter && (jumpphase > 0)) {
float axis[3];
vectorScale(axis, &torso->rotation[0], -100.0 * amount);
vectorAdd(torso->angularmomentum, axis);
vectorSaturate(torso->angularmomentum, 0.0, 18.0);
}
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 &&
(!isOutOfRing() || leftleg->isInContact() || rightleg->isInContact())) {
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 (!isOnGround() || isOutOfRing()) return;
vectorCopy(torso->momentum, movement);
vectorScale(movement, torso->invmass * waist->getMass());
vectorCopy(waist->momentum, movement);
// TK: pour conserver le moment éventuel d'un saut
torso->momentum[1] = MAX(oldmomentum[1], torso->momentum[1]);
// Wythel pour faire des saltos
/* if (jumpphase == 2 && hitcounter){
float axis[3];
vectorScale(axis, &torso->rotation[0], amount*-500);
vectorAdd(torso->angularmomentum, axis);
}*/
#if 0
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;
}*/
#endif
}
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);
}
if (hitcounter && (jumpphase == 2)) {
vectorScale(axis, &torso->rotation[6], amount * 2.0);
vectorAdd(torso->angularmomentum, axis);
}
vectorSaturate(torso->angularmomentum, 0.0, 18.0);
}
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.0);
// du bras à l'horizontal
vectorScale(axis, &lefthand->rotation[0],
20.0 / (1 + 3.0 * fabs(lefthand->rotation[1])));
vectorCopy(lefthand->angularmomentum, axis);
} else {
// vectorScale(axis, &righthand->rotation[0], 20.0);
vectorScale(axis, &righthand->rotation[0],
20.0 / (1 + 3.0 * fabs(righthand->rotation[1])));
vectorCopy(righthand->angularmomentum, axis);
}
}
void Legoman::jump(void) {
if (!leftleg->attached && !rightleg->attached)
return;
if (jumpenabled &&
(!isOutOfRing() || leftleg->isInContact() || rightleg->isInContact())) {
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};
jumpvector[0] =
3.0 * ((float)opponent->torso->position[0] - (float)torso->position[0]);
jumpvector[2] =
3.0 * ((float)opponent->torso->position[2] - (float)torso->position[2]);
if (hitcounter) {
jumpvector[0] *= 3.0;
jumpvector[2] *= 3.0;
if (!isOnGround()) {
jumpvector[1] =
((float)opponent->torso->position[1] - (float)torso->position[1]);
}
// leftleg->setGravity(false);
// rightleg->setGravity(false);
}
//#if 0
if ((!isOnGround()) && ((torso->position[0] < -(float)ARENASIZE + 1.0) ||
(torso->position[0] > (float)ARENASIZE - 1.0) ||
(torso->position[2] < -(float)ARENASIZE + 1.0) ||
(torso->position[2] > (float)ARENASIZE - 1.0))) {
// le blocko est à peu près sur le rebord, on autorise le jump du dernier
// recours
jumpvector[0] += -5.0 * (float)torso->position[0];
jumpvector[2] += -5.0 * (float)torso->position[2];
}
//#endif
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 not isOutOfRing();
}
bool Legoman::isOutOfRing(void) {
return ((torso->position[0] < -(float)ARENASIZE - 0.5) ||
(torso->position[0] > (float)ARENASIZE + 0.5) ||
(torso->position[2] < -(float)ARENASIZE - 0.5) ||
(torso->position[2] > (float)ARENASIZE + 0.5));
}
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();
}