Duck Animation Suggestion for 2D Platforms

maxman

Well-known member
I was playing Naruto awhile ago and I've known that playable characters from most mods play idle animation while releasing and after holding a duck button. We know that some characters duck with one sprite frame in an animation with pressing, holding, and releasing it, and it's no problem. The problem is that when using more than 1 frames in a duck anim like 2-4 or over, you can see that how many frame played in that anim for holding, but when you release it, it reverts back to anim idle instead of playing something like an anim unduck (for standing up for ducking; no such word for "unduck" in OpenBOR). Example, when you hold down, then frame 1 ("I'm about to get down") plays, then frame 2 ("I'm half way to get down"), and lastly frame 3 ("OK. Here I'm down here!"). But when releasing it, it's back to idle anim ("Hey that's funny. I was down here and then all of a sudden I'm back to standing up without moving up from being down here. That's probably because the engine isn't interactive enough for the duck").

anim duck

offset 23 50
delay 5
frame data/chars/mikey/duck1.png
frame data/chars/mikey/duck2.png
frame data/chars/mikey/duck3.png
frame data/chars/mikey/duck4.png #frame 4 should refer to be played all the way to frame 1 after releasing a down button from ducking and should NOT revert to anim idle after releasing it
frame data/chars/mikey/duck5.png
 
Hey White Dragon. Is it okay if you could replace anim pain40 with any follow animation like follow50 for example? I might use another follow anim to do it instead of pain anim.
 
Recently I got an idea about putting some crouching pain frames as last frames in the same pain anim. In that way, I'm not gonna waste many pain anims if I want crouching frames in the same pain anim. But I think I'm gonna make the script long in duck anim with script tags.

Example:

Code:
anim	pain #LP pain
	delay	4 #Pain from both close and far ranges of light punch
	offset	25 99
	frame	data/chars/ryu/0500000000.gif
	@cmd	velo001 -2 0 0
	delay	7
	frame	data/chars/ryu/0500000000.gif
	offset	35 100
	delay	5
	frame	data/chars/ryu/0500000010.gif
	offset	25 99
	@cmd	velo001 0 0 0
	frame	data/chars/ryu/0500000000.gif
	@cmd	aniframe "ani_follow40" 0
	frame	data/chars/ryu/0500000000.gif
	offset 26 67
	frame data/CHARS/Ryu/0502000000.gif #5
	offset 38 68
	frame data/CHARS/Ryu/0502000010.gif
	offset 45 67
	frame data/CHARS/Ryu/0502000020.gif
	offset 57 67
	frame data/CHARS/Ryu/0502000030.gif
	@cmd	aniframe "ani_follow40" 16
	frame data/CHARS/Ryu/0502000030.gif

Frame 5 is the start of crouching pain frames in anim pain above which will skip to both animation and frame from running it entirely (because of aniframe).

Code:
anim follow40 #Switch anim after anim pain#
	delay	3
	offset	25 99
	frame	data/chars/ryu/0500000000.gif #0
	@cmd beidle
	frame	data/chars/ryu/0500000000.gif
	offset	35 100
	frame	data/chars/ryu/0500000010.gif #2
	@cmd beidle
	frame	data/chars/ryu/0500000010.gif
	offset	43 97
	frame	data/chars/ryu/0500000020.gif #4
	@cmd beidle
	frame	data/chars/ryu/0500000020.gif
	offset	24 98
	frame	data/chars/ryu/0501000000.gif #6
	@cmd beidle
	frame	data/chars/ryu/0501000000.gif
	offset	31 95
	frame	data/chars/ryu/0501000010.gif #8
	@cmd beidle
	frame	data/chars/ryu/0501000010.gif
	offset	46 84
	frame	data/chars/ryu/0501000020.gif #10
	@cmd beidle
	frame	data/chars/ryu/0501000020.gif
	offset	54 80
	frame	data/chars/ryu/0501000030.gif #12
	@cmd beidle
	frame	data/chars/ryu/0501000030.gif
	offset 26 67
	frame data/CHARS/Ryu/0502000000.gif #14
	@cmd	keyint2 "ANI_DUCK" 2 "D" 0
	@cmd	keyint2 "ANI_FOLLOW6" 0 "D" 1
	frame data/CHARS/Ryu/0502000000.gif
	offset 38 68
	frame data/CHARS/Ryu/0502000010.gif #16
	@cmd	keyint2 "ANI_DUCK" 2 "D" 0
	@cmd	keyint2 "ANI_FOLLOW6" 0 "D" 1
	frame data/CHARS/Ryu/0502000010.gif
	offset 45 67
	frame data/CHARS/Ryu/0502000020.gif #18
	@cmd	keyint2 "ANI_DUCK" 2 "D" 0
	@cmd	keyint2 "ANI_FOLLOW6" 0 "D" 1
	frame data/CHARS/Ryu/0502000020.gif
	offset 57 67
	frame data/CHARS/Ryu/0502000030.gif #20
	@cmd	keyint2 "ANI_DUCK" 2 "D" 0
	@cmd	keyint2 "ANI_FOLLOW6" 0 "D" 1
	frame data/CHARS/Ryu/0502000030.gif

I know I have to set entity variables for doing it. What I want is to switch to specific frame in a specific pain animation for duckpain if I'd go for duckpain reaction. I got duckpain reaction which will switch to a pain anim. I'm planning to add animpos in anim duck for switching frame to pain anim for crouch pain. (I'm not using onpainscript currently but I'll use it later.)

Code:
  int pain = getentityvar(self, "pain");
  int attackid = getentityproperty(self, "attackid");
  int frame = getentityproperty(self, "animpos");
  
  if(pain != NULL()){
  	setentityvar(self, "pain", NULL());
  	changeentityproperty(self, "animation", openborconstant("ANI_PAIN" + pain));
  	if(attackid == openborconstant("ATK_NORMAL1")){
  		setentityvar(self, "pain", 1);
  		changeentityproperty(self, "animpos", 5);
  	}
  }

Here's my concept for onpainscript:

Code:
void main()
{
	void self = getlocalvar("self");
	void target = getentityproperty(self, "opponent");
	void damage = getlocalvar("damage");
	void AniID = getentityproperty(self, "animationid");
	int animpos = getentityproperty(self, "animpos");
	void IdlePain = getentityvar(self, "IdlePain");
	int DuckPain = getentityvar(self, "DuckPain");
	int hResolution = openborvariant("hResolution");
	int xPos = openborvariant("xpos");
	int x = getentityproperty(self, "x");
	int Tx = getentityproperty(target, "x");
	int pain = getentityvar(self, "pain");
	int attackid = getentityproperty(self, "attackid");
	
	if(damage != NULL()){
		setentityvar(self, "damage", NULL());
		changeentityproperty(self, "attacking", openborconstant("ATK_NORMAL" + damage));
		if(AniID == openborconstant("ANI_DUCK")){
			setentityvar(self, "damage", NULL());
			changeentityproperty(self, "attacking", openborconstant("ATK_NORMAL" + damage));
			changeentityproperty(self, "animpos", animpos);
		}
	}
	
	if(pain != NULL()){
		setentityvar(self, "pain", NULL());
		changeentityproperty(self, "animation", openborconstant("ANI_pain" + pain));
		//changeentityproperty(self, "animpos", animpos)
		if( x >= xPos+hResolution-10){
			changeentityproperty(target, "velocity", -1.5, 0, 0);
		}else if(x <= xPos+10){
			changeentityproperty(target, "velocity", 1.5, 0, 0);
		}
	}
	
	/*
	if(DuckPain != NULL()){
		if(vAniID == openborconstant("ANI_DUCK")){
			setentityvar(self, "DuckPain", NULL());
			changeentityproperty(self, "animpos", animpos);
			changeentityproperty(self, "animation", openborconstant("ANI_PAIN" + DuckPain + animpos));
		}
	}
	*/
	
	/*
	if(vAniID = openborconstant("ANI_DUCK")){
		if(DuckPain != NULL()){
			setentityvar(self, "DuckPain", 40); //For anim pain40
			changeentityproperty(self, "animation", openborconstant("ANI_pain" + DuckPain)); //Anim pain40 with any other pain anim
			changeentityproperty(self, "animpos", 5);
		}
	}
	*/

}
 
Back
Top Bottom