Author Topic: modulate RGB for layers  (Read 10103 times)

Tanja

  • Clever
  • Fanatic
  • ***
  • Posts: 606
    • View Profile
modulate RGB for layers
« on: 2008-01-18, 06:47:34 AM »
now this may be a special request/problem/suggestion of me because of the structure of my game.
as you may have noted in some screenshots, i've got several layers to fake deep space. they have the same graphics (flying rocks), but every layer which is farther backwards scrolls slower and its hue is slightly more bluish (as in the real world).

now the idea came to my mind, instead of colorizing the same graphic sheet, importing it and build new frame- and tilesets of it, it would go incredible faster and simplier, when i could modulate RGB for the layer itself, instead of single tiles.

at the moment, i could modulate RGB for single tiles, but i would be not so a great advantage.
because every tile of the rock tileset consists of two frames: the normal rock frame and the freezed rock frame. this method suggested me durnurd, thank you it was great idea!
colorize every single tile and then animating them all again, this maybe three times is much work.

i hope you have mercy with me and could build in this feature... please please please!

(have i mentioned the presention of the game in front of the half student body is only a week away? ::panic:: )

bluemonkmn

  • SGDK Author
  • Administrator
  • Fanatic
  • *****
  • Posts: 2761
    • ICQ Messenger - 2678251
    • MSN Messenger - BlueMonkMN@gmail.com
    • View Profile
    • http://sgdk2.sf.net/
    • Email
Re: modulate RGB for layers
« Reply #1 on: 2008-01-18, 08:53:41 AM »
now the idea came to my mind, instead of colorizing the same graphic sheet, importing it and build new frame- and tilesets of it, it would go incredible faster and simplier, when i could modulate RGB for the layer itself, instead of single tiles.

You can, if you don't mind editing the code a little.  Open LayerBase.cs and search for "GetTileFrame(x,y)"
This is where the code is that draws the tiles for the layer.  Above "for" line, you could add this block of code to check for which layer is being drawn and calculate a modulation value for it.  This example is for the sample project because it refers to Level_1_Map.Background_Lyr, which is the background layer in the sample project:
Code: [Select]
   int overrideModulation = -1;
   if (this is Level_1_Map.Background_Lyr)
   {
      overrideModulation = new ColorValue(128,128,255, 127).ToArgb();
   }

Inside the loop you will see a line that begins with "spr.Draw".  Change the last parameter from "f.Color" to "overrideModulation==-1?f.Color:overrideModulation" to use the new modulation value for background layers.

The final code will look like this:

Code: [Select]
         int overrideModulation = -1;
         if (this is Level_1_Map.Background_Lyr)
         {
            overrideModulation = new ColorValue(128,128,255, 127).ToArgb();
         }

         for (int x = nStartCol; x <= EndCol; x++)
         {
            int[] SubFrames = GetTileFrame(x,y);
            for (int nFrame = 0; nFrame < SubFrames.Length; nFrame++)
            {
               Frame f = m_Frameset[SubFrames[nFrame]];
               spr.Transform = Matrix.Multiply(f.Transform, Matrix.Translation(
                  x * nTileWidth + CurrentPosition.X + ViewRect.X,
                  y * nTileHeight + CurrentPosition.Y + ViewRect.Y, 0));
               spr.Draw(f.GraphicSheetTexture.Texture, f.SourceRect, Vector3.Empty, Vector3.Empty, overrideModulation==-1?f.Color:overrideModulation);
            }
         }
      }

Of course you have to use your own layer names, but this can be done relatively easily without any changes to SGDK2.

Of course, another possibility is to make the transparent part of all your tiles be 25% opaque (alpha=64) with maybe some blue tint, instead of entirely transparent.  (This would be done in the graphics editor, not with color modulation -- flood fill the transparent area with this bluish color).  Then they would affect all the layers behind them without using color modulation.

(have i mentioned the presention of the game in front of the half student body is only a week away? ::panic:: )
You better focus on real substantial content, then, and not details.  Do you have real playable content, or just test levels so far?

Tanja

  • Clever
  • Fanatic
  • ***
  • Posts: 606
    • View Profile
Re: modulate RGB for layers
« Reply #2 on: 2008-01-18, 11:36:10 AM »
*sings*
today, a blue monk saved my life....  :clown:  :canadian:

how cool and it WORKS!!

you may say that that tinting a few layers bluish is a unimportant detail... but 1. having those cool background layers creates all the feeling and the special look of the game. (and now i can create them with no effort! hooray!)
2. and, you haven't heard my prof saying at the beginning of the semester: "i don't care if something works! i wanna really good looking graphics!"

 :laugh:
em... playable content, well... you can drop the bags, well.....
na, it's all about the concept... i don't need more than a test level to present the game. despite this i haven't managed to get so far as i wanted to. but that's the same in every semester and for every student.
but i want to continue working on it, and building in what i dreamed of. not to forget that we present our work (the zeppelin project) in three month at the zeppelin museum in friedrichshafen! and then it shall be playable!

and for your tipp to colorize the transparent areas of the foreground layers:
man, it is an awesome idea! i wonder why i didn't think of it?? but, as so often with good ideas, i can't use it.
because the effect for the layers were good at all, but the backmost layer, the sky, would end in one overall blue tone. and that i don't want. i have already made a gradient of several blues, becoming darker and darker as you move upwards. it ends in black space with stars in it. it is way to beautiful to not use it.

edit:
cheered to soon.
how can i apply different hues to different layers?
« Last Edit: 2008-01-18, 12:17:38 PM by Morgengrauen »

bluemonkmn

  • SGDK Author
  • Administrator
  • Fanatic
  • *****
  • Posts: 2761
    • ICQ Messenger - 2678251
    • MSN Messenger - BlueMonkMN@gmail.com
    • View Profile
    • http://sgdk2.sf.net/
    • Email
Re: modulate RGB for layers
« Reply #3 on: 2008-01-18, 02:38:35 PM »
Just use different overrideModulation values depending on which layer is this layer.  What does your code look like?

Tanja

  • Clever
  • Fanatic
  • ***
  • Posts: 606
    • View Profile
Re: modulate RGB for layers
« Reply #4 on: 2008-01-18, 03:40:33 PM »
it works now! thanks!
strange, i thought i had tried that out...

do you consider to provide this at the gui? it is really a great way to make an ayers rock scene out of normal tiles, or a level completely in a silhouette look.
i wonder how to script some rules which change the hue at events. i can imagine to fake an entire day, from the rising sun till evening and night, all through colorizing the tiles with a time-based script.

bluemonkmn

  • SGDK Author
  • Administrator
  • Fanatic
  • *****
  • Posts: 2761
    • ICQ Messenger - 2678251
    • MSN Messenger - BlueMonkMN@gmail.com
    • View Profile
    • http://sgdk2.sf.net/
    • Email
Re: modulate RGB for layers
« Reply #5 on: 2008-01-19, 09:48:58 AM »
Yeah you could make the colors be affected by a counter.  Counters can be accessed from anywhere using code like:
Counter.FrameCounter.CurrentValue

Tanja

  • Clever
  • Fanatic
  • ***
  • Posts: 606
    • View Profile
Re: modulate RGB for layers
« Reply #6 on: 2008-01-19, 11:12:39 AM »
cool thing.

if i wanted (what i actually don't want, but maybe later) to provide the player a gui at the start screen, where he can change RGB of the player sprite by himself, how would i script this?
i guess there are few lines in Player.cs or SpriteBase.cs where i could do the same as with layers.

but for the input. there would have to be three textboxes into which users could insert the values. can this be made with the current version?
this feature would be useless without a preview pic. but mastering the other two points should allow this easily.

Tanja

  • Clever
  • Fanatic
  • ***
  • Posts: 606
    • View Profile
Re: modulate RGB for layers
« Reply #7 on: 2008-01-19, 01:15:46 PM »
and does sgdk2 (c#) provide a method to modulate Lab or HSB instead of RGB?
toAhsb()  ?
toAlab() ?

durnurd

  • Lead Lemming
  • Expert
  • Fanatic
  • *****
  • Posts: 1234
  • Games completed so far: 0
    • MSN Messenger - durnurd@hotmail.com
    • View Profile
    • Find My Ed
Re: modulate RGB for layers
« Reply #8 on: 2008-01-19, 05:15:10 PM »
There is no built-in conversion in C# to convert HSV to RBG that I know of or found in a cursory search.  However, you could write your own converter, if you know how those things work... I don't.  The modulation requires a Color object, which is defined specifically as (A)RGB. So you'd need something like:

public Color toARGB (byte A, byte H, byte S, byte V)
{
  //Convert to the H, S, and V to RGB however that's done
  return color;
}


Then just call that when you need to get a new color to modulate to.  However, unless you are modulating colors dynamically during the game, it would be better to figure out the values beforehand so it doesn't have to calculate the new values every frame during gameplay.
Edward Dassmesser

bluemonkmn

  • SGDK Author
  • Administrator
  • Fanatic
  • *****
  • Posts: 2761
    • ICQ Messenger - 2678251
    • MSN Messenger - BlueMonkMN@gmail.com
    • View Profile
    • http://sgdk2.sf.net/
    • Email
Re: modulate RGB for layers
« Reply #9 on: 2008-01-19, 07:49:38 PM »
There is code for converting HSV to RGB in the SGDK2 graphics editor source code (not in the project source code) which you could probably copy into your project source code:
Code: [Select]
      public static Color HSVtoRGB(double dblHue, double dblSat, double dblVal)
      {
         Color SelColor = HStoRGB(dblHue, dblSat);
         SelColor = Color.FromArgb(
            (int)Math.Round(SelColor.R * dblVal),
            (int)Math.Round(SelColor.G * dblVal),
            (int)Math.Round(SelColor.B * dblVal));
         return SelColor;
      }

      /// <summary>
      /// Get an RGB color with 100% brightness from a hue and saturation
      /// </summary>
      /// <param name="dblHue">Number from 0 to 2*pi</param>
      /// <param name="dblSat">Number from 0 to 1 where 1 is maximum saturation and 0 is gray</param>
      private static Color HStoRGB(double dblHue, double dblSat)
      {
         double RangedAngle = dblHue * 3.0 / Math.PI;
         int red, green, blue;

         if (RangedAngle < 1.0)
         {
            red = 255;
            green = (int)(Math.Round(255.0 * (1.0 - dblSat) + RangedAngle * 255.0 * dblSat));
            blue = (int)(Math.Round(255.0 * (1.0 - dblSat)));
         }
         else if (RangedAngle < 2.0)
         {
            RangedAngle = 2.0 - RangedAngle;
            red = (int)(Math.Round(255.0 * (1.0 - dblSat) + RangedAngle * 255.0 * dblSat));
            green = 255;
            blue = (int)(Math.Round(255.0 * (1.0 - dblSat)));
         }
         else if (RangedAngle < 3.0)
         {
            RangedAngle -= 2.0;
            red = (int)(Math.Round(255.0 * (1.0 - dblSat)));
            green = 255;
            blue = (int)(Math.Round(255.0 * (1.0 - dblSat) + RangedAngle * 255.0 * dblSat));
         }
         else if (RangedAngle < 4.0)
         {
            RangedAngle = 4.0 - RangedAngle;
            red = (int)(Math.Round(255.0 * (1.0 - dblSat)));
            green = (int)(Math.Round(255.0 * (1.0 - dblSat) + RangedAngle * 255.0 * dblSat));
            blue = 255;
         }
         else if (RangedAngle < 5.0)
         {
            RangedAngle -= 4.0;
            red = (int)(Math.Round(255.0 * (1.0 - dblSat) + RangedAngle * 255.0 * dblSat));
            green = (int)(Math.Round(255.0 * (1.0 - dblSat)));
            blue = 255;
         }
         else
         {
            RangedAngle = 6.0 - RangedAngle;
            red = 255;
            green = (int)(Math.Round(255.0 * (1.0 - dblSat)));
            blue = (int)(Math.Round(255.0 * (1.0 - dblSat) + RangedAngle * 255.0 * dblSat));
         }
         return Color.FromArgb(red, green, blue);
      }

Tanja

  • Clever
  • Fanatic
  • ***
  • Posts: 606
    • View Profile
Re: modulate RGB for layers
« Reply #10 on: 2008-01-20, 02:57:45 AM »
However, unless you are modulating colors dynamically during the game, it would be better to figure out the values beforehand so it doesn't have to calculate the new values every frame during gameplay.

that i haven't considered. well, we will see how much performance this will take.
and if i would use bluemonks code, the effort to achieve a simple modulation would double itself, right?

just for making it sure: when i use this modulateRGB to colorize my layers, will the game calculate it for every frame?


what about my other questions, overlooked it or just don't feel like it (i could understand this  ;) )
if i wanted (what i actually don't want, but maybe later) to provide the player a gui at the start screen, where he can change RGB of the player sprite by himself, how would i script this?
i guess there are few lines in Player.cs or SpriteBase.cs where i could do the same as with layers.

but for the input. there would have to be three textboxes into which users could insert the values. can this be made with the current version?
this feature would be useless without a preview pic. but mastering the other two points should allow this easily.

bluemonkmn

  • SGDK Author
  • Administrator
  • Fanatic
  • *****
  • Posts: 2761
    • ICQ Messenger - 2678251
    • MSN Messenger - BlueMonkMN@gmail.com
    • View Profile
    • http://sgdk2.sf.net/
    • Email
Re: modulate RGB for layers
« Reply #11 on: 2008-01-20, 08:20:08 AM »
that i haven't considered. well, we will see how much performance this will take.
and if i would use bluemonks code, the effort to achieve a simple modulation would double itself, right?
just for making it sure: when i use this modulateRGB to colorize my layers, will the game calculate it for every frame?

You shouldn't have to worry about performance in calculating a value to put into overrideModulation.  That code is outside the loop that draws tiles, and the loop that draws tiles is doing most of the work.  So the code that you are adding would only happen once per frame and not once per tile.  I don't think you'll notice a performance difference.  It does execute on every frame, though; it's just a very small amount of work (because there are no loops).

if i wanted (what i actually don't want, but maybe later) to provide the player a gui at the start screen, where he can change RGB of the player sprite by himself, how would i script this?
i guess there are few lines in Player.cs or SpriteBase.cs where i could do the same as with layers.

but for the input. there would have to be three textboxes into which users could insert the values. can this be made with the current version?
this feature would be useless without a preview pic. but mastering the other two points should allow this easily.

This is too complicated to explain, but you could do something like the window that allows the player to customize the controls (or add it to the same window).  The code for that is in Controls.cs, and is triggered from GameForm.cs in the "mnuToolsOptions_Click" function.  SGDK2 is not designed to help you create GUIs, but games.  If you want to design a GUI, you might want to download Visual C# Express, and then copy the code into the SGDK2 project, but the current release of SGDK2 is designed with Visual Studio 2003, so you might have to change some things to get the project to compile.

Jam0864

  • Contributor
  • Fanatic
  • **
  • Posts: 744
    • MSN Messenger - marmalade0864@hotmail.com
    • View Profile
    • Jam0864's Content Dump
    • Email
Re: modulate RGB for layers
« Reply #12 on: 2008-01-20, 08:30:04 AM »
i reckon you could do that without script. (I try and do everything without script because I don't understand script  :( ) just make an area for green, red and blue, each with an up arrow and a down arrow, make a sprite controlled by the mouse, when its touching up arrow on blue for example, and pressing mouseclick 1 in, then add 1 to modulateblue. so on so forth for every colour, with up and down.

you could make a preview window by placing the sprite that it's gonna effect on that map, and putting solid tiles all around him so he can't move (or find a way to disable the controls) so as you take/add r, g or b the results are obvious.

bluemonkmn

  • SGDK Author
  • Administrator
  • Fanatic
  • *****
  • Posts: 2761
    • ICQ Messenger - 2678251
    • MSN Messenger - BlueMonkMN@gmail.com
    • View Profile
    • http://sgdk2.sf.net/
    • Email
Re: modulate RGB for layers
« Reply #13 on: 2008-01-20, 08:50:58 AM »
The controls could be disabled by simply skipping the MapPlayerToInputs rule.  Either disable it in the player sprite when that map is current (by setting a counter value and checking it in the sprite rules) or, if you are using plans to MapPlayerToInputs (which the sample game does), just don't add such a plan to this map.  But yes, this could also be done using existing mechanisms if you don't need a textbox that the player can type in.

Tanja

  • Clever
  • Fanatic
  • ***
  • Posts: 606
    • View Profile
Re: modulate RGB for layers
« Reply #14 on: 2008-01-20, 08:59:36 AM »
what a cool idea jam! once i am a little bit into something, i want to do all with it, and overlook the simplest methods!
that for sure i'll try out  ;)