diff --git a/makefile.gaz b/makefile.gaz index d74506499..d4d8aa3ca 100644 --- a/makefile.gaz +++ b/makefile.gaz @@ -73,7 +73,8 @@ enemy_src := npc \ nocto \ nfskull \ nsklfish \ - ngary + ngary \ + nplatfrm projectl_src := projectl diff --git a/source/enemy/ngeneric.cpp b/source/enemy/ngeneric.cpp index 453f824df..dfb3a97c6 100644 --- a/source/enemy/ngeneric.cpp +++ b/source/enemy/ngeneric.cpp @@ -295,16 +295,6 @@ void CNpcEnemy::processGenericFixedPathWalk( int _frames, s32 *moveX, s32 *moveY } } -void CNpcEnemy::processGenericCircularPath( int _frames ) -{ - m_rotation += m_data[m_type].speed; - m_rotation %= 4096; - - Pos.vx = m_base.vx + ( ( m_extension * rcos( m_rotation ) ) >> 12 ); - Pos.vy = m_base.vy + ( ( m_extension * rsin( m_rotation ) ) >> 12 ); -} - - bool CNpcEnemy::isCollisionWithGround() { ASSERT(m_layerCollision); diff --git a/source/enemy/npc.cpp b/source/enemy/npc.cpp index 785367673..83a5d334c 100644 --- a/source/enemy/npc.cpp +++ b/source/enemy/npc.cpp @@ -209,7 +209,7 @@ void CNpcEnemy::init() { CEnemyThing::init(); - m_type = NPC_LINEAR_PLATFORM; + m_type = NPC_CLAM_STATIC; // sActorHdr *Hdr = m_skel.Load( m_data[m_type].skelType ); // m_skel.Init( Hdr ); @@ -891,13 +891,6 @@ void CNpcEnemy::processMovement(int _frames) break; } - case NPC_MOVEMENT_FIXED_CIRCULAR: - { - processGenericCircularPath( _frames ); - - break; - } - case NPC_MOVEMENT_MOTHER_JELLYFISH: { processMotherJellyfishMovement( _frames ); diff --git a/source/enemy/npc.h b/source/enemy/npc.h index f3dccaff7..b56ed84a0 100644 --- a/source/enemy/npc.h +++ b/source/enemy/npc.h @@ -116,8 +116,6 @@ public: NPC_PENDULUM, NPC_FIREBALL, NPC_SAW_BLADE, - NPC_LINEAR_PLATFORM, - NPC_CIRCULAR_PLATFORM, NPC_SMALL_JELLYFISH_1, NPC_SMALL_JELLYFISH_2, NPC_ANEMONE_1, @@ -246,7 +244,6 @@ protected: NPC_MOVEMENT_STATIC = 0, NPC_MOVEMENT_FIXED_PATH = 1, NPC_MOVEMENT_FIXED_PATH_WALK, - NPC_MOVEMENT_FIXED_CIRCULAR, NPC_MOVEMENT_MOTHER_JELLYFISH, NPC_MOVEMENT_SUB_SHARK, NPC_MOVEMENT_FLYING_DUTCHMAN, @@ -357,7 +354,6 @@ protected: void processGenericGetUserDist( int _frames, s32 *distX, s32 *distY ); void processGenericFixedPathMove( int _frames, s32 *moveX, s32 *moveY, s32 *moveVel, s32 *moveDist ); void processGenericFixedPathWalk( int _frames, s32 *moveX, s32 *moveY ); - void processGenericCircularPath( int _frames ); bool processGroundCollisionReverse( s32 *moveX, s32 *moveY ); // small jellyfish functions diff --git a/source/enemy/npcdata.cpp b/source/enemy/npcdata.cpp index 3a2cd5c27..9533de3d7 100644 --- a/source/enemy/npcdata.cpp +++ b/source/enemy/npcdata.cpp @@ -15,6 +15,10 @@ #include "enemy\npc.h" #endif +#ifndef __ENEMY_NPLATFRM_H__ +#include "enemy\nplatfrm.h" +#endif + #ifndef __PLAYER_PLAYER_H__ #include "player\player.h" #endif @@ -59,6 +63,32 @@ CNpcFriend::NPC_FRIEND_DATA CNpcFriend::m_data[NPC_FRIEND_UNIT_TYPE_MAX] = }, }; +CNpcPlatform::NPC_PLATFORM_DATA CNpcPlatform::m_data[NPC_PLATFORM_TYPE_MAX] = +{ + { // NPC_LINEAR_PLATFORM + ACTORS_CLAM_A3D, + ANIM_CLAM_CLAMSHUT, + NPC_PLATFORM_MOVEMENT_FIXED_PATH, + 3, + //512, + 2048, + true, + DAMAGE__NONE, + 0, + }, + + { // NPC_CIRCULAR_PLATFORM + ACTORS_CLAM_A3D, + ANIM_CLAM_CLAMSHUT, + NPC_PLATFORM_MOVEMENT_FIXED_CIRCULAR, + 3, + 128, + false, + DAMAGE__NONE, + 0, + }, +}; + CNpcEnemy::NPC_DATA CNpcEnemy::m_data[NPC_UNIT_TYPE_MAX] = { { // NPC_FALLING_ITEM @@ -163,41 +193,6 @@ CNpcEnemy::NPC_DATA CNpcEnemy::m_data[NPC_UNIT_TYPE_MAX] = 0, }, - { // NPC_LINEAR_PLATFORM - ACTORS_CLAM_A3D, - ANIM_CLAM_CLAMSHUT, - NPC_INIT_DEFAULT, - NPC_SENSOR_NONE, - NPC_MOVEMENT_FIXED_PATH, - NPC_MOVEMENT_MODIFIER_NONE, - NPC_CLOSE_NONE, - NPC_TIMER_NONE, - false, - 3, - //512, - 2048, - true, - DAMAGE__NONE, - 0, - }, - - { // NPC_CIRCULAR_PLATFORM - ACTORS_CLAM_A3D, - ANIM_CLAM_CLAMSHUT, - NPC_INIT_CIRCULAR_PLATFORM, - NPC_SENSOR_NONE, - NPC_MOVEMENT_FIXED_CIRCULAR, - NPC_MOVEMENT_MODIFIER_NONE, - NPC_CLOSE_NONE, - NPC_TIMER_NONE, - false, - 3, - 128, - false, - DAMAGE__NONE, - 0, - }, - { // NPC_SMALL_JELLYFISH_1 ACTORS_CLAM_A3D, ANIM_CLAM_CLAMSHUT, diff --git a/source/game/game.cpp b/source/game/game.cpp index 6403db836..83e426ad0 100644 --- a/source/game/game.cpp +++ b/source/game/game.cpp @@ -27,6 +27,10 @@ #include "enemy\npc.h" #endif +#ifndef __ENEMY_NPLATFRM_H__ +#include "enemy\nplatfrm.h" +#endif + #ifndef __PROJECTL_PROJECTL_H__ #include "projectl\projectl.h" #endif @@ -230,8 +234,8 @@ void CGameScene::initLevel() CConversation::registerConversationScript(SCRIPTS_SPEECHTEST_DAT); // Register one script for testing.. #ifdef __USER_charles__ - CNpcEnemy *enemy; - enemy=new ("test enemy") CNpcEnemy; + CNpcPlatform *enemy; + enemy=new ("test enemy") CNpcPlatform; enemy->init(); enemy->setLayerCollision( Level.getCollisionLayer() ); #endif diff --git a/source/player/player.cpp b/source/player/player.cpp index c744ae210..32ff9d25a 100644 --- a/source/player/player.cpp +++ b/source/player/player.cpp @@ -1336,15 +1336,19 @@ void CPlayer::setPlatform( CThing *newPlatform ) { int colHeight; int platformHeight; + DVECTOR newPos; + DVECTOR testPos; m_platform = newPlatform; - m_onPlatform = true; + m_onPlatform = getCentreCollision(); if ( m_onPlatform ) { + newPos = getNewCollidedPos(); + colHeight = m_layerCollision->getHeightFromGround( Pos.vx, Pos.vy, 16 ); - platformHeight = m_platform->getPos().vy - Pos.vy; + platformHeight = newPos.vy - Pos.vy; if ( platformHeight > colHeight ) { @@ -1361,7 +1365,7 @@ void CPlayer::setPlatform( CThing *newPlatform ) // have collided with a platform m_moveVel.vy=0; - Pos.vy += colHeight; + Pos = newPos; if ( !m_prevOnPlatform ) { @@ -1397,7 +1401,7 @@ void CPlayer::setPlatform( CThing *newPlatform ) } else { - Pos.vx += m_platform->getPos().vx - m_prevPlatformPos.vx; + //Pos.vx += m_platform->getPos().vx - m_prevPlatformPos.vx; } // Move the camera offset @@ -1441,6 +1445,33 @@ void CPlayer::setPlatform( CThing *newPlatform ) m_prevPlatformPos = m_platform->getPos(); } + else + { + newPlatform->removeChild( this ); + } +} + +/*---------------------------------------------------------------------- + Function: + Purpose: + Params: + Returns: + ---------------------------------------------------------------------- */ +void CPlayer::shove( DVECTOR move ) +{ + int colHeight = m_layerCollision->getHeightFromGround( Pos.vx + move.vx, Pos.vy + move.vy, 1 ); + + if( colHeight < 0 ) + { + // target position in within wall, abort + + return; + } + else + { + Pos.vx += move.vx; + Pos.vy += move.vy; + } } /*=========================================================================== diff --git a/source/player/player.h b/source/player/player.h index 1a8344164..461579466 100644 --- a/source/player/player.h +++ b/source/player/player.h @@ -160,6 +160,7 @@ public: virtual void shutdown(); virtual void think(int _frames); virtual void render(); + virtual void shove(DVECTOR move); DVECTOR getCameraPos(); diff --git a/source/thing/thing.cpp b/source/thing/thing.cpp index bbe044069..443beccef 100644 --- a/source/thing/thing.cpp +++ b/source/thing/thing.cpp @@ -25,6 +25,8 @@ #include "game\game.h" #endif +#include "utils\utils.h" + /* Std Lib ------- */ @@ -123,6 +125,21 @@ void CThingManager::thinkAllThings(int _frames) player->clearPlatform(); } + // Player -> Platform collision + thing1=s_thingLists[CThing::TYPE_PLATFORM]; + thing2=s_thingLists[CThing::TYPE_PLAYER]; + while(thing1&&thing2) + { + thing1->removeAllChild(); + if(thing1->canCollide()&& + thing1->checkCollisionAgainst(thing2)) + { + thing1->addChild( thing2 ); + thing1->collidedWith(thing2); + } + thing1=thing1->m_nextThing; + } + // Player -> Pickup collision thing1=s_thingLists[CThing::TYPE_PICKUP]; thing2=s_thingLists[CThing::TYPE_PLAYER]; @@ -277,8 +294,11 @@ void CThing::init() // Add to thing list CThingManager::addToThingList(this); - setCollisionSize(20,20); // Some temporary defaults.. (pkg) + setCollisionSize(200,20); // Some temporary defaults.. (pkg) setCollisionCentreOffset(0,0); + m_collisionAngle = 0; + m_collisionStickyBoundary = 0; + m_centreCollision = false; } /*---------------------------------------------------------------------- @@ -313,6 +333,9 @@ void CThing::think(int _frames) DVECTOR PosLast=Pos; PosDelta.vx=Pos.vx-PosLast.vx; PosDelta.vy=Pos.vy-PosLast.vy; + + m_collisionAngle++; + m_collisionAngle %= 4096; } /*---------------------------------------------------------------------- @@ -343,10 +366,54 @@ void CThing::render() if(area.x1<=511&&area.x2>=0&& area.y1<=255&&area.y2>=0) { - DrawLine(area.x1,area.y1,area.x1,area.y2,255,255,255,0); - DrawLine(area.x1,area.y2,area.x2,area.y2,255,255,255,0); - DrawLine(area.x2,area.y2,area.x2,area.y1,255,255,255,0); - DrawLine(area.x2,area.y1,area.x1,area.y1,255,255,255,0); + area=getCollisionArea(); + + SVECTOR points[4]; + VECTOR vecPoints[4]; + + points[0].vx = area.x1 - Pos.vx; + points[0].vy = area.y1 - Pos.vy; + + points[1].vx = area.x1 - Pos.vx; + points[1].vy = area.y2 - Pos.vy; + + points[2].vx = area.x2 - Pos.vx; + points[2].vy = area.y2 - Pos.vy; + + points[3].vx = area.x2 - Pos.vx; + points[3].vy = area.y1 - Pos.vy; + + MATRIX mtx; + + SetIdentNoTrans(&mtx ); + RotMatrixZ( m_collisionAngle, &mtx ); + + ApplyMatrix( &mtx, &points[0], &vecPoints[0] ); + ApplyMatrix( &mtx, &points[1], &vecPoints[1] ); + ApplyMatrix( &mtx, &points[2], &vecPoints[2] ); + ApplyMatrix( &mtx, &points[3], &vecPoints[3] ); + + vecPoints[0].vx += Pos.vx - ofs.vx; + vecPoints[0].vy += Pos.vy - ofs.vy; + + vecPoints[1].vx += Pos.vx - ofs.vx; + vecPoints[1].vy += Pos.vy - ofs.vy; + + vecPoints[2].vx += Pos.vx - ofs.vx; + vecPoints[2].vy += Pos.vy - ofs.vy; + + vecPoints[3].vx += Pos.vx - ofs.vx; + vecPoints[3].vy += Pos.vy - ofs.vy; + + //DrawLine(area.x1,area.y1,area.x1,area.y2,255,255,255,0); + //DrawLine(area.x1,area.y2,area.x2,area.y2,255,255,255,0); + //DrawLine(area.x2,area.y2,area.x2,area.y1,255,255,255,0); + //DrawLine(area.x2,area.y1,area.x1,area.y1,255,255,255,0); + + DrawLine( vecPoints[0].vx, vecPoints[0].vy, vecPoints[1].vx, vecPoints[1].vy,255,255,255,0); + DrawLine( vecPoints[1].vx, vecPoints[1].vy, vecPoints[2].vx, vecPoints[2].vy,255,255,255,0); + DrawLine( vecPoints[2].vx, vecPoints[2].vy, vecPoints[3].vx, vecPoints[3].vy,255,255,255,0); + DrawLine( vecPoints[3].vx, vecPoints[3].vy, vecPoints[0].vx, vecPoints[0].vy,255,255,255,0); area.x1=Pos.vx-10-ofs.vx; area.y1=Pos.vy-10-ofs.vy; @@ -494,6 +561,8 @@ int CThing::checkCollisionAgainst(CThing *_thisThing) int radius; int collided; + MATRIX mtx; + pos=getCollisionCentre(); thisThingPos=_thisThing->getCollisionCentre(); @@ -505,12 +574,174 @@ int CThing::checkCollisionAgainst(CThing *_thisThing) CRECT thisRect,thatRect; thisRect=getCollisionArea(); + + // ensure user 'sticks' to platform whilst it is moving along + + thisRect.x1 -= m_collisionStickyBoundary; + thisRect.y1 -= m_collisionStickyBoundary; + thisRect.x2 += m_collisionStickyBoundary; + thisRect.y2 += m_collisionStickyBoundary; + thatRect=_thisThing->getCollisionArea(); + // rotate thatPos opposite way to this CThing's collision angle, so that we can regard them both as being at 0 rotation + + // get target thing's position + + DVECTOR thatPos = _thisThing->getPos(); + + // get target thing's position relative to this thing's position + + SVECTOR relativePos; + relativePos.vx = thatPos.vx - Pos.vx; + relativePos.vy = thatPos.vy - Pos.vy; + + VECTOR newPos; + + // get target thing's collision area relative to 0 + + thatRect.x1 -= thatPos.vx; + thatRect.y1 -= thatPos.vy; + thatRect.x2 -= thatPos.vx; + thatRect.y2 -= thatPos.vy; + + SetIdentNoTrans(&mtx ); + RotMatrixZ( -m_collisionAngle, &mtx ); + + // rotation target relative position back to 0 by this thing's collision angle + + ApplyMatrix( &mtx, &relativePos, &newPos ); + + // add on this thing's position to get new target thing's position after rotation around this thing + + newPos.vx += Pos.vx; + newPos.vy += Pos.vy; + + // reposition target thing's collision area + + thatRect.x1 += newPos.vx; + thatRect.y1 += newPos.vy; + thatRect.x2 += newPos.vx; + thatRect.y2 += newPos.vy; + + // check to see if bounding boxes collide + if(((thisRect.x1>=thatRect.x1&&thisRect.x1<=thatRect.x2)||(thisRect.x2>=thatRect.x1&&thisRect.x2<=thatRect.x2)||(thisRect.x1<=thatRect.x1&&thisRect.x2>=thatRect.x2))&& ((thisRect.y1>=thatRect.y1&&thisRect.y1<=thatRect.y2)||(thisRect.y2>=thatRect.y1&&thisRect.y2<=thatRect.y2)||(thisRect.y1<=thatRect.y1&&thisRect.y2>=thatRect.y2))) { collided=true; + + // check to see if centre point (i.e. where the object is standing) collides too + + if ( ( newPos.vx >= thisRect.x1 && newPos.vx <= thisRect.x2 ) && + ( newPos.vy >= thisRect.y1 && newPos.vy <= thisRect.y2 ) ) + { + thisRect=getCollisionArea(); + _thisThing->setCentreCollision( true ); + + // 'render' collision box at correct angle + + SVECTOR testPointsNonRel[4]; + VECTOR testPoints[4]; + + testPointsNonRel[0].vx = thisRect.x1 - Pos.vx; + testPointsNonRel[0].vy = thisRect.y1 - Pos.vy; + + testPointsNonRel[1].vx = thisRect.x2 - Pos.vx; + testPointsNonRel[1].vy = thisRect.y1 - Pos.vy; + + testPointsNonRel[2].vx = thisRect.x2 - Pos.vx; + testPointsNonRel[2].vy = thisRect.y2 - Pos.vy; + + testPointsNonRel[3].vx = thisRect.x1 - Pos.vx; + testPointsNonRel[3].vy = thisRect.y2 - Pos.vy; + + SetIdentNoTrans(&mtx ); + RotMatrixZ( m_collisionAngle, &mtx ); + + int i; + + for ( i = 0 ; i < 4 ; i++ ) + { + ApplyMatrix( &mtx, &testPointsNonRel[i], &testPoints[i] ); + + testPoints[i].vx += Pos.vx; + testPoints[i].vy += Pos.vy; + } + + // now find the highest y pos + + // first set highestY to lowest of the four points + + s16 highestY = testPoints[0].vy; + + for ( i = 1 ; i < 4 ; i++ ) + { + if ( testPoints[i].vy > highestY ) // remember y is inverted + { + highestY = testPoints[i].vy; + } + } + + for ( i = 0 ; i < 4 ; i++ ) + { + int j = i + 1; + j %= 4; + + VECTOR highestX, lowestX; + + if ( testPoints[i].vx < testPoints[j].vx ) + { + lowestX = testPoints[i]; + highestX = testPoints[j]; + } + else + { + lowestX = testPoints[j]; + highestX = testPoints[i]; + } + + if ( highestX.vx == lowestX.vx ) + { + // have to compare heights of both points to get highest + + if ( lowestX.vy < highestY ) + { + highestY = lowestX.vy; + } + + if ( highestX.vy < highestY ) + { + highestY = highestX.vy; + } + } + else + { + if ( thatPos.vx >= lowestX.vx && thatPos.vx <= highestX.vx ) + { + // current position is above or below this line + + s16 testY; + + testY = lowestX.vy + ( ( thatPos.vx - lowestX.vx ) * ( highestX.vy - lowestX.vy ) ) / + ( highestX.vx - lowestX.vx ); + + if ( testY < highestY ) + { + highestY = testY; + } + } + } + } + + thatPos.vy = highestY; + + _thisThing->setNewCollidedPos( thatPos ); + } + else + { + _thisThing->setCentreCollision( false ); + } } } @@ -528,5 +759,17 @@ void CThing::processEvent(GAME_EVENT _event,CThing *_sourceThing) // do nothing by default - ignore event } +/*---------------------------------------------------------------------- + Function: + Purpose: + Params: + Returns: + ---------------------------------------------------------------------- */ +void CThing::shove( DVECTOR move ) +{ + Pos.vx += move.vx; + Pos.vy += move.vy; +} + /*=========================================================================== end */ diff --git a/source/thing/thing.h b/source/thing/thing.h index c1045016a..e8bc8b71d 100644 --- a/source/thing/thing.h +++ b/source/thing/thing.h @@ -68,12 +68,12 @@ public: typedef enum { TYPE_PICKUP, + TYPE_PLATFORM, TYPE_PLAYER, TYPE_PLAYERPROJECTILE, TYPE_NPC, TYPE_ENEMY, TYPE_ENEMYPROJECTILE, - TYPE_PLATFORM, TYPE_TRIGGER, MAX_TYPE, @@ -98,6 +98,8 @@ public: DVECTOR getPos() {return Pos;} + virtual void shove(DVECTOR move); + CThing *getNext() {return Next;} virtual void processEvent(GAME_EVENT _event,CThing *_sourceThing); @@ -135,15 +137,25 @@ protected: void setCollisionSize(int _w,int _h); void setCollisionCentreOffset(int _x,int _y) {m_collisionCentreOffset.vx=_x;m_collisionCentreOffset.vy=_y;} void setCollisionCentreOffset(DVECTOR xy) {m_collisionCentreOffset=xy;} + void setCentreCollision(bool newCentreCollision) {m_centreCollision = newCentreCollision;} + void setNewCollidedPos(DVECTOR newPos) {m_newCollidedPos = newPos;} + void setCollisionStickyBoundary(int boundary) {m_collisionStickyBoundary = boundary;} int getCollisionRadius() {return m_collisionRadius;} CRECT getCollisionArea() {return m_collisionArea;} DVECTOR getCollisionCentre() {return m_collisionCentre;} + s16 getCollisionAngle() {return m_collisionAngle;} + bool getCentreCollision() {return m_centreCollision;} + DVECTOR getNewCollidedPos() {return m_newCollidedPos;} private: DVECTOR m_collisionSize; DVECTOR m_collisionCentreOffset; int m_collisionRadius; + int m_collisionStickyBoundary; // for platforms CRECT m_collisionArea; DVECTOR m_collisionCentre; + s16 m_collisionAngle; + bool m_centreCollision; + DVECTOR m_newCollidedPos; }; diff --git a/users/paul/spongebob project/spongebob project.dsp b/users/paul/spongebob project/spongebob project.dsp index 063f5adf5..54f9e5d18 100644 --- a/users/paul/spongebob project/spongebob project.dsp +++ b/users/paul/spongebob project/spongebob project.dsp @@ -185,6 +185,14 @@ SOURCE=..\..\..\source\enemy\npcpath.h # End Source File # Begin Source File +SOURCE=..\..\..\source\enemy\nplatfrm.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\source\enemy\nplatfrm.h +# End Source File +# Begin Source File + SOURCE=..\..\..\source\enemy\nscrab.cpp # End Source File # Begin Source File