Hi all -
I'm working on an effect where characters appear to "wade" through water.
Right now it works by (1) making a DynamicSprite* dyWade from the character's currently displayed ViewFrame*, vwCurrent, (2) drawing a transparent rectangle over the bottom of dyWade, (3) assigning vwCurrent.Graphic = dyWade.Graphic, and (4) restoring vwCurrent.Graphic to its default value when the next animation frame is displayed.
This works well at low res with one issue: there's a "flicker" effect. I assume this is from the default sprite being drawn, and then the modified sprite being drawn an instant later. It's just a little distracting.
Is this something that I can work around (ie, is it possible to modify a character's current ViewFrame before it's drawn onto the screen)?
Here's the relevant code (dyWade, vwCurrent, vwLast, and lastgraphic are arrays declared elsewhere):
void RestoreLastViewFrame(this Character*) {
//restores the previously displayed ViewFrame for "this" to "lastgraphic," its default sprite
//must be called after lastgraphic is stored
vwLast[this.ID].Graphic = lastgraphic[this.ID];
vwLast[this.ID] = null;
}
void MakeWadingSprite(this Character*, int depth) {
//makes a wading sprite out of "this"'s current viewframe
// and stores it to dyWade[this.ID]
//also saves the default graphic for "this"'s current ViewFrame to lastgraphic[this.ID]
//must have stored vwCurrent[this.ID] before calling
dyWade[this.ID] = DynamicSprite.CreateFromExistingSprite(vwCurrent[this.ID].Graphic, true);
DrawingSurface* dwWade = dyWade[this.ID].GetDrawingSurface();
dwWade.DrawingColor = COLOR_TRANSPARENT;
int x1 = 0;
int x2 = dyWade[this.ID].Width;
int y2 = dyWade[this.ID].Height;
int y1 = y2 - depth;
dwWade.DrawRectangle(x1, y1, x2, y2);
dwWade.Release();
lastgraphic[this.ID] = vwCurrent[this.ID].Graphic;
}
void Wade(this Character*) { //CALLED IN REPEATEDLY_EXECUTE
vwCurrent[this.ID] = this.GetCharacterFrame(); //GetCharacterFrame(this Character*) returns ViewFrame for this.View, this.Loop, this.Sprite
if (vwLast[this.ID] == null) {
vwLast[this.ID] = vwCurrent[this.ID];
this.MakeWadingSprite(15);
vwCurrent[this.ID].Graphic = dyWade[this.ID].Graphic;
}
else if (vwLast[this.ID] != vwCurrent[this.ID]) {
this.RestoreLastViewFrame();
}
}
Try calling it in late_repeatedly_execute_always()
Yep, that did it.
That was simpler than I expected. I had completely forgotten about late_repeatedly_execute.
Thanks.