void entityPhysicsApply(struct Entity* entity, double delta_time) { entity->ephysics.acceleration = vector2dAdd(entity->ephysics.acceleration, vector2dScalarMult(delta_time, entity->ephysics.jerk)); entity->ephysics.speed = vector2dAdd(entity->ephysics.speed, vector2dScalarMult(delta_time, entity->ephysics.acceleration)); entity->ephysics.prev_position = entity->position; entity->position = vector2dAdd(entity->position, vector2dScalarMult(delta_time, entity->ephysics.speed)); }
void volleyballUpdate(struct VolleyballWorld* world, double delta_time) { //gravity for (struct EntityListNode* node = world->super.entities; node != NULL; node = node->next) { if (!node->entity->ephysics.b_static) { node->entity->ephysics.speed = vector2dAdd(node->entity->ephysics.speed, vector2dScalarMult(delta_time, world->wphysics.gravity)); } } //apply entity physics for (struct EntityListNode* node = world->super.entities; node != NULL; node = node->next) { if (node->entity == world->ball && node->entity->position.y > 50 - (world->ball->sprite->h)) { node->entity->ephysics.speed.y *= -1.0; //node->entity->position.y = 50 - node->entity->sprite->h - 0.1; } if (node->entity == world->ball && node->entity->position.x < 0) { node->entity->ephysics.speed.x *= -1.0; //node->entity->position.x = 0.1; } if (node->entity == world->ball && node->entity->position.x > 80 - world->ball->sprite->w) { node->entity->ephysics.speed.x *= -1.0; //node->entity->position.x = 80 - node->entity->sprite->w - 0.1; } if (!node->entity->ephysics.b_static) { entityPhysicsApply(node->entity, delta_time); } if (node->entity == world->player1 || node->entity == world->player2) { if (node->entity->position.y > 40.0) { node->entity->position.y = 40.0; struct Vector2d zero_vector = { 0.0, 0.0 }; node->entity->ephysics.jerk = zero_vector; node->entity->ephysics.acceleration = zero_vector; node->entity->ephysics.speed = zero_vector; } } } for (struct Entity* entity = world->player1; ; entity = world->player2) { struct Entity* ball = world->ball; struct Vector2d g_ball_center = vector2dAdd(ball->ephysics.center, ball->position); struct Vector2d g_entity_center = vector2dAdd(entity->ephysics.center, entity->position); struct Vector2d distance = vector2dSubtract(g_ball_center, g_entity_center); if (vector2dMagnitude(distance) < (ball->ephysics.radius + entity->ephysics.radius)) { struct Vector2d mov_vector = vector2dSubtract(ball->position, ball->ephysics.prev_position); struct Vector2d ret_vector = vector2dNormalize(vector2dSymmetry(distance, mov_vector)); ball->ephysics.speed = vector2dScalarMult(vector2dMagnitude(ball->ephysics.speed), ret_vector); ball->ephysics.acceleration = vector2dScalarMult(vector2dMagnitude(ball->ephysics.acceleration), ret_vector); } if (entity == world->player2) { break; } } /*for (struct Entity* entity = world->player1; ; entity = world->player2) { struct Entity* ball = world->ball; struct Vector2d g_ball_center = vector2dAdd(ball->ephysics.center, ball->position); struct Vector2d g_entity_center = vector2dAdd(entity->ephysics.center, entity->position); struct Vector2d distance = vector2dSubtract(g_ball_center, g_entity_center); if (vector2dMagnitude(distance) < (ball->ephysics.radius + entity->ephysics.radius)) { double alpha = atan2(g_ball_center.y - g_entity_center.y, g_ball_center.x - g_entity_center.x); double beta = atan2(ball->ephysics.speed.y, ball->ephysics.speed.x); double new_beta = 2 * alpha - beta + M_PI; double length_beta = vector2dMagnitude(ball->ephysics.speed); double ball_speed_x_old = ball->ephysics.speed.x; //ball->ephysics.speed.x = -cos(new_beta) ball->ephysics.speed.x = -cos(new_beta) * length_beta; ball->ephysics.speed.y = sin(new_beta) * length_beta; if (ball->ephysics.speed.x + ball_speed_x_old <= 4e-8 && ball->ephysics.speed.x + ball_speed_x_old >= -4e-8) { ball->ephysics.speed.x = ball_speed_x_old; } ball->position.x = g_entity_center.x - ball->ephysics.radius + (cos(alpha) * (entity->ephysics.radius + ball->ephysics.radius)); ball->position.y = g_entity_center.y - ball->ephysics.radius - (sin(alpha) * (entity->ephysics.radius + ball->ephysics.radius)); } if (entity == world->player2) { break; } }*/ //ball <> player1 /* distance2 = GetDistance2(collision_ball.x, collision_ball.y, collision_p1.x, collision_p1.y); if (distance2 < collision_distance2) { alpha = atan2(collision_ball.y - collision_p1.y, collision_ball.x - collision_p1.x); beta = atan2(ball->GetSpeedY(), ball->GetSpeedX()); new_beta = alpha + alpha - beta + pi; length_beta = sqrt((ball->GetSpeedX() ball->GetSpeedX()) + (ball->GetSpeedY() ball->GetSpeedY())); ball_vector_x_old = ball->GetSpeedX(); ball->SetAngularVelocity((beta - new_beta + pi) / pi 180 0.01); ball->SetAngularVelocity(ball->GetAngularVelocity() * ball->GetAngularVelocity()); ball->SetSpeedX(-cos(new_beta) length_beta + (player1_vector_x inh_vector)); ball->SetSpeedY(sin(new_beta) length_beta + (player1->GetSpeedY() inh_vector)); if (ball->GetSpeedX() + ball_vector_x_old <= vector_tolerance && ball->GetSpeedX() + ball_vector_x_old >= -vector_tolerance) ball->SetSpeedX(ball_vector_x_old); ball->SetposX(collision_p1.x - ballRadius + (cos(alpha) * (playerRadius + ballRadius))); ball->SetposY(ScreenHeight - collision_p1.y - ballRadius - (sin(alpha) * (playerRadius + ballRadius))); } */ //check for collisions multiple times in case collision handling creates new collisions /*for (int i = 0; i < 1; i++) { for (struct EntityListNode* node1 = world->super.entities; node1 != NULL; node1 = node1->next) { for (struct EntityListNode* node2 = node1->next; node2 != NULL; node2 = node2->next) { // ARON SHAME: node2 = node2 = node2->next if (!(node1->entity->ephysics.b_collides && node2->entity->ephysics.b_collides)) { continue; } struct Entity* entity1 = node1->entity; struct Entity* entity2 = node2->entity; unsigned int points_len; struct Vector2d* collision_points = collisionPixelPerfect(entity1, entity2, &points_len); //if collision if (collision_points != NULL) { //failsafe - not sure if ever used bool e1_failsafe = false; bool e2_failsafe = false; //if more than one collision point if (points_len > 1) { //make trend line (tl) based on the collision points - our bouncing line struct Vector2d tl_vector = vector2dTrendLine(collision_points, points_len); struct Vector2d tl_start = vector2dCenterOfMass(collision_points, points_len); //check if entities are affected by collisions //bouncing //entity1 if (!entity1->ephysics.b_static && entity1->ephysics.b_affected_by_collisions) { //prev position -> position = displacement vector; displacement (ds) //magic struct Vector2d displacement_vector = vector2dSubtract(entity1->position, entity1->ephysics.prev_position); if (vector2dMagnitude(displacement_vector) > 0.000001) { struct Vector2d tl_ds_intersection = vector2dLineLineIntersection(tl_start, tl_vector, entity1->ephysics.prev_position, displacement_vector, &e1_failsafe); if (!e1_failsafe) { struct Vector2d new_vector = vector2dNormalize(vector2dReflection(tl_vector, displacement_vector)); double collision_distance = vector2dPointPointDistance(entity1->position, tl_ds_intersection); entity1->ephysics.prev_position = entity1->position; entity1->position = vector2dAdd(tl_ds_intersection, vector2dScalarMult(collision_distance, new_vector)); entity1->ephysics.jerk = vector2dScalarMult(entity1->ephysics.bounciness*vector2dMagnitude(entity1->ephysics.jerk), new_vector); entity1->ephysics.acceleration = vector2dScalarMult(entity1->ephysics.bounciness*vector2dMagnitude(entity1->ephysics.acceleration), new_vector); entity1->ephysics.speed = vector2dScalarMult(entity1->ephysics.bounciness*vector2dMagnitude(entity1->ephysics.speed), new_vector); } } } //entity2 if (!entity2->ephysics.b_static && entity2->ephysics.b_affected_by_collisions) { struct Vector2d displacement_vector = vector2dSubtract(entity2->position, entity2->ephysics.prev_position); if (vector2dMagnitude(displacement_vector) > 0.000001) { struct Vector2d tl_ds_intersection = vector2dLineLineIntersection(tl_start, tl_vector, entity2->ephysics.prev_position, displacement_vector, &e1_failsafe); if (!e1_failsafe) { struct Vector2d new_vector = vector2dNormalize(vector2dReflection(tl_vector, displacement_vector)); double collision_distance = vector2dPointPointDistance(entity2->position, tl_ds_intersection); entity2->ephysics.prev_position = entity2->position; entity2->position = vector2dAdd(tl_ds_intersection, vector2dScalarMult(collision_distance, new_vector)); entity2->ephysics.jerk = vector2dScalarMult(entity2->ephysics.bounciness*vector2dMagnitude(entity2->ephysics.jerk), new_vector); entity2->ephysics.acceleration = vector2dScalarMult(entity2->ephysics.bounciness*vector2dMagnitude(entity2->ephysics.acceleration), new_vector); entity2->ephysics.speed = vector2dScalarMult(entity2->ephysics.bounciness*vector2dMagnitude(entity2->ephysics.speed), new_vector); } } } } if (points_len == 1 || e1_failsafe || e2_failsafe) { struct Vector2d cp_CoM = vector2dCenterOfMass(collision_points, points_len); // center of mass of collision points if ((!entity1->ephysics.b_static && entity1->ephysics.b_affected_by_collisions) && (points_len == 1 || e1_failsafe)) { struct Vector2d speed_normalized = vector2dNormalize(entity1->ephysics.speed); struct Vector2d pos_cp_CoM_normalized = vector2dNormalize(vector2dSubtract(cp_CoM, entity1->position)); //position -> cp_CoM struct Vector2d virtual_tl_vector = vector2dNormal(vector2dAdd(speed_normalized, pos_cp_CoM_normalized)); //virtual trend line vector struct Vector2d displacement_vector = vector2dSubtract(entity1->position, entity1->ephysics.prev_position); if (vector2dMagnitude(displacement_vector) > 0.000001) { struct Vector2d tl_ds_intersection = vector2dLineLineIntersection(cp_CoM, virtual_tl_vector, entity1->ephysics.prev_position, displacement_vector, &e1_failsafe); if (!e1_failsafe) { struct Vector2d new_vector = vector2dNormalize(vector2dReflection(virtual_tl_vector, displacement_vector)); double collision_distance = vector2dPointPointDistance(entity1->position, tl_ds_intersection); entity1->ephysics.prev_position = entity1->position; entity1->position = vector2dAdd(cp_CoM, vector2dScalarMult(collision_distance, new_vector)); entity1->ephysics.jerk = vector2dScalarMult(entity1->ephysics.bounciness*vector2dMagnitude(entity1->ephysics.jerk), new_vector); entity1->ephysics.acceleration = vector2dScalarMult(entity1->ephysics.bounciness*vector2dMagnitude(entity1->ephysics.acceleration), new_vector); entity1->ephysics.speed = vector2dScalarMult(entity1->ephysics.bounciness*vector2dMagnitude(entity1->ephysics.speed), new_vector); } } } if ((!entity2->ephysics.b_static && entity2->ephysics.b_affected_by_collisions) && (points_len == 1 || e2_failsafe)) { struct Vector2d speed_normalized = vector2dNormalize(entity1->ephysics.speed); struct Vector2d pos_cp_CoM_normalized = vector2dNormalize(vector2dSubtract(cp_CoM, entity1->position)); //position -> cp_CoM struct Vector2d virtual_tl_vector = vector2dNormal(vector2dAdd(speed_normalized, pos_cp_CoM_normalized)); //virtual trend line vector struct Vector2d displacement_vector = vector2dSubtract(entity2->position, entity2->ephysics.prev_position); if (vector2dMagnitude(displacement_vector) > 0.000001) { struct Vector2d tl_ds_intersection = vector2dLineLineIntersection(cp_CoM, virtual_tl_vector, entity2->ephysics.prev_position, displacement_vector, &e1_failsafe); if (!e1_failsafe) { struct Vector2d new_vector = vector2dNormalize(vector2dReflection(virtual_tl_vector, displacement_vector)); double collision_distance = vector2dPointPointDistance(entity2->position, tl_ds_intersection); entity2->ephysics.prev_position = entity2->position; entity2->position = vector2dAdd(cp_CoM, vector2dScalarMult(collision_distance, new_vector)); entity2->ephysics.jerk = vector2dScalarMult(entity2->ephysics.bounciness*vector2dMagnitude(entity2->ephysics.jerk), new_vector); entity2->ephysics.acceleration = vector2dScalarMult(entity2->ephysics.bounciness*vector2dMagnitude(entity2->ephysics.acceleration), new_vector); entity2->ephysics.speed = vector2dScalarMult(entity2->ephysics.bounciness*vector2dMagnitude(entity2->ephysics.speed), new_vector); } } } } //no need to call it on NULL ptr free(collision_points); } } } }*/ }