Skip to content

Commit

Permalink
Added support of the one-side collision resolving
Browse files Browse the repository at this point in the history
For example, resolve collision from top only (sizable blocks, clouds, thin bridges, etc.), resolve from left/right (one-directed ways), resolve from bottom (needed for invisible blocks to be hit from the bottom... also making mean traps to jail player in the muddy stinky hole)
  • Loading branch information
Wohlstand committed Aug 14, 2016
1 parent 29a65b4 commit b0a2fe8
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 12 deletions.
63 changes: 54 additions & 9 deletions miniphysics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,33 @@ void MiniPhysics::initTestCommon(LevelData *fileP)
for(int i=0; i<file.blocks.size(); i++)
{
int id = 0;
int blockSide = obj::Block_ALL;
LevelBlock& blk = file.blocks[i];
switch(blk.id)
{
case 358: case 357: case 321: id = obj::SL_RightBottom; break;
case 359: case 360: case 319: id = obj::SL_LeftBottom; break;
case 363: case 364: id = obj::SL_LeftTop; break;
case 362: case 361: id = obj::SL_RightTop; break;
case 366:
id = obj::SL_LeftBottom;
blockSide = obj::Block_TOP; break;
case 495:
blockSide = obj::Block_RIGHT;
id = obj::SL_Rect; break;
case 25: case 575:
blockSide = obj::Block_TOP;
id = obj::SL_Rect; break;
case 500:
blockSide = obj::Block_BOTTOM;
id = obj::SL_Rect; break;
default: id = obj::SL_Rect; break;
}
obj box(blk.x, blk.y, id);
box.m_w = blk.w;
box.m_h = blk.h;
box.m_blocked[0] = blockSide;
box.m_blocked[1] = blockSide;
objs.push_back(box);
if(blk.id == 159)
movingBlock.push_back(&objs.last());
Expand Down Expand Up @@ -666,6 +681,8 @@ void MiniPhysics::processCollisions()
if( isBlockFloor(&objs[i]))
{
tipRectT://Impacted at top of block (bottom of player)
if((objs[i].m_blocked[pl.m_filterID]&obj::Block_TOP) == 0)
goto tipRectT_Skip;
pl.m_y = objs[i].m_y - pl.m_h;
pl.m_velY = objs[i].m_velY;
pl.m_stand = true;
Expand All @@ -692,11 +709,15 @@ void MiniPhysics::processCollisions()
}
}
}
tipRectT_Skip:;
} else {
//'bottom
if( isBlockCeiling(&objs[i]) )
{
tipRectB://Impacted at bottom of block (top of player)
if((objs[i].m_blocked[pl.m_filterID]&obj::Block_BOTTOM) == 0)
goto tipRectB_Skip;

pl.m_y = objs[i].m_y + objs[i].m_h;
pl.m_velY = objs[i].m_velY;
contactAt = obj::Contact_Bottom;
Expand All @@ -716,7 +737,7 @@ void MiniPhysics::processCollisions()
speedNum = 0.0;
}
}
//tipRectB_Skip:;
tipRectB_Skip:;
}
}
} else {
Expand All @@ -741,6 +762,9 @@ void MiniPhysics::processCollisions()
}
tipRectL://Impacted at left (right of player)
{
if((objs[i].m_blocked[pl.m_filterID]&obj::Block_LEFT) == 0)
goto tipRectL_Skip;

if(pl.m_allowHoleRuning)
{
if( (pl.bottom() < (objs[i].top() + 2.0)) &&
Expand All @@ -749,7 +773,6 @@ void MiniPhysics::processCollisions()
goto tipRectT;
}
pl.m_x = objs[i].m_x - pl.m_w;
//pl.m_touchLeftWall = objs[i].betweenV(pl.centerY());
double &splr = pl.m_velX;
double &sbox = objs[i].m_velX;
xSpeedWasReversed = splr <= sbox;
Expand Down Expand Up @@ -781,6 +804,9 @@ void MiniPhysics::processCollisions()
}
tipRectR://Impacted at right (left of player)
{
if((objs[i].m_blocked[pl.m_filterID]&obj::Block_RIGHT) == 0)
goto tipRectR_Skip;

if(pl.m_allowHoleRuning)
{
if( (pl.bottom() < (objs[i].top() + 2.0)) &&
Expand All @@ -789,7 +815,6 @@ void MiniPhysics::processCollisions()
goto tipRectT;
}
pl.m_x = objs[i].m_x + objs[i].m_w;
//pl.m_touchRightWall = objs[i].betweenV(pl.centerY());
double &splr = pl.m_velX;
double &sbox = objs[i].m_velX;
xSpeedWasReversed = splr >= sbox;
Expand All @@ -804,11 +829,16 @@ void MiniPhysics::processCollisions()
}
}
}

if( (pl.m_stand) || (pl.m_velX_source == 0.0) || xSpeedWasReversed)
tm = -2;

tipTriangleShape://Check triangular collision
if(contactAt == obj::Contact_None)
{
//Avoid infinite loop for case of skipped collision resolving
contactAt=obj::Contact_Skipped;

k = objs[i].m_h / objs[i].m_w;
switch(objs[i].m_id)
{
Expand Down Expand Up @@ -844,6 +874,9 @@ void MiniPhysics::processCollisions()
}
else if( pl.bottom() > objs[i].m_y + ( (pl.m_x - objs[i].m_x) * k) - 1 )
{
if((objs[i].m_blocked[pl.m_filterID]&obj::Block_TOP) == 0)
goto skipTriangleResolving;

pl.m_y = objs[i].m_y + ( (pl.m_x - objs[i].m_x) * k ) - pl.m_h;
pl.m_velY = objs[i].m_velY;
pl.m_onSlopeFloor = true;
Expand All @@ -868,8 +901,6 @@ void MiniPhysics::processCollisions()
speedNum += 1.0;
contactAt = obj::Contact_Top;
doCliffCheck = true;
//standingOn = &objs[i];
//l_slopeFloor.push_back(&objs[i]);
if(pl.m_onSlopeCeiling)
{
if( findMinimalHeight(objs[i].m_id, objs[i].rect(),
Expand Down Expand Up @@ -917,6 +948,9 @@ void MiniPhysics::processCollisions()
}
else if(pl.bottom() > objs[i].m_y + ((objs[i].right() - pl.m_x - pl.m_w) * k) - 1 )
{
if((objs[i].m_blocked[pl.m_filterID]&obj::Block_TOP) == 0)
goto skipTriangleResolving;

pl.m_y = objs[i].m_y + ( (objs[i].right() - pl.m_x - pl.m_w) * k) - pl.m_h;
pl.m_velY = objs[i].m_velY;
pl.m_onSlopeFloor = true;
Expand All @@ -939,8 +973,6 @@ void MiniPhysics::processCollisions()
speedNum += 1.0;
contactAt = obj::Contact_Top;
doCliffCheck = true;
//standingOn = &objs[i];
//l_slopeFloor.push_back(&objs[i]);
if(pl.m_onSlopeCeiling)
{
if( findMinimalHeight(objs[i].m_id, objs[i].rect(),
Expand Down Expand Up @@ -987,6 +1019,9 @@ void MiniPhysics::processCollisions()
}
else if(pl.m_y < objs[i].bottom() - ((pl.m_x - objs[i].m_x) * k) )
{
if((objs[i].m_blocked[pl.m_filterID]&obj::Block_BOTTOM) == 0)
goto skipTriangleResolving;

double oldY = pl.m_oldy;
pl.m_y = objs[i].bottom() - ((pl.m_x - objs[i].m_x) * k);
pl.m_velY = fabs(oldY-pl.m_y);
Expand Down Expand Up @@ -1047,6 +1082,9 @@ void MiniPhysics::processCollisions()
}
else if(pl.m_y < objs[i].bottom() - ((objs[i].right() - pl.m_x - pl.m_w) * k))
{
if((objs[i].m_blocked[pl.m_filterID]&obj::Block_BOTTOM) == 0)
goto skipTriangleResolving;

double oldY = pl.m_oldy;
pl.m_y = objs[i].bottom() - ((objs[i].right() - pl.m_x - pl.m_w) * k);
if( pl.m_velX > 0.0)
Expand Down Expand Up @@ -1088,6 +1126,8 @@ void MiniPhysics::processCollisions()
blockSkip = true;
}
}
skipTriangleResolving:;

} else {
//If shape is not rectangle - check triangular collision
if( objs[i].m_id != obj::SL_Rect )
Expand All @@ -1112,7 +1152,9 @@ void MiniPhysics::processCollisions()
/* ********************Find wall touch blocks************************ */
if( figureTouch(pl, objs[i], 0.0, -1.0) )
{
if(pl.betweenV( objs[i].centerY() ) && (objs[i].m_id == obj::SL_Rect) )
if( pl.betweenV( objs[i].centerY() ) &&
(objs[i].m_id == obj::SL_Rect) &&
(objs[i].m_blocked[pl.m_filterID]==obj::Block_ALL) )
{
if(pl.centerX() < objs[i].centerX())
{
Expand Down Expand Up @@ -1144,7 +1186,10 @@ void MiniPhysics::processCollisions()
break;
}

if( (objs[i].m_id == obj::SL_Rect) && recttouch(pl.m_oldx, pl.m_oldy, pl.m_w, pl.m_h, objs[i].m_oldx, objs[i].m_oldy, objs[i].m_w, objs[i].m_h) )
if( (objs[i].m_id == obj::SL_Rect) &&
(objs[i].m_blocked[pl.m_filterID]==obj::Block_ALL) &&
recttouch(pl.m_oldx, pl.m_oldy, pl.m_w, pl.m_h,
objs[i].m_oldx, objs[i].m_oldy, objs[i].m_w, objs[i].m_h) )
{
l_possibleCrushers.push_back(&objs[i]);
pl.m_crushed = true;
Expand Down
22 changes: 19 additions & 3 deletions miniphysics.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,16 @@ class obj
Contact_Top,
Contact_Bottom,
Contact_Left,
Contact_Right
Contact_Right,
Contact_Skipped
};
enum BlockedSides{
Block_NONE = 0,
Block_LEFT = 0x1,
Block_TOP = 0x2,
Block_RIGHT = 0x4,
Block_BOTTOM = 0x8,
Block_ALL = 0xF,
};

obj(int x=0, int y=0, int id=0) :
Expand Down Expand Up @@ -84,7 +93,9 @@ class obj
m_onSlopeCeilingOld(false),
m_onSlopeCeilingShape(0),
m_onSlopeCeilingRect{0.0, 0.0, 0.0, 0.0},
m_onSlopeYAdd(0.0)
m_onSlopeYAdd(0.0),
m_blocked{Block_ALL, Block_ALL},
m_filterID(0)
{}
obj(const obj& o) :
m_id(o.m_id),
Expand Down Expand Up @@ -118,14 +129,17 @@ class obj
m_onSlopeCeilingOld(o.m_onSlopeCeilingOld),
m_onSlopeCeilingShape(o.m_onSlopeCeilingShape),
m_onSlopeCeilingRect(o.m_onSlopeCeilingRect),
m_onSlopeYAdd(o.m_onSlopeYAdd)
m_onSlopeYAdd(o.m_onSlopeYAdd),
m_blocked{o.m_blocked[0], o.m_blocked[1]},
m_filterID(o.m_filterID)
{}

void paint(QPainter &p, double cameraX, double cameraY)
{
double x = round(m_x-cameraX);
double y = round(m_y-cameraY);
p.setBrush(Qt::gray);
p.setOpacity(m_blocked[0]==Block_ALL ? 1.0 : 0.5 );
if(m_crushed && m_crushedOld)
{
p.setBrush(Qt::red);
Expand Down Expand Up @@ -260,6 +274,8 @@ class obj
int m_onSlopeCeilingShape;
objRect m_onSlopeCeilingRect;
double m_onSlopeYAdd;
int m_blocked[2];
int m_filterID;
};

struct LevelData;
Expand Down
9 changes: 9 additions & 0 deletions test.lvlx
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,15 @@ ID:174;X:2016;Y:224;W:32;H:32;
ID:358;X:1888;Y:96;W:32;H:32;
ID:174;X:1856;Y:224;W:32;H:32;
ID:359;X:2016;Y:160;W:32;H:32;
ID:495;X:1184;Y:160;W:32;H:32;
ID:495;X:1184;Y:128;W:32;H:32;
ID:495;X:1184;Y:96;W:32;H:32;
ID:495;X:1184;Y:64;W:32;H:32;
ID:366;X:1216;Y:32;W:64;H:32;
ID:366;X:1280;Y:64;W:64;H:32;
ID:500;X:1344;Y:160;W:32;H:32;
ID:500;X:1376;Y:160;W:32;H:32;
ID:500;X:1408;Y:160;W:32;H:32;
BLOCK_END
LAYERS
LR:"Default";
Expand Down

0 comments on commit b0a2fe8

Please sign in to comment.