YolkfolkThe Dizzy Fansite 0 logged in0 playing
Community discussion

Climb ladder up and down

Started by Marcell Fischer on 28 April 2020 • 2,704 views

8 posts
#55798

Hello and good evening.

Thank you Grandad for your quick reply. {yolkfolk}:cheers:

I followed your instructions and unfortunately I always get an error message after I "stick" to the ladder. - I tried it for hours and almost played your tricky game "Hush". I like your crazy stories in your games. I also think it's good that your game codes are publicly unpacked without a password.

Since the ladder problem is still around, I looked for it in other games and found it at Jamie's "PirateShipDizzy". Here is exactly what I'm looking for. Easy climbing up and down as soon as I stand on any ladder.

And what shall I tell you, it just doesn't work in my version. Whenever I'm at the ladder, Dizzy just does a somersault. At some point I noticed that there is no "jumping" in Jamie's game. In his game means jumping = climbing. And that's probably the reason why it doesn't work for me, isn`t it?!?! {yolkfolk}:scratch:

How can I avoid that?

Stay healthy

Kalle

👍 0
#88074

Too much lockdown for me - sorry Kalle, you also need to copy the movement2 file into your new game as that deals with the movement of going up and down a ladder.

Some of my later games are password protected. Mainly ones that have extra 'Easter Egg' areas.

PS - I've also found some of Jamie's coding far too complicated without his help {yolkfolk}:scratch:

👍 0
#88077

Hello everybody,

I know exactly what you mean. The current restrictions are driving you crazy. That's why I try to distract myself with my little, perfect game world.
Hold on, Grandad. {yolkfolk}:cheers:

I have made little progress on climbing. Climbing up and down ladders works. Unfortunately I can no longer jump and Dizzy does not break out of climbing mode. (see image)

I have currently added the following lines of code to the standard code.

def.gs

#def PTILE_CLIMB 25 // available

#def MAT_CLIMBER 10 // climbing material (void)
#def MAT_CLIMBSTOP 11 // top climbing stop material (void)

gamedef.gs

#def STATUS_CLIMB 98 // set status for Dizzy Climb movement
#def STATUS_CLIMBIDLE 99 // set status for Dizzy Climb Idle movement

#def P_DIRY 64 // used in climbing mode. -1=up, 1=down

 handlers.gs

MaterialSetColor( MAT_CLIMBER, 0xFFC8C800 );
MaterialSetColor( MAT_CLIMBSTOP, 0xFFC8C800 );

func HandlerGameUpdate()

if( SUPPORT_JUMPUP&&!IsMaterialInsidePlayer(MAT_CLIMBER) )
UseUpForJump();

 movement.gs (entire file)

/////////////////////////////////////////////////////////////////////////////////
// movement.gs
// Custom player movement
/////////////////////////////////////////////////////////////////////////////////

#def CM_STEPX 4 // move step x
#def CM_STEPY 4 // move step y; used in adjustments
#def CM_STEPYMAX 7 // move step y; used in jumps and falls
#def CM_BOXW 16 // collision box width
#def CM_BOXH 20 // collision box height

func MIN(a,b) { return (a<b)?a:b; } ///////////////////////////////////////////////////////////////////////////////// // Custom Move - main update function ///////////////////////////////////////////////////////////////////////////////// func CM_Update() { status = PlayerGet(P_STATUS); // input status if( status==STATUS_IDLE || status==STATUS_WALK || status==STATUS_CLIMB || status==STATUS_CLIMBIDLE ) { CM_EnterKeyState(); status = PlayerGet(P_STATUS); // re-read status } if( status==STATUS_IDLE ) CM_UpdateIdle(); else if( status==STATUS_WALK ) CM_UpdateWalk(); else if( status==STATUS_CLIMB ) CM_UpdateClimb(); 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
{
if(IsMaterialInsidePlayer(MAT_CLIMBER)&&!IsMaterialInsidePlayer(MAT_CLIMBSTOP))
{
CM_EnterClimbIdle();
}
else
if(status==STATUS_IDLE&&IsMaterialInsidePlayer(MAT_CLIMBSTOP))
{
CM_EnterIdle();
}
else
if(!IsMaterialInsidePlayer(MAT_CLIMBSTOP))
{
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();
}
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// ENTER STATES
//////////////////////////////////////////////////////////////////////////////////////////////////

func CM_EnterIdle()
{
PlayerSet(P_STATUS, STATUS_IDLE);
PlayerSet(P_DIR, 0);
PlayerSet(P_POW, 0);
PlayerSet(P_FLIP, PlayerGet(P_FLIP) & FLIPY);

tile = PlayerGet(P_COSTUME)+PlayerGet(P_TILEIDLE)+PlayerGet(P_EMOTION);
if( PlayerGet(P_TILE)!=tile )
{
PlayerSet(P_FRAME, 0);
PlayerSet(P_TILE, tile);
}
}
func CM_EnterClimb( diry )
{
PlayerSet(P_STATUS, STATUS_CLIMB);
PlayerSet(P_DIRY, diry);
PlayerSet(P_POW, 0);
PlayerSet(P_TILEWALK, PTILE_CLIMB);

tile = PlayerGet(P_COSTUME)+PlayerGet(P_TILEWALK);
if( PlayerGet(P_TILE)!=tile )
{
PlayerSet(P_FRAME, 0);
PlayerSet(P_TILE, tile);
}
}
func CM_EnterClimbIdle()
{
PlayerSet(P_STATUS, STATUS_CLIMBIDLE);
PlayerSet(P_DIRY, 0);
PlayerSet(P_POW, 0);
PlayerSet(P_TILEWALK, PTILE_CLIMB);

tile = PlayerGet(P_COSTUME)+PlayerGet(P_TILEWALK);
if( PlayerGet(P_TILE)!=tile )
{
PlayerSet(P_FRAME, 0);
PlayerSet(P_TILE, tile);
}
}
func CM_EnterWalk( dir )
{
PlayerSet(P_STATUS, STATUS_WALK);
PlayerSet(P_DIR, dir);
PlayerSet(P_POW, 0);
PlayerSet(P_TILEWALK, PTILE_WALK);
PlayerSet(P_FLIP, (PlayerGet(P_FLIP) & FLIPY) | (dir==-1));

tile = PlayerGet(P_COSTUME)+PlayerGet(P_TILEWALK);
if( PlayerGet(P_TILE)!=tile )
{
PlayerSet(P_FRAME, 0);
PlayerSet(P_TILE, tile);
}
}

func CM_EnterFall()
{
PlayerSet(P_STATUS, STATUS_FALL);
PlayerSet(P_POW, 1);
}

func CM_EnterRoll()
{
PlayerSet(P_POW,1); // cut fall power to roll on ground

tile = PlayerGet(P_TILE);
costume = PlayerGet(P_COSTUME);
if( tile==costume+PlayerGet(P_TILEUP) || tile==costume+PlayerGet(P_TILEJUMP) ) // only when jumping
{
tileframes = TileGet(TileFind(tile),TILE_FRAMES);
frame = CM_ComputeFrame( PlayerGet(P_FRAME), tileframes, PlayerGet(P_ANIM) );
//if( frame < tile->m_frames-1 ) return; // don't enter idle unless last frame reached; untill then stay in roll
if( frame != 0 ) return; // don't enter idle unless last frame reached; untill then stay in roll
}

CM_EnterKeyState(); // be sure to stop the fall, just in case the fall handler doesn't

HandlerFall();

PlayerSet(P_STUNLEVEL,0); // clear stun level
}

func CM_EnterKeyState()
{
if( PlayerGet(P_LIFE)<=0 ) { CM_EnterIdle(); return; } // prepare to die dir = 0; diry = 0; if( GetKey(KEY_RIGHT) ) dir++; if( GetKey(KEY_LEFT) ) dir--; if( GetKey(KEY_UP) ) diry--; if( GetKey(KEY_DOWN) ) diry++; // walk while at bottom of ladder or on ground if(dir!=0&&CM_CheckFallY(1)==0) { CM_EnterWalk(dir); } else // walk while at top of ladder if(dir!=0&&IsMaterialInsidePlayer(MAT_CLIMBSTOP)) { CM_EnterWalk(dir); } else // walk anywhere else if(dir!=0&&!IsMaterialInsidePlayer(MAT_CLIMBER)) { CM_EnterWalk(dir); } else // climb down when above ground if(diry==1&&IsMaterialInsidePlayer(MAT_CLIMBER)&&CM_CheckFallY(1)==1) { CM_EnterClimb(diry); } else // climb up when above ground (but not at top) if(diry==-1&&IsMaterialInsidePlayer(MAT_CLIMBER) &&!IsMaterialInsidePlayer(MAT_CLIMBSTOP)&&CM_CheckClimb()==1) { CM_EnterClimb(diry); } else // idle while on ladder if(diry==0&&IsMaterialInsidePlayer(MAT_CLIMBER) &&!IsMaterialInsidePlayer(MAT_CLIMBSTOP)&&CM_CheckFallY(1)!=0) { CM_EnterClimbIdle(); } // idle while at top of ladder else if(diry==0&&IsMaterialInsidePlayer(MAT_CLIMBSTOP)) { CM_EnterIdle(); } // idle while at bottom of ladder or anywhere else else { CM_EnterIdle(); } } ///////////////////////////////////////////////////////////////////////////////// // UPDATE STATES ///////////////////////////////////////////////////////////////////////////////// func CM_UpdateIdle() { if( CM_CheckLift()==1 ) // move on lifts { PlayerSet(P_X, PlayerGet(P_X) + 1*CM_STEPX); } if( CM_CheckLift()==-1 ) // move on lifts { PlayerSet(P_X, PlayerGet(P_X) + -1*CM_STEPX); } PlayerSet(P_FRAME,PlayerGet(P_FRAME)+1); } func CM_UpdateWalk() { if( CM_CheckLift()==1 ) // move on lifts { PlayerSet(P_X, PlayerGet(P_X) + 1*CM_STEPX); } if( CM_CheckLift()==-1 ) // move on lifts { PlayerSet(P_X, PlayerGet(P_X) + -1*CM_STEPX); } dir = PlayerGet(P_DIR); if( CM_CheckWalkX()&&CM_CheckDoor(dir)==-1 ) { PlayerSet(P_X, PlayerGet(P_X) + PlayerGet(P_DIR)*CM_STEPX); } if( CM_CheckDoor(dir)!=-1 ) { Update_Door(); } PlayerSet(P_FRAME,PlayerGet(P_FRAME)+1); } func CM_UpdateClimb() { diry = PlayerGet(P_DIRY); if( diry==1||(diry==-1&&CM_CheckJumpY(CM_STEPY)==4&&!IsMaterialInsidePlayer(MAT_CLIMBSTOP)) ) PlayerSet(P_Y, PlayerGet(P_Y) + PlayerGet(P_DIRY)*CM_STEPX); PlayerSet(P_FRAME,PlayerGet(P_FRAME)+1); } func CM_UpdateFall() { pow = PlayerGet(P_POW); step = MIN(pow,CM_STEPYMAX); step2 = CM_CheckFallY(step); if(step2>3)
{
PlayerSet(P_DEATH,2);
PlayerSet(P_LIFE,0);
PlayerSet(P_TILE, PTILE_FALL);
Disable_Lifts(); // disable all 'hard collision'
}
else
{
PlayerSet(P_TILE, PTILE_IDLE);
}

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 );
else
CM_EnterRoll();
}
else
{
pow++;
PlayerSet(P_POW,pow);
}
}

func CM_UpdateScripted()
{
if(PlayerGet(P_ANIM)!=0)
PlayerSet(P_FRAME, PlayerGet(P_FRAME)+1);
}

/////////////////////////////////////////////////////////////////////////////////
// CHECKS
/////////////////////////////////////////////////////////////////////////////////

// check side, only above 8 bottom pixels. if bottom is blocked it will step-up on it
func CM_CheckWalkX()
{
x1=0;y1=0;x2=0;y2=0;
PlayerMakeBB(&x1,&y1,&x2,&y2);
dir = PlayerGet(P_DIR);
if(dir==1)
return MaterialCheckFree( x2,y1,x2+CM_STEPX,y2-4 );
else
if(dir==-1)
return MaterialCheckFree( x1-CM_STEPX,y1,x1,y2-4 );
else
return false;
}

func CM_CheckDoor(dir)
{
//find player position
px = PlayerGet(P_X);
py = PlayerGet(P_Y);

if(dir==-1)
{
//set box corner coords
boxx = px-12;
boxy = py-14;
boxx2 = px-10;
boxy2 = py;
}
if(dir==1)
{
//set box corner coords
boxx = px+10;
boxy = py-14;
boxx2 = px+12;
boxy2 = py;
}

pcount = ObjPresentCount();
for(pidx=0;pidx<=pcount-1;pidx++) // iterate present objects { idx = ObjPresentIdx(pidx); // object index if(ObjGet(idx,O_DISABLE)==0) // check if disabled { dx = ObjGet(idx,O_X); dy = ObjGet(idx,O_Y); dx2 = dx+ObjGet(idx,O_W); dy2 = dy+ObjGet(idx,O_H); if((boxx>=dx&&boxx2<=dx2)&&(boxy>=dy&&boxy2<=dy2)) { if(ObjGet(idx,O_CLASS)==9) // check if a door { GameSet(G_CURRDOOR,idx); return idx; } } } } GameSet(G_CURRDOOR,-1); return -1; } func CM_CheckLift() { //find player position px = PlayerGet(P_X); py = PlayerGet(P_Y); //set box corner coords boxx = px-2; boxy = py+10; boxx2 = px+2; boxy2 = py+14; pcount = ObjPresentCount(); for(pidx=0;pidx<=pcount-1;pidx++) // iterate present objects { idx = ObjPresentIdx(pidx); // object index if(ObjGet(idx,O_DISABLE)==0) // check if disabled { dx = ObjGet(idx,O_X); dy = ObjGet(idx,O_Y); dx2 = dx+ObjGet(idx,O_W); dy2 = dy+ObjGet(idx,O_H); if((boxx2>=dx&&boxx<=dx2)&&(boxy>=dy&&boxy2<=dy2)) { if(ObjGet(idx,O_CLASS)==11&&ObjGet(idx,O_LIFTDIR)==0) // check if a horizontal lift { if(ObjGet(idx,O_STATUS)==0) dir=-1; if(ObjGet(idx,O_STATUS)==1) dir=1; if(CM_CheckDoor(dir)==-1) return dir; } } } } return 0; } func CM_CheckClimb() { //find player position px = PlayerGet(P_X) - GameGet(G_ROOMX)*GameGet(G_ROOMW); py = PlayerGet(P_Y) - GameGet(G_ROOMY)*GameGet(G_ROOMH); //set box corner coords boxx = px-8; boxy = py-14; boxa = MaterialRead(boxx,boxy,2,16); //set box corner coords boxx = px+6; boxy = py-14; boxb = MaterialRead(boxx,boxy,2,16); if((boxa==1024&&boxb==1024) ||(boxa==1025&&boxb==1025) ||(boxa==3072&&boxb==3072)) return 1; else return 0; } func CM_CheckJumpX() { x1=0;y1=0;x2=0;y2=0; PlayerMakeBB(&x1,&y1,&x2,&y2); dir = PlayerGet(P_DIR); if(dir==1) return MaterialCheckFree( x2,y1,x2+CM_STEPX,y2-8 ); else if(dir==-1) return MaterialCheckFree( x1-CM_STEPX,y1,x1,y2-8 ); else return false; } // check material above the box and see how far can it go func CM_CheckJumpY( step ) { x1=0;y1=0;x2=0;y2=0; PlayerMakeBB(&x1,&y1,&x2,&y2); return MaterialGetFreeDist(x1,y1-step,x2,y1,1,1); // bottom to top } func CM_CheckFallX() { x1=0;y1=0;x2=0;y2=0; PlayerMakeBB(&x1,&y1,&x2,&y2); dir = PlayerGet(P_DIR); if(dir==1) return MaterialCheckFree( x2,y1,x2+CM_STEPX,y2-8 ); else if(dir==-1) return MaterialCheckFree( x1-CM_STEPX,y1,x1,y2-8 ); else return false; } // check material under the box and see how far can it go func CM_CheckFallY( step ) { x1=0;y1=0;x2=0;y2=0; PlayerMakeBB(&x1,&y1,&x2,&y2); return MaterialGetFreeDist(x1,y2,x2,y2+step,0,0); // top to bottom } // collision inside box bottom will rise dizzy up with maximum CM_STEPY func CM_CheckCollision() { x1=0;y1=0;x2=0;y2=0; PlayerMakeBB(&x1,&y1,&x2,&y2); step = MaterialGetFreeDist(x1,y2-CM_STEPY,x2,y2,0,1); // top to bottom if(step<CM_STEPY) // has some block PlayerSet(P_Y,PlayerGet(P_Y)-(CM_STEPY-step)); // rise up } // return material if jumper or -1 if not func CM_CheckJumper() { 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_JUMPFIX) ) return MAT_JUMPFIX; else if( materials & (1<<MAT_JUMPPRO) ) return MAT_JUMPPRO; else return -1; // no jumpers } func CM_CheckCollidersSnap() { snap = 0; x1=0;y1=0;x2=0;y2=0; PlayerMakeBBW(&x1,&y1,&x2,&y2); // bound in world // test snap up - get max colliders distance inside player's bound dist = ColliderSnapDistance(x1,y1,x2,y2); if(dist>0) // got collision
{
step = MIN(dist,CM_STEPY);
PlayerSet(P_Y, PlayerGet(P_Y)-step);
snap=1; // snap up
}
else
{
// test snap down - get min colliders distance below player's bound
dist = ColliderSnapDistance(x1,y2,x2,y2+CM_STEPY+1); // max
step = CM_STEPY+1-dist; // min
if(step<=CM_STEPY) // got collision under { PlayerSet(P_Y, PlayerGet(P_Y)+step); snap=1; // snap down } } if( snap && PlayerGet(P_STATUS)==STATUS_FALL ) // stop falls CM_EnterRoll(); return snap; } ///////////////////////////////////////////////////////////////////////////////// // return clamped and animated frame func CM_ComputeFrame( frame, framecount, anim ) { if( anim==1 ) // play { if( frame>framecount-1 )
frame=framecount-1;
else
if( frame<0 ) frame=0; } else if( anim==2 ) // loopl { if( framecount>0 )
frame = frame % framecount;
else
frame = 0;
}
return frame;
}

/////////////////////////////////////////////////////////////////////////////////

 It looks like this in the editor

Perhaps this is the right head nut for you, Noggin the Nog,
and I would be happy if you could free the poor guy from climbing and let him jump again. {yolkfolk}:redfaced:

Kind Regards
Kalle

👍 0
#88078
My bad Kalle, I forgot about one tiny little thing, which I also forgot to put in my notes. Forget all those extra defines.

All you need is:
the func LadderCollide() (either in the game.gs or util.gs files),
the Movement2.gs file copied into the new game (and the title added to the list of included files in dizzy.gs).
...and the following added to the end of the def.gs file (after the player variables section)

int laddbott
int laddtop
int ladddx

Now the CollideObject functions used to make Dizzy climb (and walk or jump off the ladder, rope etc) should work properly
👍 0
#88081

Hello and good day Grandad,

I followed your instructions for hours and I finally managed to get the little guy to climb.

The following additional lines of code brought the long-awaited success.

// Custom movement test
custommove = PlayerGet (P_CUSTOMMOVE);
if (custommove == 0) //engine default
{
PlayerSet(P_W, CM_BOXW);
PlayerSet(P_H, CM_BOXH);
}

else
if (custommove == 1) //activate climbing code
{
CM2_Update();
}
else
if (custommove == 2) // activate running code
{
CM_Update();
}
}

 I still have 2 questions.

1. Once at the top of the ladder, Dizzy doesn't go down. It "sticks" to the top of the ladder, but then it just falls off. Is that correct?
2. Would Dizzy climb the ladder without "sticking"? If so, which lines of code do I have to remove?

Thanks again for your help and we hear each other.

Best Regards

Kalle

👍 0
#88082
Oops! Sorry, I thought that I only added the extra coding when I included 'running' in the coding which is another custom movement.

The normal problems with how Dizzy reacts at the top or bottom of the 'collide' function are normally sorted by adjusting the top and bottom y co-ordinates. I usually save the game just before attempting to climb the ladder and then change the laddtop or laddbott numbers either by adding or subtracting, then reloading the game and trying again. Don't forget that the engine uses the 'middle' of the tile so you have to add '12' to the starting or end 'y' position, same as when you move Dizzy through a doorway or cave using the PlayerSet command so that he appears on the ground.

I usually start with 8 pixels then 'fine tune' as necessary. You won't get error messages when reloading the game as that only happens if you've altered the map or changed any of the properties of a brush on the map.
👍 0
#88083

Hello and good evening Grandad,

Many thanks for your time and patience for me. {yolkfolk}:cheers:
I'll try it out in a quiet minute. It is good to know that optimal climbing can work.
Now I will continue to deal with the map.

Best Regards

Kalle

👍 0
#89290

[quote data-userid="279" data-postid="88074"]

Too much lockdown for me – sorry Kalle, you also need to copy the movement2 file into your new game as that deals with the movement of going up and down a ladder.

Some of my later games are password protected. Mainly ones that have extra ‘Easter Egg’ areas.

PS – I’ve also found some of Jamie’s coding far too complicated without his help {yolkfolk}:scratch:  

[/quote]

For Pirate Ship Dizzy, I rewrote a lot of the code and stripped out literally everything I didn't need. The idea was that I could make levels in the editor and not have to worry about coding anything in them - object properties would sort absolutely everything. From pirates only going to the edge of platforms to keys opening the correct doors, the lot. It's all coded just once :smile:

I do recall I did some climbing code in Mystic Forest Dizzy, but I'm damned if I remember how I did it! 'tis a long time ago now! {yolkfolk}:joy:

👍 0