was anyone ever able to recreate leaves animating in low resolution games (320x240 // 320x180) through code in success?
I am looking for an effect similar to the one in Owlboy.
Spoiler
(https://i.imgur.com/X0nKoks.gif)
I looked over the Underwater module, because it's the most similar I could remember, but I don't understand yet how to modify until a flailing effect can be made.
Spoiler
LeavesAnimation.asc
// new module script
#define MAX_FRAMES 10
#define MAX_BLOCKS 128
int block_w;
int block_h;
int block_x[MAX_BLOCKS];
int block_y[MAX_BLOCKS];
bool Leaves_enabled = false;
int original_graphic;
float tt = 0.0;
float t = 0.0;
float a[MAX_FRAMES], b[MAX_FRAMES], c[MAX_FRAMES];
DynamicSprite * dyn_spr;
static void LeavesAnimation::SetBaseGaphic(int leavesGraphic){
if(dyn_spr!=null){
dyn_spr.Delete();
}
original_graphic = leavesGraphic;
dyn_spr = DynamicSprite.CreateFromExistingSprite(original_graphic, true);
}
static int LeavesAnimation::GetGaphic(){
if(dyn_spr!=null){
return dyn_spr.Graphic;
}
return 0;
}
static void LeavesAnimation::Enable() {
float scalar = 8000.0;
int i = 0;
int delta1 = Random(MAX_FRAMES-1);
int delta2 = Random(MAX_FRAMES-1);
int delta3 = Random(MAX_FRAMES-1);
while (i < MAX_FRAMES) {
a[i] = Maths.Cos(Maths.Pi*IntToFloat((delta1+i)%MAX_FRAMES)/IntToFloat(MAX_FRAMES)); //IntToFloat( Random(2000)*(Random(1)-1) )/scalar;
b[i] = Maths.Sin(Maths.Pi*IntToFloat((delta2+i)%MAX_FRAMES)/IntToFloat(MAX_FRAMES)); //IntToFloat( Random(2000)*(Random(1)-1) )/scalar;
c[i] = Maths.Cos(Maths.Pi*IntToFloat((delta3+i)%MAX_FRAMES)/IntToFloat(MAX_FRAMES)); //IntToFloat( Random(2000)*(Random(1)-1) )/scalar;
i++;
}
block_w = Game.SpriteWidth[original_graphic]/48;
block_h = Game.SpriteHeight[original_graphic]/24;
i = 0;
while (i < MAX_BLOCKS) {
block_x[i] = Random(Game.SpriteWidth[original_graphic]- 1 - block_w);
block_y[i] = Random(Game.SpriteHeight[original_graphic] - 1 - block_h);
i++;
}
Leaves_enabled = true;
}
static void LeavesAnimation::Disable() {
Leaves_enabled = false;
}
float get_gradient_x(int xi, int yi) {
float x = IntToFloat(xi)/160.0 - 1.0;
float y = IntToFloat(yi)/160.0 - 1.0;
float dx = 0.0;
int i = 0;
while (i < MAX_FRAMES) {
dx += a[i]*t*Maths.Cos(a[i]*t*x + b[i]*t*y + c[i]);
i++;
}
return dx;
}
float get_gradient_y(int xi, int yi) {
float x = IntToFloat(xi)/160.0 - 1.0;
float y = IntToFloat(yi)/160.0 - 1.0;
float dy = 0.0;
int i = 0;
while (i < MAX_FRAMES) {
dy += b[i]*t*Maths.Cos(a[i]*t*x + b[i]*t*y + c[i]);
i++;
}
return dy;
}
function offset_a_block(DrawingSurface *surf, int x, int y, int w, int h) {
int xoff = FloatToInt(1.0*get_gradient_x(x + w/2, y + w/2));
int yoff = FloatToInt(1.0*get_gradient_y(x + h/2, y + h/2));
xoff = Utils.clampInt(xoff, 1, -1);
yoff = Utils.clampInt(yoff, 1, 0);
//w = Utils.clampInt(w, Game.SpriteWidth[original_graphic]-x, 1);
//w = Utils.clampInt(w, Game.SpriteHeight[original_graphic]-y, 1);
DynamicSprite *ds = DynamicSprite.CreateFromDrawingSurface(surf, x, y, w, h);
//surf.DrawingColor = COLOR_TRANSPARENT;
//surf.DrawRectangle(x, y, x+w, y+w);
surf.DrawImage(x - xoff, y - yoff, ds.Graphic);
}
function repeatedly_execute_always() {
if (Leaves_enabled) {
if(dyn_spr==null){
return;
}
if(getCurrentFrame()%4!=0){
return;
}
tt = tt + 0.01;
float k = Utils.clampFloat((2.0*Maths.Pi*Maths.Sin(tt)), 8.0, 0.0) ; ///8.0;
t=1.0;
if(dyn_spr!=null){
dyn_spr.Delete();
}
dyn_spr = DynamicSprite.CreateFromExistingSprite(original_graphic, true);
//SetBackgroundFrame(0);
// repeatedly grab a random chunk from bg 1 and paste it to bg 0, slightly offset
DrawingSurface *surf = dyn_spr.GetDrawingSurface(); //Room.GetDrawingSurfaceForBackground(0);
int i = 0;
while (i < MAX_BLOCKS) {
if(Random(FloatToInt(k))==0){
block_x[i] = Random(Game.SpriteWidth[original_graphic]- 1 - block_w);
block_y[i] = Random(Game.SpriteHeight[original_graphic] - 1 - block_h);
}
//int x = Random(Game.SpriteWidth[original_graphic]- 1 - block_w);
//int y = Random(Game.SpriteHeight[original_graphic] - 1 - block_h);
offset_a_block(surf, block_x[i], block_y[i], block_w, block_h);
i++;
}
surf.Release();
}
}
// draw some more around the player
// ViewFrame *frame = Game.GetViewFrame(player.View, player.Loop, player.Frame);
// int graphic = frame.Graphic;
// int height = FloatToInt(IntToFloat(Game.SpriteHeight[graphic]*player.Scaling)/100.0);
// int width = FloatToInt(IntToFloat( Game.SpriteWidth[graphic]*player.Scaling)/100.0);
// int left = player.x - width/2;
// int top = player.y - height - player.z;
// i = 0;
// while (i < 32) {
// i++;
// int w = Room.Width/64;
// int x = left - w/2 + Random(width - 1);
// int y = top - w/2 + Random(height - 1);
// if (x < 0) x = 0;
// else if (x >= Room.Width - w) x = Room.Width - 1 - w;
// if (y < 0) y = 0;
// else if (y >= Room.Height - w) y = Room.Height - 1 - w;
// offset_a_block(surf, x, y, w);
// }
LeavesAnimation.ash
// new module header
struct LeavesAnimation {
import static void Enable();
import static void Disable();
import static void SetBaseGaphic(int leavesGraphic);
import static int GetGaphic();
};
Here is a different gif idea (but I still can't understand how to implement leaf animation on the bg...)Spoiler
(https://i.imgur.com/6Y0SHRd.gif)