Camouflage - theRAPTLab/gsgo GitHub Wiki
See !116
[[TOC]]
This implements scriptable camouflage parameters for predators and prey.
The first implementation for detecting the visibility of Moths against Trees was a hack that relied on Moths setting their own visibility after landing on a tree. That approach was adequate for a simple simulation demo, but does not easily support changing colors over multiple rounds and mutations. It also does not allow for different types of visibility for different agents. More importantly, it does not allow for easy student script changes to predator color detection. (Changing the script would have required developing a Script UI that could change javascript expressions inside an ifExpr
expression nested inside a when
, e.g.:
when Moth centerTouches TreeFoliage [[
ifExpr {{ Moth.callFeatMethod('Costume', 'colorHSVWithinRange', Moth.prop.color.value, TreeFoliage.prop.color.value, 0.2, 1, 0.2)}} [[
// color matches, fade away and set un-visionable
...
]]
...
]]
). Furthermore, changing detectability would require separately changing the Moth landing test as well as predator's seek Movement settings, two different scripts in two different blueprints.
A better method for implementing camouflage would be to rely on simple featProps definitions for Predators' Vision, e.g.
// Set detection thresholds
featProp Vision colorHueDetectionThreshold setTo 0.2
featProp Vision colorValueDetectionThreshold setTo 0.2
...
// Seek based on detection of color against background
featCall Movement seekNearestVisibleColor Moth
...
// Show when Moth as been spotted
when Predator seesCamouflaged Moth [[
// glow Moth to show it's been spotted
...
]]
This can be easily changed in any script block and does not require convoluted test expressions. It also sets the same level of detection for seeks as well as when
sim condition tests across the board. And, it allows different agents to have different levels of vision detection.
Implementing this required changes to many features.
Camouflage is a fairly complex operation. In essence, it involves a predator agent's Vision feature being able to detect a target agent against the target agent's background agent color.
graph TD
A[Agent:Predator] -->|vision| B[Agent:Moth]
B --> |touches:bounds-in-bounds| C[Agent:Tree]
To use Camouflage you have to:
1A. Set target and background agent's Costume colors
via setColorize
.
Camouflage relies on programmatically-set colorized
colors of agents. It does not detect spritesheet/image colors.
e.g.
# BLUEPRINT Moth
# PROGRAM DEFINE
useFeature Costume
featCall Costume setColorize 0 0.1 0.9
# BLUEPRINT Tree
# PROGRAM DEFINE
useFeature Costume
featcall Costume setColorize 0 0.1 0.6
1B. Turn on Physics for the target and background agent.
We use a touch test determine the background of the target agent. So Physics needs to be on for both the target and the background agent.
e.g.
# BLUEPRINT Moth
# PROGRAM DEFINE
// allow detection of moths touching trees for camouflage test
useFeature Physics
# BLUEPRINT Tree
# PROGRAM DEFINE
// allow detection of moths touching trees for camouflage test
useFeature Physics
1C. Turn on binb
touch test for target against background agent.
We use a touch test determine the background of the target agent. So touches needs to be on for the target agent and it needs to monitor 'binb' touches against the background.
e.g.
# BLUEPRINT Moth
# PROGRAM DEFINE
// allow detection of moths touching trees for camouflage test
useFeature Touches
featCall Touches monitor Tree binb
- Make the target agent Visionable
Adding the Vision feature will automatically make the target agent visible.
e.g.
# BLUEPRINT Moth
# PROGRAM DEFINE
// Sets visionable true so predator can see us
useFeature Vision
- Set the Predator's Vision color thresholds
By default, all colors are detectable. If we want to limit the range of colors that the predator can detect (technically we're limiting the "color differences the predator can detect"), then we need to set threshold values. The difference in color between the target agent and the background agent needs to exceed the threshold in order to be detected.
e.g.
# BLUEPRINT Predator
# PROGRAM DEFINE
useFeature Vision
featProp Vision colorHueDetectionThreshold setTo 0.2
featProp Vision colorValueDetectionThreshold setTo 0.2
For example, in this case, if the target hue is 0.3 while the background hue is 0.4, the difference between the colors is 0.1, which is under the hue threshold of 0.2, so the target agent will not be visible. On the other hand, if the background hue is 0.7, then the difference is 0.3, which is greater than the threshold, so the target IS visible.
We don't set colorSaturationDetectionTreshold
, so it defaults to 0, which means we will be able to detect any or no difference in saturation.
- Have the Predator seek agents by color
Use the seekNearestVisibleColor
Movement method to tell the Predator to only seek non-camouflaged Moths.
e.g.
# BLUEPRINT Predator
# PROGRAM DEFINE
useFeature Movement
featCall Movement seekNearestVisibleColor Moth
The Predator will seek out (and eat if scripted to) any non-camouflaged Moths. The Predator will ignore any Moths that are camouflaged.
- Do something when the Predator sees a camouflaged target agent
Sometimes you might need to take some extra actions when a target agent is seen by a predator, e.g. the target might take evasive action or we might Glow the target so we can see when it's been spotted.
Use the seesCamouflaged
condition to do this.
e.g.
when Predator seesCamouflaged Moth [[
// spotted! Glow!
featCall Moth.Costume setGlow 0.1
]]
Sets the threshold for color detection. Agent colors are detectable against a background color if the difference between the agent color and the background color is greater than the threshold value.
NOTE: This uses the Agent's Costume and the target Agent's background Agent color
property. It does NOT detect a sprite's color by sampling the spritesheet/image.
The default value is 0, which will match any value, so detection is always possible.
The detection uses difference <=
threshold. So if the difference is 0.2 and the threshold is set to 0.2, the difference does NOT exceed the threshold and the color is NOT detected.
These are all GVarNumbers, sop use the setTo
and value
methods to interact with them.
featProp Vision colorHueDetectionThreshold setTo <value>
where <value>
is a number from 0 to 1.
The isCamouflaged
method returns true if the target agent can not be detected against the background color.
NOTE: You shouldn't need to use this method. This is mostly a private method.
graph TD
A[Agent:Predator] -->|vision| B[Agent:Moth]
B --> |touches:bounds-in-bounds| C[Agent:Tree]
featCall Vision isCamouflaged <backgroundColor> <hueRange> <saturationRange> <valueRange>
where
-
<backgroundColor>
is a number -
<hueRange>
is a number between 0 and 1 -
<saturationRange>
is a number between 0 and 1 -
<valueRange>
is a number between 0 and 1
If the difference between the agent color H/S/V and the backgroundColor H/S/V is within the H/S/V range, then the agent is considered camouflaged.
In general, this is used by Vision feature itself in m_IsTargetColorVisible
to determine the visibility of a target agent. While it can be used in an ifExpr
, use it with careful consideration as it tests the current agent's color against the background color. In most cases you'll be wanting to test some other target agent and against an arbitrary background color, which is set automatically via m_IsTargetColorVisible
What an agent can and can't see is determined during the SIM/AGENTS_UPDATE
phase. Vision's update loop will set the canSeeCone
and canSeeColor
Map properties of the viewer agent based on the viewDistance
, viewAngle
, and color*DetectionThreshold
values.
agent.canSeeCone
Map -- Map of target agents the agent can see within the vision cone.
agent.canSeeColor
Map -- Map of target agents the agent can detect against the target agent's background color based on the color*DetectionThreshold
values (where * = 'Hue', 'Saturation', or 'Value').
Like seekNearestVisible
, this will tell an agent to seek the nearest non-camouflaged agent of the specified blueprint type.
Set the color*DetectionThreshold
Vision values of the viewing agent before using this. These thresholds determine the level of color difference necessary before a color can be discerned against a background.
- Physics
- Touches
- Costume
- Vision
featCall Movement seekNearestVisibleColor <blueprint>
where <blueprint>
is a blueprint name, e.g. Moth
.
featCall Touches getTouchingAgent <touchType>
will return the first agent that passes the <touchType>
type test relative to this agent.
TouchTypes include:
-
c2c
-- center to center -
c2b
-- center to bounds -
b2b
-- bounds to bounds (any edge touching another edge) -
binb
-- bounds in bounds (first agent inside second agent)
This is primarily used by Vision's m_IsTargetColorVisible
call to get the background agent of the target.
Returns true if the source agent can detect the target agent's color against the target agent's background agent. If the target agent's color is too similar to the target agent's background agent color then the target agent is not seen.
Set the source agent's color*DetectionThreshold
Vision properties to set the detection threshold.
when Predator seesCamouflaged Moth