A set of functions that make it easy to loop through colors and create rainbow effect. After copying all the functions from the snippet below the user can implement 2 simple function calls that will take care of the complex process behind it. These functions are:
1. "ShiftColorHue" which changes the color with variable speed, it has the following parameters:
0@ - speed_step - how fast the color change occurs (from 1 to ~30)
1@ - direction (1-rgb order, 2-reversed order)
2@ - hue variable which needs to be dedicated for this snippet (from 1 to 359, it's actually the only variable that is required in external code for this snippet)
2. "GetCLRfromHSV" which converts Hue (the actual color of the color ;p), Saturation, and Value into 3 values between 0-255 (that could be later used as RGB). It has the following parameters:
0@ - Hue (0 - 360 int)
1@ - Saturation (0.0 - 1.0 float)
2@ - Value (0.0 - 1.0 float)
There's also a function which can be used to make the colors more aesthetic called "RYB_to_RGB". Using it will result in the colors shown on the right wheel from this image based on Red-Yellow-Blue. I guess most programmers use RGB distribution so using that function would make the rainbow effect somewhat unique. The function takes 3 integers between 0-255 and returns also 3 integers between 0-255. It's based on the work of Nathan Gossett and Baoquan Chen.
Full code example tested with Cleo 4.1, Samp 0.3.7 and Sampfuncs 5.3.1
1. "ShiftColorHue" which changes the color with variable speed, it has the following parameters:
0@ - speed_step - how fast the color change occurs (from 1 to ~30)
1@ - direction (1-rgb order, 2-reversed order)
2@ - hue variable which needs to be dedicated for this snippet (from 1 to 359, it's actually the only variable that is required in external code for this snippet)
2. "GetCLRfromHSV" which converts Hue (the actual color of the color ;p), Saturation, and Value into 3 values between 0-255 (that could be later used as RGB). It has the following parameters:
0@ - Hue (0 - 360 int)
1@ - Saturation (0.0 - 1.0 float)
2@ - Value (0.0 - 1.0 float)
There's also a function which can be used to make the colors more aesthetic called "RYB_to_RGB". Using it will result in the colors shown on the right wheel from this image based on Red-Yellow-Blue. I guess most programmers use RGB distribution so using that function would make the rainbow effect somewhat unique. The function takes 3 integers between 0-255 and returns also 3 integers between 0-255. It's based on the work of Nathan Gossett and Baoquan Chen.
Full code example tested with Cleo 4.1, Samp 0.3.7 and Sampfuncs 5.3.1
Code:
{$CLEO}
0000: NOP
repeat
wait 50
until 0AFA: is_samp_available
31@ = 0 // hue 0 - 359 (variable required to keep track of the colour)
while true
wait 0
call @ShiftColorHue 3 speed_step 1 direction 1 hue_var 31@ _returned_hue_var 31@ // it increases/decreases 31@ variable between 0-359
call @GetCLRfromHSV 3 hue 31@ saturation 1.0 value 1.0 _returnedColor 1@ 2@ 3@
// Holding enter presents what "RYB_to_RGB" function does, RGB distribution has too much green/blue from my point of view
// It appears too bright if the saturation isn't lowered. RYB seems to be more aesthetic to me but lacks bright colors like cyan or magenta.(check google for better comparison)
if key_down 13
then
call @RYB_to_RGB 3 RYB 1@ 2@ 3@ _RGB 1@ 2@ 3@ // idk how it will behave if you change "Saturation" and "Value" to something other than 1.0
printf "That's right my nigga:)" 1000
else
printf "Hold ENTER for ~R~Red~W~-Yellow-~B~Blue~W~ instead of ~R~Red~W~-~G~Green~W~-~B~Blue" 1000
end
// Drawing
0B67: render a 255 r 1@ g 2@ b 3@ to_argb 0@
call @Draw 1 0@
end
//
// FUNCTIONS
//
:Draw
0B5A: get_screen_resolution 30@ 31@
30@/=2
31@/=3
0085: 29@ = 30@ // (int)
29@/=2
0B70: render draw_polygon_pos 30@ 31@ size 29@ 29@ corners 8 rotation 0.0 color 0@ //0@, 1@ [int] 2@, 3@ [int], 4@ [int], 5@ [float], 6@ [int]
ret 0
:RYB_to_RGB_GetSingleClr
{
0@ - R
1@ - Y
2@ - B
3@ - front_up_left : [1, 1, 0],
4@ - front_up_right: [1, 0.5, 0],
5@ - "front_down_left": [1, 1, 1],
6@ - "front_down_right": [1, 0, 0],
7@ - "back_up_left": [0, 0.66, 0.2],
8@ - "back_up_right": [0.2, 0.094, 0],
9@ - "back_down_left": [0.163, 0.373, 0.6],
10@ - "back_down_right": [0.5, 0.0, 0.5],
}
/*
3@ *= 255.0
4@ *= 255.0
5@ *= 255.0
6@ *= 255.0
7@ *= 255.0
8@ *= 255.0
9@ *= 255.0
10@ *= 255.0
*/
//chatmsg "%.2f %.2f %.2f" -1 0@ 1@ 2@
call @Interpolate 5 val 0@ range 0.0 255.0 front_up_left 3@ front_up_right 4@ _side_front_up 11@
call @Interpolate 5 val 0@ range 0.0 255.0 front_down_left 5@ front_down_right 6@ _side_front_down 12@
call @Interpolate 5 val 0@ range 0.0 255.0 back_up_left 7@ back_up_right 8@ _side_back_up 13@
call @Interpolate 5 val 0@ range 0.0 255.0 back_down_left 9@ back_down_right 10@ _side_back_down 14@
//chatmsg "%.2f %.2f %.2f %.2f" -1 11@ 12@ 13@ 14@
call @Interpolate 5 val 1@ range 0.0 255.0 side_front_down 12@ side_front_up 11@ _side_vert_front 15@
call @Interpolate 5 val 1@ range 0.0 255.0 side_back_down 14@ side_back_up 13@ _side_vert_back 16@
call @Interpolate 5 val 2@ range 0.0 255.0 side_vert_front 15@ side_vert_back 16@ _returnedValue 17@
/*
sideways_front_up = Interpolate(r, [0,1], [
RYB_RGB_cube["front_up_left"][i],
RYB_RGB_cube["front_up_right"][i]
])
sideways_front_down = Interpolate(r, [0,1], [
RYB_RGB_cube["front_down_left"][i],
RYB_RGB_cube["front_down_right"][i]
])
sideways_back_up = Interpolate(r, [0,1], [
RYB_RGB_cube["back_up_left"][i],
RYB_RGB_cube["back_up_right"][i]
])
sideways_back_down = Interpolate(r, [0,1], [
RYB_RGB_cube["back_down_left"][i],
RYB_RGB_cube["back_down_right"][i]
])
*/
//17@ *= 255.0
0092: 17@ = float 17@ to_integer
ret 1 17@
:RYB_to_RGB
{
0@ 1@ 2@ - Red, Yellow, Blue (integers 0-255)
More info and python example: https://github.com/michalmonday/RGB_rainbowLoop/blob/master/RYB_RGB_conversion_rainbowLoop.py
}
0093: 0@ = integer 0@ to_float
0093: 1@ = integer 1@ to_float
0093: 2@ = integer 2@ to_float
call @RYB_to_RGB_GetSingleClr 11 RYB 0@ 1@ 2@ interpolation_cube_corners 255.0 255.0 255.0 255.0 0.0 51.0 41.565 127.5 _returnedRed 21@
call @RYB_to_RGB_GetSingleClr 11 RYB 0@ 1@ 2@ interpolation_cube_corners 255.0 127.5 255.0 0.0 168.3 23.97 95.115 0.0 _returnedGreen 22@
call @RYB_to_RGB_GetSingleClr 11 RYB 0@ 1@ 2@ interpolation_cube_corners 0.0 0.0 255.0 0.0 51.0 0.0 153.0 127.5 _returnedBlue 23@
ret 3 21@ 22@ 23@
:Interpolate
{
All floats:
0@ - value
1@ - Lower border of initial range
2@ - Higher border of initial range
3@ - Lower border of desired range
4@ - Higher border of desired range
}
0087: 31@ = 2@ // float
0063: 31@ -= 1@ // (s[1] - s[0])
0063: 0@ -= 1@ // (val - s[0])
0087: 30@ = 4@ // float
0063: 30@ -= 3@ // (s2[1] - s2[0])
006B: 30@ *= 0@ // (s2[1] - s2[0]) * (val - s[0])
0073: 30@ /= 31@ // (s2[1] - s2[0]) * (val - s[0]) / (s[1] - s[0])
005B: 3@ += 30@ // (float)
ret 1 3@
//call @ShiftColor 2 speed_step 3 direction 1 variable_keeping_track 31@
:ShiftColorHue
{
0@ - speed_step - how fast the color change occurs
1@ - direction (1-rgb order, 2-reversed order)
2@ - hue variable which needs to be dedicated for this snippet (it's actually the only variable that is required in external code for this snippet)
}
if 1@ == 1
then
005A: 2@ += 0@ // (int)
if 2@ > 359
then
2@ = 0
end
end
if 1@ == 2
then
0062: 2@ -= 0@ // (int)
if 001B: 0 > 2@
then
2@ = 359
end
end
ret 1 2@
//call @GetRGBfromHSV 3 hue 31@ saturation 1.0 value 1.0 _returnedRGB 1@ 2@ 3@
:GetCLRfromHSV
{
0@ - Hue (0 - 360 int)
1@ - Saturation (0.0 - 1.0 float)
2@ - Value (0.0 - 1.0 float)
}
0085: 25@ = 0@ // hue copy
0093: 0@ = integer 0@ to_float
//C = value * saturation
0087: 31@ = 1@ // C
006B: 31@ *= 2@ // C
//X = C * (1.0 - abs((hue/60.0)%2 - 1.0))
0087: 30@ = 0@ // hue
30@ /= 60.0 // (hue/60.0)
if and // fix for the bugged 0b14 (when float is used, idk if it happens with int too)
30@ >= 2.0
0023: 4.0 > 30@
then
30@ -= 2.0
else
if and
30@ >= 4.0
0023: 6.0 > 30@
then
30@ -= 4.0
else
if and
30@ >= 6.0
0023: 8.0 > 30@
then
30@ -= 6.0
end
end
end
0B14: 30@ = 30@ MOD 2.0 // sampfuncs modulo function is probably not working for numbers that are at least twice as big, or because it's float... idk
//printf "X= %.2f" 1000 30@
30@ -= 1.0
0097: make 30@ absolute_float
29@ = 1.0
0063: 29@ -= 30@ // (1.0 - abs((hue/60.0)%2 - 1.0))
0087: 30@ = 31@ // X = C *
006B: 30@ *= 29@ // X = C * (1.0 - abs((hue/60.0)%2 - 1.0))
//m = value - C
0087: 29@ = 2@
0063: 29@ -= 31@ // m = value - C
// C = 31@
// X = 30@
// m = 29@
//printf "C= %.2f X= %.2f m= %.2f" 1000 31@ 30@ 29@
//sectionList (0 - 0, C - 1, X - 2)
alloc 28@ 100
0085: 27@ = 28@ // (int)
0085: 26@ = 28@ // (int)
//[C, X, 0],
0A8C: write_memory 28@ size 4 value 1 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 2 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 0 virtual_protect 0
28@+=4
//[X, C, 0],
0A8C: write_memory 28@ size 4 value 2 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 1 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 0 virtual_protect 0
28@+=4
//[0, C, X],
0A8C: write_memory 28@ size 4 value 0 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 1 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 2 virtual_protect 0
28@+=4
//[0, X, C],
0A8C: write_memory 28@ size 4 value 0 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 2 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 1 virtual_protect 0
28@+=4
//[X, 0, C],
0A8C: write_memory 28@ size 4 value 2 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 0 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 1 virtual_protect 0
28@+=4
//[C, 0, X],
0A8C: write_memory 28@ size 4 value 1 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 0 virtual_protect 0
28@+=4
0A8C: write_memory 28@ size 4 value 2 virtual_protect 0
//section = sectionList[hue/60]
25@ /= 60 // hue/60
25@ *= 12
005A: 27@ += 25@ // (int)
0A8D: 21@ = read_memory 27@ size 4 virtual_protect 0
27@ += 4
0A8D: 22@ = read_memory 27@ size 4 virtual_protect 0
27@ += 4
0A8D: 23@ = read_memory 27@ size 4 virtual_protect 0
// 21@ 22@ 23@ have now values from 0 to 2 (they're just indicators)
0093: 21@ = integer 21@ to_float
0093: 22@ = integer 22@ to_float
0093: 23@ = integer 23@ to_float
call @AssignHSVSectionValue 3 21@ 31@ 30@ _ret 21@
call @AssignHSVSectionValue 3 22@ 31@ 30@ _ret 22@
call @AssignHSVSectionValue 3 23@ 31@ 30@ _ret 23@
005A: 21@ += 29@ // (int)
005A: 22@ += 29@ // (int)
005A: 23@ += 29@ // (int)
21@ *= 255.0
22@ *= 255.0
23@ *= 255.0
0092: 21@ = float 21@ to_integer
0092: 22@ = float 22@ to_integer
0092: 23@ = float 23@ to_integer
free 26@
ret 3 21@ 22@ 23@
:AssignHSVSectionValue
{
0@ - indicator_1
1@ - val_C
2@ - val_X
}
if 0@ == 0.0
then
ret 1 0.0
else
if 0@ == 1.0
then
ret 1 1@
else
if 0@ == 2.0
then
ret 1 2@
end
end
end
ret 1 0.0