mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-23 01:59:43 +01:00
Don't treat spikes as solid for non-humanoid entities
There's always been a bit of an inconsistency in the game where enabling invincibility would make spikes so solid that enemies and moving platforms would treat spikes as solid and bounces off of them. This fixes that by adding an `invincible` parameter to collision functions, so the functions will only treat spikes as solid if that parameter is true, and the parameter passed will only be true if it's called for an entity that is a humanoid and invincibility mode is enabled. Also, for clarity, `spikecollide` is renamed to `towerspikecollide` because it's only used for tower spikes. And as a small optimization, `checktowerspikes` returns early if invincibility mode is enabled.
This commit is contained in:
parent
cc61194bed
commit
f0aa1a8cae
4 changed files with 59 additions and 47 deletions
|
@ -16,6 +16,11 @@
|
||||||
|
|
||||||
bool entityclass::checktowerspikes(int t)
|
bool entityclass::checktowerspikes(int t)
|
||||||
{
|
{
|
||||||
|
if (map.invincibility)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!INBOUNDS_VEC(t, entities))
|
if (!INBOUNDS_VEC(t, entities))
|
||||||
{
|
{
|
||||||
vlog_error("checktowerspikes() out-of-bounds!");
|
vlog_error("checktowerspikes() out-of-bounds!");
|
||||||
|
@ -32,25 +37,25 @@ bool entityclass::checktowerspikes(int t)
|
||||||
int tempy = getgridpoint(temprect.y);
|
int tempy = getgridpoint(temprect.y);
|
||||||
int tempw = getgridpoint(temprect.x + temprect.w - 1);
|
int tempw = getgridpoint(temprect.x + temprect.w - 1);
|
||||||
int temph = getgridpoint(temprect.y + temprect.h - 1);
|
int temph = getgridpoint(temprect.y + temprect.h - 1);
|
||||||
if (map.spikecollide(tempx, tempy)) return true;
|
if (map.towerspikecollide(tempx, tempy)) return true;
|
||||||
if (map.spikecollide(tempw, tempy)) return true;
|
if (map.towerspikecollide(tempw, tempy)) return true;
|
||||||
if (map.spikecollide(tempx, temph)) return true;
|
if (map.towerspikecollide(tempx, temph)) return true;
|
||||||
if (map.spikecollide(tempw, temph)) return true;
|
if (map.towerspikecollide(tempw, temph)) return true;
|
||||||
if (temprect.h >= 12)
|
if (temprect.h >= 12)
|
||||||
{
|
{
|
||||||
int tpy1 = getgridpoint(temprect.y + 6);
|
int tpy1 = getgridpoint(temprect.y + 6);
|
||||||
if (map.spikecollide(tempx, tpy1)) return true;
|
if (map.towerspikecollide(tempx, tpy1)) return true;
|
||||||
if (map.spikecollide(tempw, tpy1)) return true;
|
if (map.towerspikecollide(tempw, tpy1)) return true;
|
||||||
if (temprect.h >= 18)
|
if (temprect.h >= 18)
|
||||||
{
|
{
|
||||||
tpy1 = getgridpoint(temprect.y + 12);
|
tpy1 = getgridpoint(temprect.y + 12);
|
||||||
if (map.spikecollide(tempx, tpy1)) return true;
|
if (map.towerspikecollide(tempx, tpy1)) return true;
|
||||||
if (map.spikecollide(tempw, tpy1)) return true;
|
if (map.towerspikecollide(tempw, tpy1)) return true;
|
||||||
if (temprect.h >= 24)
|
if (temprect.h >= 24)
|
||||||
{
|
{
|
||||||
tpy1 = getgridpoint(temprect.y + 18);
|
tpy1 = getgridpoint(temprect.y + 18);
|
||||||
if (map.spikecollide(tempx, tpy1)) return true;
|
if (map.towerspikecollide(tempx, tpy1)) return true;
|
||||||
if (map.spikecollide(tempw, tpy1)) return true;
|
if (map.towerspikecollide(tempw, tpy1)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4132,7 +4137,7 @@ bool entityclass::checkblocks(const SDL_Rect& temprect, const float dx, const fl
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool entityclass::checkwall(const SDL_Rect& temprect, const float dx, const float dy, const float dr, const bool skipblocks, const bool skipdirblocks)
|
bool entityclass::checkwall(const bool invincible, const SDL_Rect& temprect, const float dx, const float dy, const float dr, const bool skipblocks, const bool skipdirblocks)
|
||||||
{
|
{
|
||||||
//Returns true if entity setup in temprect collides with a wall
|
//Returns true if entity setup in temprect collides with a wall
|
||||||
if(skipblocks)
|
if(skipblocks)
|
||||||
|
@ -4144,41 +4149,41 @@ bool entityclass::checkwall(const SDL_Rect& temprect, const float dx, const floa
|
||||||
int tempy = getgridpoint(temprect.y);
|
int tempy = getgridpoint(temprect.y);
|
||||||
int tempw = getgridpoint(temprect.x + temprect.w - 1);
|
int tempw = getgridpoint(temprect.x + temprect.w - 1);
|
||||||
int temph = getgridpoint(temprect.y + temprect.h - 1);
|
int temph = getgridpoint(temprect.y + temprect.h - 1);
|
||||||
if (map.collide(tempx, tempy)) return true;
|
if (map.collide(tempx, tempy, invincible)) return true;
|
||||||
if (map.collide(tempw, tempy)) return true;
|
if (map.collide(tempw, tempy, invincible)) return true;
|
||||||
if (map.collide(tempx, temph)) return true;
|
if (map.collide(tempx, temph, invincible)) return true;
|
||||||
if (map.collide(tempw, temph)) return true;
|
if (map.collide(tempw, temph, invincible)) return true;
|
||||||
if (temprect.h >= 12)
|
if (temprect.h >= 12)
|
||||||
{
|
{
|
||||||
int tpy1 = getgridpoint(temprect.y + 6);
|
int tpy1 = getgridpoint(temprect.y + 6);
|
||||||
if (map.collide(tempx, tpy1)) return true;
|
if (map.collide(tempx, tpy1, invincible)) return true;
|
||||||
if (map.collide(tempw, tpy1)) return true;
|
if (map.collide(tempw, tpy1, invincible)) return true;
|
||||||
if (temprect.h >= 18)
|
if (temprect.h >= 18)
|
||||||
{
|
{
|
||||||
tpy1 = getgridpoint(temprect.y + 12);
|
tpy1 = getgridpoint(temprect.y + 12);
|
||||||
if (map.collide(tempx, tpy1)) return true;
|
if (map.collide(tempx, tpy1, invincible)) return true;
|
||||||
if (map.collide(tempw, tpy1)) return true;
|
if (map.collide(tempw, tpy1, invincible)) return true;
|
||||||
if (temprect.h >= 24)
|
if (temprect.h >= 24)
|
||||||
{
|
{
|
||||||
tpy1 = getgridpoint(temprect.y + 18);
|
tpy1 = getgridpoint(temprect.y + 18);
|
||||||
if (map.collide(tempx, tpy1)) return true;
|
if (map.collide(tempx, tpy1, invincible)) return true;
|
||||||
if (map.collide(tempw, tpy1)) return true;
|
if (map.collide(tempw, tpy1, invincible)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (temprect.w >= 12)
|
if (temprect.w >= 12)
|
||||||
{
|
{
|
||||||
int tpx1 = getgridpoint(temprect.x + 6);
|
int tpx1 = getgridpoint(temprect.x + 6);
|
||||||
if (map.collide(tpx1, tempy)) return true;
|
if (map.collide(tpx1, tempy, invincible)) return true;
|
||||||
if (map.collide(tpx1, temph)) return true;
|
if (map.collide(tpx1, temph, invincible)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool entityclass::checkwall(const SDL_Rect& temprect)
|
bool entityclass::checkwall(const bool invincible, const SDL_Rect& temprect)
|
||||||
{
|
{
|
||||||
// Same as above but use default arguments for blocks
|
// Same as above but use default arguments for blocks
|
||||||
return checkwall(temprect, 0, 0, 0, true, false);
|
return checkwall(invincible, temprect, 0, 0, 0, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
float entityclass::hplatformat(const int px, const int py)
|
float entityclass::hplatformat(const int px, const int py)
|
||||||
|
@ -4396,7 +4401,9 @@ bool entityclass::entitycollidefloor( int t )
|
||||||
temprect.w = entities[t].w;
|
temprect.w = entities[t].w;
|
||||||
temprect.h = entities[t].h;
|
temprect.h = entities[t].h;
|
||||||
|
|
||||||
if (checkwall(temprect)) return true;
|
const bool invincible = map.invincibility && entities[t].ishumanoid();
|
||||||
|
|
||||||
|
if (checkwall(invincible, temprect)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4414,7 +4421,9 @@ bool entityclass::entitycollideroof( int t )
|
||||||
temprect.w = entities[t].w;
|
temprect.w = entities[t].w;
|
||||||
temprect.h = entities[t].h;
|
temprect.h = entities[t].h;
|
||||||
|
|
||||||
if (checkwall(temprect)) return true;
|
const bool invincible = map.invincibility && entities[t].ishumanoid();
|
||||||
|
|
||||||
|
if (checkwall(invincible, temprect)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4438,8 +4447,10 @@ bool entityclass::testwallsx( int t, int tx, int ty, const bool skipdirblocks )
|
||||||
if (entities[t].rule == 0) dx = entities[t].vx;
|
if (entities[t].rule == 0) dx = entities[t].vx;
|
||||||
float dr = entities[t].rule;
|
float dr = entities[t].rule;
|
||||||
|
|
||||||
|
const bool invincible = map.invincibility && entities[t].ishumanoid();
|
||||||
|
|
||||||
//Ok, now we check walls
|
//Ok, now we check walls
|
||||||
if (checkwall(temprect, dx, dy, dr, skipblocks, skipdirblocks))
|
if (checkwall(invincible, temprect, dx, dy, dr, skipblocks, skipdirblocks))
|
||||||
{
|
{
|
||||||
if (entities[t].vx > 1.0f)
|
if (entities[t].vx > 1.0f)
|
||||||
{
|
{
|
||||||
|
@ -4483,8 +4494,10 @@ bool entityclass::testwallsy( int t, float tx, float ty )
|
||||||
if (entities[t].rule == 0) dy = entities[t].vy;
|
if (entities[t].rule == 0) dy = entities[t].vy;
|
||||||
float dr = entities[t].rule;
|
float dr = entities[t].rule;
|
||||||
|
|
||||||
|
const bool invincible = map.invincibility && entities[t].ishumanoid();
|
||||||
|
|
||||||
//Ok, now we check walls
|
//Ok, now we check walls
|
||||||
if (checkwall(temprect, dx, dy, dr, skipblocks, false))
|
if (checkwall(invincible, temprect, dx, dy, dr, skipblocks, false))
|
||||||
{
|
{
|
||||||
if (entities[t].vy > 1)
|
if (entities[t].vy > 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -129,8 +129,8 @@ public:
|
||||||
|
|
||||||
bool checktowerspikes(int t);
|
bool checktowerspikes(int t);
|
||||||
|
|
||||||
bool checkwall(const SDL_Rect& temprect, const float dx, const float dy, const float dr, const bool skipblocks, const bool skipdirblocks);
|
bool checkwall(const bool invincible, const SDL_Rect& temprect, const float dx, const float dy, const float dr, const bool skipblocks, const bool skipdirblocks);
|
||||||
bool checkwall(const SDL_Rect& temprect);
|
bool checkwall(const bool invincible, const SDL_Rect& temprect);
|
||||||
|
|
||||||
float hplatformat(const int px, const int py);
|
float hplatformat(const int px, const int py);
|
||||||
|
|
||||||
|
|
|
@ -672,19 +672,18 @@ void mapclass::settowercolour(int t)
|
||||||
updatebgobj(graphics.titlebg);
|
updatebgobj(graphics.titlebg);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mapclass::spikecollide(int x, int y)
|
bool mapclass::towerspikecollide(int x, int y)
|
||||||
{
|
{
|
||||||
if (invincibility) return false;
|
|
||||||
if (tower.at(x,y,0)>= 6 && tower.at(x,y,0) <= 11) return true;
|
if (tower.at(x,y,0)>= 6 && tower.at(x,y,0) <= 11) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mapclass::collide(int x, int y)
|
bool mapclass::collide(int x, int y, const bool invincible)
|
||||||
{
|
{
|
||||||
if (towermode)
|
if (towermode)
|
||||||
{
|
{
|
||||||
if (tower.at(x, y, 0) >= 12 && tower.at(x, y, 0) <= 27) return true;
|
if (tower.at(x, y, 0) >= 12 && tower.at(x, y, 0) <= 27) return true;
|
||||||
if (invincibility)
|
if (invincible)
|
||||||
{
|
{
|
||||||
if (tower.at(x, y, 0) >= 6 && tower.at(x, y, 0) <= 11) return true;
|
if (tower.at(x, y, 0) >= 6 && tower.at(x, y, 0) <= 11) return true;
|
||||||
}
|
}
|
||||||
|
@ -692,14 +691,14 @@ bool mapclass::collide(int x, int y)
|
||||||
else if (tileset == 2)
|
else if (tileset == 2)
|
||||||
{
|
{
|
||||||
int tile;
|
int tile;
|
||||||
if (y == -1) return collide(x, y + 1);
|
if (y == -1) return collide(x, y + 1, invincible);
|
||||||
if (y == 29+extrarow) return collide(x, y - 1);
|
if (y == 29+extrarow) return collide(x, y - 1, invincible);
|
||||||
if (x == -1) return collide(x + 1, y);
|
if (x == -1) return collide(x + 1, y, invincible);
|
||||||
if (x == 40) return collide(x - 1, y);
|
if (x == 40) return collide(x - 1, y, invincible);
|
||||||
if (x < 0 || y < 0 || x >= 40 || y >= 29 + extrarow) return false;
|
if (x < 0 || y < 0 || x >= 40 || y >= 29 + extrarow) return false;
|
||||||
tile = contents[TILE_IDX(x, y)];
|
tile = contents[TILE_IDX(x, y)];
|
||||||
if (tile >= 12 && tile <= 27) return true;
|
if (tile >= 12 && tile <= 27) return true;
|
||||||
if (invincibility)
|
if (invincible)
|
||||||
{
|
{
|
||||||
if (tile >= 6 && tile <= 11) return true;
|
if (tile >= 6 && tile <= 11) return true;
|
||||||
}
|
}
|
||||||
|
@ -707,17 +706,17 @@ bool mapclass::collide(int x, int y)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int tile;
|
int tile;
|
||||||
if (y == -1) return collide(x, y + 1);
|
if (y == -1) return collide(x, y + 1, invincible);
|
||||||
if (y == 29+extrarow) return collide(x, y - 1);
|
if (y == 29+extrarow) return collide(x, y - 1, invincible);
|
||||||
if (x == -1) return collide(x + 1, y);
|
if (x == -1) return collide(x + 1, y, invincible);
|
||||||
if (x == 40) return collide(x - 1, y);
|
if (x == 40) return collide(x - 1, y, invincible);
|
||||||
if (x < 0 || y < 0 || x >= 40 || y >= 29+extrarow) return false;
|
if (x < 0 || y < 0 || x >= 40 || y >= 29+extrarow) return false;
|
||||||
tile = contents[TILE_IDX(x, y)];
|
tile = contents[TILE_IDX(x, y)];
|
||||||
if (tile == 1) return true;
|
if (tile == 1) return true;
|
||||||
if (tileset==0 && tile == 59) return true;
|
if (tileset==0 && tile == 59) return true;
|
||||||
if (tile>= 80 && tile < 680) return true;
|
if (tile>= 80 && tile < 680) return true;
|
||||||
if (tile == 740 && tileset==1) return true;
|
if (tile == 740 && tileset==1) return true;
|
||||||
if (invincibility)
|
if (invincible)
|
||||||
{
|
{
|
||||||
if (tile>= 6 && tile <= 9) return true;
|
if (tile>= 6 && tile <= 9) return true;
|
||||||
if (tile>= 49 && tile <= 50) return true;
|
if (tile>= 49 && tile <= 50) return true;
|
||||||
|
|
|
@ -59,9 +59,9 @@ public:
|
||||||
|
|
||||||
void settowercolour(int t);
|
void settowercolour(int t);
|
||||||
|
|
||||||
bool spikecollide(int x, int y);
|
bool towerspikecollide(int x, int y);
|
||||||
|
|
||||||
bool collide(int x, int y);
|
bool collide(int x, int y, bool invincible);
|
||||||
|
|
||||||
void settile(int xp, int yp, int t);
|
void settile(int xp, int yp, int t);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue