Clip building techniques such that each 'colour' is accessib

  • yossarian
  • Newbie
  • Newbie
  • yossarian
  • Posts: 8

Post 3+ Months Ago

Hi all,

This is a bit messy to describe but I think it's an interesting topic and I hope someone can shed some light for me.

There is a problem I've been toying with and I can't find a 'good' solution.

I'm working on a bunch of flash games. The animation style doesn't lend itself fully to automated tweening. Some things need to be redrawn on occassion. An example is a shoe. When the character walks, we have a few frames of handdrawn keyframes as the toe bends compared to the rest of the foot.

So far, so good.

I want - at a future date - to allow players to choose their character's colours and have them replace existing colours on my graphics.

For example, the girl character has tights with two tones. Just now, they are both shades of green. In the future, I will store (via 'normal' web site back end) profile informatin for each player and will allow them to chose two tones to repllace those on the tights.

Again, so far so good.

In theory.

As far as how to do this... forget the 'colour picking' part - that's easy. And ignore the webby back end bit - that's easy too.

But as far as I can see, when I apply a colour transform to a MovieClip, it changes the whole clip's colour.

This means that I need my artist to break each individual graphic she draws into a few movie clips and give the instances names.

I have been thinking that I would swap the colours in a fashion similar to this pseudocode:

Code: [ Select ]
start game
place character MC on the stage, invisible.
maintain a list of MC's (so far, just player avatar)
while ( MC list != empty) {
  get next movie clip
  examine each property of clip and if "instanceof MovieClip" is true, add it to my list
  examine "_name" of the MC to see if it contains a predefined word (such as "skintone" - so 'ankle_skintone')
  if (match) {
   look up table and apply colour transform
  }
}
  1. start game
  2. place character MC on the stage, invisible.
  3. maintain a list of MC's (so far, just player avatar)
  4. while ( MC list != empty) {
  5.   get next movie clip
  6.   examine each property of clip and if "instanceof MovieClip" is true, add it to my list
  7.   examine "_name" of the MC to see if it contains a predefined word (such as "skintone" - so 'ankle_skintone')
  8.   if (match) {
  9.    look up table and apply colour transform
  10.   }
  11. }
OK. so you may suggest a better route - but in a very small demo, this works fine.

BUT!

Because the animation has redrawn keyframes, when I hit a new keyframe for whatever MC needs one, the NEW drawing hasn't had its colours changed.

It's obvious, and I can see why (it's not on stage in my initial loop).

What isn't obvious is how I can fix this issue.

Now, I COULD make sure that the animator places each component-graphic on the stage in the MC's initial frame - and manages key framing by controlling x/y and _visible - but that's a bit messy.

I could also ask the artist to put a function call or something in every key frame, but IMHO that's a terrible idea! - It's messy, it spreads my code all over the place... it has an artist programming... bad bad bad.

The whole thing is quite messy already actually, because it requires such careful breaking down and building up of MC's.

So...

I have either one question or two!

"The one question version"

Can you advise how, with my current implementation idea, I can access 'future' MC's - so with a 'leg' MC, not just access the current 'tights_dark_green' and 'tights_light_green' areas, but also the future MC's corresponding areas?

"The two question version"

Is there a better way to do this ( '"palette switching" actionscript' Google searches didn't show up much)?


So...

Thanks for anyone who got this far!

Any advice or suggestions would be much appreciated.

Muchos Grazias!

David
  • Anonymous
  • Bot
  • No Avatar
  • Posts: ?
  • Loc: Ozzuland
  • Status: Online

Post 3+ Months Ago

  • dhonsvick
  • Beginner
  • Beginner
  • dhonsvick
  • Posts: 49

Post 3+ Months Ago

Shot in the dark, you look like you may have tried everything but my approach would be on of 2 thing.......what I am not sure of is how the changes will be effected on Keyframes.

I would have my Characters as Movies with clips inside them

Girl -----
-----------Tights
-----------eyes
-----------shirt

Now you would be able to tale to the pieces directly


var colorchange = new Color(girl.tights);
colorchange.setRGB(0x397CBD);

var colorchange = new Color(girl.shirt);
colorchange.setRGB(0xccccff);


or perhaps girl.shirt._alpha = 0; )

Other thing you could do is is have you designers Draw few sets of clothes and attach the MovieClips to the same depth at their counter parts

say the girls tights is at 6 on depth

you have some green tights in library with linkage set to green


First I would get the coordinates of the existing Pair of tights

var tx = girl.tights._x;
var ty = girl.tights._y;

var myTights = girl.attachMovie("green","tights",6);
myTights._x = tx;
myTights._y = ty;

If you are tweening with girl with key frame animation you may have to make a tween that looks like clip that looks like this

Girl-----------------
girlpos1
-shirt
-tights
girlpos2
-shirt
-tights

and then you would have to change color or replace a couple instances of the tights

by accessing the clips by ther paths
girl.girlpos1.tights
or
girl.girlpos2.tights

this would entail multiple items in library for her tights and shirts one for each pos or color......or simply changing the color on every Keyframe r "girlpos"" in the main "girl" instance. it would also require evey keyframe of the girl instance to be its own instanced moveclip so that you could communicate with it.


Again, I dont do much with actual Tweens as I do manly apps. But that is how I would approach the problem.
  • graphixboy
  • Control + Z
  • Mastermind
  • User avatar
  • Posts: 1828
  • Loc: In the Great White North

Post 3+ Months Ago

If your using flash 8 or greater you might want to look at the bitmapData Class. This class allows you to capture the pixel data of a section of your flash movie (movieclip, graphic, jpeg, etc) and store it as an array. You then have the option to change the values of each pixel so you could check if a pixel is green and then have flash redraw it as pink, etc.

This might get a little messy as you have to do it for multiple frames, and I don't think I would try to do it every time you need the clip. Just do it once at the beginning and then always access the new updated clip, etc

Bitmap Data Class via LiveDocs
  • yossarian
  • Newbie
  • Newbie
  • yossarian
  • Posts: 8

Post 3+ Months Ago

Bitmap data might be a good approach to this. I'm not sure.

I found an alternative solution that is quite easy for both the artist and I to use.

I created a class called ColourSwap that has a bunch of transforms and has a function that can look at a var and choose which to apply.

Then I created a bunch of 'EBugColouredObject' classes which extend MovieClip and add this var (e-Bug is the name of our project).

The constructor in these new classes instanciates ColourSwap and calls the convertColour method on it.

Finally, the artist "linkage's" any clip of a solid colour that may need to change and gives it the appropriate ActionScript 2 class.

So for example "LightGreenColouredObject" etc...

This works because when Flash puts these objects on the stage, it also instanciates the clips and since we extended the clips we get to do our thing. Yay us.

Just a FYI:

Origininally, I put the convertColour function in frame1 in the main timeline (not the clip's timeline).

I was then in my class constructor calling _root.convertcolour(this).

This worked for all the swapped in movie clips but NOT for the ones put down on the stage inside Flash.

I'm not sure but it implies that the clips that are placed on stage are constructed BEFORE the code is read from frame 1.

This is a good thing because it means that you can refer to clips by name from the code in frame 1.

This is a bad thing because it means clips can't access _root functions.

I could be wrong but that was the behaviour and why I created my classes.
  • yossarian
  • Newbie
  • Newbie
  • yossarian
  • Posts: 8

Post 3+ Months Ago

Also...

My code isn't really optimised yet. It might be better to merge ColourSwap class into EBugColouredObject etc...

At the bottom is some of the most relevant code for anyone who wants to do something similar.

And finally... you can see the result of the efforts in the early draft art below:

http://paidiasoftware.com/e-Bug/pictchurs/before.swf
http://paidiasoftware.com/e-Bug/pictchurs/after.swf


code for ColourSwap

Code: [ Select ]
import flash.geom.ColorTransform;

class ColourSwap extends MovieClip{
    
    var skinTransform:ColorTransform;
    var darkGreenTransform:ColorTransform;
    var lightGreenTransform:ColorTransform;
    var pinkTransform:ColorTransform;
    var yellowTransform:ColorTransform;
    var orangeTransform:ColorTransform; 
    var blueTransform:ColorTransform;
    var target_mc:MovieClip;
    var param_interval:Number;
        
    function ColourSwap() {
        skinTransform = new ColorTransform();
        darkGreenTransform = new ColorTransform();
        lightGreenTransform = new ColorTransform();
        pinkTransform = new ColorTransform();
        yellowTransform = new ColorTransform();
        orangeTransform = new ColorTransform();
        blueTransform = new ColorTransform();
        
        // TODO - these are hardcoded - should be drawn from load vars
        skinTransform.rgb = 0x964B2A;
        darkGreenTransform.rgb = 0x2A7996;
        lightGreenTransform.rgb = 0x6CC1E0;
        pinkTransform.rgb = 0xFF0505;
        yellowTransform.rgb = 0xC1FF05;
        orangeTransform.rgb = 0xFFFF80;    
        blueTransform.rgb = 0x400040;    
    }    
    
    function convertColours(topMC:MovieClip):Void {
        var clips:Array = new Array();
        clips.push(topMC);
        while (clips.length > 0) {
            var currentMC:MovieClip = MovieClip(clips.pop());
            
            // add child MC's to array - will only find those at this level, none inside arrays or objects
            for (var nextItem in currentMC) {
                if ((currentMC[nextItem] instanceof MovieClip)) {
                    clips.push(currentMC[nextItem]);
                }
            }
            
            // look for keywords and transform as appropriate
            if ( currentMC.eBugColour == "skin") {
                currentMC.transform.colorTransform = skinTransform;
            } else if ( currentMC.eBugColour == "orange") {
                currentMC.transform.colorTransform = orangeTransform;
            } else if ( currentMC.eBugColour == "dark_green") {
                currentMC.transform.colorTransform = darkGreenTransform;
            } else if ( currentMC.eBugColour == "light_green") {
                currentMC.transform.colorTransform = lightGreenTransform;
            } else if ( currentMC.eBugColour == "pink") {
                currentMC.transform.colorTransform = pinkTransform;
            } else if ( currentMC.eBugColour == "yellow") {
                currentMC.transform.colorTransform = yellowTransform;
            } else if ( currentMC.eBugColour == "blue") {
                currentMC.transform.colorTransform = blueTransform;
            }
            //currentMC.stop();
        } // end while
    }
}
  1. import flash.geom.ColorTransform;
  2. class ColourSwap extends MovieClip{
  3.     
  4.     var skinTransform:ColorTransform;
  5.     var darkGreenTransform:ColorTransform;
  6.     var lightGreenTransform:ColorTransform;
  7.     var pinkTransform:ColorTransform;
  8.     var yellowTransform:ColorTransform;
  9.     var orangeTransform:ColorTransform; 
  10.     var blueTransform:ColorTransform;
  11.     var target_mc:MovieClip;
  12.     var param_interval:Number;
  13.         
  14.     function ColourSwap() {
  15.         skinTransform = new ColorTransform();
  16.         darkGreenTransform = new ColorTransform();
  17.         lightGreenTransform = new ColorTransform();
  18.         pinkTransform = new ColorTransform();
  19.         yellowTransform = new ColorTransform();
  20.         orangeTransform = new ColorTransform();
  21.         blueTransform = new ColorTransform();
  22.         
  23.         // TODO - these are hardcoded - should be drawn from load vars
  24.         skinTransform.rgb = 0x964B2A;
  25.         darkGreenTransform.rgb = 0x2A7996;
  26.         lightGreenTransform.rgb = 0x6CC1E0;
  27.         pinkTransform.rgb = 0xFF0505;
  28.         yellowTransform.rgb = 0xC1FF05;
  29.         orangeTransform.rgb = 0xFFFF80;    
  30.         blueTransform.rgb = 0x400040;    
  31.     }    
  32.     
  33.     function convertColours(topMC:MovieClip):Void {
  34.         var clips:Array = new Array();
  35.         clips.push(topMC);
  36.         while (clips.length > 0) {
  37.             var currentMC:MovieClip = MovieClip(clips.pop());
  38.             
  39.             // add child MC's to array - will only find those at this level, none inside arrays or objects
  40.             for (var nextItem in currentMC) {
  41.                 if ((currentMC[nextItem] instanceof MovieClip)) {
  42.                     clips.push(currentMC[nextItem]);
  43.                 }
  44.             }
  45.             
  46.             // look for keywords and transform as appropriate
  47.             if ( currentMC.eBugColour == "skin") {
  48.                 currentMC.transform.colorTransform = skinTransform;
  49.             } else if ( currentMC.eBugColour == "orange") {
  50.                 currentMC.transform.colorTransform = orangeTransform;
  51.             } else if ( currentMC.eBugColour == "dark_green") {
  52.                 currentMC.transform.colorTransform = darkGreenTransform;
  53.             } else if ( currentMC.eBugColour == "light_green") {
  54.                 currentMC.transform.colorTransform = lightGreenTransform;
  55.             } else if ( currentMC.eBugColour == "pink") {
  56.                 currentMC.transform.colorTransform = pinkTransform;
  57.             } else if ( currentMC.eBugColour == "yellow") {
  58.                 currentMC.transform.colorTransform = yellowTransform;
  59.             } else if ( currentMC.eBugColour == "blue") {
  60.                 currentMC.transform.colorTransform = blueTransform;
  61.             }
  62.             //currentMC.stop();
  63.         } // end while
  64.     }
  65. }



And below here is code for EBugColouredItem

Code: [ Select ]
class EBugColouredItem extends MovieClip {
    var eBugColour:String;
    
    function init() {
        var ct:ColourSwap = new ColourSwap();
        ct.convertColours(this);    
    }
}
  1. class EBugColouredItem extends MovieClip {
  2.     var eBugColour:String;
  3.     
  4.     function init() {
  5.         var ct:ColourSwap = new ColourSwap();
  6.         ct.convertColours(this);    
  7.     }
  8. }



And finally, you do one of these for each colour (again - not optimised my process yet)

DarkGreenColouredObject

Code: [ Select ]
class DarkGreenColouredObject extends EBugColouredItem{    
    function DarkGreenColouredObject() {
        this.eBugColour = "dark_green";
        super.init();
    }    
}
  1. class DarkGreenColouredObject extends EBugColouredItem{    
  2.     function DarkGreenColouredObject() {
  3.         this.eBugColour = "dark_green";
  4.         super.init();
  5.     }    
  6. }

Post Information

  • Total Posts in this topic: 5 posts
  • Users browsing this forum: No registered users and 12 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.