Costume - theRAPTLab/gsgo GitHub Wiki

See !97 !108 !177


Overview

Color

There are three color systems: RGB, HSV, and a ColorScale.

  • Color is stored in the Costume Feature as HSV.
  • RGB is converted to HSV during the update loop.
  • ColorScale color is also set during the update loop (the color is applied directly rather than converting through RGB).

During the update loop the Feature color HSV properties are converted to a HEX/RGB color value and the agent.prop.color property is set to the color.

(This is why in general you should not set agent.prop.color directly: the agent.prop.color property is overridden with every Costume feature update loop.)

Costumes

Any agent can be assigned a costume. Costumes can be static PNGs, spritesheets (via TexturePacker), or an animation sequence.


color property

Colorizes a character by overlaying the color on top of the base sprite color. When using the Wizard, the color can be selected via a popup color picker.

Syntax

featProp character.Costume.setToColor <decimal>

where <decimal> is a decimal number corresponding to the hex RGB color. e.g. #FF0000 is 16711680

There are many ways to set character colors (see all the featCall methods and featProps for Costume), each of which may override others. In general, we recommend using the featProp character.Costume.color setToColor approach.

Priority Order During each Costume update loop, colors are applied in this order:

  • ColorScaleIndex -- if a ColorScaleIndex value is set, it will override any color featProp (used for Moths to set a graduated scale of white to black moths).
  • color featProp -- If the color featProp is set, it will override other color featCall methods and featProps
  • HSV values from featProp or featCalls -- Otherwise, the character will use the HSV values previously set by any featCall or featProps.

Note that you should NOT use agent.prop.color to set color as agent.prop.color is overwritten by the Costume Feature with each update loop.

setCostume method

Syntax

featCall agent.Costume.setCostume '<costumeName>' <pose>

where <costumeName> is either:

  • a PNG file reference (e.g. bee.png => featCall agent.Costume.setCostume 'bee.png')
  • a TexturePacker spritesheet (e.g. bee.json => featCall agent.Costume.setCostume 'bee.json'`)

and <pose> is the frame number in the spritesheet. is optional.

flipX and flipY property

Flip the sprite texture either along the x-axis or y-axis during Physics updates.

Syntax

featProp Costume flipX setTo <boolean> where <boolean> is true or false.

Flipping is implemented by PIXIjs via a negative scale setting. Setting this property to true will tell the Physics feature to use a negative scale when sizing the sprite.

Currently most Costume updates are handled by other Features, so setting this property will have no immediate effect. We need to rewrite Costume do its own phase loop processing in order to do that.

To Use

  1. Make sure Physics feature is enabled.
  2. Set the property

colorHue, colorSaturation, colorValue property

Costumes now use HSV as the core color model. You can now set these properties directly. The agent color will be set automatically during the SIM/VIS_UPDATE phase based on the three values.

IMPORTANT! You MUST either:

  1. Call setColorize or setColorizeHSV to initialize the colors first or
  2. Set all three parameters before changing just one. These values default to undefined so if you set, say colorValue without having set colorHue and colorSaturation, then the resulting color would be unpredictable because hue and saturation have not been set.

All RGB and randomize colorization routines have been updated to set the HSV properties.

The color feature properties make it easier to programmatically change color values without resorting to stack operations.

Syntax

featProp Costume colorHue setTo <value> featProp Costume colorSaturation setTo <value> featProp Costume colorValue setTo <value>

where <value> is a number between 0 and 1.

Since the properties are GVarNumbers, you can use any GVarNumber method.

Examples

e.g. to darken, you might call featProp Costume colorValue sub 0.1

e.g. to set a random darken you might call (this will darken the color by anywhere between 0 and 0.2) featProp Costume colorValue subRnd 0.2


setColorize

Syntax

featCall Costume setColorize <red> <green> <blue>

where <red>, <green>, and <blue> are values between 0 and 1.

This will apply both a ColorOverlay at 50% alpha, and an AdjustmentFilter to the sprite.

resetColorize

Syntax

featCall Costume resetColorize

This will remove the color overlay and adjustment filters and restore the sprite to its original colors.

randomizeColor

Syntax

featCall Costume randomizeColor <red> <green> <blue>

This will change the existing colorized color of the sprite by a random +/- amount. The color values allow you to control how much the color should deviate from the original color.

For example, if you have a green sprite, and you want to randomize ONLY the green levels, you could call:

featCall Costume randomizeColor 0 1 0

With this call green might be changed by as much as 1.0. But red and blue would never be changed.

On the other hand, if you have a green sprite, and want only small changes in red and blue, you could call:

featCall Costume randomizeColor 0.2 0 0.2

With this call green will never be changed, but red and blue might vary by as much as 0.2 in either direction. e.g. if the sprite's red color was originally 0.5, the 0.2 randomization value might set it to as low as 0.3 and as high as 0.7.

You'll have to play with the values to determine what works best for a given sprite image.

setColorizeHSV method

Colorizes the agent using Hue/Saturation/Value parameters.

Syntax

featCall Costume setColorizeHSV <hue> <saturation> <value>

where <hue>, <saturation>, and <value> are numbers between 0 and 1.

randomizeColorHSV method

Changes the existing colorization of the agent with a random value using Hue/Saturation/Value parameters.

Syntax

featCall Costume randomizeColorHSV <hue> <saturation> <value>

where <hue>, <saturation>, and <value> are numbers between 0 and 1 representing the +/- range for random variation. e.g. if <hue> was 0.2, then the randomized color could have a hue of the current hue +/- 0.2.

Notes:

  • Generally you'll want to set the color first, then use randomizeColorHSV to shift it.
  • To allow the full range of values, use a h/s/v of 1. To not allow any variation, use 0.

colorHSVWithinRange method

Tests whether the two passed colors are within range of each other. For example, this is used to see if a moth color matches the tree color it is resting on.

Syntax

featCall Costume colorHSVWithinRange <color1> <color2> <hue> <saturation> <value>

where

  • <color1> and <color2> are hex colors to be compared
  • <hue>, <saturation>, and <value> are numbers between 0 and 1 representing the +/- range for comparison. e.g. if <hue> was 0.2, and <color1> had a hue of 0.5 and <color2> had a hue of 0.7 then, colorHSVWithinRange would return true. The test used is <= for each dimension, e.g. Math.abs(<color1h> - <color2h>) <= <hue>.

This is most likely used in an ifExpr expression, e.g.:

  ifExpr {{ Moth.callFeatMethod('Costume', 'colorHSVWithinRange', Moth.prop.color.value, TreeTrunk.prop.color.value, 0.2, 1, 0.2)}} [[
    // make the moth invisilbe if the Moth color and TreeTrunk color are similar
    featProp Vision visionable setTo false
  ]]

Notes:

  • To ignore a dimension, use 1. For example, calling colorHSVWithinRange with 1 1 1 would match all colors, while calling t with 1 1 0.2 would match any two colors that were within a <value> of 0.2.
  • Using 0 for any h/s/v value would result in no colors ever matching.

Color Scale

Agent colors can be assigned to a predefined series of colors in a graded scale. To use this feature, you need to:

  1. Define the colorscale: intHSVColorScale
  2. Set a Costume property: colorScaleIndex

See !113 Mini-Rounds for a full example.

initHSVColorScale method

This defines the color scale, setting the basic starting color values (HSV), the color dimension to vary across the scale, and the number of steps in the scale.

Currently you can vary only one scale type. e.g. you can vary value but you can't also vary saturation at the same time.

Syntax

featCall Costume initHSVColorScale <baseHue> <baseSaturation> <baseValue> <type> <count>

where

  • <baseHue> <baseSaturation> <baseValue> defines the starting color of the scale.
  • <type> defines the color dimension to vary: hue, saturation, or value
  • <count> is the number of steps in the scale.

In order to make it possible for students to create their own color schemes, we split the sinlge featCall Costume initHSVColorScale 0 0 1 'value' 11 into individual featProp settings.

Each dimension can now be set separately.

If a value is omitted, the default values are used.

Calls with default values

featProp Costume colorScaleHue setTo 0
featProp Costume colorScaleSaturation setTo 0
featProp Costume colorScaleValue setTo 1
featProp Costume colorScaleType setTo 'value'
featProp Costume colorScaleSteps setTo 5
featCall Costume initHSVColorScale

is the equivalent of

featCall Costume initHSVColorScale 0 0 1 'value' 11

Example

featCall Costume initHSVColorScale 0 0 1 'value' 11

This will create a scale of 11 gray values. 0 0 1 is white, since there is no saturation and value is maxed.

colorScaleIndex property

To set the agent to a color in the scale, just set the colorScaleIndex property. The corresponding color will be automatically applied during the VIS_UPDATE cycle.

colorScaleIndex is a GVarNumber, so you can use GVar math.

We implemented this as a featProperty so that you can easily do math with it.

For example, this will set the agent to the 9th color in the scale.

featProp Costume colorScaleIndex setTo 9

For example, this will change the colorScaleIndex value by a random value up to +/-2.

featProp Costume colorScaleIndex addRnd -2 2 true

How to Use Color Methods

The colorize methods are all part of the Costume Feature.

Example:

# PROGRAM DEFINE
useFeature Costume
featCall Costume setCostume 'bee.json' 0
// Turn the bee green
featCall Costume setColorize 0 1 0
# PROGRAM UPDATE
when Moth touches Tree [[
  // when moth touches tree show the true colors
  featCall Costume resetColorize
]]
when Moth touches Mushroom [[
  // when moth touches Mushroom show psychedelic color changes
  featCall Costume randomizeColor 1 1 1
]]

Adding Art

The recent changes to asset management should make it really easy to add, update, and remove art assets for any installation:

  • Any art can simply be added to the /gs_assets/local/sprites folder.
  • There is no need to use TexturePacker to create a spritesheet (.json file) if you do not need it.
  • There is no need to create an asset manifest file.
  • Use the filename to set the costume name, e.g. featCall Costume setCostume 'bird.jpg'

For example, you can draw a bird using any art program of your choice, save it as "bird.jpg" and move it into /gs_assets/local/sprites/bird.jpg. e.g. featCall Costume setCostume 'hawk.png'

Adding Animations

Per Corey's request, we have made it easy to create animations with a new setAnimatedCostume command.

  1. Name your graphic files with a number at the end representing the animation frame, e.g. fly1.png, fly2.png, fly3.png.
  2. Save them in /gs_assets/local/sprites.
  3. Instead of using setCostume, call setAnimatedCostume. e.g.
featCall Costume setAnimatedCostume 'fly1.png'

The Costume feature will find the last number before the extension and use that as the starting frame. The system will then look for fly2.png as the next frame, and so on, until it can't find any more frames. At which point it'll return to the first frame.

  1. You can set the frame rate as the last parameter.
featCall Costume setAnimatedCostume 'fly1.png' 1

This will update the animation every 1 second.

By default the frame rate is 0.3.

I used Corey's method of frame rate calculation, which is more akin to "every n seconds" or "go to the next frame every n seconds". So the default frame rate of 0.3 is "change frames every 0.3 seconds", a leisurely rate.

We might consider changing it to a true "frames per second" value, e.g. 30 would be running 30 updates per second.


A few general notes:

  • Animations only run when the simulation is running. So you need to push "START ROUND" to see the animation.
  • You can start the animation on a specific frame. When the animation loops, it will start again with the first frame. e.g. if you call featCall Costume setAnimatedCostume 'fly3.png', the system will start with fly3, go to fly 4, fly5, etc. until it hits the last frame, then it'll start back at fly3.
  • Don't use leading 0's. The system will ignore the leading zero for the next frame, e.g. if you use toot01.jpg, the next frame will be toot2.jpg.
  • If you skip a number, the animation will loop. e.g. if you have fly1, fly2, fly4 (no fly3), then the animation will just loop between fly1 and fly2. When the system can't find an animation frame, it assumes it's time to loop.
⚠️ **GitHub.com Fallback** ⚠️