Creating long Traces on the snowground

ABK

Well-known member
Hey guys im trying to find a way to create long rtaces that will be drawn in a way that wont piece them apart when steering my buttslides.
When im sliding straight then it looks fine, but when im steering up/down then you can see how disconnected they become.
Im using separate entities fired by projectile command but id like to figure out something better maybe something for updatescript ?
So for example i would have long piece of graphics and it would be spawned line by line by script ? So when i move up/down then each line will be properly connected to each other and provide me with smoother shapes , maybe curves , not sure how it would look like.
Or maybe theres totally other idea, maybe someone did that before ?
I remember Bloodbane had that hydra enemy that neck made from balls follows the head in nice sinusoids , and i was thinking if thats how it should be done.
Heres what i have when sliding straight
https://drive.google.com/file/d/1W2C0yMCMmXeefMqFSXtL1PFRhSFBbuR_/view?usp=sharing
Animation1.gif


And heres the problem when i press up/down to control and steer him:
Animation2.gif

https://drive.google.com/file/d/1SejUAzGOxSu6c4pnPP-W15Ex8YFtyZAM/view?usp=sharing


- Also one thing i want to get is a bit of slide when moving around on ground , kinda like on ice,mario had it a bit and some platformers have it, is there a way to do it in a compact way?
Cause i guess checking every entity and applying extra velocity with decrease at all times on the ground is going to be taxing ?
 
I remember Bloodbane had that hydra enemy that neck made from balls follows the head in nice sinusoids

  :o , I need to check which hydra you refer to. I did code Vehelits and its neck system which allows neck pieces to follow the head but they don't move in sinusoid pattern.

Back to topic,
So when i move up/down then each line will be properly connected to each other and provide me with smoother shapes , maybe curves , not sure how it would look like.

That sounds like drawing curve using line pieces. If the pieces were dot shaped, the result could be smoother but you'd  have to spawn more of them.
The only idea I had ATM is to spawn the line and adjust its angle to match moving/sliding direction.
 
I found your code in contra mod, i was referring to metal snake entity built from multiple ones that follow the head but i think it wont work in this situation.
I want also be able to remove the traces after like 2 seconds, so they might need ID, also im not sure if you can drawsprite and assign it some ID to remove.
Or its just better to use entities , that would bump entitycound very fast, cause its 1 line per pixel and it would have to be like 200 lines each time snowman slides... would be crazy dumb actually to use entity to draw the traces.
 
i was referring to metal snake entity built from multiple ones that follow the head

Oh the QuetzalMetal. Simply put, it's a boss followed by cascading body pieces i.e piece 1 follows the head, piece 2 follows piece 2 and so on.

would be crazy dumb actually to use entity to draw the traces.

Well, if you're aiming for smooth curve then yes, you'd need tons of entities to draw the curve and that would be too much.
However, if you want simple curve for snow trail from sliding, you won't need that many entities. You can do as I have suggested above: spawn the line and adjust its angle to match moving/sliding direction.
Here's function to do that:
Code:
void spawnTrack(void Shot, float dx, float dy, float dz)
{ // Spawns track and angled it based on velocity
   void self = getlocalvar("self");
   int Vx = getentityproperty(self, "xdir");
   int Vz = getentityproperty(self, "zdir");
   void vShot = spawn01(Shot, dx, dy, dz);
   int Angle = antitang2(Vz, Vx);

   changedrawmethod(vShot, "reset", 1);
   changedrawmethod(vShot, "rotate", Angle);
}
void antitang2(float y, float x)
{// Calculating inverse tangent with atan + quadrant check
// For complex plane
  float Hasil; float c;

  c = 0.5*2/x; // redundant but necessary

  if(x==0 && y>0){
    Hasil = 90;
  } else if(x==0 && y<0){
    Hasil = -90;
  } else if(x==0 && y==0){
    Hasil = 0; // the result is supposed to be undefined
  } else if(x>0 && y>=0){ // 1st quadrant
    Hasil = atan(y*c);
  } else if(x>0 && y<0){ // 4th quadrant
    Hasil = atan(y*c) + 360;
  } else if(x<0){ // 2nd & 3rd quadrant
    Hasil = atan(y*c) + 180;
  }

  return Hasil;
}

I've tried this and the result is good enough  ;D.
Oh you'd need to set offset for track entity at left center instead of middle center for good result.

Usage example:
anim run
@script
  spawnTrack("Garis", 0, 0, 0);
@end_script
loop 1
...

Garis is just a line sprite whose offset is at left center.
 
There might be something to it, i modified my trace shape into C not tilted plane cause your code works better with it and angles arent so linear  i just have to borrow your rotation code to apply to each spawn i make , cause i have to adjust how often it spawns manyually.
Thanks a lot.
 
Bloodbane it works very nice but i have tried to add z offset so when character is on a  basemap then it rotates the images too,.
I know it has too many unpredictable variables but i have pretty much one type of basemap with one height so id like at least be able to adapt it to that one, but what can i do to make it do something? So far this is how i adapted your functions( adding "a" to antitang2 thats taken in follow1 anim  :
Code:
 anim	follow1
	loop	0
	@script
    void self = getlocalvar("self");
	int pindex 	= getentityproperty(self,"playerindex");
		void moveup 	=  playerkeys(pindex, 0, "moveup");
	void movedown 	=  playerkeys(pindex, 0, "movedown");
	int  iDirection = getentityproperty(self, "direction");
 int sx = getentityproperty(self,"x");
 int sz = getentityproperty(self,"z");
    int Vx = getentityproperty(self, "xdir");
   int Vz = getentityproperty(self, "zdir");
     int a = getentityproperty(self, "a");
 int sped = 6.4;
	void fX;
	void	step3;
	float x;
	float y;
    float x;
	float y;
	float Hasil;
	float c;
    c = 0.5*2/x;
   int Angle = antitang2(Vz, Vx);
	if (iDirection == 0){ //Is entity facing left?                  
    fX = -fX; //Reverse X direction to match facing.
	sped = -sped;
		
	}
		if (frame > 1 ){
	changeentityproperty(self, "velocity", sped, 0, 0);
	}
			if (frame > 5 && frame < 22 ){
		clearspawnentry();
	setspawnentry("name","step3");

	changeentityproperty(step3, "direction", fX );

   changedrawmethod(step3, "reset", 1);
   changedrawmethod(step3, "rotate", Angle);
    changeentityproperty(step3, "position", sx, sz, 0);
	step3	= spawn();
	}
	if (frame > 22){
	changeentityproperty(self, "velocity", 0, 0, 0);
	}
	if (moveup)
	{
	changeentityproperty(self, "velocity", NULL(),-2.0,NULL());
	}
	if (movedown)
	{
	changeentityproperty(self, "velocity", NULL(),2.0,NULL());
	}
	@end_script		
	offset	90 284
	bbox	47 113 82 172
	delay	4
	sound	data/sounds/jump.wav
	frame	data/chars/bouli/jump12.gif
	sound	data/sounds/throw.wav
	frame	data/chars/bouli/jump11.gif
	bbox	47 65 82 172
	offset	90 257
	frame	data/chars/bouli/jump10.gif
	bbox	47 109 82 126
	offset	94 232
	frame	data/chars/bouli/jump09.gif
	bbox	79 109 82 126
	offset	122 228
	frame	data/chars/bouli/FALL8.gif
	frame	data/chars/bouli/FALL7.gif
	frame	data/chars/bouli/FALL6.gif
	HITFX	data/sounds/beatg.wav
	attack	69 155 78 75 10 1 0 0 25 20
	dropv	5 3
	delay	4
	frame	data/chars/bouli/FALL5.gif
	offset	120 225
	frame	data/chars/bouli/FALL4.gif
	offset	123 221
	frame	data/chars/bouli/FALL3.gif
	offset	127 218
	frame	data/chars/bouli/FALL2.gif
	offset	129 217
	frame	data/chars/bouli/FALL1.gif
	offset	127 218
	frame	data/chars/bouli/FALL2.gif
	offset	123 221
	frame	data/chars/bouli/FALL3.gif
	offset	120 225
	frame	data/chars/bouli/FALL4.gif
	offset	122 228
	frame	data/chars/bouli/FALL5.gif
	ATTACK	0 0 0 0 0 0 0 0 0 0
	delay	4
	offset	125 225
	bbox	84 54 82 172
	frame	data/chars/bouli/FALL6.gif
	frame	data/chars/bouli/FALL7.gif
	frame	data/chars/bouli/FALL8.gif
	frame	data/chars/bouli/FALL9.gif 

And this is my animationscript whjere i tried to edit antitang2 function so when im on basemap it works properly too:
Code:
void spawnTrack(void Shot, float dx, float dy, float dz)
{ // Spawns track and angled it based on velocity
   void self = getlocalvar("self");
   int Vx = getentityproperty(self, "xdir");
   int Vz = getentityproperty(self, "zdir");
   void vShot = spawn01(Shot, dx, dy, dz);
   int Angle = antitang2(Vz, Vx);

   changedrawmethod(vShot, "reset", 1);
   changedrawmethod(vShot, "rotate", Angle);
}
void antitang2(float y, float x, float a)
{// Calculating inverse tangent with atan + quadrant check
// For complex plane
  float Hasil; float c;

  c = 0.5*2/x; // redundant but necessary

  if(x==0 && y>0 && a==0){
    Hasil = 90;
  } else if(x==0 && y<0 ){
    Hasil = -90;
  } else if(x==0 && y==0 && a==0){
    Hasil = 0; // the result is supposed to be undefined
  } else if(x>0 && y>=0 ){ // 1st quadrant
    Hasil = atan(y*c);
	  } else if(x>0 && a>=0 ){ // 1st quadrant
    Hasil = atan(a*c);
  } else if(x>0 && y<0){ // 4th quadrant
    Hasil = atan(y*c) + 360;
	  } else if(x>0 && a<0){ // 4th quadrant
    Hasil = atan(a*c) + 360;
  } else if(x<0){ // 2nd & 3rd quadrant
    Hasil = atan(y*c) + 180;
  }
  

  return Hasil;
}

void spawn01(void vName, float fX, float fY, float fZ)
{
	//spawn01 (Generic spawner)
	//Damon Vaughn Caskey
	//07/06/2007
	//
	//Spawns entity next to caller.
	//
	//vName: Model name of entity to be spawned in.
	//fX: X location adjustment.
	//fY: Y location adjustment.
      //fZ: Z location adjustment.

	void self = getlocalvar("self"); //Get calling entity.
	void vSpawn; //Spawn object.
	int  iDirection = getentityproperty(self, "direction");

	clearspawnentry(); //Clear current spawn entry.
      setspawnentry("name", vName); //Acquire spawn entity by name.

	if (iDirection == 0){ //Is entity facing left?                  
          fX = -fX; //Reverse X direction to match facing.
	}

      fX = fX + getentityproperty(self, "x"); //Get X location and add adjustment.
      fY = fY + getentityproperty(self, "a"); //Get Y location and add adjustment.
      fZ = fZ + getentityproperty(self, "z"); //Get Z location and add adjustment.
	
	vSpawn = spawn(); //Spawn in entity.

	changeentityproperty(vSpawn, "position", fX, fZ, fY); //Set spawn location.
	changeentityproperty(vSpawn, "direction", iDirection); //Set direction.
    
	return vSpawn; //Return spawn.
}

void spawner(void vName, float fX, float fY, float fZ,float fmap, void Ani )
{
	//spawn01 (Generic spawner)
	//Damon Vaughn Caskey
	//07/06/2007
	//
	//Spawns entity next to caller.
	//
	//vName: Model name of entity to be spawned in.
	//fX: X location adjustment.
	//fY: Y location adjustment.
      //fZ: Z location adjustment.

	void self = getlocalvar("self"); //Get calling entity.
	void vSpawn; //Spawn object.
	int  iDirection = getentityproperty(self, "direction");
	clearspawnentry(); //Clear current spawn entry.
      setspawnentry("name", vName); //Acquire spawn entity by name.

	if (iDirection == 0){ //Is entity facing left?                  
          fX = -fX; //Reverse X direction to match facing.
	}

      fX = fX + getentityproperty(self, "x"); //Get X location and add adjustment.
      fY = fY + getentityproperty(self, "a"); //Get Y location and add adjustment.
      fZ = fZ + getentityproperty(self, "z"); //Get Z location and add adjustment.
	
	vSpawn = spawn(); //Spawn in entity.

	changeentityproperty(vSpawn, "position", fX, fZ, fY); //Set spawn location.
	changeentityproperty(vSpawn, "direction", iDirection); //Set direction.
	changeentityproperty(vSpawn, "map", fmap); //Set map.   
     changeentityproperty(vSpawn, "animation", openborconstant(Ani)); //Change the animation
	return vSpawn; //Return spawn.
}

void vel( float Vx, float Vy, int Flip)
{// Dash with desired speed!
    void self = getlocalvar("self");
    int dir = getentityproperty(self,"direction");

    if(dir==0 && Flip==1){ // Facing left?
      Vx = -Vx ;
    }

    changeentityproperty(self, "velocity", Vx, 0, Vy); //Move!
}

void leap( float Vx, float Vy, int Flip)
{// Leap with desired speed!
    void self = getlocalvar("self");
    int dir = getentityproperty(self,"direction");

    if(dir==0 && Flip==1){ // Facing left?
      Vx = -Vx ;
    }

    tossentity(self, Vy, Vx); //Leap!
}

Basemap is this :
Code:
basemap 1747 850 500 1000 0 170
basemap 2247 850 500 1000 170 0
Im open to editing basemap of course just to make it look properly.
Entity that represents traces is type TRAP not NONE because NONE is not affected by basemap and is displayed where real ground is, way under character, so im not sure if i should leave it trap or none and change its altitude maybe and rotation by script functions.
I measured altitude on basemap and its 166 when im standing on it on top.
Heres visual on what it is :
bor---0057.gif
 
Back
Top Bottom