snek_vs_snacc/ball.c

120 lines
2.6 KiB
C

#include <stdlib.h>
#include <assert.h>
#include <curses.h>
#include "game.h"
#include "ball.h"
#include "player.h"
void init_ball(BALL* b, int x, int y, char dir, int value) {
b -> position.x = x;
b -> position.y = y;
b -> old_position.x = x;
b -> old_position.y = y;
b -> direction = dir;
b -> value = value;
b -> color = value + 2;
b -> move_tick = 0;
}
//MOVEMENT STUFF
int is_ball_passable(FIELD* f, POINT* p) {
//TODO: take obstacles into account
return p -> x > 0 &&
p -> x < f -> width - 1 &&
p -> y > 0 &&
p -> y < f -> height - 1;
}
void add_to_point(POINT* p1, POINT* p2) {
p1 -> x = p1 -> x + p2 -> x;
p1 -> y = p1 -> y + p2 -> y;
}
void direction_to_point(POINT* p, char dir) {
if(dir & 0x0010) {
p -> x = 1;
} else {
p -> x = -1;
}
if(dir & 0x0001) {
p -> y = 1;
} else {
p -> y = -1;
}
}
char point_to_direction(POINT* p) {
assert((p -> x == 1 || p -> x == -1) && (p -> y == 1 || p -> y == -1));
char dir = 0;
dir = dir | (p -> x == 1 ? 0x10 : 0);
dir = dir | (p -> y == 1 ? 0x1 : 0);
return dir;
}
void bounce(BALL* b, FIELD* f) {
POINT* pos = &(b -> position);
POINT dir;
//check if y is obstructed
direction_to_point(&dir, b -> direction);
dir.x = 0;
add_to_point(&dir, pos);
int invertY = !is_ball_passable(f, &dir);
//check if x is obstructed
direction_to_point(&dir, b -> direction);
dir.y = 0;
add_to_point(&dir, pos);
int invertX = !is_ball_passable(f, &dir);
//invert direction away from obstruction
direction_to_point(&dir, b -> direction);
dir.x = invertX ? -dir.x : dir.x;
dir.y = invertY ? -dir.y : dir.y;
b -> direction = point_to_direction(&dir);
}
void move_ball(FIELD* f, int i) {
BALL* b = f -> balls[i];
POINT* pos = &b -> position;
POINT direction_vector;
direction_to_point(&direction_vector, b -> direction);
add_to_point(&direction_vector, pos);
b -> old_position.x = b -> position.x;
b -> old_position.y = b -> position.y;
bounce(b, f);
if (is_ball_passable(f, &direction_vector)) {
b -> position = direction_vector;
} else {
direction_to_point(&direction_vector, b -> direction);
add_to_point(&direction_vector, pos);
b -> position = direction_vector;
}
if (is_on_player(f -> player, &b -> position)) {
if (f -> player -> body[f -> player -> head_ptr] -> x == pos -> x &&
f -> player -> body[f -> player -> head_ptr] -> y == pos -> y) {
eat_ball(f, i);
} else {
set_lost(f -> state);
}
}
}
void move_balls(FIELD* f) {
for (int i = 0; i < f -> ball_count; i++) {
BALL* b = f -> balls[i];
b -> move_tick += (b -> value * b -> value);
if (b -> move_tick > 15) {
b -> move_tick = 0;
move_ball(f, i);
}
}
}