Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Simple Color Change Script (timed)

Little Ming
The Invisible Man
Join date: 31 Mar 2005
Posts: 84
08-17-2005 15:38
I'm trying to make a simple color change script (without a on/off)... I just want it to change between 2 colors on a 1 second timer. I'm not sure how to do this, I'm very new to scripting, trying to learn by disecting other scripts. hehe if anyone could help me or write up a commented script for me to look at and learn from it'd be helpful ^^ thankies
Judah Jimador
Registered User
Join date: 13 Mar 2005
Posts: 230
08-17-2005 16:46
Hey, Little!

I think this should work.

CODE

vector COLOR_1 = <1.0,0.0,0.0>; // Pure red
vector COLOR_2 = <0.0,1.0,0.0>; // Pure green

integer USE_COLOR_1;

default {
state_entry() {
USE_COLOR_1 = FALSE;
llSetTimerEvent( 1.0 );
}

timer() {
if (USE_COLOR_1)
llSetColor( COLOR_1, ALL_SIDES );
else
llSetColor( COLOR_2, ALL_SIDES );

USE_COLOR_1 = !USE_COLOR_1;
}
}
}


Haven't tested it, though.

-- jj
Judah Jimador
Registered User
Join date: 13 Mar 2005
Posts: 230
08-17-2005 16:57
Oh...if you want to explore states a little more...

unlike some mechanisms, which get cleaned up whenever there's a state transition, timers run across all states. Each script (task) has one timer associated with it, and any state can start, stop, or intercept the timer.

So this'll also work:

CODE

vector FIRST_COLOR = <1.0,0.0,0.0>;
vector SECOND_COLOR = <0.0,1.0,0.0>;

float TIMER_INTERVAL = 1.0;

default {
state_entry() {
//
// all states will hear this timer until one of them
// stops it using llSetTimerEvent( 0.0 )
//
llSetTimerEvent( TIMER_INTERVAL );
//
// start the color cycle
//
state first_color;
}
}

state first_color {
state_entry() {
llSetColor( FIRST_COLOR, ALL_SIDES );
}

timer() {
state second_color;
}
}

state second_color {
state_entry() {
llSetColor( SECOND_COLOR, ALL_SIDES );
}

timer() {
state first_color;
}
}
a lost user
Join date: ?
Posts: ?
08-17-2005 19:01
CODE
list colors = ["<1,0,0>","<0,1,0>","<0,0,1>"]; // red green adn blue, add as many as you like
integer counter;
integer total_colors;

default
{
state_entry()
{
llSetTimerEvent(1.0);
total_colors = llGetListLength(colors);
}

timer()
{
llSetColor(llList2Vector(colors,counter),ALL_SIDES);
counter++;
if(counter == total_colors) counter = 0;
}
}


oops just two colors? :P sorry.. I got excited :P
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
08-18-2005 03:00
Hi Little Ming,

As you can see from the above replies several ways of doing the same thing. All have advantages and disadvantages.

I'd personally have gone for something like Gaz's approach - it's neat and you can easily go back and reuse it with more colours if you need to. Modifying the others for more colours gets increasingly hard and wasteful of code.

This is one of the joys, frustrations and fun of scripting - there are nearly always several ways to do any job, picking the one that best fits your needs is always tricky.

As a little add on I was thinking about making it something like a dance light with random times and colours - and thought of half a dozen ways of doing that whilst writing this reply.
Judah Jimador
Registered User
Join date: 13 Mar 2005
Posts: 230
08-18-2005 06:26
Oh, yeah, Eloise is right..as far as maintainability goes, Gaz's example wins hands-down.

The first one I gave is bare-bones; the second is contrived to show a bit about states.

Either of them would be a royal pain in the haunches to extend. I definitely shoulda mentioned that they weren't examples of what the techie rags like to call "best practices."

As a matter of fact, I was thinking while I typed in the second one that it might be beneficial to LSL newbies to re-visit this mini-problem from time to time, to show different LSL features one or two at a time...since lists have been demo'd now, I guess next up would be to read color settings from a configuration notecard.

After that, I dunno, a central Blink Server updating a gridwide network of blinking color objects with new blink strategies every midnight...? :D

-- jj
Michael Psaltery
Registered User
Join date: 6 Jun 2004
Posts: 57
08-18-2005 09:22
Another option to consider is to create a two-color texture with your desired colors and apply to the object. Scale it so that only one of the colors can be seen. Then use texture controls to set attributes to flip between the colors.

I think this is a pretty efficient way to do it.
(pseudocode)
state default;
float offset;
state_entry()
{
set timer 1 second
}
timer()
{
set texture parameters (offset);
offset = offset * -1
}

So, every time you hit the timer, it flips the texture and changes the offset. You never need to deal with states, because you don't really care what the color is at any time as
long as it's switching between the two. Changing colors can be done by just replacing the texture, so no scripting changes are required after that.

Alternatively... it might be possible to just use texture rotation at a really slow rate to change from color to color. Apply a texture with a smooth gradient between the two colors and set the texture rotation. If the effect works for you, you can remove the script, and the colors should continue to change. (but I think the script has to stay if you copy or re-rez the object).
Little Ming
The Invisible Man
Join date: 31 Mar 2005
Posts: 84
08-18-2005 12:49
Wow, thank you all for such a positive response to my post. You're replies were all VERY helpful ^^ I see there's a LOT I need to learn yet. I didn't realize there were so many ways to do the same thing. But then I spose that is a bit nieve of me. I guess scripting is like english, 100 ways to say the same thing. LoL ^^ Thank you all very much for the help, I'm gonna get back to disecting these and learning more about them, but I wanted to take the time to say thanks :D
Upshaw Underhill
Techno-Hobbit
Join date: 13 Mar 2003
Posts: 293
08-18-2005 13:40
Or if you want to keep from lagging the Sim you can use this version:
/54/c8/30739/1.html

which uses a texture and no script at all (well, briefly but it self deletes)

L8r,
UU
_____________________
Hank Ramos
Lifetime Scripter
Join date: 15 Nov 2003
Posts: 2,328
08-18-2005 13:43
Here is an extremely laggy version, but cool looking...

CODE
default
{
state_entry()
{
while (TRUE)
{
llSetColor(<llFrand(1.0), llFrand(1.0), llFrand(1.0)>, ALL_SIDES);
}
}
}
Ethan Cinquetti
Registered User
Join date: 5 Jul 2005
Posts: 24
My Own Newbie Effort
08-18-2005 19:36
I'm just really learning my way around LSL, and currently intrigued by the potential of linked messages. It struck me that this might be an interesting little exercise in distributed processing. So, without further ado, three separate scripts in a single prim, dedicated to one simple task...


This is the timekeeper, which broadcasts a clock tick to every other script in the same prim:
CODE


//
// These two message ID's appear in all three scripts.
//
integer TICK_MSG = 101;
integer NEW_COLOR_MSG = 102;

default
{
state_entry() { llSetTimerEvent( 1.0 ); }

timer() { llMessageLinked( LINK_THIS, TICK_MSG, "", "" ); }
}



Here's the color selector, which uses a variation of the list strategy already posted:
CODE

integer TICK_MSG = 101;
integer NEW_COLOR_MSG = 102;

vector red = <1.0, 0.0, 0.0 >;
vector green = < 0.0, 1.0, 0.0 >;

list colors = [ red, green ];

integer current_color_index = 0;

default
{
link_message( integer sender, integer num, string s, key k ) {
//
// Was it a clock tick? If so, broadcast the next available color
// to all interested scripts in the same prim
//
if ( num == TICK_MSG ) {
llMessageLinked( LINK_THIS,
NEW_COLOR_MSG,
llList2String( colors, current_color_index ),
"" );
current_color_index++;
if ( current_color_index == llGetListLength( colors ) )
current_color_index = 0;
}
}
}



And finally, the painter task, which ignores the clock tick, but listens for new color selections and paints the prim:
CODE

integer TICK_MSG = 101;
integer NEW_COLOR_MSG = 102;

default
{
link_message( integer sender_id, integer num, string s, key id ) {
if ( num == NEW_COLOR_MSG )
llSetColor( (vector)s, ALL_SIDES );
}
}



Much to my delight, it works! LSL is very intriguing...

- Ethan
a lost user
Join date: ?
Posts: ?
08-18-2005 22:10
Well yes, that will work quite well and it even works around the 0.2 delay caused by llSetColor() and llSetLinkColor(), however there is no real need for the second script. It could all have been done in the first script. Also consider:


Use this for the color control:
CODE

list colors = [<1,0,0>,<0,1,0>,<0,0,1>];
integer total_prims;
integer total_colors;

default
{
state_entry()
{
total_colors = llGetListLength(colors);
total_prims = llGetNumberOfPrims();
integer iteration;
while(TRUE)
{
for(iteration = 1; iteration < total_prims; iteration++)
{
llMessageLinked(iteration, 0, llList2String( colors, llRound( llFrand(total_colors - 1) ) ), "");
}
}
}
}


Then use this for each prim you want to change color:
CODE

default
{
link_message(integer sender, integer number, string message, key data)
{
llSetLinkColor(llGetLinkNumber() ,(vector)message, ALL_SIDES);
}
}


This works aorund the 0.2 second delay, and sends a random color from the list to each of the prims, that is each prim will recieve its own random color.. not just a single random color to the entire link_set.

You could use the same principle for doing it on a single prim, using the faces:
CODE

list colors = [<1,0,0>,<0,1,0>,<0,0,1>];
integer total_faces;
integer total_colors;

default
{
state_entry()
{
total_colors = llGetListLength(colors);
total_faces = llGetNumberOfSides();
integer iteration;
while(TRUE)
{
for(iteration = 0; iteration < total_faces; iteration++)
{
llMessageLinked(LINK_SET, iteration, llList2String(colors, llRound( llFrand( total_colors - 1) ) ), "");
}
}
}
}


Then use this to change the color of the faces:
CODE

default
{
link_message(integer sender, integer number, string message, key data)
{
llSetColor((vector)message, number);
}
}


Provided all the prims are the same type (eg. all six-sided boxes or all cylinders.. whatever) you could then link them all together with the color changer inside to change all of the prim faces of the entire link_set.
Ruthven Willenov
Darkness in your light
Join date: 16 Jan 2008
Posts: 965
05-20-2008 10:58
From: Judah Jimador
Oh...if you want to explore states a little more...

unlike some mechanisms, which get cleaned up whenever there's a state transition, timers run across all states. Each script (task) has one timer associated with it, and any state can start, stop, or intercept the timer.

So this'll also work:

CODE

vector FIRST_COLOR = <1.0,0.0,0.0>;
vector SECOND_COLOR = <0.0,1.0,0.0>;

float TIMER_INTERVAL = 1.0;

default {
state_entry() {
//
// all states will hear this timer until one of them
// stops it using llSetTimerEvent( 0.0 )
//
llSetTimerEvent( TIMER_INTERVAL );
//
// start the color cycle
//
state first_color;
}
}

state first_color {
state_entry() {
llSetColor( FIRST_COLOR, ALL_SIDES );
}

timer() {
state second_color;
}
}

state second_color {
state_entry() {
llSetColor( SECOND_COLOR, ALL_SIDES );
}

timer() {
state first_color;
}
}


well i know this script and thread is quite old, but anyways, i hacked at this one a bit to use it for a light flicker, i wanted to implent it into a candle script that has a touch start. (candles lit-light flickers, candles off-light off) but i couldn't get it to work the way i want. i added a third color and blah blah blah. when the flame came on it ran thru the light cycle once and stopped, can't figure out how to get it to work continuously while the flames are on and turn off when the flames are off. i'd be fine with running it in a seperate script with a touch start and touch off, but i can't figure that out either
Dora Gustafson
Registered User
Join date: 13 Mar 2007
Posts: 779
05-20-2008 11:25
I have not read all the thread( in 2005 I was not here LOL), but this is another approach, I guess:
CODE

// rolling texture, Studio Dora, Dora Gustafson 2008-04-04

integer side = 0; // Prim face number
integer x_frames = 2;
integer y_frames = 3;
float start = 0.0; // first frame
float length = 0.0; // number of frames, 0 is all frames
float rate = 2.0 // frames/S

default
{
state_entry()
{
integer mode = ANIM_ON | LOOP;
llSetTextureAnim( mode, side, x_frames, y_frames, start, length, rate );
}
}

This particular script works with a texture in 6 colors, 2 by 3 fields.
Add a texture with the colors you want and there you have a low lag color changer
_____________________
From Studio Dora
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
05-20-2008 13:43
Just add colours as needed...

CODE

integer OnOff;
float Delay = 0.5;
list lColours = [<1.0,0.0,0.0>, <0.0,1.0,0.0>, <0.0,0.0,1.0>];
integer x;

default
{
touch_start(integer total_number)
{
llSetTimerEvent((OnOff = !OnOff) * Delay);
}

timer()
{
llSetColor(llList2Vector(lColours, x), ALL_SIDES);
x++;
if(x >= llGetListLength(lColours)) x = 0;
}
}



hmm... now I look this looks suspiciously similar to post #4 :p
Ruthven Willenov
Darkness in your light
Join date: 16 Jan 2008
Posts: 965
05-31-2008 09:51
From: Pale Spectre
Just add colours as needed...

CODE

integer OnOff;
float Delay = 0.5;
list lColours = [<1.0,0.0,0.0>, <0.0,1.0,0.0>, <0.0,0.0,1.0>];
integer x;

default
{
touch_start(integer total_number)
{
llSetTimerEvent((OnOff = !OnOff) * Delay);
}

timer()
{
llSetColor(llList2Vector(lColours, x), ALL_SIDES);
x++;
if(x >= llGetListLength(lColours)) x = 0;
}
}



hmm... now I look this looks suspiciously similar to post #4 :p


i'm not in world to try it, but does it cycle the colors continuously until touched again to turn it off? and what is the integer x for?
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
05-31-2008 13:57
The expression: OnOff = !OnOff will change between zero and 1 each time a touch event occurs.

So: llSetTimerEvent((OnOff = !OnOff) * Delay) will turn the timer off, or turn it on with the value in float Delay (in this example this will give timer settings of: 0.5, 0, 0.5, 0 etc... controled by touch)

The integer x is simply counting through the index values for list lColours (in this example: 0, 1, 2, 0, 1, 2, etc...). As x is set to zero when this condition is met: x >= llGetListLength(lColours), it will automagically increment correctly for whatever length of list is used.

So yes, it will cycle the colours continuously until touched again to turn it off. The integer x is being used as the index position in list lColour. Oh, and the value in float Delay determines how quickly the colours change.

:D
Ruthven Willenov
Darkness in your light
Join date: 16 Jan 2008
Posts: 965
06-03-2008 07:31
well, i hacked it to use it for light, it certainly flickers, but doesn't turn the light off when the timer is turned off:

From: someone

integer OnOff;
float Delay = 0.5;
list lColours = [<1.0,0.0,0.0>, <0.0,1.0,0.0>, <0.0,0.0,1.0>];
integer x;

default
{
touch_start(integer total_number)
{
llSetTimerEvent((OnOff = !OnOff) * Delay);
}

timer()
{
llSetPrimitiveParams([PRIM_POINT_LIGHT, TRUE,llList2Vector(lColours, x), 1.0, 5.0, 0.6]);
x++;
if(x >= llGetListLength(lColours)) x = 0;
}
}