Showing posts with label puck flipper. Show all posts
Showing posts with label puck flipper. Show all posts

Monday, July 28, 2008

Second Life Physics Scripting - Pinball #21 - Puck Flipper Collisions

Blackjack! No, pinball! I think we have a game! At least the mechanic of a game. This is the first time I've felt like this could actually be a little bit fun to play and I feel like I'm geting closer to something playable. Very cool.

Here is the puck flipper collision script.


collision_start(integer total_number)
{
if (llDetectedName(0) == "ball")
{
// positions are in global coordinates

// find the position of the collision...
vector colpos = llDetectedPos(0);
//llOwnerSay("colpos = "+(string)colpos);

// find the location of the puck prim
vector locpos = llGetPos();
//llOwnerSay("locpos = "+(string)locpos);

// subtract two to get local coordinates on the puck
colpos = locpos - colpos;
//llOwnerSay("colpos = "+(string)colpos);

// divide by the global rotation so we are back
// in the original build orientation
rotation locrot = llGetRot();
colpos = colpos / locrot;
//llOwnerSay("colpos after rot = "+(string)colpos);

// find the size of the wedge
vector sz = llList2Vector(llGetPrimitiveParams([PRIM_SIZE]),0);
//llOwnerSay("puck size = "+(string)sz);
// this size is pre-rotations. We are interested in the Y value

// find the width of the puck
float puckwid = sz.y/4;

// the start of the puck, origin is center so divide by 2
float puckstart = (curval * puckwid) - (sz.y/2);
float puckend = puckstart + puckwid + puck_overlap;
puckstart = puckstart - puck_overlap;

if ((colpos.y>=puckstart) && (colpos.y<=puckend))
{
//llOwnerSay("PUCK IN CURCOL "+(string) curval);

// the dir we what to pushin
vector pushdir = <1,0,0>;
pushdir = pushdir * locrot;
//llOwnerSay("push dir = "+(string)pushdir);

llPushObject(llDetectedKey(0), pushdir, <0,0,0>, FALSE);
}
else
{
// shoot it towards the back wall because
// if it is going slow and they get the puck
// under the ball it seems like it should shoot away
// the dir we what to pushin
vector pushdir = <-1,0,0>;
pushdir = pushdir * locrot;
//llOwnerSay("push dir = "+(string)pushdir);

llPushObject(llDetectedKey(0), pushdir, <0,0,0>, FALSE);
}
}
}


Since the last version I added the checks to see which portion of the puck flipper the ball is actually hitting. Just a simple division by the number of pucks in the texture and then a check to see if it is in the currently active portion of the puck.

After playing with it for a while I added the extra push towards the back wall if it isn't in the puck area. It seemed like I was able to move the puck under the ball a lot and it felt like it should shoot away, but there is really no easy way to tell where the ball is every move of the puck, so I decided to shoot it towards the back wall.

Up next, a ball launcher and a ball killer when it hits the back wall. From there, a game start and game end condition, then maybe some extras besides simple bumpers. Somewhere in there I'll have to move to some real art from the plywood. Very cool.

Friday, July 25, 2008

Second Life Physics Scripting - Pinball #20 - Complete Puck Flipper System

Is this ever going to end? 20 posts already and there still seems like a ton of game code to add. This next step was all about trying to figure out where the ball crossed what I'm now calling the "puck flipper". I just typed it in once and it stuck, but now that I look at it I don't think it's the best name since it seems like the brain really wants to swap the f and p. Maybe it's just my brain? Oh well, it's in the code now.

Removing the flipper and hooking up the new puck flipper to the machine was a pretty simple exercise and only took a few minutes.


Anyway, it was pretty easy to setup the collision system, but actually a little hard to figure out where it crosses when you think about it in larger terms. Look at this first step.


collision_start(integer total_number)
{
if (llDetectedName(0) == "ball")
{
// positions are in global coordinates

// find the position of the collision...
vector colpos = llDetectedPos(0);
//llOwnerSay("colpos = "+(string)colpos);

// find the location of the puck prim
vector locpos = llGetPos();
//llOwnerSay("locpos = "+(string)locpos);

// subtract two to get local coordinates on the puck
colpos = locpos - colpos;
}
}

This is pretty straight forward. Take the positions of the two elements and subtract their positions. This will give you the coordinates local to the puck. If you divide the y size by 4, this gives you the size of each puck positions. Multiply by the current puck and position and add a little bit in each direction and you can then compare that to the Y collision position.

Easy you say. Until you start to rotate the pinball machine around. I've built it aligned along the X axis, but if you rotate it 90 degrees into the Y axis then all the calculations will no longer work! You have to take this rotation into account. This next piece shows that code.


collision_start(integer total_number)
{
if (llDetectedName(0) == "ball")
{
// find the position of the collision...
vector colpos = llDetectedPos(0);
//llOwnerSay("colpos = "+(string)colpos);

// find the location of the puck prim
vector locpos = llGetPos();
//llOwnerSay("locpos = "+(string)locpos);

// subtract two to get local coordinates on the puck
colpos = locpos - colpos;
llOwnerSay("colpos = "+(string)colpos);

// divide by the global rotation so we are back
// in the original build orientation
rotation locrot = llGetRot();
colpos = colpos / locrot;
llOwnerSay("colpos after rot = "+(string)colpos);
}
}

Don't think I'm some sort of genuis and this just fell out of my brain. I spent at least an hour tweaking to get this right. For the longest time I had what I originally wrote colpos = colpos * locrot;. After I got my view port inside the pinball machine and dropped the ball at both edges a bunch of times I realized the Y values were giving opposite results when the table was rotated. I figured that using division of the rotation might swap the signs and sure enough it did and now I can move on.

I really like the puck mechanic so far and think it will be really effective. I think it will be even better if I used it with more than 4 positions. Given a bunch of positions it might even look just like a pong puck and allow for some really cool game mechanics. I've not seen anyone use this yet, so I'm excited to see this in action.