Monday, June 30, 2008

Need Second Life volunteers for a quick photo

The Second Life pinball machine is coming along nicely. I'm over two weeks ahead on blog posts so you should be seeing slow, but significant progress over the coming weeks.

I'm getting to the point where I'm deciding on the art theme of the pinball machine and I've decided I would like to make it a "Second Life pinball machine". That means that I need to get some good in world photos that might work as the score board and table background. If you would be interested in being notified (and possibly immortalized on a pinball machine) when I would get everyone together, please send me an e-mail (wood@side8.com, SL:Wood Wheels) and I'll pick a time and a date for the shoot. Also if you have ideas for a place that might work well I'm open to suggestions. I'm thinking something on a hillside or pyramid shape will allow more people to fit in the sort of vertical space I'm needing.

Friday, June 27, 2008

Second Life Script - Number Texture Display #2

Once I had a working number I had to place a few of them in sequence and allow a master prim to control them.



I had to first have a way for the root prim (the scoreboard) to send a message to the individual numbers telling them to update their display. I did this with a link message.


integer MSG_SET_NUM = 141; // arbitray message number
link_message(integer from, integer msg_id, string str, key id)
{
if (msg_id == MSG_SET_NUM)
{
curval = (integer)str;
llOwnerSay("setting num to "+(string)curval);
doOffset();
}
}


Then in the root prim I had to find the individual link numbers of the linked numbers. This is done like this. You first iterate through the list of links and find the ones named 1,10,100,1000 and save their link number. An avatar siting on the item will have a key and will have the highes link number so you have to skip them.

integer thousands = -1;
integer hundreds = -1;
...
state_entry()
{
integer current_link_nr = llGetNumberOfPrims();
// Check if it's more than one
if (1 <>0)
{
if (llGetLinkName(current_link_nr)=="1")
{
llOwnerSay("found 1: "+(string)current_link_nr);
one = current_link_nr;
}
else if (llGetLinkName(current_link_nr)=="10")
{
ten = current_link_nr;
llOwnerSay("found 10: "+(string)current_link_nr);
}
....
current_link_nr--;
}
}
}


Then when the number is changed, you send get the value of the thousands, then hundreds, then tens, then ones and send each on to the various number displays.



integer MSG_SET_NUM = 141; // the same message id defined in the number
doSendNumbers()
{
integer itmp = curval;
if (itmp>10000)
itmp=9999;

integer i;
i = itmp / 1000;
llOwnerSay("thousands = "+(string)i);
if (thousand!=-1)
{
// send the value to the thousands number
llMessageLinked(thousand, MSG_SET_NUM, (string)i, NULL_KEY);
}
itmp = itmp - (i*1000);

i = itmp / 100;
llOwnerSay("hundreds = "+(string)i);
if (hundred!=-1)
{
llMessageLinked(hundred, MSG_SET_NUM, (string)i, NULL_KEY);
}
itmp = itmp - (i*100);
.....


I had one more method on the scoreboard. When an avatar touches the scoreboard I increment the value and send the value out to the various individual numbers.

touch_start(integer total_number)
{
curval++;
if (curval>9999)
curval = 0;

doSendNumbers();
}

Thursday, June 26, 2008

Second Life Script - Number Texture Display

I needed a number display system. I've seen these in other items, but as usual I'm willing to just figure it out and build my own.

I first created a simple 16x256 pixel image of all the numbers. I made 16 numbers because textures are all power of two stuff. I doubt I'll do any hexadecimal displays, but I had the extra room.


I then used hit and miss to figure out the offsets for the numbers. I found the change from one number to the next was about 0.6 then worked backwards and forwards until I had both edges and -0.47 and +0.47. To make this programticall, I used (0.47*2)/16 to get 0.05875 which I tried, then finally figured out that I needed to divide by 15 because one cell is not counted in the actual size. That gave me an offset of 0.62666666.

integer curval = 0;
doOffset()
{
float ftmp = -0.47+(curval*0.062666);
llOwnerSay("offset ="+(string)ftmp);
llOffsetTexture(ftmp,0.0,ALL_SIDES);
}

default
{
state_entry()
{
doOffset();
}

touch_start(integer total_number)
{
// u offsets
//0=-0.47
//1=-0.41
//2=-0.35
//3=-0.29 *
//4=-0.22
//5=-0.16
//6=-0.10
//7=-0.04 *
//8=0.03
//9=0.09
//A=0.15
//B=0.21
//C=0.28 *
//D=0.34
//E=0.41
//F=0.47
// 0.47*2/15 = 0.06266666
curval++;
if (curval>16)
curval = 0;
doOffset();
}
}

There is one glaring problem I noticed after I got the number image uploaded. I probably need one cell that is only transparent so I can turn of the number. I'll do this later with another image upload and use -1 to display the blank number, but then I will not be able to show a hexadecimal number! Oh well... I'll probably end up making the other columns numeric symbols like dollar, pound, comma, period and such.



Make sure you apply the number texture to only one face. The rest of the faces are completely transparent. A simple trick is to select the texture face on the build dialog, then click on the individual faces to apply the texture to only that face.

Wednesday, June 25, 2008

Second Life Physics Scripting - Pinball #4

I need to make the ball a little smarter when it got stuck on the lower slope. I got a little crazy and added something to try and keep it at a constant velocity of 0.42M (the size of the ball), since anything faster than this can cause it to move through a wall across a frame rate. This is the final script.

float movebump = 0.2;
float maxspeed = 0.42;
float speeddiff = 0.02;
// http://lslwiki.net/lslwiki/wakka.php?wakka=llApplyImpulse
default
{
state_entry()
{
llSetTimerEvent(1.0); // generate a timer event every 1 second
}

timer()
{
//vector ra = <llFrand(movebump),llFrand(movebump),llFrand(movebump)>;
//llOwnerSay("ball moving "+(string)ra);
//llOwnerSay("ball moving mag "+(string)llVecMag(ra));
vector vel = llGetVel();
float velmag = llVecMag(vel);

// check for anything above or below the maximum velocity
if ( (velmag>0) && ((velmag>maxspeed+speeddiff) || (velmag<maxspeed-speeddiff)))
{
//llOwnerSay("oldvelmag = "+(string)llVecMag(vel));
// need to slow or speed up the ball
float magdev = maxspeed / velmag;
vel = vel * magdev;

// take that new velocity and apply it to the ball
llApplyImpulse(llGetMass()*vel,FALSE);
//llOwnerSay("newvelmag = "+(string)llVecMag(vel));
}
else if (velmag==0)
{
// need to give it a random bump!
vector ra = <llFrand(movebump),llFrand(movebump),llFrand(movebump)>;
//llOwnerSay("ball moving "+(string)ra);
llOwnerSay("ball vel 0 move bump = "+(string)llVecMag(ra));
// give the ball a little wiggle
llPushObject(llGetKey(), ra, <0,0,0>, FALSE);
}
//llOwnerSay("ball vel "+(string)llGetVel());
// give the ball a little wiggle
//llPushObject(llGetKey(), ra, <0,0,0>, FALSE);
}
}

I think there are still problems with it, because it should have been a problem in that it would never slow down and move down the board in the way I "thought" I coded it, but it does work, but it also still gets stuck briefly. I had to add the check for 0 velocity at the end because it was getting divide by zero and that else (velmag==0) piece of code was all I really needed in the first place. I'll have to revisit it, but at least it doesn't get stuck indefinitely any longer, but it still gets stuck a lot more than I'm willing to live with.

Tuesday, June 24, 2008

Second Life Physics Scripting - Pinball #3

The ball kept getting stuck, and I was looking for clever ways to keep it from getting stuck. This is what I tried as a script within the ball itself.

float movemax = 0.002;

default
{
state_entry()
{
llSetTimerEvent(1.0); // generate a timer event every 1 second
}

timer()
{
vector ra = ;
//llOwnerSay("ball moving "+(string)ra);
//llOwnerSay("ball moving mag "+(string)llVecMag(ra));
// give the ball a little wiggle
llPushObject(llGetKey(), ra, <0,0,0>, FALSE);
}
}

A simple timer and an added small push no matter if it needs it or not. This worked well for the steeper grade, but it still gets stuck on the machine with the "curved" slope (two planes one steeper than the other). It keeps getting stuck in the angle between the two planes. I either need to check the velocity every second and give it a bigger push if it is lower than some amount, or place some sort of accelerator in the area of the change in angle. It'll probably need to be some sort of combo between the two because I think I'll need the accelerator to make the game more interesting since the ball seems to have lost a lot of momentum once it reaches the "curve".

Monday, June 23, 2008

Second Life Physics Scripting - Pinball #2

The problems I was seeing with missed collision detection were (I believe) mostly fixed. The velocity of an object cannot exceed it's size or it may travel farther than itself in a single frame tick.


float maxspeed = 0.42;
default
{
collision_start(integer total_number)
{
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);

// direction from wall to ball
vector pos3 = pos2-pos;

pos3.x = pos3.x*4;
integer ra = (integer) llFrand(1.0)-1;
pos3.y = pos3.y*ra;

/// check the magnitude of the speed versus the max speed
float mag = llVecMag(pos3);
if (mag>maxspeed)
{
// limit the speed to the max magnitude
float magdev = maxspeed / mag;
pos3 = pos3 * magdev;
}
llPushObject(llDetectedKey(0), pos3, <0,0,0>, FALSE);
}
}
}

The Lindens chose this method to increase performance. The alternative would be to check for collisions multiple times during each fram as something moves. It would be nice if there were one more flag where you could turn on a finer granularity on an object, say multiple checks based on it's size, but for now it will have to be a slower game if I'm going to continue making a pinball game.

I created this contraption to test my scripts for bounce through. The pink ball just bounces up into the first wall and goes through it if it is going too fast. It hits the top wall without losing the ball and I can rerun the test. I have been able to get away with a little larger value than the object size because there is some immedite friction before it reaches the wall, but that just means that it WILL still happen so I'll need to account for a ball off the table, but it should/better be infrequent.

Friday, June 20, 2008

Second Life Physics Scripting - Pinball

I have been continuing to learn Linden Scripting Langage (lsl) in Second Life. I was stuck for a while on a board game and 2d video game idea and decided to move on to something else. My latest round of work has been learning the physics engine. I've been doing this by building a pinball machine.



The basics of this are in the collision_start method in the backwall of the pinball machine. The ball is a simple sphere with physics turned on.

default
{
collision_start(integer total_number)
{
//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);

// subtract the two positions to find the direction from the wall to the ball
vector pos3 = pos2-pos;
//llOwnerSay("pos = "+(string)pos+" pos2="+(string)pos2);
//llOwnerSay("pos3 = "+(string)pos3);

// do some multiplication to get a big bounce
pos3.x = pos3.x*4;

// change the y direction in minute ways to create a random bounce
integer ra = (integer) llFrand(1.0)-1;
pos3.y = pos3.y*ra;

// push the ball in that direction
llPushObject(llDetectedKey(0), pos3, <0,0,0>, FALSE);
}
}
}

This failed miserably since the ball kept leaping off the table. After a lot of reading it turns out that the collision system in second life only does detection on each frame so if the ball is moving fast it will be across the wall between frames and you have to go hunting for the ball. I'll discuss solutions in upcoming posts.

Thursday, June 19, 2008

Second Life Land Grab - Bay City #2

I've been thinking more about the Bay City Land grab. It seems like the Lindens struck a nerve and people are really excited about this new land. To me, the difference is in the roads and always having an open side to your land. Up until now it seemed like you could get trapped very easily by a couple of bad neighbors unless you wanted to spend a lot on a big space and waste a lot of it.

Then I was wondering why the Lindens didn't think about this earlier? They've said their initial designs came directly from Snow Crash and as I remember, roads were an integral part of the VR system in the book, so why no roads until now? Seems odd to me, but at least they finally figured it out. Now all they need to do is replicate this land style a few hundred more times and get the prices out of the stratosphere!

For those starting new sims, know that open space is important to a community and greatly affects land prices.

Here is a screen shot of a map that shows how much of this brand new land is up for sale. All the prices are over $200,000L (about $100US) for 1024. Here is a link/slurl for Bay City Imaginario (http://slurl.com/secondlife/Bay%20City%20-%20Imaginario/28/70/45) so you can check out those prices for yourself.

Wednesday, June 18, 2008

Second Life Land Grab - Bay City

I finally decided to get a little piece of my own land in Second Life. I was searching around trying to find a good plot for some simple builds and a group I'm helping. I was watching auctions and searching around and noticed the new community of Bay City being auctioned off. People were paying more for 1024 meter ($190,000L = $700US) plots than they were paying for a whole island. I'm not sure that these people are completely sane, but the land they were buying was nice. It had a lot of open space and roads between plots so land was not sandwiched in between four different neighbors.

Try visiting that area now, it is mostly baren with most of those 1024M plots up for resale for around $280,000L=$1000US. Crazy.

I passed on Bay City then noticed that the Lindens are starting to build roads through some of the older sims. I found a spot that had the acquired land for roads next to it, but no road built yet. I bought a small 512M plot next to that. I paid about $11L/Sq meter. Land value is basically around $7L/Sq Meter unless it has some geography. Since it was going to be next to a road I figured it was worth a little more and it fit my needs. I don't like all the subdividing that is going on along the roads. People selling tiny plots next to the roads for pure advertising. I found one that does not have a lot of that going on.