Fixed collision detection if player moves parallel to line
This commit is contained in:
110
src/game.c
110
src/game.c
@@ -40,48 +40,81 @@ void game_init(game_t* game, uint16_t ticks_per_sec) {
|
|||||||
game->ticks_sum_sec = 0;
|
game->ticks_sum_sec = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Checks if the player head (+pixels in moving direction) collides with the line with the points start & end
|
||||||
bool game_check_line_collision(player_t* player, point_t start, point_t end, uint8_t pixels){
|
bool game_check_line_collision(player_t* player, point_t start, point_t end, uint8_t pixels){
|
||||||
|
|
||||||
bool line_is_horizontal = (start.y == end.y);
|
bool line_is_horizontal = (start.y == end.y);
|
||||||
bool player_is_horizontal = (player->direction == left || player->direction == right);
|
bool player_is_horizontal = (player->direction == left || player->direction == right);
|
||||||
|
|
||||||
if(line_is_horizontal == player_is_horizontal){ // if player moves parallel to the line, there is no point in checking
|
if(line_is_horizontal == player_is_horizontal){ // if player moves parallel to the line
|
||||||
return false; // no collision possible because parallel moving
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!player_is_horizontal && (player->position.x < min(start.x, end.x) || player->position.x > max(start.x, end.x))){
|
if(player_is_horizontal && start.y != player->position.y ) {
|
||||||
return false; // if player is passing by horizontally, no collision possible
|
return false; // player is not on the same height as the line, no collision possible
|
||||||
}
|
}
|
||||||
|
|
||||||
if(player_is_horizontal && (player->position.y < min(start.y, end.y) || player->position.y > max(start.y, end.y))){
|
|
||||||
return false; // if player is passing by vertically, no collision possible
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(player->direction){
|
if(!player_is_horizontal && start.x != player->position.x ) {
|
||||||
case up:
|
return false; // player is not on the same column as the line, no collision possible
|
||||||
if(player->position.y > start.y && ((int16_t)player->position.y - pixels) <= start.y) {
|
}
|
||||||
return true; // going up and hitting a line segment
|
|
||||||
}
|
switch(player->direction){
|
||||||
break;
|
case up:
|
||||||
case down:
|
if(((int16_t)player->position.y - pixels) <= max(start.y,end.y) && ((int16_t)player->position.y - pixels) >= min(start.y,end.y)) {
|
||||||
if(player->position.y < start.y && ((int16_t)player->position.y + pixels) >= start.y) {
|
return true; // player head is inside of line
|
||||||
return true; // going down and hitting a line segment
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case down:
|
||||||
case left:
|
if(((int16_t)player->position.y + pixels) >= min(start.y,end.y) && ((int16_t)player->position.y + pixels) <= max(start.y,end.y)) {
|
||||||
if(player->position.x > start.x && ((int16_t)player->position.x - pixels) <= start.x) {
|
return true;
|
||||||
return true; // going left and hitting a line segment
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case left:
|
||||||
case right:
|
if(((int16_t)player->position.x - pixels) <= max(start.x,end.x) && ((int16_t)player->position.x - pixels) >= min(start.x,end.x)) {
|
||||||
if(player->position.x < start.x && ((int16_t)player->position.x + pixels) >= start.x) {
|
return true;
|
||||||
return true; // going right and hitting a line segment
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case right:
|
||||||
|
if(((int16_t)player->position.x + pixels) >= min(start.x,end.x) && ((int16_t)player->position.x + pixels) <= max(start.x,end.x)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else { //Player moves antiparalell to the line
|
||||||
|
|
||||||
|
if(!player_is_horizontal && (player->position.x < min(start.x, end.x) || player->position.x > max(start.x, end.x))){
|
||||||
|
return false; // if player is passing by horizontally, no collision possible
|
||||||
|
}
|
||||||
|
|
||||||
|
if(player_is_horizontal && (player->position.y < min(start.y, end.y) || player->position.y > max(start.y, end.y))){
|
||||||
|
return false; // if player is passing by vertically, no collision possible
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(player->direction){
|
||||||
|
case up:
|
||||||
|
if(player->position.y > start.y && ((int16_t)player->position.y - pixels) <= start.y) {
|
||||||
|
return true; // going up and hitting a line segment
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case down:
|
||||||
|
if(player->position.y < start.y && ((int16_t)player->position.y + pixels) >= start.y) {
|
||||||
|
return true; // going down and hitting a line segment
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case left:
|
||||||
|
if(player->position.x > start.x && ((int16_t)player->position.x - pixels) <= start.x) {
|
||||||
|
return true; // going left and hitting a line segment
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case right:
|
||||||
|
if(player->position.x < start.x && ((int16_t)player->position.x + pixels) >= start.x) {
|
||||||
|
return true; // going right and hitting a line segment
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check if the player head (+pixels in moving direction) collides with the game field boundary
|
||||||
bool game_check_boundary_collision(game_t* game, player_t* player, uint8_t pixels){
|
bool game_check_boundary_collision(game_t* game, player_t* player, uint8_t pixels){
|
||||||
|
|
||||||
// Check boundary collision
|
// Check boundary collision
|
||||||
@@ -111,6 +144,7 @@ bool game_check_boundary_collision(game_t* game, player_t* player, uint8_t pixel
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check if the player (+pixels in moving direction) collides with any other player (including itself)
|
||||||
bool game_check_player_collision(game_t* game, player_t* player, uint8_t pixels){
|
bool game_check_player_collision(game_t* game, player_t* player, uint8_t pixels){
|
||||||
// Check for collisions with players (including self)
|
// Check for collisions with players (including self)
|
||||||
for(int i = 0; i < PLAYER_COUNT; i++){
|
for(int i = 0; i < PLAYER_COUNT; i++){
|
||||||
@@ -138,7 +172,8 @@ bool game_check_player_collision(game_t* game, player_t* player, uint8_t pixels)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game_check_collision(game_t* game, player_t* player, uint8_t pixels){ // Check boundary and player collisions
|
//Check if the player (+pixels in moving direction) collides either with other players (including self) or the game field boundary
|
||||||
|
bool game_check_collision(game_t* game, player_t* player, uint8_t pixels) {
|
||||||
|
|
||||||
// Check for collisions with boundarys
|
// Check for collisions with boundarys
|
||||||
if(game_check_boundary_collision(game, player, pixels)){
|
if(game_check_boundary_collision(game, player, pixels)){
|
||||||
@@ -153,6 +188,8 @@ bool game_check_collision(game_t* game, player_t* player, uint8_t pixels){ // Ch
|
|||||||
return false; // no collision!
|
return false; // no collision!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Update the player state and draw the player. The player head will be moved by "pixels" in moving direction.
|
||||||
|
//Returns true if the player state has changed
|
||||||
bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
|
bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
|
||||||
|
|
||||||
bool direction_change = false;
|
bool direction_change = false;
|
||||||
@@ -226,6 +263,7 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
|
|||||||
return state_changed; // return state
|
return state_changed; // return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Calculates two colors out of the 16 bits, passed in confbits.
|
||||||
void game_get_color(uint16_t confbits, uint16_t* player1_color, uint16_t* player2_color) {
|
void game_get_color(uint16_t confbits, uint16_t* player1_color, uint16_t* player2_color) {
|
||||||
|
|
||||||
//we have 4 bits per player color, we use 1 bit for red, 2 for green, 1 for blue
|
//we have 4 bits per player color, we use 1 bit for red, 2 for green, 1 for blue
|
||||||
@@ -260,6 +298,8 @@ void game_get_color(uint16_t confbits, uint16_t* player1_color, uint16_t* player
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Calculates one step of the game, when the game is in the init state
|
||||||
|
//Returns true if the function was blocking, and deltaTicks should be reset
|
||||||
bool game_step_init(game_t* game) {
|
bool game_step_init(game_t* game) {
|
||||||
|
|
||||||
//Draw welcome bitmap
|
//Draw welcome bitmap
|
||||||
@@ -276,6 +316,8 @@ bool game_step_init(game_t* game) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Calculates one step of the game, when the game is in the prestart state
|
||||||
|
//Returns true if the function was blocking, and deltaTicks should be reset
|
||||||
bool game_step_prestart(game_t* game) {
|
bool game_step_prestart(game_t* game) {
|
||||||
|
|
||||||
//Draw "Player x: Color" Strings
|
//Draw "Player x: Color" Strings
|
||||||
@@ -427,6 +469,8 @@ bool game_step_prestart(game_t* game) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Calculates one step of the game, when the game is in the running state
|
||||||
|
//Returns true if the function was blocking, and deltaTicks should be reset
|
||||||
bool game_step_running(game_t* game, uint64_t delta_time)
|
bool game_step_running(game_t* game, uint64_t delta_time)
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -484,6 +528,8 @@ bool game_step_running(game_t* game, uint64_t delta_time)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Calculates one step of the game, when the game is in the ended state
|
||||||
|
//Returns true if the function was blocking, and deltaTicks should be reset
|
||||||
bool game_step_ended(game_t* game) {
|
bool game_step_ended(game_t* game) {
|
||||||
|
|
||||||
// Kill screen
|
// Kill screen
|
||||||
|
|||||||
Reference in New Issue
Block a user