multiple balls

This commit is contained in:
Zack Buhman 2025-12-05 13:14:33 -06:00
parent 617b12c9f9
commit 5299fa66af
5 changed files with 86 additions and 37 deletions

View File

@ -10,6 +10,15 @@ extern "C" {
double destroyed_time; double destroyed_time;
}; };
struct ball_state {
float ball_x;
float ball_y;
float ball_dx;
float ball_dy;
};
#define MAX_BALLS 20
struct game_state { struct game_state {
struct block_state blocks[28 * 13]; struct block_state blocks[28 * 13];
const uint8_t * level; const uint8_t * level;
@ -18,10 +27,8 @@ extern "C" {
float paddle_x; float paddle_x;
float paddle_y; float paddle_y;
float ball_x; struct ball_state balls[MAX_BALLS];
float ball_y; int balls_launched;
float ball_dx;
float ball_dy;
double start_time; double start_time;
double time; double time;

View File

@ -6,6 +6,7 @@
extern "C" { extern "C" {
#endif #endif
void launch_ball(struct game_state * state);
void reset_level(struct game_state * state); void reset_level(struct game_state * state);
void update(struct game_state * state, double time); void update(struct game_state * state, double time);

View File

@ -163,7 +163,7 @@ int main()
double frames = 1; double frames = 1;
const char * last_gamepad_name = NULL; const char * last_gamepad_name = NULL;
struct game_state state; struct game_state state = {0};
reset_level(&state); reset_level(&state);
state.start_time = glfwGetTime(); state.start_time = glfwGetTime();
@ -179,14 +179,27 @@ int main()
float paddle_dx = 0.0; float paddle_dx = 0.0;
//float paddle_dy = 0.0; //float paddle_dy = 0.0;
static bool last_x_press = false;
bool x_press = false;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
int present = glfwJoystickPresent(GLFW_JOYSTICK_1 + i); int present = glfwJoystickPresent(GLFW_JOYSTICK_1 + i);
int is_gamepad = glfwJoystickIsGamepad(GLFW_JOYSTICK_1 + i); int is_gamepad = glfwJoystickIsGamepad(GLFW_JOYSTICK_1 + i);
int count; int count;
const float * axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, &count); const float * axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, &count);
//printf("present, %d %d %s %d\n", i, count, name, is_gamepad); //printf("present, %d %d %s %d\n", i, count, name, is_gamepad);
if (present && is_gamepad && count == 6) { if (present && is_gamepad && count == 6) {
const unsigned char * buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, &count);
/*
printf("buttons count %d\n", count);
for (int i = 0; i < count; i++) {
printf("[% 2d % 2d] ", i, buttons[i]);
}
printf("\n");
*/
x_press = buttons[0] != 0;
const char * name = glfwGetJoystickName(GLFW_JOYSTICK_1 + i); const char * name = glfwGetJoystickName(GLFW_JOYSTICK_1 + i);
if (name != last_gamepad_name) { if (name != last_gamepad_name) {
printf("active gamepad: `%s`; axes: %d\n", name, count); printf("active gamepad: `%s`; axes: %d\n", name, count);
@ -204,6 +217,11 @@ int main()
} }
} }
if (!last_x_press && x_press) {
launch_ball(&state);
}
last_x_press = x_press;
float extent = 0.25; float extent = 0.25;
state.paddle_x += paddle_dx; state.paddle_x += paddle_dx;
if (state.paddle_x < extent) if (state.paddle_x < extent)

View File

@ -222,12 +222,15 @@ void render(mesh paddle_mesh,
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// render ball // render balls
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
{ for (int i = 0; i < state->balls_launched; i++) {
struct ball_state& ball = state->balls[i];
mat4x4 rx = rotate_y(PI / 2.0f); mat4x4 rx = rotate_y(PI / 2.0f);
mat4x4 t = translate(vec3(state->ball_x * 4.0f, -state->ball_y * 2.0f, 0.0)); vec3 ball_position = vec3(ball.ball_x * 4.0f, -ball.ball_y * 2.0f, 0.0);
mat4x4 t = translate(ball_position);
mat4x4 trans = a * t * rx; mat4x4 trans = a * t * rx;
mat3x3 normal_trans = submatrix(rx, 3, 3); mat3x3 normal_trans = submatrix(rx, 3, 3);

View File

@ -12,16 +12,26 @@
#include "math/float_types.hpp" #include "math/float_types.hpp"
#include "math/transform.hpp" #include "math/transform.hpp"
void launch_ball(struct game_state * state)
{
if (state->balls_launched >= MAX_BALLS)
return;
struct ball_state& ball = state->balls[state->balls_launched];
ball.ball_x = state->paddle_x;
ball.ball_y = 25.0;
ball.ball_dx = 0.1;
ball.ball_dy = -0.1;
state->balls_launched += 1;
}
void reset_level(struct game_state * state) void reset_level(struct game_state * state)
{ {
state->paddle_x = 0.0; state->paddle_x = 0.0;
state->paddle_y = 26.0; state->paddle_y = 26.0;
state->ball_x = 0.0; launch_ball(state);
state->ball_y = 25.0;
state->ball_dx = 0.1;
state->ball_dy = 0.1;
state->start_time = 0.0; state->start_time = 0.0;
@ -36,19 +46,19 @@ void reset_level(struct game_state * state)
} }
} }
static inline void ball_collision_response(struct game_state * state, static inline void ball_collision_response(struct ball_state& ball,
struct collision_data& cd) struct collision_data& cd)
{ {
state->ball_x = cd.escape_position.x / 4.0f; ball.ball_x = cd.escape_position.x / 4.0f;
state->ball_y = -cd.escape_position.y / 2.0f; ball.ball_y = -cd.escape_position.y / 2.0f;
vec3 vel = reflect(vec3(state->ball_dx, state->ball_dy, 0), cd.bounds_normal); vec3 vel = reflect(vec3(ball.ball_dx, ball.ball_dy, 0), cd.bounds_normal);
state->ball_dx = vel.x; ball.ball_dx = vel.x;
state->ball_dy = vel.y; ball.ball_dy = vel.y;
} }
void update(struct game_state * state, double time) void update_ball(struct game_state * state, struct ball_state& ball, double time)
{ {
vec3 ball_position = vec3(state->ball_x * 4.0f, -state->ball_y * 2.0f, 0.0); vec3 ball_position = vec3(ball.ball_x * 4.0f, -ball.ball_y * 2.0f, 0.0);
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// block collision // block collision
@ -70,7 +80,7 @@ void update(struct game_state * state, double time)
struct collision_data cd; struct collision_data cd;
bool collided = aabb_circle_collision(block_position, ball_position, block_bounds, &cd); bool collided = aabb_circle_collision(block_position, ball_position, block_bounds, &cd);
if (collided) { if (collided) {
ball_collision_response(state, cd); ball_collision_response(ball, cd);
state->blocks[block_ix].destroyed_time = time; state->blocks[block_ix].destroyed_time = time;
} }
} }
@ -86,31 +96,41 @@ void update(struct game_state * state, double time)
struct collision_data cd; struct collision_data cd;
bool collided = aabb_circle_collision(paddle_position, ball_position, paddle_bounds, &cd); bool collided = aabb_circle_collision(paddle_position, ball_position, paddle_bounds, &cd);
if (collided) { if (collided) {
ball_collision_response(state, cd); ball_collision_response(ball, cd);
} }
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// arena collision // arena collision
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
if ((state->ball_x + state->ball_dx * 0.4) > 12.25f) { if ((ball.ball_x + ball.ball_dx * 0.4) > 12.25f) {
state->ball_x = 12.25f; ball.ball_x = 12.25f;
state->ball_dx = -state->ball_dx; ball.ball_dx = -ball.ball_dx;
} else if ((state->ball_x + state->ball_dx * 0.4) < -0.25f) { } else if ((ball.ball_x + ball.ball_dx * 0.4) < -0.25f) {
state->ball_x = -0.25f; ball.ball_x = -0.25f;
state->ball_dx = -state->ball_dx; ball.ball_dx = -ball.ball_dx;
} }
if ((state->ball_y + state->ball_dy * 0.4) > 27.0f) { if ((ball.ball_y + ball.ball_dy * 0.4) > 27.0f) {
//state->ball_y = 27.0f; //ball.ball_y = 27.0f;
//state->ball_dy = -state->ball_dy; //ball.ball_dy = -ball.ball_dy;
} else if ((state->ball_y + state->ball_dy * 0.4) < 0.0f) { } else if ((ball.ball_y + ball.ball_dy * 0.4) < 0.0f) {
state->ball_y = 0.0f; ball.ball_y = 0.0f;
state->ball_dy = -state->ball_dy; ball.ball_dy = -ball.ball_dy;
} }
state->ball_x += state->ball_dx; ball.ball_x += ball.ball_dx;
state->ball_y += state->ball_dy; ball.ball_y += ball.ball_dy;
}
void update(struct game_state * state, double time)
{
for (int i = 0; i < state->balls_launched; i++) {
if (state->balls[i].ball_y > 30.0f)
continue;
update_ball(state, state->balls[i], time);
}
state->time = time; state->time = time;
state->remaining = 20.0 - (time - state->start_time); state->remaining = 20.0 - (time - state->start_time);