120 lines
2.6 KiB
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);
|
|
}
|
|
}
|
|
}
|