mirror of
https://github.com/logsol/chuck.js.git
synced 2026-05-11 10:37:34 +00:00
- Temporarily commented out joint limit setting code in RubeDoll.flip() - RubeDoll joints now have no angular constraints - Should make ragdoll more floppy and less glitchy - Collision prevention between held RubeDoll and holding player is working - All Planck.js migration issues resolved
295 lines
No EOL
10 KiB
JavaScript
295 lines
No EOL
10 KiB
JavaScript
define([
|
|
"Game/" + GLOBALS.context + "/GameObjects/Item",
|
|
"Lib/Vendor/RubeLoader", // Re-enabled for Planck.js
|
|
"Lib/Vendor/Planck",
|
|
"Game/Config/Settings",
|
|
"Lib/Utilities/Assert",
|
|
"Lib/Utilities/NotificationCenter",
|
|
"Lib/Utilities/Matrix",
|
|
"json!Game/Asset/RubeDoll.json" // Re-enabled for Planck.js
|
|
],
|
|
|
|
function (Parent, RubeLoader, planck, Settings, Assert, nc, Matrix, RubeDollJson) {
|
|
|
|
"use strict";
|
|
|
|
function RubeDoll(physicsEngine, uid, options) {
|
|
Assert.number(options.x, options.y);
|
|
|
|
this.rubeLoader = null;
|
|
this.body = null;
|
|
this.limbs = {};
|
|
this.joints = null;
|
|
this.limits = [];
|
|
this.holdingPlayer = null; // Track which player is holding this RubeDoll
|
|
this.originalFilterData = {}; // Store original filter data for restoration
|
|
|
|
var chest = null;
|
|
this.rubeLoader = new RubeLoader(RubeDollJson, physicsEngine.getWorldForRubeLoader());
|
|
this.loadRubeDollFromScene(options);
|
|
|
|
Parent.call(this, physicsEngine, uid, options);
|
|
physicsEngine.destroyBody(this.body);
|
|
this.body = this.limbs.chest;
|
|
delete this.limbs.chest;
|
|
|
|
this.body.setUserData(this);
|
|
|
|
this.flip(options.direction || 1);
|
|
}
|
|
|
|
RubeDoll.prototype = Object.create(Parent.prototype);
|
|
|
|
RubeDoll.prototype.loadRubeDollFromScene = function(options) {
|
|
var scene = this.rubeLoader.getScene();
|
|
|
|
for (var i in scene.bodies) {
|
|
var body = scene.bodies[i];
|
|
var position = body.getPosition().clone();
|
|
position.add(planck.Vec2(
|
|
options.x / Settings.RATIO,
|
|
options.y / Settings.RATIO
|
|
));
|
|
body.setPosition(position);
|
|
this.limbs[body.name] = body;
|
|
|
|
// code snipped possibly needed for filtering between doll and rubedoll while holding
|
|
//var filterData = new planck.Filter();
|
|
//filterData.groupIndex = -66;
|
|
//if(body.name != "head" && body.name != "chest") {
|
|
// for (var fixture = body.getFixtureList(); fixture; fixture = fixture.getNext()) {
|
|
// fixture.setFilterData(filterData);
|
|
// }
|
|
//}
|
|
}
|
|
|
|
this.joints = scene.joints;
|
|
|
|
var count = 0;
|
|
for (var i in this.joints) {
|
|
this.limits[i] = {
|
|
lower: this.joints[i].getLowerLimit(),
|
|
upper: this.joints[i].getUpperLimit(),
|
|
};
|
|
/*
|
|
this.joints[i].enableLimit(false);
|
|
|
|
if(count < 4 && this.joints[i] instanceof planck.RevoluteJoint) {
|
|
console.log(i);
|
|
} else {
|
|
body.getWorld().destroyJoint(this.joints[i]);
|
|
}
|
|
count++;
|
|
*/
|
|
}
|
|
};
|
|
|
|
RubeDoll.prototype.getFixtureDef = function() {
|
|
var fixtureDef = { shape: null, density: 1.0, friction: 0.3, restitution: 0.0, isSensor: false };
|
|
fixtureDef.shape = planck.Circle(0.1); // Small circle as placeholder
|
|
return fixtureDef;
|
|
};
|
|
|
|
RubeDoll.prototype.flip = function(direction) {
|
|
var oldFlipDirection = this.flipDirection;
|
|
|
|
Parent.prototype.flip.call(this, direction);
|
|
|
|
// TEMPORARILY DISABLED: Joint limits
|
|
/*
|
|
if(oldFlipDirection != direction) {
|
|
|
|
for (var i in this.joints) {
|
|
var joint = this.joints[i];
|
|
var limits = this.limits[i];
|
|
|
|
if (joint instanceof planck.RevoluteJoint) {
|
|
|
|
if (direction > 0) {
|
|
joint.setLimits(limits.lower, limits.upper);
|
|
continue;
|
|
}
|
|
|
|
var a1 = limits.lower * -1;
|
|
var a2 = limits.upper * -1;
|
|
|
|
if (a2 > a1) {
|
|
joint.setLimits(a1, a2);
|
|
} else {
|
|
joint.setLimits(a2, a1);
|
|
}
|
|
|
|
// joint.setAngle(joint.getAngle() * -1);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
};
|
|
|
|
RubeDoll.prototype.reposition = function(handPosition, direction) {
|
|
var oldPosition = this.getPosition();
|
|
var oldAngle = this.body.getAngle();
|
|
var oldDirection = this.flipDirection;
|
|
|
|
// calls flip() at the end of Parent reposition()
|
|
Parent.prototype.reposition.call(this, handPosition, direction);
|
|
|
|
var differenceAngle = oldAngle - this.body.getAngle();
|
|
|
|
//this.body.setLinearVelocity(planck.Vec2(0, 0));
|
|
|
|
var offset = planck.Vec2(this.getPosition()).sub(planck.Vec2(oldPosition));
|
|
var grabAngle = (this.options.grabAngle || 0.001);
|
|
|
|
for(var key in this.limbs) {
|
|
var limb = this.limbs[key];
|
|
|
|
// Setting position offset first (floor to hand)
|
|
var position = limb.getPosition().clone();
|
|
position.add(offset);
|
|
limb.setPosition(position);
|
|
|
|
// grabing local point to "rotate" around (x, y position transform only)
|
|
var localPoint = this.body.getLocalPoint(limb.getPosition().clone());
|
|
|
|
// create rotation from chest rotation difference
|
|
var rot = planck.Rot(differenceAngle);
|
|
|
|
// rotate the local point using static method
|
|
var rotatedPoint = planck.Rot.mul(rot, localPoint);
|
|
|
|
// translating back to global position
|
|
var globalPoint = this.body.getWorldPoint(rotatedPoint);
|
|
limb.setPosition(globalPoint);
|
|
|
|
// relative limb rotating by chest rotation difference
|
|
var d = (oldDirection == direction) ? -1 : 1;
|
|
limb.setAngle((limb.getAngle() - differenceAngle) * d);
|
|
|
|
//limb.setType('static');
|
|
//limb.setLinearVelocity(planck.Vec2(0, 0));
|
|
}
|
|
};
|
|
|
|
RubeDoll.prototype.setVelocities = function(options) {
|
|
Assert.number(options.linearVelocity.x, options.linearVelocity.y);
|
|
Assert.number(options.angularVelocity);
|
|
|
|
this.body.setLinearVelocity(options.linearVelocity);
|
|
this.body.setAngularVelocity(options.angularVelocity);
|
|
for(var name in this.limbs) {
|
|
this.limbs[name].setLinearVelocity(options.linearVelocity);
|
|
}
|
|
};
|
|
|
|
RubeDoll.prototype.getPosition = function() {
|
|
return this.body.getPosition().clone();
|
|
};
|
|
|
|
RubeDoll.prototype.getHeadPosition = function() {
|
|
return this.limbs.head.getPosition().clone();
|
|
};
|
|
|
|
RubeDoll.prototype.setUpdateData = function(update) {
|
|
|
|
Parent.prototype.setUpdateData.call(this, update);
|
|
|
|
for(var name in update.limbs) {
|
|
Assert.number(update.limbs[name].p.x, update.limbs[name].p.y);
|
|
Assert.number(update.limbs[name].a);
|
|
Assert.number(update.limbs[name].lv.x, update.limbs[name].lv.y);
|
|
Assert.number(update.limbs[name].av);
|
|
|
|
this.limbs[name].setAwake(true);
|
|
this.limbs[name].setPosition(update.limbs[name].p);
|
|
this.limbs[name].setAngle(update.limbs[name].a);
|
|
this.limbs[name].setLinearVelocity(update.limbs[name].lv);
|
|
this.limbs[name].setAngularVelocity(update.limbs[name].av);
|
|
}
|
|
}
|
|
|
|
RubeDoll.prototype.preventCollisionWithPlayer = function(player) {
|
|
this.holdingPlayer = player;
|
|
|
|
// Generate a unique negative group index for this held RubeDoll
|
|
var uniqueGroupIndex = -(1000 + this.uid);
|
|
|
|
// Store original filter data and set new collision filter for RubeDoll limbs
|
|
for (var name in this.limbs) {
|
|
var limb = this.limbs[name];
|
|
var fixtureList = limb.getFixtureList();
|
|
|
|
for (var fixture = fixtureList; fixture; fixture = fixture.getNext()) {
|
|
// Store original filter data
|
|
this.originalFilterData[fixture] = {
|
|
groupIndex: fixture.getFilterGroupIndex()
|
|
};
|
|
|
|
// Set new filter to prevent collision with holding player
|
|
fixture.setFilterGroupIndex(uniqueGroupIndex);
|
|
}
|
|
}
|
|
|
|
// Also set the holding player's doll body to the same group index
|
|
if (player && player.doll && player.doll.body) {
|
|
var dollBody = player.doll.body;
|
|
var fixtureList = dollBody.getFixtureList();
|
|
|
|
for (var fixture = fixtureList; fixture; fixture = fixture.getNext()) {
|
|
// Store original filter data for doll
|
|
this.originalFilterData[fixture] = {
|
|
groupIndex: fixture.getFilterGroupIndex()
|
|
};
|
|
|
|
// Set new filter to prevent collision with held RubeDoll
|
|
fixture.setFilterGroupIndex(uniqueGroupIndex);
|
|
}
|
|
}
|
|
};
|
|
|
|
RubeDoll.prototype.restoreCollisionWithPlayer = function() {
|
|
if (!this.holdingPlayer) return;
|
|
|
|
// Restore original filter data for RubeDoll limbs
|
|
for (var name in this.limbs) {
|
|
var limb = this.limbs[name];
|
|
var fixtureList = limb.getFixtureList();
|
|
|
|
for (var fixture = fixtureList; fixture; fixture = fixture.getNext()) {
|
|
if (this.originalFilterData[fixture]) {
|
|
fixture.setFilterGroupIndex(this.originalFilterData[fixture].groupIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Also restore the holding player's doll body collision filters
|
|
if (this.holdingPlayer && this.holdingPlayer.doll && this.holdingPlayer.doll.body) {
|
|
var dollBody = this.holdingPlayer.doll.body;
|
|
var fixtureList = dollBody.getFixtureList();
|
|
|
|
for (var fixture = fixtureList; fixture; fixture = fixture.getNext()) {
|
|
if (this.originalFilterData[fixture]) {
|
|
fixture.setFilterGroupIndex(this.originalFilterData[fixture].groupIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.holdingPlayer = null;
|
|
this.originalFilterData = {};
|
|
};
|
|
|
|
RubeDoll.prototype.destroy = function() {
|
|
// Restore collision before destroying
|
|
this.restoreCollisionWithPlayer();
|
|
|
|
var world = this.body.getWorld();
|
|
|
|
for (var name in this.limbs) {
|
|
world.destroyBody(this.limbs[name]);
|
|
}
|
|
|
|
Parent.prototype.destroy.call(this);
|
|
};
|
|
|
|
return RubeDoll;
|
|
}); |