Ejemplo n.º 1
0
void
vnormal(float *v)
{
    vscale(v,1.0/vlength(v));
}
Ejemplo n.º 2
0
/*
 *  Given an axis and angle, compute quaternion.
 */
void axis_to_quat(double a[3] , double phi , double q[4]) {
	vnormal(a);
	vcopy(a, q);
	vscale(q, (double) sin(phi / 2.0f));
	q[3] = (double) cos(phi / 2.0f);
}
Ejemplo n.º 3
0
void vnormal(double *v) {
	vscale(v, 1.0f / vlength(v));
}
Ejemplo n.º 4
0
void
DoFlares(GLfloat from[3], GLfloat at[3], GLfloat light[3], GLfloat near_clip)
{
  GLfloat view_dir[3], tmp[3], light_dir[3], position[3], dx[3], dy[3],
    center[3], axis[3], sx[3], sy[3], dot, global_scale = 1.5;
  GLuint bound_to = 0;
  int i;

  /* view_dir = normalize(at-from) */
  vdiff(view_dir, at, from);
  vnorm(view_dir);

  /* center = from + near_clip * view_dir */
  vscale(tmp, view_dir, near_clip);
  vadd(center, from, tmp);

  /* light_dir = normalize(light-from) */
  vdiff(light_dir, light, from);
  vnorm(light_dir);

  /* light = from + dot(light,view_dir)*near_clip*light_dir */
  dot = vdot(light_dir, view_dir);
  vscale(tmp, light_dir, near_clip / dot);
  vadd(light, from, light_dir);

  /* axis = light - center */
  vdiff(axis, light, center);
  vcopy(dx, axis);

  /* dx = normalize(axis) */
  vnorm(dx);

  /* dy = cross(dx,view_dir) */
  vcross(dy, dx, view_dir);

  glDisable(GL_DEPTH_TEST);
  glDisable(GL_DITHER);
  glEnable(GL_BLEND);
  glBlendFunc(GL_ONE, GL_ONE);

  for (i = 0; i < num_flares; i++) {
    vscale(sx, dx, flare[i].scale * global_scale);
    vscale(sy, dy, flare[i].scale * global_scale);

    glColor3fv(flare[i].color);
    /* Note logic below to eliminate duplicate texture binds. */
    if (flare[i].type < 0) {
      if (bound_to)
	glEnd();
      glBindTexture(GL_TEXTURE_2D, shineTex[shine_tic]);
      bound_to = shineTex[shine_tic];
      shine_tic = (shine_tic + 1) % 10;
      glBegin(GL_QUADS);
    } else {
      if (bound_to != flareTex[flare[i].type]) {
	glEnd();
        glBindTexture(GL_TEXTURE_2D, flareTex[flare[i].type]);
        bound_to = flareTex[flare[i].type];
	glBegin(GL_QUADS);
      }
    }

    /* position = center + flare[i].loc * axis */
    vscale(tmp, axis, flare[i].loc);
    vadd(position, center, tmp);

    glTexCoord2f(0.0, 0.0);
    vadd(tmp, position, sx);
    vadd(tmp, tmp, sy);
    glVertex3fv(tmp);

    glTexCoord2f(1.0, 0.0);
    vdiff(tmp, position, sx);
    vadd(tmp, tmp, sy);
    glVertex3fv(tmp);

    glTexCoord2f(1.0, 1.0);
    vdiff(tmp, position, sx);
    vdiff(tmp, tmp, sy);
    glVertex3fv(tmp);

    glTexCoord2f(0.0, 1.0);
    vadd(tmp, position, sx);
    vdiff(tmp, tmp, sy);
    glVertex3fv(tmp);
  }
  glEnd();
}
Ejemplo n.º 5
0
void settle_sheet(
  tectonic_sheet *ts,
  size_t iterations,
  float dt,
  float equilibrium_distance,
  float spring_constant,
  int hold_edges
) {
  size_t iter, i, j;
  size_t idx, idx_a, idx_b, idx_c;
  size_t pw, ph;
  pw = sheet_pwidth(ts);
  ph = sheet_pheight(ts);
  vector *a, *b, *c; // the points of the current triangle
  vector *f; // the force on the current point
  vector tmp; // vector used for intermediate calculations
  for (iter = 0; iter < iterations; ++iter) {
    // First pass: compute forces by iterating over triangles in the sheet:
    for (i = 0; i < ts->width; ++i) {
      for (j = 0; j < ts->height; ++j) {
        idx_a = sheet_pidx_a(ts, i, j);
        idx_b = sheet_pidx_b(ts, i, j);
        idx_c = sheet_pidx_c(ts, i, j);
        a = &(ts->points[idx_a]);
        b = &(ts->points[idx_b]);
        c = &(ts->points[idx_c]);
        if (i % 2 == j % 2) { // if this triangle points up
          // All six forces on all three corners of this triangle:
          // a <- b
          f = &(ts->forces[idx_a]);
          spring_force(b, a, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);

          // a <- c
          spring_force(c, a, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);

          // b <- a
          f = &(ts->forces[idx_b]);
          spring_force(a, b, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);

          // b <- c
          spring_force(c, b, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);

          // c <- a
          f = &(ts->forces[idx_c]);
          spring_force(a, c, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);

          // c <- b
          spring_force(b, c, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);
        } else if (i == 0 && (j % 2 == 1)) {
          // Both forces on our a <-> b edge:
          // a <- b
          f = &(ts->forces[idx_a]);
          spring_force(b, a, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);

          // b <- a
          f = &(ts->forces[idx_b]);
          spring_force(a, b, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);
        } else if ((i == ts->width - 1) && (j % 2 == 0) ) {
          // Both forces on our a <-> c edge:
          // a <- c
          f = &(ts->forces[idx_a]);
          spring_force(c, a, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);

          // c <- a
          f = &(ts->forces[idx_c]);
          spring_force(a, c, &tmp, equilibrium_distance, spring_constant);
          vadd_to(f, &tmp);
        }
      }
    }
    // Second pass: apply forces (iterating over points this time)
    for (i = 0; i < pw; ++i) {
      for (j = 0; j < ph; ++j) {
        idx = sheet_pidx(ts, i, j);
        f = &(ts->forces[idx]);
        if (
          hold_edges
        &&
          (i == 0 || i == pw - 1 || j == 0 || j == ph - 1)
        ) {
          vzero(f);
          continue;
        }
        vscale(f, dt);
        vadd_to(&(ts->points[idx]), f);
        vzero(f);
      }
    }
  }
}
Ejemplo n.º 6
0
//-----------------------------------------------------------------------------
void RunGame()
{
	// Control main ship
	if (g_gs == GS_VICTORY || g_gs == GS_STARTING)
	{
		if (MAIN_SHIP.vel.y < SHIP_CRUISE_SPEED)
		{
			MAIN_SHIP.vel.y = SAFEADD(MAIN_SHIP.vel.y, SHIP_INC_SPEED, SHIP_CRUISE_SPEED);
		}
		MAIN_SHIP.fuel = SAFESUB(MAIN_SHIP.fuel, FRAME_FUEL_COST);
	}

	// Heal main ship
	if (g_gs != GS_DYING)
	{
		if (MAIN_SHIP.energy < MAX_ENERGY && MAIN_SHIP.fuel > MIN_FUEL_FOR_HEAL)
		{
			MAIN_SHIP.energy = SAFEADD(MAIN_SHIP.energy, ENERGY_HEAL_PER_FRAME, MAX_ENERGY);
			MAIN_SHIP.fuel = SAFESUB(MAIN_SHIP.fuel, FUEL_HEAL_PER_FRAME);
			LOG(("- energy: %f, fuel: %f\n", MAIN_SHIP.energy, MAIN_SHIP.fuel));
		}
	}

	// Move entities
	for (int i = MAX_ENTITIES - 1; i >= 0; i--)
	{
		if (g_entities[i].type != E_NULL)
		{
			g_entities[i].pos = vadd(g_entities[i].pos, g_entities[i].vel);

			// Remove entities that fell off screen
			if (g_entities[i].pos.y < g_camera_offset - G_HEIGHT)
				g_entities[i].type = E_NULL;
		}
	}

	// Advance "stars"
	for (int i = 0; i < MAX_ENTITIES; i++)
	{
		if (g_entities[i].type == E_STAR)
			g_entities[i].gfxscale *= 1.008f;
	}

	// Dont let steering off the screen
	if (MAIN_SHIP.pos.x < MAINSHIP_RADIUS)
		MAIN_SHIP.pos.x = MAINSHIP_RADIUS;
	if (MAIN_SHIP.pos.x > G_WIDTH - MAINSHIP_RADIUS)
		MAIN_SHIP.pos.x = G_WIDTH - MAINSHIP_RADIUS;

	// Check collisions
	if (g_gs == GS_PLAYING)
	{
		// Check everything against ship
		for (int i = 1; i < MAX_ENTITIES; i++)
		{
			// Should check against ship?
			if (g_entities[i].type == E_ROCK
				|| g_entities[i].type == E_JUICE
				|| g_entities[i].type == E_MINE
				|| g_entities[i].type == E_DRONE)
			{
				float distance = vlen2(vsub(g_entities[i].pos, MAIN_SHIP.pos)); // Distance from object to ship
				float crash_distance = CORE_FSquare(g_entities[i].radius + MAIN_SHIP.radius); // Minimum allowed distance before crash
				if (distance < crash_distance)
				{
					switch (g_entities[i].type)
					{
					case E_ROCK:
						if (g_entities[i].energy > 0)
						{
							MAIN_SHIP.energy = SAFESUB(MAIN_SHIP.energy, ROCK_CRASH_ENERGY_LOSS);
							MAIN_SHIP.vel.y = SHIP_START_SPEED;
							
							// Set rock velocity
							vec2 vel_direction = vsub(g_entities[i].pos, MAIN_SHIP.pos); // direction of rock velocity, away from ship
							vec2 normalized_vel_direction = vunit(vel_direction); // normalize
							vec2 vel = vscale(normalized_vel_direction, CRASH_VEL); // Scale, ie give the rock correct speed.
							g_entities[i].vel = vel;
							g_entities[i].energy = 0;
						}
						break;

					case E_JUICE:
						MAIN_SHIP.fuel = SAFEADD(MAIN_SHIP.fuel, JUICE_FUEL, MAX_FUEL);
						g_entities[i].type = E_NULL;
						break;

					case E_MINE:
						MAIN_SHIP.energy = SAFESUB(MAIN_SHIP.energy, MINE_CRASH_ENERGY_LOSS);
						MAIN_SHIP.vel.y = SHIP_START_SPEED;
						g_entities[i].type = E_NULL;
						break;

					case E_DRONE:
						MAIN_SHIP.energy = SAFESUB(MAIN_SHIP.energy, MINE_CRASH_ENERGY_LOSS);
						MAIN_SHIP.vel.y = SHIP_START_SPEED;
						g_entities[i].type = E_NULL;
						break;

					default:
						break;
					}
				}
			}
			else if (g_entities[i].type == E_ROCKET)
			{
				// Check all hit-able objects against this rocket
				for (int j = 1; i < MAX_ENTITIES; j++) 
				{
					// Should check against rocket?
					if (g_entities[j].type == E_ROCK
						|| g_entities[j].type == E_MINE
						|| g_entities[j].type == E_DRONE)
					{
						float distance = vlen2(vsub(g_entities[i].pos, g_entities[j].pos));
						float crash_distance = CORE_FSquare(g_entities[i].radius + g_entities[j].radius);
						if (distance < crash_distance)
						{
							// Impact!
							g_entities[i].type = E_NULL;
							g_entities[j].type = E_NULL;

							break;
						}
					}
				}
			}
		}
	}

	// Generate new level elements as we advance
	GenNextElements();

	// Possibly insert new juice
	if (g_gs == GS_PLAYING)
	{
		float trench = MAIN_SHIP.pos.y - g_current_race_pos; // How much advanced from previous frame
		if (CORE_RandChance(trench * JUICE_CHANCE_PER_PIXEL))
		{
			vec2 pos = vmake(CORE_FRand(0.f, G_WIDTH), g_camera_offset + G_HEIGHT + GEN_IN_ADVANCE); // Random x, insert 400y above window
			vec2 vel = vmake(CORE_FRand(-1.f, +1.f), CORE_FRand(-1.f, +1.f)); // Random small velocity to make rocks "float"
			InsertEntity(E_JUICE, pos, vel, JUICE_RADIUS, g_juice, false, true);
		}
	}

	// Set camera to follow the main ship
	g_camera_offset = MAIN_SHIP.pos.y - G_HEIGHT / 8.f;

	g_current_race_pos = MAIN_SHIP.pos.y;
	if (g_gs == GS_PLAYING)
	{
		if (g_current_race_pos >= RACE_END) // Check if victory
		{
			g_gs = GS_VICTORY;
			g_gs_timer = 0.f;
			MAIN_SHIP.gfxadditive = true;
		}
	}

	// Advance game mode
	g_gs_timer += FRAMETIME;
	switch (g_gs)
	{
	case GS_STARTING:
		if (g_gs_timer >= STARTING_TIME) // Start delay before starting to play
		{
			g_gs = GS_PLAYING;
			g_gs_timer = 0.f;
		}
		break;
	case GS_DYING:
		if (g_gs_timer >= DYING_TIME)
		{
			ResetNewGame();
		}
		break;
	case GS_PLAYING:
		if (MAIN_SHIP.energy <= 0.f || MAIN_SHIP.fuel <= 0.f) // No energy or fuel --> die
		{
			g_gs = GS_DYING;
			g_gs_timer = 0.f;
			MAIN_SHIP.gfx = g_ship_RR;
		}
		break;
	case GS_VICTORY:
		if (CORE_RandChance(1.f / 10.f))
		{
			InsertEntity(E_STAR, MAIN_SHIP.pos, vadd(MAIN_SHIP.vel, vmake(CORE_FRand(-5.f, 5.f), CORE_FRand(-5.f, 5.f))), 0, g_star, false, true);
		}
		
		if (g_gs_timer >= 8.f) // Should use VICTORY_TIME, but stupid VS dont want me to...
		{
			ResetNewGame();
		}
		break;
	}
	g_time_from_last_rocket += FRAMETIME;
}