void process_game(t_game *game) { int collisiontype; int i; if (game->playing) { handle_bar_position(game); if (!game->bar.sticky_ball) { i = -1; while (++i < 10) { if ((collisiontype = future_ball_collision(game))) { handle_collision(game, collisiontype); break ; } else do_ball_motion(game); } } if (game->ball.y > WIN_HEIGHT - BAR_MARGIN + 15) reset_game(game); if (count_brick(game->bricks->next) == 0) change_level(game); } }
void update(float dt) { // Update view pitch += 1.2f * dPitch * dt; yaw += 1.2f * dYaw * dt; set_view(pitch, yaw); // Set X/Z velocity depending on input velocity.x = velocity.z = 0.0f; if (keys[KEY_A] & 1) { velocity.x += 3.0f * cosf(M_PI - yaw); velocity.z += 3.0f * sinf(M_PI - yaw); } if (keys[KEY_W] & 1) { velocity.x += 3.0f * cosf(-M_PI / 2 - yaw); velocity.z += 3.0f * sinf(-M_PI / 2 - yaw); } if (keys[KEY_S] & 1) { velocity.x += 3.0f * cosf(M_PI / 2 - yaw); velocity.z += 3.0f * sinf(M_PI / 2 - yaw); } if (keys[KEY_D] & 1) { velocity.x += 3.0f * cosf(-yaw); velocity.z += 3.0f * sinf(-yaw); } // Simulate gravity velocity.y -= 20.0f * dt; // Handle block collision (head, lower body and feet) vec3 headPos = playerPos; vec3 lowerPos = playerPos; lowerPos.y -= 1.0f; vec3 footPos = playerPos; footPos.y -= 1.8f; handle_collision(headPos, &velocity); handle_collision(lowerPos, &velocity); handle_collision(footPos, &velocity); // Apply motion playerPos.x += velocity.x * dt; playerPos.y += velocity.y * dt; playerPos.z += velocity.z * dt; }
static int fill_hashtable(struct elf_htable *htable, struct kernel_symbol *start, struct kernel_symbol *stop, long s_offset) { struct kernel_symbol *ksym; uint32_t nb; unsigned long hvalue; int last_chain_slot; /* sanity check */ if ((htable->elf_buckets == NULL) || (htable->chains == NULL)) return -1; /* Initialize buckets and chains with -1 that means empty */ memset(htable->elf_buckets, -1, htable->nbucket * sizeof(uint32_t)); memset(htable->chains, -1, htable->nchain * sizeof(uint32_t)); nb = htable->nbucket; for (ksym = start, hvalue = 0; ksym < stop; ksym++, hvalue++) { const unsigned char *name = GET_KSTRING(ksym, s_offset); unsigned long h = gnu_hash(name); unsigned long idx = h % nb; uint32_t *slot = &htable->elf_buckets[idx]; /* * Store the index of the export symbol ksym in its * related __ksymtable in the hash table buckets for * using during lookup. * If the slot is alredy used ( != -1) then we have a collision * it needs to create an entry in the chain */ if (*slot == EMPTY_SLOT) *slot = hvalue; else { if (handle_collision(htable, *slot, hvalue) < 0) /* Something wrong happened */ return -1; } } /* * Update the chain lenght with the best value * so that we will cut unused entries beyond this upper limit * In the best case, when there are not collisions, htable->chains * will be 0 size... good ! */ /* Look for upper chains empty slot */ for (last_chain_slot = htable->nchain; --last_chain_slot >= 0 && htable->chains[last_chain_slot] == EMPTY_SLOT;); htable->nchain = last_chain_slot + 1; debugp("\t> Shortest chain lenght = %d\n", htable->nchain); return 0; }
inline bool Racer::run(double tmintv) { assert(!has_arrived_); // up run uprun(tmintv); // side run siderun(tmintv); RaceTrack::ColliType colli; if ( racetrack_->terminal_arrived(pos_) ) { return !(has_arrived_ = true); } else if ( racetrack_->chk_collision(pos_, colli) && (last_colli_ != colli) ) { handle_collision(colli); //DEBUG_LOG("1: %u Collision %d At (%f, %f)", p_->id, colli.item, pos_.y, pos_.x); if ( colli.item == ITEM_track_border ) { // collided at border if ( racetrack_->chk_collision(pos_, colli) && (last_colli_ != colli) ) { handle_collision(colli); if ( !racetrack_->edible(colli.item) ) { last_colli_ = colli; } } //DEBUG_LOG("2: %u Collision %d At (%f, %f)", p_->id, colli.item, pos_.y, pos_.x); } else if ( !racetrack_->edible(colli.item) ) { last_colli_ = colli; } } //DEBUG_LOG("id=%u UpSpd=%f SideSpd=%f UpAcc=%f SideAcc=%f " // "Pos=%f, %f\n", p_->id, upspeed_, sidespeed_, upacc_, 0.0/*sideacc_*/, pos_.y, pos_.x); return true;
void World::detect_collisions() { // Handle collisions with local objects //double minDistance = 20.0; for (std::vector<Object_mpi *>::iterator itr = objects.begin(); itr != objects.end(); ++itr) { for (std::vector<Object_mpi *>::iterator otherItr = itr; otherItr != objects.end(); ++otherItr) { if ((*itr)->getID() != (*otherItr)->getID()) { // Get distance between centers of spheres double distance = sqrt( pow((*itr)->x()-(*otherItr)->x(), 2) + pow((*itr)->y()-(*otherItr)->y(), 2) + pow((*itr)->z()-(*otherItr)->z(), 2) ); //if (distance < minDistance) minDistance = distance; //if (rank == 0) std::cout << "radius: " << (*itr)->getRadius() << std::endl; if (distance < 2*(*itr)->getRadius()) { handle_collision((*itr), (*otherItr)); //std::cout << "LOCAL BOUNCE" << std::endl; } } } } //if (rank == 0) std::cout << "min distance: " << minDistance << std::endl; detect_collisions_world_boundaries(); }
/* Handle collisions: return the max of the used slot of the chain -1 in case of error */ int handle_collision(struct elf_htable *htable, unsigned long idx, unsigned long value) { uint32_t *slot; /* sanity check: check chain's boundary */ if (idx >= htable->nchain) return -1; slot = &htable->chains[idx]; /* Fill the chains[idx] with the new value, if empty. */ if (*slot == EMPTY_SLOT) { *slot = value; return 0; } /* * If the slot is already used, used the value itself * as a new index for the next chain entry. * Do it recursively. */ return handle_collision(htable, *slot, value); }
/*------------------------------------------------------------------------*/ static uint32 sieve_lattice_batch(msieve_obj *obj, lattice_fb_t *L) { uint32 i, j, k; p_soa_var_t * p_array = (p_soa_var_t *)L->p_array; p_soa_var_t * q_array = (p_soa_var_t *)L->q_array; uint32 num_poly = L->poly->num_poly; uint32 num_p = p_array->num_p; for (i = 0; i < q_array->num_p; i++) { uint64 q = q_array->p[i]; uint128 q2 = wide_sqr64(q); uint32 q2_w = montmul32_w(q2.w[0]); uint128 q2_r = montmul128_r(q2); uint32 num_p_done = 0; time_t curr_time; double elapsed; while (num_p_done < num_p) { uint64 *plist = p_array->p + num_p_done; uint128 pinvlist[INVERT_BATCH_SIZE]; uint32 curr_num_p = MIN(INVERT_BATCH_SIZE, num_p - num_p_done); batch_invert(plist, curr_num_p, pinvlist, q2, q2_r, q2_w); for (j = 0; j < curr_num_p; j++) { uint64 p = plist[j]; uint128 pinv = pinvlist[j]; uint64 lattice_size = p_array->lattice_size[num_p_done+j]; uint128 test1; test1.w[0] = (uint32)lattice_size; test1.w[1] = (uint32)(lattice_size >> 32); test1.w[2] = 0; test1.w[3] = 0; for (k = 0; k < num_poly; k++) { uint128 qroot, proot, res; qroot = q_array->roots[k][i]; proot = p_array->roots[k][num_p_done+j]; res = montmul128(pinv, modsub128(qroot, proot, q2), q2, q2_w); if (cmp128(res, test1) < 0) { handle_collision(L->poly, k, p, proot, res, q); } } } num_p_done += curr_num_p; } if (obj->flags & MSIEVE_FLAG_STOP_SIEVING) return 1; curr_time = time(NULL); elapsed = curr_time - L->start_time; if (elapsed > L->deadline) return 1; } return 0; }
// Calculate the consequences of a collision between two pool balls. // It's handled like a 2D elastic collision between two circles, really; // Sorry, no jumping the cue ball at this point. // The long double precision is unnecessary; it's just there because I // was trying to eliminate potential precision errors while debugging // a really stupid typo in the collision detection code and t ended // up a long double. // // thanks to http://www.vobarian.com/collisions/2dcollisions2.pdf // for the algorithm and sample code // // other is the other ball; it will be moved into the position of collision // // t*time_fraction is the multiplier for dx,dz to move the balls into the position where they collide // t may be 0.0 if some balls intersected :/ // // // Note that this algorithm moves the balls immediately and then // updates movement_remaining. A more sound implementation would // make a list of all the possible collisions, wind time to the first // collision, update that, and recalculate everything. However, this // is not meant to be a totally rigorous physics simulation. // We don't need all that. We need just enough physics to have fun. // void PoolBall::handle_collision(PoolBall& other, long double t, double time_fraction) { if (mass == 0.0 || other.mass == 0.0) return; // ephemeral entities do not collide // roll balls to the point of impact if (t != 0.0 && time_fraction != 0.0) { actually_reposition(dx*t*time_fraction, dz*t*time_fraction); movement_remaining -= t; other.actually_reposition(other.dx*t*time_fraction, other.dz*t*time_fraction); other.movement_remaining -= t; } // unit normal and unit tangent vectors double uNx = other.x - x; // normal double uNz = other.z - z; double mag = sqrt(uNx*uNx + uNz*uNz); uNx /= mag; // normalized (unit) normal uNz /= mag; // untangle stupid-ass intersected spheres. ugh! if (abs(t) < std::numeric_limits<double>::epsilon()) { other.actually_reposition((diameter-mag) * uNx * 1.0001, (diameter-mag) * uNz * 1.0001); return handle_collision(other, -1.0, 0); // uNz, uNz, etc. have to be recalculated } double uTx = -uNz; // unit tangent double uTz = uNx; // scalar projections of velocities onto above vectors double v1n = dotProduct(uNx, uNz, dx, dz); double v1t = dotProduct(uTx, uTz, dx, dz); double v2n = dotProduct(uNx, uNz, other.dx, other.dz); double v2t = dotProduct(uTx, uTz, other.dx, other.dz); // tangential velocities don't change in a purely elastic collision // apply coefficient of restitution to the velocity projections v1n *= COrestitution; v2n *= COrestitution; // normal velocities do: double v1n_prime = (v1n * (mass - other.mass) + 2.0 * other.mass * v2n) / (mass + other.mass); double v2n_prime = (v2n * (other.mass - mass) + 2.0 * mass * v1n) / (mass + other.mass); // the new velocity vectors are vXn_prime * uN + vXt * uT dx = v1n_prime * uNx + v1t * uTx; dz = v1n_prime * uNz + v1t * uTz; other.dx = v2n_prime * uNx + v2t * uTx; other.dz = v2n_prime * uNz + v2t * uTz; // play a collision sound Mix_PlayChannel(index%8, Sounds::ballclack, 0); Mix_Volume(index%8, (int) (64.0 * ((abs(v1n_prime) + abs(v2n_prime)) / (max_speed*2.0)))); // scale the volume to the total normal velocity relative to max speed that two balls could have // 128 is max channel volume but it's rude to blast max volume at people //next_channel(); }
// called for the ball to update its stupid position and crash into other stupid things // this needs the full declaration of PoolTable to function, hence this location.... void PoolBall::move(double base_time_fraction) { if (movement_remaining == 0.0) return; // sanity check... if (dx*base_time_fraction > table->length || dz*base_time_fraction > table->length) { fprintf(stderr, "velocity insanity.\n"); return; } if (!inplay) return; double time_fraction = base_time_fraction * movement_remaining; double fdx = dx * time_fraction; double fdz = dz * time_fraction; // test for collisions with the walls // this uses some algorithms based on the collision of a ray with a plane, in 2D // the original 3D formula is here: http://www.cs.princeton.edu/courses/archive/fall00/cs426/lectures/raycast/sld017.htm // or here: http://cgafaq.info/wiki/Ray_Plane_Intersection // or dozens of other pages on the net, some with fewer typos than others // though they're not really specific to any number of dimensions... // t = N·(Q-E) / N·D // where N is a normal vector of the plane, Q is a point on the plane, // E is the ray origin, // and D is the ray's direction vector // if t < 0, the plane is behind the origin // if N·D=0, the ray is parallel to the plane // if t >=0, the intersection point is E + tD double NdotD, numerator, tx, tz; double Qx, Qz; double Nx, Nz; if (fdx > 0.0) { // test distance to right wall Qx = table->width/2; Qz = 0; Nx = -1; Nz = 0; NdotD = dotProduct(Nx, Nz, fdx, fdz); numerator = dotProduct(Nx, Nz, Qx-(x+diameter/2), Qz-z); // x+diameter/2 rather than just x because we're testing the collison // of the surface of the ball rather than its center tx = numerator / NdotD; } else if (fdx < 0.0) { // try the left wall Qx = -table->width/2; Qz = 0; Nx = 1; Nz = 0; NdotD = dotProduct(Nx, Nz, fdx, fdz); numerator = dotProduct(Nx, Nz, Qx-(x-diameter/2), Qz-z); tx = numerator / NdotD; } else tx = 1000000.0; // just some impossibly-large number if (fdz > 0.0) { // test distance to near wall Qx = 0; Qz = table->length/2; Nx = 0; Nz = -1; NdotD = dotProduct(Nx, Nz, fdx, fdz); numerator = dotProduct(Nx, Nz, Qx-x, Qz-(z+diameter/2)); // x+diameter/2 rather than just x because we're testing the collison // of the surface of the ball rather than its center tz = numerator / NdotD; } else if (fdz < 0.0) { // try the far wall Qx = 0; Qz = -table->length/2; Nx = 0; Nz = 1; NdotD = dotProduct(Nx, Nz, fdx, fdz); numerator = dotProduct(Nx, Nz, Qx-x, Qz-(z-diameter/2)); tz = numerator / NdotD; } else tz = 1000000.0; // just some impossibly-large number // the ball will be closer to one of the sides than the other, probably if (tx < tz) { if (tx < 1.0) { //fprintf(stderr, "tx==%g\n", tx); double t_rest = 1.0 - tx; // {x,y} + {fdx,fdy} * tx = the point where the ball hits the table actually_reposition(fdx*tx, fdz*tx); test_pocket(); dx *= -1; // BOUNCE! :D movement_remaining = t_rest; return move(time_fraction); } } else { if (tz < 1.0) { //fprintf(stderr, "tz==%g\n", tz); double t_rest = 1.0 - tz; // {x,y} + {fdx,fdy} * tx = the point where the ball hits the table actually_reposition(fdx*tz, fdz*tz); test_pocket(); dz *= -1; // BOUNCE! :D movement_remaining = t_rest; return move(time_fraction); } } // wall code done // test for collisions with other balls // I found this to be very helpful: // http://twobitcoder.blogspot.com/2010/04/circle-collision-detection.html double Vabx, Vabz; double Pabx, Pabz; long double a, b, c; // sort the balls by distance, check nearest for collisions first PoolBall *sorted[table->maxballs]; for (int r = 0, w = 0; r < table->maxballs; ++w, ++r) sorted[w] = table->ball[r]; current_ball = this; // for PoolBall_distance_cmp(); see its implementation qsort(sorted, table->balls, sizeof(PoolBall*), PoolBall_distance_cmp); for (int i = 0; i < table->balls; ++i) { if (sorted[i]->index == index) continue; // could probably just start at index 1 but let's not make this confusing... // test whether other ball has already run move() this frame??? XXX if (!(sorted[i]->inplay)) continue; // Don't collide with balls in pockets... Pabx = x - sorted[i]-> x; // vector in the direction of the other ball? or whatever? derp Pabz = z - sorted[i]-> z; // sanity-check current distance! if ((Pabx*Pabx + Pabz*Pabz) < diameter*diameter) { //fputs("unfortunate intersection.\n", stderr); handle_collision(*(sorted[i]), 0.0, time_fraction); fdx = dx * time_fraction; fdz = dz * time_fraction; //break; // Just stop doing things, algorithm. Clearly you're not good at them. } Vabx = fdx - sorted[i]->dx*time_fraction; // relative velocity vector Vabz = fdz - sorted[i]->dz*time_fraction; if (abs(Vabx) < 0.00000001) Vabx = 0.0; if (abs(Vabz) < 0.00000001) Vabz = 0.0; if (Vabx == 0.0 && Vabz == 0.0) continue; // no relative motion? clearly not going to collide, huh. a = dotProduct(Vabx, Vabz, Vabx, Vabz); b = 2 * dotProduct(Pabx, Pabz, Vabx, Vabz); c = dotProduct(Pabx, Pabz, Pabx, Pabz) - diameter*diameter; // b^2-4ac is the discriminant of the quadratic polynomial if ((b*b - 4*a*c) >= 0.0) { // we have one or two roots long double t0, t1, t; t0 = quadratic_formula0(a, b, c); t1 = quadratic_formula1(a, b, c); if (t0 < 0.0 && t1 < 0.0) { //puts("past collision?"); continue; } if (t0 < 0.0) t = t1; else if (t1 < 0.0) t = t0; else if (t0 < t1) t = t0; else t = t1; //printf("%g, %g\n", t1, t0); if (t >= 0.0 && t <= 1.0) { /* printf("OMG bonk: %g, %g?!\n", (double)t, (double) (pow((x+t*fdx) - (sorted[i]->x + t * sorted[i]->dx * time_fraction), 2) + pow((z+t*fdz) - (sorted[i]->z + t * sorted[i]->dz * time_fraction), 2) - pow(diameter, 2))); */ handle_collision(*(sorted[i]), t, time_fraction); time_fraction = base_time_fraction * movement_remaining; // movement_remaining was updated by handle_collision()... fdx = dx * time_fraction; fdz = dz * time_fraction; // now we can keep looping without recursing, yes? } } } movement_remaining = 0.0; actually_reposition(fdx, fdz); // no collisions, simple case }
/*------------------------------------------------------------------------*/ static uint32 sieve_lattice_batch(msieve_obj *obj, lattice_fb_t *L) { uint32 i, j, k; p_soa_var_t * p_array = (p_soa_var_t *)L->p_array; p_soa_var_t * q_array = (p_soa_var_t *)L->q_array; uint32 num_poly = L->poly->num_poly; uint32 num_p = p_array->num_p; for (i = 0; i < q_array->num_p; i++) { uint32 q = q_array->p[i]; uint64 q2 = wide_sqr32(q); uint32 q2_w = montmul32_w((uint32)q2); uint64 q2_r = montmul64_r(q2); uint32 num_p_done = 0; time_t curr_time; double elapsed; while (num_p_done < num_p) { uint32 *plist = p_array->p + num_p_done; uint64 pinvlist[INVERT_BATCH_SIZE]; uint32 curr_num_p = MIN(INVERT_BATCH_SIZE, num_p - num_p_done); batch_invert(plist, curr_num_p, pinvlist, q2, q2_r, q2_w); for (j = 0; j < curr_num_p; j++) { uint32 p = plist[j]; uint64 pinv = pinvlist[j]; uint32 lattice_size = p_array->lattice_size[num_p_done+j]; for (k = 0; k < num_poly; k++) { uint64 qroot, proot, res; qroot = q_array->roots[k][i]; proot = p_array->roots[k][num_p_done+j]; res = montmul64(pinv, modsub64(qroot, proot, q2), q2, q2_w); if (res < lattice_size) { uint128 r, off; r.w[0] = (uint32)proot; r.w[1] = (uint32)(proot >> 32); r.w[2] = 0; r.w[3] = 0; off.w[0] = (uint32)res; off.w[1] = (uint32)(res >> 32); off.w[2] = 0; off.w[3] = 0; handle_collision(L->poly, k, (uint64)p, r, off, (uint64)q); } } } num_p_done += curr_num_p; } if (obj->flags & MSIEVE_FLAG_STOP_SIEVING) return 1; curr_time = time(NULL); elapsed = curr_time - L->start_time; if (elapsed > L->deadline) return 1; }