289 lines
6.4 KiB
ActionScript 3
289 lines
6.4 KiB
ActionScript 3
const double orbitSpeedFactor = 2.0;
|
|
|
|
tidy class Orbit : Component_Orbit, Savable {
|
|
Object@ center_obj;
|
|
vec3d center_pos;
|
|
double radius;
|
|
|
|
double yearPos;
|
|
double yearLen;
|
|
|
|
double dayPos;
|
|
double dayLen;
|
|
bool delta = false;
|
|
|
|
Orbit() {
|
|
dayLen = 0;
|
|
yearLen = 0;
|
|
}
|
|
|
|
void load(SaveFile& data) {
|
|
data >> center_obj;
|
|
if(center_obj is null)
|
|
data >> center_pos;
|
|
|
|
data >> radius;
|
|
data >> yearPos;
|
|
data >> yearLen;
|
|
data >> dayPos;
|
|
data >> dayLen;
|
|
}
|
|
|
|
void save(SaveFile& data) {
|
|
data << center_obj;
|
|
if(center_obj is null)
|
|
data << center_pos;
|
|
|
|
data << radius;
|
|
data << yearPos;
|
|
data << yearLen;
|
|
data << dayPos;
|
|
data << dayLen;
|
|
}
|
|
|
|
void orbitTick(Object& obj, double time) {
|
|
if(yearLen != 0) {
|
|
yearPos = (yearPos + time) % yearLen;
|
|
vec3d position;
|
|
|
|
quaterniond rotation = quaterniond_fromAxisAngle(vec3d_up(), yearPos / yearLen * twopi);
|
|
position = rotation * vec3d_front(radius);
|
|
|
|
if(center_obj is null) {
|
|
position += center_pos;
|
|
}
|
|
else {
|
|
if(!center_obj.initialized)
|
|
return;
|
|
position += center_obj.position;
|
|
}
|
|
|
|
if(time > 0.01) {
|
|
vec3d newVel = (position - obj.position) / time;
|
|
obj.acceleration = (newVel - obj.velocity) / time;
|
|
obj.velocity = newVel;
|
|
}
|
|
obj.position = position;
|
|
|
|
if(obj.hasMover)
|
|
obj.clearMovement();
|
|
}
|
|
else {
|
|
obj.position += obj.velocity * time;
|
|
obj.velocity += obj.acceleration * time;
|
|
}
|
|
if(dayLen != 0) {
|
|
if(dayLen < 0) {
|
|
vec3d center = obj.position;
|
|
if(center_obj is null)
|
|
center = center_pos;
|
|
else
|
|
center = center_obj.position;
|
|
|
|
obj.rotation = quaterniond_fromVecToVec(vec3d_front(), obj.position - center);
|
|
}
|
|
else {
|
|
dayPos = (dayPos + time) % dayLen;
|
|
obj.rotation = quaterniond_fromAxisAngle(vec3d_up(), dayPos / dayLen * twopi);
|
|
}
|
|
}
|
|
}
|
|
|
|
void setOrbitPct(Object& obj, double pct) {
|
|
yearPos = yearLen * pct;
|
|
orbitTick(obj, 0);
|
|
delta = true;
|
|
}
|
|
|
|
void orbitRadius(Object& obj, double newRadius) {
|
|
radius = newRadius;
|
|
orbitTick(obj, 0);
|
|
delta = true;
|
|
}
|
|
|
|
void orbitAround(Object& obj, vec3d point) {
|
|
orbitAround_minRad(obj, point, 0.0);
|
|
}
|
|
|
|
void orbitAround(Object& obj, double minRadius, vec3d point) {
|
|
orbitAround_minRad(obj, point, minRadius);
|
|
}
|
|
|
|
void stopOrbit() {
|
|
yearLen = 0;
|
|
}
|
|
|
|
bool get_inOrbit() {
|
|
return yearLen != 0;
|
|
}
|
|
|
|
void remakeStandardOrbit(Object& obj, bool orbitPlanets = true) {
|
|
Region@ reg = obj.region;
|
|
yearLen = 0;
|
|
if(reg is null)
|
|
return;
|
|
if(reg.starCount == 0)
|
|
return;
|
|
if(obj.position.distanceTo(reg.position) < obj.radius)
|
|
return;
|
|
Object@ orbObj;
|
|
if(orbitPlanets && !obj.isPlanet)
|
|
@orbObj = reg.getOrbitObject(obj.position);
|
|
if(orbObj !is null)
|
|
obj.orbitAround(orbObj);
|
|
else
|
|
obj.orbitAround(200, reg.position);
|
|
}
|
|
|
|
Object@ getOrbitingAround() {
|
|
return center_obj;
|
|
}
|
|
|
|
bool get_hasOrbitCenter() const {
|
|
return center_obj !is null;
|
|
}
|
|
|
|
bool isOrbitingAround(Object@ around) const {
|
|
if(around is center_obj)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
void orbitAround(Object& obj, vec3d position, vec3d origin) {
|
|
obj.position = position;
|
|
orbitAround(obj, origin);
|
|
}
|
|
|
|
void orbitAround_minRad(Object& obj, vec3d point, double minRadius = 0) {
|
|
vec3d offset = (obj.position - point);
|
|
center_pos = point;
|
|
@center_obj = null;
|
|
radius = max(offset.length, minRadius);
|
|
double angle = (vec2d(obj.position.x, -obj.position.z) - vec2d(point.x, -point.z)).radians();
|
|
if(angle < 0)
|
|
angle += twopi;
|
|
yearLen = sqrt(pow(radius, 3.0)) / orbitSpeedFactor;
|
|
yearPos = yearLen * angle / twopi;
|
|
orbitTick(obj, 0);
|
|
delta = true;
|
|
}
|
|
|
|
void orbitAround(Object& obj, vec3d point, double orbRadius) {
|
|
center_pos = point;
|
|
@center_obj = null;
|
|
radius = orbRadius;
|
|
yearLen = sqrt(pow(radius, 3.0)) / orbitSpeedFactor;
|
|
double angle = (vec2d(obj.position.x, -obj.position.z) - vec2d(point.x, -point.z)).radians();
|
|
if(angle < 0)
|
|
angle += twopi;
|
|
yearPos = yearLen * angle / twopi;
|
|
orbitTick(obj, 0);
|
|
delta = true;
|
|
}
|
|
|
|
void orbitAround(Object& obj, Object& around, double orbRadius, double angle) {
|
|
@center_obj = around;
|
|
radius = orbRadius;
|
|
yearLen = sqrt(pow(radius, 3.0)) / orbitSpeedFactor;
|
|
yearPos = yearLen * angle / twopi;
|
|
orbitTick(obj, 0);
|
|
delta = true;
|
|
}
|
|
|
|
void orbitAround(Object& obj, Object& around, double orbRadius) {
|
|
@center_obj = around;
|
|
radius = orbRadius;
|
|
yearLen = sqrt(pow(radius, 3.0)) / orbitSpeedFactor;
|
|
double angle = (vec2d(obj.position.x, -obj.position.z) - vec2d(around.position.x, -around.position.z)).radians();
|
|
if(angle < 0)
|
|
angle += twopi;
|
|
yearPos = yearLen * angle / twopi;
|
|
orbitTick(obj, 0);
|
|
delta = true;
|
|
}
|
|
|
|
void orbitAround(Object& obj, Object& around) {
|
|
@center_obj = around;
|
|
radius = max(obj.position.distanceTo(around.position), obj.radius + around.radius);
|
|
yearLen = sqrt(pow(radius, 3.0)) / orbitSpeedFactor;
|
|
double angle = (vec2d(obj.position.x, -obj.position.z) - vec2d(around.position.x, -around.position.z)).radians();
|
|
if(angle < 0)
|
|
angle += twopi;
|
|
yearPos = yearLen * angle / twopi;
|
|
orbitTick(obj, 0);
|
|
delta = true;
|
|
}
|
|
|
|
void orbitSpin(Object& obj, double dayLength, bool staticPos) {
|
|
dayLen = dayLength;
|
|
if(staticPos && dayLen > 0)
|
|
dayPos = gameTime % dayLen;
|
|
else
|
|
dayPos = 0;
|
|
orbitTick(obj, 0);
|
|
delta = true;
|
|
}
|
|
|
|
void orbitDuration(double duration) {
|
|
yearLen = duration;
|
|
}
|
|
|
|
void writeOrbit(const Object& obj, Message& msg) {
|
|
msg << float(yearLen);
|
|
msg << float(dayLen);
|
|
msg.writeFixed(dayPos, 0.0, dayLen);
|
|
|
|
if(center_obj !is null) {
|
|
msg.write1();
|
|
msg << center_obj;
|
|
}
|
|
else {
|
|
msg.write0();
|
|
msg.writeMedVec3(center_pos);
|
|
}
|
|
|
|
msg << float(radius);
|
|
msg.writeFixed(yearPos, 0.0, yearLen);
|
|
|
|
if(yearLen == 0) {
|
|
msg.writeMedVec3(obj.position);
|
|
msg.writeSmallVec3(obj.velocity);
|
|
}
|
|
}
|
|
|
|
void readOrbit(Object& obj, Message& msg) {
|
|
yearLen = msg.read_float();
|
|
dayLen = msg.read_float();
|
|
dayPos = msg.readFixed(0.0, dayLen);
|
|
|
|
if(msg.readBit()) {
|
|
msg >> center_obj;
|
|
}
|
|
else {
|
|
center_pos = msg.readMedVec3();
|
|
@center_obj = null;
|
|
}
|
|
|
|
radius = msg.read_float();
|
|
yearPos = msg.readFixed(0.0, yearLen);
|
|
|
|
if(yearLen == 0) {
|
|
obj.position = msg.readMedVec3();
|
|
obj.velocity = msg.readSmallVec3();
|
|
}
|
|
}
|
|
|
|
bool writeOrbitDelta(const Object& obj, Message& msg) {
|
|
if(!delta && yearLen != 0)
|
|
return false;
|
|
delta = false;
|
|
msg.write1();
|
|
writeOrbit(obj, msg);
|
|
return true;
|
|
}
|
|
|
|
void readOrbitDelta(Object& obj, Message& msg) {
|
|
readOrbit(obj, msg);
|
|
}
|
|
}
|