diff options
| author | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
| commit | c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch) | |
| tree | df9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/scape/VelocityBehavior.java | |
| download | worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip | |
Initial commit
Diffstat (limited to 'NET/worlds/scape/VelocityBehavior.java')
| -rw-r--r-- | NET/worlds/scape/VelocityBehavior.java | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/NET/worlds/scape/VelocityBehavior.java b/NET/worlds/scape/VelocityBehavior.java new file mode 100644 index 0000000..9858355 --- /dev/null +++ b/NET/worlds/scape/VelocityBehavior.java @@ -0,0 +1,260 @@ +package NET.worlds.scape; + +import java.io.IOException; + +public class VelocityBehavior extends SwitchableBehavior implements FrameHandler, BumpHandler { + private RollingAttribute attr; + private long lastTime; + public float linearVel; + public float linearDamp; + protected Point3 dir; + public float angularVel; + public float angularDamp; + public Point3 axis; + private boolean bumplock = false; + private static Object classCookie = new Object(); + + public VelocityBehavior( + Point3Temp linearVectorPerSecond, float linearDampingPerSecond, Point3Temp angularAxis, float angularDegPerSecond, float angularDampingPerSecond + ) { + this.dir = new Point3(); + this.linearVel = 0.0F; + this.linearDamp = linearDampingPerSecond; + this.addVelocity(linearVectorPerSecond); + this.axis = new Point3(angularAxis); + this.axis.normalize(); + this.angularVel = angularDegPerSecond; + this.angularDamp = angularDampingPerSecond; + } + + public VelocityBehavior() { + this(Point3Temp.make(0.0F, 0.0F, 0.0F)); + } + + public VelocityBehavior(Point3Temp vel) { + this(vel, 0.0F, Point3Temp.make(0.0F, 0.0F, 1.0F), 0.0F, 0.0F); + } + + public void setDir(Point3Temp d) { + double len = Math.sqrt(d.x * d.x + d.y * d.y + d.z * d.z); + if (len == 0.0) { + this.dir.x = 0.0F; + this.dir.y = 0.0F; + this.dir.z = 0.0F; + } else { + this.dir.x = (float)(d.x / len); + this.dir.y = (float)(d.y / len); + this.dir.z = (float)(d.z / len); + } + } + + public VelocityBehavior addVelocity(Point3Temp vector) { + this.dir.times(this.linearVel).plus(vector); + float len = this.dir.length(); + if (len > 0.0F) { + this.dir.dividedBy(len); + } + + this.linearVel = len; + return this; + } + + public void setNotifyAttribute(RollingAttribute attr) { + this.attr = attr; + } + + @Override + public boolean handle(FrameEvent e) { + this.bumplock = false; + WObject o = e.receiver; + float dT = (float)(e.time - this.lastTime) / 1000.0F; + if (this.lastTime == 0L) { + this.lastTime = e.time; + return true; + } else { + this.lastTime = e.time; + if (this.linearVel != 0.0F) { + Point3Temp dist = Point3Temp.make(this.dir).times(dT * this.linearVel); + o.moveThrough(dist); + if (this.linearDamp != 0.0F) { + this.linearVel = (float)(this.linearVel * Math.exp(-this.linearDamp * dT)); + if (Math.abs(this.linearVel) < this.linearDamp * 16.0F) { + this.linearVel = 0.0F; + if (this.attr != null) { + this.attr.notifyStopped(); + } + } + } + } + + if (this.angularVel != 0.0F) { + o.spin(this.axis.x, this.axis.y, this.axis.z, this.angularVel * dT); + if (this.angularDamp != 0.0F) { + this.angularVel = (float)(this.angularVel * Math.exp(-this.angularDamp * dT)); + if (Math.abs(this.angularVel) < this.angularDamp * 0.6F) { + this.angularVel = 0.0F; + } + } + } + + return true; + } + } + + @Override + public boolean handle(BumpEventTemp b) { + if (this.bumplock) { + return true; + } else { + if (this.attr != null) { + this.attr.handle(b); + } else { + this.processBumpEvent(b); + } + + this.bumplock = true; + return true; + } + } + + public void processBumpEvent(BumpEventTemp b) { + b.postBumpPath.minus(b.postBumpPath); + if (this.dir.x != 0.0F || this.dir.y != 0.0F || this.dir.z != 0.0F) { + WObject bumper = b.receiver == b.target ? (WObject)b.source : b.target; + Point3Temp norm; + if (!(bumper instanceof Camera) && !(bumper instanceof Hologram)) { + norm = Point3Temp.make(b.bumpNormal); + } else { + float orientation = (float)((360.0F - bumper.getYaw() + 90.0F) * Math.PI / 180.0); + norm = Point3Temp.make((float)Math.cos(orientation), (float)Math.sin(orientation), 0.0F); + } + + float lb = (float)Math.sqrt(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z); + norm.x /= lb; + norm.y /= lb; + norm.z /= lb; + float projection = Math.abs(this.dir.x * norm.x + this.dir.y * norm.y + this.dir.z * norm.z); + this.dir.x = this.dir.x + norm.x * 2.0F * projection; + this.dir.y = this.dir.y + norm.y * 2.0F * projection; + this.dir.z = this.dir.z + norm.z * 2.0F * projection; + double n = Math.sqrt(this.dir.x * this.dir.x + this.dir.y * this.dir.y + this.dir.z * this.dir.z); + if (n != 0.0) { + this.dir.x = (float)(this.dir.x / n); + this.dir.y = (float)(this.dir.y / n); + this.dir.z = (float)(this.dir.z / n); + } + } + } + + @Override + public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException { + Object ret = null; + switch (index - offset) { + case 0: + if (mode == 0) { + ret = FloatPropertyEditor.make(new Property(this, index, "Linear Velocity")); + } else if (mode == 1) { + ret = new Float(this.linearVel); + } else if (mode == 2) { + this.linearVel = (Float)value; + } + break; + case 1: + if (mode == 0) { + ret = FloatPropertyEditor.make(new Property(this, index, "Linear Damping")); + } else if (mode == 1) { + ret = new Float(this.linearDamp); + } else if (mode == 2) { + this.linearDamp = (Float)value; + } + break; + case 2: + if (mode == 0) { + ret = Point3PropertyEditor.make(new Property(this, index, "Direction")); + } else if (mode == 1) { + ret = new Point3(this.dir); + } else if (mode == 2) { + this.dir = (Point3)value; + } + break; + case 3: + if (mode == 0) { + ret = FloatPropertyEditor.make(new Property(this, index, "Angular Velocity")); + } else if (mode == 1) { + ret = new Float(this.angularVel); + } else if (mode == 2) { + this.angularVel = (Float)value; + } + break; + case 4: + if (mode == 0) { + ret = FloatPropertyEditor.make(new Property(this, index, "Angular Damping")); + } else if (mode == 1) { + ret = new Float(this.angularDamp); + } else if (mode == 2) { + this.angularDamp = (Float)value; + } + break; + case 5: + if (mode == 0) { + ret = Point3PropertyEditor.make(new Property(this, index, "Axis")); + } else if (mode == 1) { + ret = new Point3(this.axis); + } else if (mode == 2) { + this.axis = (Point3)value; + } + break; + default: + ret = super.properties(index, offset + 6, mode, value); + } + + return ret; + } + + @Override + public String toString() { + return super.toString() + + "[lin. velocity " + + this.linearVel + + ", lin. damp " + + this.linearDamp + + ", direction " + + this.dir + + ", ang. vel " + + this.angularVel + + ", ang. damp " + + this.angularDamp + + ", axis " + + this.axis + + "]"; + } + + @Override + public void saveState(Saver s) throws IOException { + s.saveVersion(0, classCookie); + super.saveState(s); + s.saveFloat(this.linearVel); + s.saveFloat(this.linearDamp); + s.save(this.dir); + s.saveFloat(this.angularVel); + s.saveFloat(this.angularDamp); + s.save(this.axis); + } + + @Override + public void restoreState(Restorer r) throws IOException, TooNewException { + switch (r.restoreVersion(classCookie)) { + case 0: + super.restoreState(r); + this.linearVel = r.restoreFloat(); + this.linearDamp = r.restoreFloat(); + this.dir = (Point3)r.restore(); + this.angularVel = r.restoreFloat(); + this.angularDamp = r.restoreFloat(); + this.axis = (Point3)r.restore(); + return; + default: + throw new TooNewException(); + } + } +} |