You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
4.5 KiB
184 lines
4.5 KiB
package net.sector.entities.natural;
|
|
|
|
|
|
import static org.lwjgl.opengl.GL11.*;
|
|
import net.sector.Constants;
|
|
import net.sector.collision.ColliderSphere;
|
|
import net.sector.entities.EEntity;
|
|
import net.sector.entities.Entity;
|
|
import net.sector.entities.orbs.EntityOrbShield;
|
|
import net.sector.models.Models;
|
|
import net.sector.models.PhysModel;
|
|
|
|
import com.porcupine.coord.Coord;
|
|
import com.porcupine.coord.Vec;
|
|
import com.porcupine.math.Calc;
|
|
|
|
|
|
|
|
/**
|
|
* Asteroid entity
|
|
*
|
|
* @author Ondřej Hruška (MightyPork)
|
|
*/
|
|
public class EntityAsteroid extends EntityNatural {
|
|
|
|
|
|
private int texture = 0;
|
|
/** Rotation speed */
|
|
protected double rotSpeed = 0;
|
|
|
|
private PhysModel rock;
|
|
|
|
private double renderScale = 0;
|
|
private double scale = 1;
|
|
private double healthMax;
|
|
|
|
/**
|
|
* Asteroid entity
|
|
*
|
|
* @param scale asteroid scale
|
|
* @param pos asteroid center position
|
|
* @param motion asteroid motion
|
|
* @param texture asteroid texture index
|
|
*/
|
|
public EntityAsteroid(double scale, Coord pos, Vec motion, int texture) {
|
|
|
|
this.texture = texture;
|
|
this.rotDir.setTo(-1 + rand.nextDouble() * 2, -1 + rand.nextDouble() * 2, -1 + rand.nextDouble() * 2);
|
|
this.rotAngle.set(rand.nextDouble() * 360);
|
|
this.rotSpeed = -5 + rand.nextDouble() * 10;
|
|
|
|
this.collidePriority = 0;
|
|
|
|
this.scale = scale;
|
|
rock = Models.pickAsteroidOfType(texture);
|
|
|
|
this.renderScale = rock.renderScale * scale;
|
|
|
|
this.healthMax = this.health = rock.health * scale;
|
|
this.lifetime = -1;
|
|
this.mass = rock.getMass(scale);
|
|
collider = new ColliderSphere(pos, rock.colliderRadius * scale);
|
|
this.motion.setTo(motion);
|
|
this.scoreValue = (int) Math.round(rock.getScore(scale));
|
|
|
|
this.MAX_SPEED = 0.2 * (0.3 / mass);
|
|
|
|
setGlobalMovement(true);
|
|
}
|
|
|
|
@Override
|
|
public double getHealthMax() {
|
|
return healthMax;
|
|
}
|
|
|
|
//private static Object3D model = new Object3D("res/models/asteroid03.obj", true);
|
|
/**
|
|
* Asteroid entity
|
|
*
|
|
* @param scale asteroid scale
|
|
* @param pos asteroid position
|
|
* @param motion asteroid motion
|
|
*/
|
|
public EntityAsteroid(double scale, Coord pos, Vec motion) {
|
|
this(scale, pos, motion, rand.nextInt(Models.rockTypes.length));
|
|
}
|
|
|
|
|
|
@Override
|
|
public void onImpact(Entity hitBy) {
|
|
defaultOnImpact(hitBy);
|
|
this.rotSpeed = Calc.clampd(this.rotSpeed + rand.nextGaussian(), -5, 5);
|
|
|
|
if (hitBy instanceof EntityAsteroid) {
|
|
((EntityAsteroid) hitBy).rotSpeed = Calc.clampd(((EntityAsteroid) hitBy).rotSpeed + rand.nextGaussian(), -5, 5);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onUpdate() {
|
|
rotAngle.add(rotSpeed * Constants.SPEED_MUL);
|
|
}
|
|
|
|
@Override
|
|
public void render(double delta) {
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
Coord p = getPos().getDelta(delta);
|
|
glTranslated(p.x, p.y, -p.z);
|
|
glRotated(rotAngle.delta(delta), rotDir.x, rotDir.y, rotDir.z);
|
|
glScaled(renderScale, renderScale, renderScale);
|
|
rock.model.render();
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
@Override
|
|
public boolean belongsToZone(double zFrom, double zTo) {
|
|
return Calc.inRange(collider.pos.z, zFrom - collider.radius, zTo + collider.radius);
|
|
}
|
|
|
|
@Override
|
|
public void onDeath() {
|
|
explodeForce(getPos(), getRadius() * 14, true);
|
|
|
|
//explodeForce(getPos(), mass / 2, true);
|
|
|
|
if (scale > 0.4) {
|
|
int pieces = 2 + rand.nextInt(7);
|
|
|
|
double vol = Calc.sphereGetVolume(scale) * 0.4;
|
|
|
|
double approxPerPart = vol / pieces;
|
|
|
|
double[] volumes = new double[pieces];
|
|
|
|
for (int i = 0; i < pieces; i++) {
|
|
double v = 0.05 + ((rand.nextDouble() + rand.nextDouble()) / 2) * approxPerPart;
|
|
if (v > vol) v = vol;
|
|
vol -= v;
|
|
if (v < 0) v = Calc.sphereGetVolume(0.05 + rand.nextDouble() * 0.1);
|
|
volumes[i] = v;
|
|
}
|
|
|
|
|
|
for (int i = 0; i < pieces; i++) {
|
|
double newScale = Calc.sphereGetRadius(volumes[i]);
|
|
|
|
if (newScale < 0.05) newScale = 0.05;
|
|
|
|
Coord apos = this.getPos();
|
|
|
|
double r = getRadius() * 0.6;
|
|
|
|
apos.add_ip(-r + rand.nextDouble() * (r) * 2, 0, -r + rand.nextDouble() * (r) * 2);
|
|
|
|
Vec amotion = getPos().vecTo(apos).norm(0.05 + rand.nextDouble() * 0.1);
|
|
Entity e;
|
|
scene.add(e = new EntityAsteroid(newScale, apos, amotion, texture));
|
|
e.health *= 0.1;
|
|
e.scoreValue *= 0.6;
|
|
e.healthMul = healthMul * 0.8;
|
|
|
|
// tiny rocks will eventually disappear.
|
|
if (newScale < 0.15) e.lifetime = (int) (Constants.FPS_UPDATE * (0.3 + rand.nextDouble() * 5));
|
|
}
|
|
}
|
|
|
|
if (lastDamageSource.getType() == EEntity.SHOT_GOOD && rand.nextInt(3) == 0 && scale > 0.5) {
|
|
if (scene.playerShip.body.shieldSystem.getLoadRatio() < 1) {
|
|
scene.add(new EntityOrbShield(getPos(), scale * 600 * (0.6 + rand.nextDouble() * 0.7)));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public EEntity getType() {
|
|
return EEntity.NATURAL;
|
|
}
|
|
|
|
}
|
|
|