Wednesday, July 23, 2008

Second LIfe Physics Scripting - Pinball #18 - Integrated Flipper

Okay, after all that work on the flipper I tried to integrate it anyway just to see if the mechanice was salvagable. It was a complete bust. The collisions did not occur properly while the rotation was in progress and overall system did not behave at all like a pinball flipper. I tried to add the llPushObject code to the flipper when it was on only, but then trying to trap the ball with the flipper had all kinds of issues. Overall, it was a complete waste of time.


Just for fun, here is the complete flipper_rotate_listener script.


integer MSG_RIGHT_ON_NUM = 5115;
integer MSG_RIGHT_OFF_NUM = 5116;
integer MSG_LEFT_ON_NUM = 5117;
integer MSG_LEFT_OFF_NUM = 5118;

rotation start_rot;
vector start_pos;
integer orig_axis_flag = FALSE;
vector orig_axis;

integer on=FALSE;
integer cur_rotation=0;
integer max_rotation = -60;
integer rotation_tick = -20;
float timer_gap = 0.1;

float bumpspeed_waiting = 0.2;
float bumpspeed_on = 0.62;
float bumpspeed_off = 0.01;

default
{
state_entry()
{
start_rot = llGetLocalRot();
start_pos = llGetLocalPos();

state waiting;
}
}

state waiting
{
state_entry()
{
}

link_message(integer from, integer msg_id, string str, key id)
{
if (msg_id == MSG_RIGHT_ON_NUM)
{
llOwnerSay("flipper rotate on");
state rotate_on;

}
else if (msg_id == MSG_RIGHT_OFF_NUM)
{
state rotate_off;
}
}

} // state waiting

state rotate_on
{
state_entry()
{
llSetTimerEvent(timer_gap);
}

timer()
{
if (((rotation_tick>0) && (cur_rotation>max_rotation)) ||
((rotation_tick>0) && (cur_rotation>max_rotation)))

{
cur_rotation = cur_rotation + rotation_tick;

// what is currently pointing up in the z direction
// was originally in the -y direction.
if (!orig_axis_flag)
{
orig_axis_flag = TRUE;
orig_axis = llVecNorm(<0,-1,0> * llGetLocalRot());
}

// a rotation around the parents z normal
//rotation z_45 = make_quaternion(parent_norm,rotation_tick*DEG_TO_RAD);
rotation z_rot = llAxisAngle2Rot(orig_axis,rotation_tick*DEG_TO_RAD);

// we need to find the axis which is the heal of the wedge
// the original orientation of the flipper wedge is <0,0,1>
// i use -1 to point at the heal of the wedge
vector norm = <0,0,-1>;
// rotate that norm so it points towards the point of the wedge
norm = llVecNorm(norm * llGetLocalRot());
// find the size of the wedge
vector sz = llList2Vector(llGetPrimitiveParams([PRIM_SIZE]),0);
// get the center location of the wedge
vector flipper_pos = llGetLocalPos();
// find the offset distance from the center
vector offset = norm * (sz.z / 2);
// add that offset to the flipper_pos to get the axis
vector rot_axis = flipper_pos + offset;

// calculate the new rotation by adding the z axis rotation
// z_rot is the old name it is really z_plusang
rotation new_rot = llGetLocalRot()*z_rot;
// http://wiki.secondlife.com/wiki/Rotation
// set the new local rotation
llSetLocalRot(new_rot);

// lsl wiki solution for non center rotation
vector new_pos = rot_axis + ((flipper_pos - rot_axis) * z_rot);
llSetPos(new_pos);
}
else
{
// stop the timer and wait for the off event
llSetTimerEvent(0);
}
} // timer

collision_start(integer total_number)
{
//llOwnerSay("Collision start");
//llOwnerSay(llDetectedName(0) + " collided with me!");
if (llDetectedName(0) == "ball")
{
// need to find the direction from the backwall to the ball
vector pos = llGetPos();
list a = llGetObjectDetails(llDetectedKey(0), ([OBJECT_POS]));
vector pos2 = llList2Vector(a,0);
//vector pos3 = pos-pos2;
vector pos3 = llVecNorm(pos2-pos);
llOwnerSay("bump pos3 = "+(string)pos3);
//if (pos3.z>0) // it's not behind us
//{
//pos3.y = pos3.y*2;
//integer ra = (integer) llFrand(1.0)-1;

pos3 = pos3 * bumpspeed_on;
llOwnerSay("bump mag = "+(string)llVecMag(pos3));

//float mag = llVecMag(pos3);
//if (mag>maxspeed)
//{
// float magdev = maxspeed / mag;
// pos3 = pos3 * magdev;
//
// mag = llVecMag(pos3);
//}
//llOwnerSay("sidewall = "+(string)pos3);

llPushObject(llDetectedKey(0), pos3, <0,0,0>, FALSE);
//}

}
}

link_message(integer from, integer msg_id, string str, key id)
{

if (msg_id == MSG_RIGHT_OFF_NUM)
{
llSetTimerEvent(0);
state rotate_off;
}
}
} // state rotate_on

state rotate_off
{
state_entry()
{
// already in local coords since child prim
llSetPos(start_pos);
llSetLocalRot(start_rot);
cur_rotation = 0;
state waiting;
}
link_message(integer from, integer msg_id, string str, key id)
{

if (msg_id == MSG_RIGHT_ON_NUM)
{
state rotate_on;
}
}
} // state rotate_off


And the pay and keyboard script in the pinball parent.


integer right_flipper = -1;
integer left_flipper = -1;

integer MSG_RIGHT_ON_NUM = 5115;
integer MSG_RIGHT_OFF_NUM = 5116;
integer MSG_LEFT_ON_NUM = 5117;
integer MSG_LEFT_OFF_NUM = 5118;

default
{
state_entry()
{
integer current_link_nr = llGetNumberOfPrims();
// Check if it's more than one
if (1 < current_link_nr)
{
// avatars sitting on us get added at the end, so subtract...
while (llGetAgentSize(llGetLinkKey(current_link_nr)))
--current_link_nr;

while(current_link_nr>0)
{
if (llGetLinkName(current_link_nr)=="right_flipper")
{
llOwnerSay("found right_flipper: "+(string)current_link_nr);
right_flipper = current_link_nr;
}
else if (llGetLinkName(current_link_nr)=="left_flipper")
{
llOwnerSay("found right_flipper: "+(string)current_link_nr);
left_flipper = current_link_nr;
}
current_link_nr--;
}
}
}

run_time_permissions(integer perm)
{
// permissions dialog answered
if (perm & PERMISSION_TAKE_CONTROLS)
{
// we got a yes
// take left, right, up and down controls
llTakeControls(CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT | CONTROL_UP | CONTROL_DOWN, TRUE, FALSE);
}
}

touch_start(integer total_number)
{
llSay(0, "Would you like to play? I'll need to take over your keyboard.");
llSay(0, "This doesn't work yet, it's still under construction.");
llSay(0, "The only key that works is 'd' and even then, the flipper is off the actual table, getting closer and there is only one of them...");
llSay(0, "To get your keys back simply click on the Release Keys button just above the Fly button");

integer perm= llGetPermissions();

if (!perm&PERMISSION_TAKE_CONTROLS)
{
llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS);
// get permission to take controls
}
else
{
llSay(0,"We have permission to take control...trying");
llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS);
//llTakeControls(CONTROL_LEFT| CONTROL_RIGHT | CONTROL_UP | CONTROL_DOWN,
// TRUE, TRUE);
}
}
control(key id, integer held, integer change)
{
//llSay(0, "control id="+(string)id);
//llSay(0, " held="+(string)held+" change="+(string)change);
//llSay(0, " ROT_RIGHT"+(string)CONTROL_ROT_RIGHT);
if ((held&CONTROL_ROT_RIGHT) && (change&CONTROL_ROT_RIGHT))
{
//llSay(0," right flipper on");
llMessageLinked(right_flipper, MSG_RIGHT_ON_NUM, "", NULL_KEY);

}
else if (((held&CONTROL_ROT_RIGHT)==0) && (change&CONTROL_ROT_RIGHT))
{
//llSay(0," right flipper off");
llMessageLinked(right_flipper, MSG_RIGHT_OFF_NUM, "", NULL_KEY);
}

}
}

No comments: