diff --git a/source/level/layercollision.cpp b/source/level/layercollision.cpp index 41761fbc0..2b61cc48c 100644 --- a/source/level/layercollision.cpp +++ b/source/level/layercollision.cpp @@ -273,6 +273,72 @@ int CLayerCollision::getHeightFromGroundNonSB(int _x,int _y,int _maxHeight) return distanceFromGround; } +/*****************************************************************************/ +int CLayerCollision::getHeightFromGroundCart(int _x,int _y,int _maxHeight) +{ + int mapX,mapY,xFraction,yFraction; + int distanceFromGround; + int colHeight; + int maxHeightToCheck; + + mapX=_x>>4; + mapY=(_y>>4)*MapWidth; + xFraction=_x&0x0f; + yFraction=16-(_y&0x0f); + distanceFromGround=0; + + colHeight=s_collisionTable[((Map[mapX+mapY]&COLLISION_TILE_MASK)*16)+xFraction]; + if ( (Map[mapX+mapY] & COLLISION_TYPE_MASK) == COLLISION_TYPE_FLAG_DAMAGE ) + { + colHeight = 0; + } + if(colHeight) + { + // Inside a collision block.. find the nearest ground above this point + maxHeightToCheck=-_maxHeight-16; // Need to check one block more incase we cross onto a new block + while(colHeight==16) + { + mapY-=MapWidth; + distanceFromGround-=16; + if(distanceFromGround<=maxHeightToCheck) + { + return -_maxHeight; + } + colHeight=s_collisionTable[((Map[mapX+mapY]&COLLISION_TILE_MASK)*16)+xFraction]; + if ( (Map[mapX+mapY] & COLLISION_TYPE_MASK) == COLLISION_TYPE_FLAG_DAMAGE ) + { + colHeight = 0; + } + } + distanceFromGround+=yFraction-colHeight; + if(distanceFromGround<-_maxHeight)distanceFromGround=-_maxHeight; + + } + else + { + // Not inside a collision block.. find the nearest ground below this point + maxHeightToCheck=_maxHeight+16; // Need to check one block more incase we cross onto a new block + while(colHeight==0) + { + mapY+=MapWidth; + distanceFromGround+=16; + if(distanceFromGround>=maxHeightToCheck) + { + return _maxHeight; + } + colHeight=s_collisionTable[((Map[mapX+mapY]&COLLISION_TILE_MASK)*16)+xFraction]; + if ( (Map[mapX+mapY] & COLLISION_TYPE_MASK) == COLLISION_TYPE_FLAG_DAMAGE ) + { + colHeight = 0; + } + } + distanceFromGround+=yFraction-colHeight; + if(distanceFromGround>_maxHeight)distanceFromGround=_maxHeight; + } + + return distanceFromGround; +} + /*****************************************************************************/ #ifdef __SHOW_COLLISION__ #include "gfx\prim.h" diff --git a/source/level/layercollision.h b/source/level/layercollision.h index de9138d1a..51002cd0d 100644 --- a/source/level/layercollision.h +++ b/source/level/layercollision.h @@ -25,6 +25,7 @@ virtual void shutdown(); u8 Get(int X,int Y) {return(Map[X+(Y*MapWidth)]&COLLISION_TILE_MASK);} int getHeightFromGround(int _x,int _y,int _maxHeight=32); int getHeightFromGroundNonSB(int _x,int _y,int _maxHeight=32); + int getHeightFromGroundCart(int _x,int _y,int _maxHeight=32); int getCollisionBlock(int _x,int _y) {return Map[(_x>>4)+((_y>>4)*MapWidth)];} u8 *getMapPtr(int _x,int _y) {return(&Map[(_x>>4)+((_y>>4)*MapWidth)]);} diff --git a/source/platform/pcart.cpp b/source/platform/pcart.cpp index 0d7c6be08..c9ec3ece6 100644 --- a/source/platform/pcart.cpp +++ b/source/platform/pcart.cpp @@ -45,6 +45,8 @@ void CNpcCartPlatform::postInit() calculateNonRotatedCollisionData(); m_playerAttached = false; + m_rebound = false; + m_reboundTimer = 0; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -60,6 +62,11 @@ void CNpcCartPlatform::processMovement( int _frames ) bool pathComplete; + if ( m_reboundTimer > 0 ) + { + m_reboundTimer -= _frames; + } + if ( !m_playerAttached ) { m_playerAttached = true; @@ -76,20 +83,10 @@ void CNpcCartPlatform::processMovement( int _frames ) if ( m_isActivated ) { - m_npcPath.thinkFlat( Pos, &pathComplete, &distX, &distY, &heading ); - - if ( !pathComplete ) + if ( m_rebound ) { - moveX = ( m_carSpeed >> 8 ) * _frames; + moveX = -4 * _frames; - if ( heading == 2048 ) - { - moveX = -moveX; - } - } - - if ( m_inJump ) - { m_vertSpeed += 192; if ( m_vertSpeed > ( 5 << 8 ) ) @@ -103,60 +100,103 @@ void CNpcCartPlatform::processMovement( int _frames ) moveY = ( m_vertSpeed >> 8 ) * _frames; - groundHeight = CGameScene::getCollision()->getHeightFromGround( Pos.vx + moveX, Pos.vy + moveY, 16 ); + groundHeight = CGameScene::getCollision()->getHeightFromGroundCart( Pos.vx + moveX, Pos.vy + moveY, 16 ); if ( groundHeight < 0 ) { // have touched down - m_inJump = false; + m_rebound = false; moveY += groundHeight; } + + Pos.vx += moveX; + Pos.vy += moveY; } else { - // check for vertical movement + m_npcPath.thinkFlat( Pos, &pathComplete, &distX, &distY, &heading ); - s32 checkDist = yMovement + 50; - - groundHeight = CGameScene::getCollision()->getHeightFromGround( Pos.vx + moveX, Pos.vy, checkDist ); - - if ( groundHeight < checkDist ) + if ( !pathComplete ) { - // groundHeight <= yMovement indicates either just above ground or on or below ground + moveX = ( m_carSpeed >> 8 ) * _frames; - moveY = groundHeight; + if ( heading == 2048 ) + { + moveX = -moveX; + } + } + + if ( m_inJump ) + { + m_vertSpeed += 192; + + if ( m_vertSpeed > ( 5 << 8 ) ) + { + m_vertSpeed = 5 << 8; + } + else if ( m_vertSpeed < -( 6 << 8 ) ) + { + m_vertSpeed = -( 6 << 8 ); + } + + moveY = ( m_vertSpeed >> 8 ) * _frames; + + groundHeight = CGameScene::getCollision()->getHeightFromGroundCart( Pos.vx + moveX, Pos.vy + moveY, 16 ); + + if ( groundHeight < 0 ) + { + // have touched down + + m_inJump = false; + moveY += groundHeight; + } } else { - // fall + // check for vertical movement - moveY = yMovement; - } + s32 checkDist = yMovement + 50; - if ( moveY < 0 ) - { - m_carSpeed -= 1; + groundHeight = CGameScene::getCollision()->getHeightFromGroundCart( Pos.vx + moveX, Pos.vy, checkDist ); - if ( m_carSpeed < ( 2 << 8 ) ) + if ( groundHeight < checkDist ) { - m_carSpeed = ( 2 << 8 ); + // groundHeight <= yMovement indicates either just above ground or on or below ground + + moveY = groundHeight; + } + else + { + // fall + + moveY = yMovement; + } + + if ( moveY < 0 ) + { + m_carSpeed -= 1; + + if ( m_carSpeed < ( 2 << 8 ) ) + { + m_carSpeed = ( 2 << 8 ); + } + } + else if ( moveY > 0 ) + { + m_carSpeed += 20; + + if ( m_carSpeed > ( 6 << 8 ) ) + { + m_carSpeed = ( 6 << 8 ); + } } } - else if ( moveY > 0 ) - { - m_carSpeed += 20; - if ( m_carSpeed > ( 6 << 8 ) ) - { - m_carSpeed = ( 6 << 8 ); - } - } + Pos.vx += moveX; + Pos.vy += moveY; } - Pos.vx += moveX; - Pos.vy += moveY; - // sort out draw rotation DVECTOR testPos1, testPos2; @@ -169,7 +209,7 @@ void CNpcCartPlatform::processMovement( int _frames ) s32 yDiff; - yDiff = CGameScene::getCollision()->getHeightFromGround( testPos1.vx, testPos1.vy, sensorDist + 1 ); + yDiff = CGameScene::getCollision()->getHeightFromGroundCart( testPos1.vx, testPos1.vy, sensorDist + 1 ); if ( yDiff <= sensorDist ) { @@ -178,7 +218,7 @@ void CNpcCartPlatform::processMovement( int _frames ) testPos1.vy += yDiff; } - yDiff = CGameScene::getCollision()->getHeightFromGround( testPos2.vx, testPos2.vy, sensorDist + 1 ); + yDiff = CGameScene::getCollision()->getHeightFromGroundCart( testPos2.vx, testPos2.vy, sensorDist + 1 ); if ( yDiff <= sensorDist ) { @@ -193,10 +233,29 @@ void CNpcCartPlatform::processMovement( int _frames ) heading = ratan2( yDist, xDist ); setCollisionAngle( heading ); + + if ( m_reboundTimer <= 0 ) + { + switch ( CGameScene::getCollision()->getCollisionBlock( testPos2.vx, testPos2.vy - 8 ) & COLLISION_TYPE_MASK ) + { + case COLLISION_TYPE_FLAG_DAMAGE: + { + m_vertSpeed = -8 << 8; + m_reboundTimer = 2 * GameState::getOneSecondInFrames(); + m_rebound = true; + Pos.vy -= 8; + + break; + } + + default: + break; + } + } } else { - groundHeight = CGameScene::getCollision()->getHeightFromGround( Pos.vx, Pos.vy, yMovement + 16 ); + groundHeight = CGameScene::getCollision()->getHeightFromGroundCart( Pos.vx, Pos.vy, yMovement + 16 ); if ( groundHeight <= yMovement ) { diff --git a/source/platform/pcart.h b/source/platform/pcart.h index 96e8ef3f0..a7f1ac230 100644 --- a/source/platform/pcart.h +++ b/source/platform/pcart.h @@ -34,6 +34,9 @@ protected: u8 m_inJump; s32 m_vertSpeed; u8 m_playerAttached; + u8 m_rebound; + + s32 m_reboundTimer; }; #endif \ No newline at end of file