예제 #1
0
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);
	}
}
예제 #2
0
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;
}
예제 #4
0
파일: racer.hpp 프로젝트: Zhanyin/taomee
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;
예제 #5
0
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);
}
예제 #7
0
/*------------------------------------------------------------------------*/
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;
}
예제 #8
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();
}
예제 #9
0
// 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
}
예제 #10
0
/*------------------------------------------------------------------------*/
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;
	}