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