ID:265646
 
All of the daynight cycles Ive seen around byond work basically the same, create a black dotted overlay and overlay it on everything in the world. That method works, but it can sometimes make the icons look jagged and the transiton between the two looks pretty choppy.

I came up with this;

var
cycle = "day"
maxTimer = 10
minTimer = -10
timer = minTimer
timerRate = 1
timeDelay = 1

world



New()

..()
DayNight()

proc

DayNight()

if(cycle == "day")
timer += timerRate
else
timer -= timerRate

if(timer >= maxTimer)
timer = maxTimer
cycle = "night"
else if(timer <= minTimer)
timer = minTimer
cycle = "day"

for(var/atom/A in world)
if(istype(A,/mob) || istype(A,/obj) || istype(A,/turf/))
if(cycle == "day")
A.icon -= rgb(timer,timer,timer)
else
A.icon += rgb(timer,timer,timer)
spawn(timeDelay) DayNight()


It alters the rgb data of everything in the world, darkening or lightening it depending on the current cycle. It works fine except that every time the cycle repeats, the icon gets it's rgb values more and more "blandish", eventually making it blend into a compltely white or black icon. Which... sucks. Why does that happen, in my mind if you subtract 20 from an icon's red value, and then later on add 20 back, it should look like it looked before the red subtraction, right?

Also, am I right in assuming altering the rgb data of every tile in the world will bring with it a wave of lag? ATM it works fine with a small map but Im pretty sure when you get into the full blown rpg maps, itll have a slow effect.

- Conj'
Yeah, this method will produce SERIOUS lag in any mid to large size map. Though it's a good idea, and often looks better than dithering the map, it's just not efficient. =/ Trust me, I've gone through the same path as you. I've just decided not to mess with day/night for now. Maybe we'll get some feature in the future that will help with it, for now, I don't mess with it.
For now, a much easier thing to do is pre-generate night-time icons, then just set the icons on the map to the darker night-time version. Something better probably could be done dynamically when alpha layers are available for developers to use in 4.0.

~~> Unknown Person
The Conjuror wrote:
It works fine except that every time the cycle repeats, the icon gets it's rgb values more and more "blandish", eventually making it blend into a compltely white or black icon. Which... sucks. Why does that happen, in my mind if you subtract 20 from an icon's red value, and then later on add 20 back, it should look like it looked before the red subtraction, right?

The reason for this is that the rgb values clip at 0 and 255. Let's walk through what is going on in your cycle. Say atom Blue starts with a plain blue icon RGB of 0,0,255.

The cycle begins, timer is -10 and cycle = "day". When Daynight is called, timer becomes -9. Daynight ties to subtract RGB(-9, -9, -9) from Blue. RGB(-9,-9,-9) clips at 0, so you are subtracting plain black (0,0,0) and the icon does not change. Blue is still 0,0,255

The loop does this through several cycles, until it finally gets to rgb(1,1,1). Timer is now 1, Blue is (0,0,254).

Next cycle, timer = 2, Blue is (0,0,252). It's now subtracting (2,2,2) from everything.
Timer = 3, Blue = (0,0,249)
Timer = 4, Blue = (0,0,245)
Timer = 5, Blue = (0,0,240)
Timer = 6, Blue = (0,0,234)
Timer = 7, Blue = (0,0,227)
Timer = 8, Blue = (0,0,219)
Timer = 9, Blue = (0,0,210)
Timer = 10, cycle now = "night" and it starts adding the RGB value. Blue becomes (10,10,220). Some red and green have crept into the icon.
Timer = 9, Blue = (19,19,229)
Timer = 8, Blue = (27,27,237)
Timer = 7, Blue = (34,34,244)
Timer = 6, Blue = (40,40,250)
Timer = 5, Blue = (45,45,255). The blue componant is now maxed out and can increase no further. The loop will keep adding red and green, washing out the blue even more.
Timer = 4, Blue = (49,49,255)
Timer = 3, Blue = (52,52,255)
Timer = 2, Blue = (54,54,255)
Timer = 1, Blue = (55,55,255).
Again, any timer values between 0 and -10 will produce rgb(0,0,0) and result in no change.

Each cycle, the red and green will gain another 10, because the 10 is always added as it toggles to night and is not subtracted again. After 20 days or so, everything will be white, rgb(255,255,255).


A better way to do it would be icon multiplication. It scales all the colors. Make your mintimer the lowest percentage of color that you want(0 for complete darkness, 0.5 for 50% darkness.) maxtimer should be 1 for full color (100%). Your rate should be a decimal value like 0.1.

You also need to store the initial icon instead of working from the modified icon. You can use the initial() proc, or simply make another variable for the initial icon. Then when you try to retrieve the initial icon, just check to be sure there is one.
For example, this would be inside you for(var/atom/A...) loop:
if(!A.base_icon) A.base_icon = A.icon // initialize base_icon
A.icon = A.base_icon * timer




Also, am I right in assuming altering the rgb data of every tile in the world will bring with it a wave of lag? ATM it works fine with a small map but Im pretty sure when you get into the full blown rpg maps, itll have a slow effect.

Yes, with large worlds it will be extremely slow. Area based day/night systems are pretty much lagless, and when alpha transparency is part of BYOND it will be able to shade icons properly instead of using annoying dither patterns.
In response to Shadowdarke
Hey Shadow good to see your still around :),

That makes sense, I was looking for a way to figure out an atom's original icon, that base_icon command skipped right by me. Ill try changing the code around following your tips and post results, but later on.

Thanks for all the input everyone.
- Conj'
In response to The Conjuror
Or you could make use of the initial proc.

var/oicon=initial(src.icon)


initial() obviously returns the initial value of any given variable.

-Exophus
In response to Exophus
Exophus wrote:
Or you could make use of the initial proc.

var/oicon=initial(src.icon)

initial() obviously returns the initial value of any given variable.

-Exophus

I mentioned that as well, but initial() only returns the static variable stored in code. If you do any sort of manipulations before the daycycle (like using alternate icons in a dmp or altering the icons in New()), they will be lost of you use initial().