An ice piece of work...

Need help with using DizzyAGE then look here
macon
Hard Boiled Egg
Posts: 174
Joined: Mon Apr 30, 2007 1:08 pm
Location: Grimsby, England

Post by macon » Fri Nov 27, 2009 8:29 pm

Queex wrote:(In fact, switching over to custom movement all the time seems to simply double how fast Dizzy moves...)
That happened to me once. I was going to report it to Alex but was unable to replicate it.

Queex
Hard Boiled Egg
Posts: 124
Joined: Thu Oct 22, 2009 5:04 pm

Post by Queex » Fri Nov 27, 2009 8:44 pm

Ah, I got it. Need to set P_CUSTOMMOVE to 1.
- Lost Temple Dizzy -
- Iron Tower Dizzy -

delta
Hard Boiled Egg
Posts: 3965
Joined: Fri Feb 09, 2007 7:08 pm
Location: North West
Contact:

Post by delta » Fri Nov 27, 2009 9:04 pm

Queex wrote:Okay, I think I need help.

I need some way of detecting when Dizzy has just been falling sideways when he lands on ice, because by the time that HandlerPlayerUpdate() is called, he's already been set to idle and any previous directional information has been lost.
you could always define another player variable, something like P_PREVDIR, and set it each time P_DIR is changed, but don't reset it when P_DIR is reset, if you see what i mean. Then P_PREVDIR stays the same as the previous direction, 'remembering' it.
Image

Image

"Quotes from the internet may not be genuine" - Abraham Lincoln

Queex
Hard Boiled Egg
Posts: 124
Joined: Thu Oct 22, 2009 5:04 pm

Post by Queex » Fri Nov 27, 2009 9:55 pm

I think I've got it more-or-less how I want it.

I've drawn a slipping animation, with the index 24. So now I have, in addition to the small definition additions delta already had:

In def.gs:

Code: Select all

#def PTILE_SLIP 24
In handlers.gs:

Code: Select all

func HandlerPlayerUpdate()
{
	// println("HANDLER PLAYERUPDATE");
	
	// Player set costume
	costume = 0;
	if(ID_SCUBA!=-1) costume = InventoryHasItem(ID_SCUBA) ? 30 : 0;
	//PlayerSet(P_COSTUME,costume);

	// Check Player Wind
	windinside = IsMaterialInsidePlayer(MAT_WIND);
	windunder = IsMaterialUnderPlayer(MAT_WIND);
	if( windinside || windunder )
	{
		extra = (windinside)?gs_rand(WINDPOW):0;
		power = WINDPOW-gs_rand(WINDPOW*2+1)+extra;
		PlayerSet(P_Y, PlayerGet(P_Y)-power);
	}
	
	// Check clouds
	if(IsMaterialUnderPlayer(MAT_CLOUD))
	{
		PlayerSet(P_Y, PlayerGet(P_Y)+1);
	}
	
[color="Red"]	// Check Ice
	if(!(IsMaterialUnderPlayer(MAT_BLOCK) || IsMaterialUnderPlayer(MAT_CLIMB))){
    if(IsMaterialUnderPlayer(MAT_ICE) && !InventoryHasItem(ID_CRAMPON)){
      GameSet(G_ICEWALK,1); //when stood directly on ice
    }
	}
	if(PlayerGet(P_STATUS)==STATUS_FALL && !InventoryHasItem(ID_CRAMPON)){
    GameSet(G_ICEWALK,1); //when falling
  }[/color]
	
	// Check WaterPlay
	if( SUPPORT_WATERPLAY ) 
		PlayerUpdateWaterPlay();
	
	// Check Player damage
	if(IsMaterialInsidePlayer(MAT_KILL)) 
	{
		if(PlayerGet(P_LIFE)>0)
		{
			PlayerSet(P_LIFE,0);
			PlayerSet(P_DEATH,0); // set cause of death if needed
		}
	}
	else
	if(IsMaterialInsidePlayer(MAT_HURT)) 
	{
		if(PlayerGet(P_LIFE)>0)
		{
			PlayerHurt(DIZ_HURT);
			if(PlayerGet(P_LIFE)==0)
				PlayerSet(P_DEATH,0); // set cause of death if needed
		}
	}

	// Check Player must die
	if(PlayerGet(P_LIFE)<0) PlayerSet(P_LIFE,0);

	if(PlayerGet(P_LIFE)<=0 && PlayerGet(P_STATUS)!=STATUS_SCRIPTED)
		if( (PlayerGet(P_MATCENTER)==MAT_WATER) || PlayerGet(P_STATUS)==STATUS_IDLE ) // only if in water or in idle
		{
			if(PlayerGet(P_MATCENTER)==MAT_WATER)
				ScrRequest( gs_fid("PlayerPlayDeadWater") );
			else
				ScrRequest( gs_fid("PlayerPlayDead") );
		}
		
	// Check Respawn Position
	status = PlayerGet(P_STATUS);
	if( ( status==STATUS_IDLE || status==STATUS_WALK ) && 
		IsPlayerSafe() && IsPlayerStable() && 
		PlayerGet(P_SAFE) &&
		PlayerGet(P_LIFE)>0 )
	{
		// remember relevant info to use in case of a respawn event
		PlayerSet(P_XSAFE,PlayerGet(P_ X) );
		PlayerSet(P_YSAFE,PlayerGet(P_Y));
		MusicStore();
	}
	
	// Custom movement test
	[color="Red"]if(GameGet(G_ICEWALK)==1) {
    PlayerSet(P_CUSTOMMOVE,1);
    CM_Update();
  } else {
    PlayerSet(P_CUSTOMMOVE,0);
  }[/color]
}
In movement.gs:

Code: Select all

func CM_Update()
{
	status = PlayerGet(P_STATUS);
	
	// input status
	if( status==STATUS_IDLE || status==STATUS_WALK [color="Red"]|| status==STATUS_ICE[/color])
	{
		CM_EnterKeyState();
		status = PlayerGet(P_STATUS); // re-read status
	}
	
	if( status==STATUS_IDLE )
		CM_UpdateIdle();
	else
	if( status==STATUS_WALK )
		CM_UpdateWalk();
	else
	[color="Red"]if( status==STATUS_ICE )
		CM_UpdateIce();
	else[/color]
	if( status==STATUS_JUMP )
		CM_UpdateJump();
	else
	if( status==STATUS_FALL )
		CM_UpdateFall();
	else
	if( status==STATUS_SCRIPTED )
		CM_UpdateScripted();
	
	if( PlayerGet(P_STATUS)!=STATUS_SCRIPTED )
	{
		snap = CM_CheckCollidersSnap();
		status = PlayerGet(P_STATUS);

		// stand check only if not already snapped to collider
		if( !snap && (status==STATUS_IDLE || status==STATUS_WALK) )
		{
			h = CM_CheckFallY(1); // see if it can fall 
			if(h>0) // if any space below then enter in fall
			{
				CM_EnterFall();
				PlayerSet(P_Y,PlayerGet(P_Y)+1); 
				PlayerSet(P_POW,PlayerGet(P_POW)+1); // force one step down (DIZZYMATCH)
			}
		}
		
		// fix collision by rising dizzy
		CM_CheckCollision();
	}
}
and

Code: Select all

func CM_UpdateFall()
{
	if( CM_CheckFallX() )
		PlayerSet(P_X, PlayerGet(P_ X) + PlayerGet(P_DIR)*CM_STEP X) ;

	pow = PlayerGet(P_POW);
	step = MIN(pow,CM_STEPYMA X) ;
	step2 = CM_CheckFallY(step);
	PlayerSet(P_Y, PlayerGet(P_Y)+step2);

	PlayerSet(P_FRAME, PlayerGet(P_FRAME)+1); // keep last tile
	PlayerSet(P_STUNLEVEL, PlayerGet(P_STUNLEVEL)+1);

	// stopping fall if fall step was reduced
	if(step2<step)
	{
		// check for jumpers
		mat = CM_CheckJumper();
		if( mat>=0 ) {// it's a jumper!
			CM_EnterJumper( mat );
		[color="Red"]} else if(CM_CheckOnlyIceUnderneath()>=0 && !InventoryHasItem(ID_CRAMPON)){
      CM_EnterIce(PlayerGet(P_DIR));[/color]
    } else {
        GameSet(G_ICEWALK,0);
			CM_EnterRoll();
	  }
	}
	else
	{
		pow++;
		PlayerSet(P_POW,pow);
	}
}
and the new functions:

Code: Select all

func CM_EnterIce( dir )
{
	PlayerSet(P_STATUS, STATUS_ICE); 
	PlayerSet(P_DIR, dir);
	PlayerSet(P_POW, 0);
	PlayerSet(P_FLIP, (PlayerGet(P_FLIP) & FLIPY) | (dir==-1));

  if(dir==0){
    tile = PlayerGet(P_COSTUME)+PlayerGet(P_TILEIDLE);
  } else {
    tile = PTILE_SLIP;
  }
	if( PlayerGet(P_TILE)!=tile )
	{
		PlayerSet(P_FRAME, 0);
		PlayerSet(P_TILE, tile);
	}
}

Code: Select all

func CM_UpdateIce()
{
  if(IsMaterialUnderPlayer(MAT_BLOCK) || IsMaterialUnderPlayer(MAT_CLIMB)){
    GameSet(G_ICEWALK,0);
    PlayerSet(P_STATUS,STATUS_IDLE);//to avoid locking out input
    //pull next state from key commands.
    CM_EnterKeyState();
  } else if(!IsMaterialUnderPlayer(MAT_ICE)){
    PlayerEnterFall();
  } else {
    if( CM_CheckWalkX() )
      PlayerSet(P_X, PlayerGet(P_ X) + PlayerGet(P_DIR)*CM_STEP X) ;
    PlayerSet(P_FRAME,PlayerGet(P_FRAME)+1);
  }
}

Code: Select all

func CM_CheckOnlyIceUnderneath()
{
  x1=0;y1=0;x2=0;y2=0;
	PlayerMakeBB(&x1,&y1,&x2,&y2);
	materials = MaterialRead(x1,y2,x2,y2+1); // read materials under the player

	// check all jump materials bits and return the material if found or -1 if no jumper
	// add more if your game has more jumping materials ...
	if( materials & (1<<MAT_BLOCK) || materials & (1<<MAT_CLIMB)){
    return -1;
	} else if( materials & (1<<MAT_ICE) ){
    return MAT_ICE;
  } else {
    return -1; // should not reach this, actually, but never mind...
  }
}
- Lost Temple Dizzy -
- Iron Tower Dizzy -

Queex
Hard Boiled Egg
Posts: 124
Joined: Thu Oct 22, 2009 5:04 pm

Post by Queex » Sat Nov 28, 2009 1:50 pm

I thought I had it cracked, but Dizzy still doesn't slip if he falls onto ice.

What's bizarre is that looking into it deeper I find that MaterialRead is returning 1153 for Dizzy's bounding box and the line underneath it. Breaking it down-

1 air
128 block
1024 ice

Which is maddening as there is clearly no block material anywhere near him. Why is this internal function returning a material that isn't inside the area specified?
- Lost Temple Dizzy -
- Iron Tower Dizzy -

Post Reply