• All, I am currently in the process of migrating domain registrations. During this time there may be some intermittent outages or slowdowns. Please contact staff if you have any questions.
Animated Background Layers

Animated Background Layers

Great, thanks Damon Caskey!

I'm using "changelayerproperty" to switch between "retro" or "high definition" graphics in SOR2X, I discovered this function after take a look in the source code. But I never thought to use this function for animation purpose in level design, it was a brilliant idea.
 
danno & Kratus,

Thanks for the props, they are much appreciated. I've updated the original post to hopefully explain better when you might want (and not want) to employ this method.

DC
 
Im glad more experiments are being done with fglayers, theyre great.
Ill definitely make some functions to control them dynamically.
 
Damon Caskey said:
danno & Kratus,

Thanks for the props, they are much appreciated. I've updated the original post to hopefully explain better when you might want (and not want) to employ this method.

Hello , i have a little issue with an animation.

cycleSprite("fglayer", 3, 18, 17);


fglayer  data/bgs/sor2/st1a/greencartel1.gif  100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel2.gif  100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel3.gif  100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel4.gif  100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel5.gif  100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel6.gif  100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel7.gif  100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel8.gif  100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel9.gif  100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel10.gif 100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel11.gif 100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel12.gif 100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel13.gif 100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel14.gif 100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel15.gif 100 0 0.6 264 14 0 0 1 1 1 0
fglayer  data/bgs/sor2/st1a/greencartel16.gif 100 0 0.6 264 14 0 0 1 1 1 0


The thing is that, the animation works OK, but it doesnt start instantly, like if the delay (animation speed) i put in the animation applies at the start of the animation too, so until the animation starts, there is a delay.

https://www.youtube.com/watch?v=AjH6kbilw0k

Did you saw the delay to start the animation?

How can i make the animation to start in the instant it appears  without that delay at the start?
 
pepodmc

This "cycleSprite" script is a custom version I'm using for SOR2X, I didn't see this delay before because I'm only using it for simple and small animations only.
I will check the script to see what's causing the delay, but for large and complex animations maybe it's better using entities instead.
 
Kratus said:
pepodmc

This "cycleSprite" script is a custom version I'm using for SOR2X, I didn't see this delay before because I'm only using it for simple and small animations only.
I will check the script to see what's causing the delay, but for large and complex animations maybe it's better using entities instead.

Large, because complex it isnt.

yeah, if you can take a look would be great.

But if it cant be fixed, no problem.
 
Kratus and pepodmc,

I haven't seen your function, but I can venture a guess. If you are comparing elapsed time to some variable for your timing, you have to remember elapsed time resets any time the engine loads a new scene (level, high score, select screen, etc.). If your timing variable isn't reset too, it's going to start out of sync when the next scene loads and your timer is frozen until elapsed time catches up.

This is true for local variables inside persistent scripts (update.c, keyall.c, etc.) or for ANY global variable.

DC
 
Great tutorial but i would much rather use a panel entity. Using a 24bit png sounds amazing how does transparency work with high colour images ?
 
msmalik681 said:
Great tutorial but i would much rather use a panel entity. Using a 24bit png sounds amazing how does transparency work with high colour images ?

For me, the situation where you must/should use it is when you want to make an animated background.

"Scrolling Accuracy: Entity positions are updated using a different formula than layers. As a result, entities used as background objects may have an unavoidable intermittent one pixel offset when positioned over a layer with equal scroll speed"

In the situation of my video it wasnt necesary, i only wanted to use it because it use less resources than an entity.
 
pepodmc

In fact DC is right, I'm not clearing the variables properly in the "cycleSprite" script. Thanks Damon Caskey :)

But we had another problem. When the level starts, all layers will start activated and the script will deactivate gradually one by one, until only one remains on the screen. And the more layers an animation has, the longer it takes to work, this is why I didn't detect this issue before.

Now I updated the script with two fixes:
1) Clear all local variables when a new level starts
2) Disable all layers except for the last when any new level starts

Please, update your script with the new code above in the file "main.c" at the path "data/scripts/updatelevel/main.c".

Code:
void cycleSprite(void type, int startIndex, int endIndex, float frameDelay, float cycleDelay)
{//Apply simple sprite cycle effects to avoid creating new entities
	float timeCurrent	= openborvariant("elapsed_time");
	float timeCounter	= getlocalvar("timeCounter"+type+startIndex);
	int levelCurrent	= openborvariant("current_level");
	int levelPrevious	= getlocalvar("levelPrevious");
	int frameCurrent	= getlocalvar("frameCurrent"+type+startIndex);
	int frameNext		= getlocalvar("frameNext"+type+startIndex);
	int frameStart		= getlocalvar("frameStart"+type+startIndex);

	//CLEAR ALL LOCAL VARIABLES WHEN THE LEVEL CHANGES
	if(levelCurrent != levelPrevious){clearlocalvar();setlocalvar("levelPrevious", levelCurrent);}
	
	//START ALL VARIABLES
	if(timeCounter == NULL()){setlocalvar("timeCounter"+type+startIndex, timeCurrent+frameDelay);}
	if(frameCurrent == NULL()){setlocalvar("frameCurrent"+type+startIndex, endIndex);}
	if(frameNext == NULL()){setlocalvar("frameNext"+type+startIndex, startIndex);}
	if(frameStart == NULL()){setlocalvar("frameStart"+type+startIndex, startIndex);}

	//DISABLE ALL LAYERS EXCEPT FOR THE LAST, WHEN THE SCRIPT STARTS
	while(frameStart < endIndex-1){
		frameStart = getlocalvar("frameStart"+type+startIndex);

		changelayerproperty(type, frameStart, "enabled", 0);
		setlocalvar("frameStart"+type+startIndex, frameStart+1);
	}
	
	//EXECUTE ALL TASKS
	if(getglobalvar("activeText") == 0 || getglobalvar("activeText") == NULL()){

		//DELAY REACHED THE LIMIT?? EXECUTE ALL TASKS
		if(timeCurrent > timeCounter){

			//DEFINE THE CURRENT FRAME
			if(frameCurrent < endIndex){
				setlocalvar("frameCurrent"+type+startIndex, frameCurrent+1);
				setlocalvar("timeCounter"+type+startIndex, timeCurrent+frameDelay);
			}
			else
			{
				if(cycleDelay != NULL()){setlocalvar("timeCounter"+type+startIndex, timeCurrent+frameDelay+cycleDelay);}
				setlocalvar("frameCurrent"+type+startIndex, startIndex);
			}

			//DEFINE THE NEXT FRAME
			if(frameNext < endIndex){
				setlocalvar("frameNext"+type+startIndex, frameNext+1);
				setlocalvar("timeCounter"+type+startIndex, timeCurrent+frameDelay);
			}
			else
			{
				if(cycleDelay != NULL()){setlocalvar("timeCounter"+type+startIndex, timeCurrent+frameDelay+cycleDelay);}
				setlocalvar("frameNext"+type+startIndex, startIndex);
			}

			//CHANGE LAYERS
			changelayerproperty(type, frameCurrent, "enabled", 0);
			changelayerproperty(type, frameNext, "enabled", 1);
		}
	}
}
 
Kratus said:
pepodmc

In fact DC is right, I'm not clearing the variables properly in the "cycleSprite" script. Thanks Damon Caskey :)

It works OK, but there is one last thing i noticed.

The sprite placed on the screen using this method has no quake effect.

Look, the first is the sprite placed as an entity (the Cinammon beach  sprite):


And this is the sprite applied with the Cicle Sprite method:







Its possible to add the quake effect to the sprites using this cycle sprite method?
 
pepodmc

Its possible to add the quake effect to the sprites using this cycle sprite method?
Yeah, I'm using it on the SOR2X v2.3 in some levels. Below is an example of the "fglayer" properties.

Code:
##BGLAYER PROPERTIES
#filepath xratio zratio xoffset zoffset xspace zspace xrepeat zrepeat transp alpha w-mode amp wl ws move quake neon

#FGLAYER PROPERTIES
#filepath zpos xratio zratio xoffset zoffset xspace zspace xrepeat zrepeat transp alpha w-mode amp wl ws move quake neon
 
Kratus said:
pepodmc

Its possible to add the quake effect to the sprites using this cycle sprite method?
Yeah, I'm using it on the SOR2X v2.3 in some levels. Below is an example of the "fglayer" properties.

Code:
##BGLAYER PROPERTIES
#filepath xratio zratio xoffset zoffset xspace zspace xrepeat zrepeat transp alpha w-mode amp wl ws move quake neon

#FGLAYER PROPERTIES
#filepath zpos xratio zratio xoffset zoffset xspace zspace xrepeat zrepeat transp alpha w-mode amp wl ws move quake neon

Sorry, i have a txt with fglayer properties but its incomplete compared to this one XD.

Thanks!!

Edit: Yeah, it worked
 
Update: Restored waterfall image attachments. Modify formatting to take advantage of Xenoforo's BB code.

DC
 
Can background be counted as a layer? I believe not.

Also, is there a level property that can change the facing of the layer like entity's facing/direction property? Do you think layer property can do the job?
 
You can't flip a layer without passing it through a screen... I even spelled that out in the tutorial.
 
Back
Top Bottom