// init_scene initializes the global variable g_projectiles immediately after // a shot has been fired. void init_scene() { struct Tank *t = &g_tanks[g_current_tank]; Vector dir = { sin(D2R(t->s.turret_angle))*cos(D2R(t->s.weapon_angle)), sin(D2R(t->s.weapon_angle)), cos(D2R(t->s.turret_angle))*cos(D2R(t->s.weapon_angle)), }; Vector pos; // FIX ME!! Is this the right way to handle tank angle? // vv_add(dir, t->o.props.angular_position); v_norm(dir); // FIX ME!! We do not fire from the end of the barrel vv_cpy(pos, t->o.props.position); vv_add(pos, t->m.turret_base); vv_add(pos, t->m.weapon_base); printf("New projectile\n"); printf("Position: %f %f %f\n", pos[0], pos[1], pos[2]); printf("Direction: %f %f %f\n", dir[0], dir[1], dir[2]); printf("Tank pos: %f %f %f\n", t->o.props.position[0], t->o.props.position[1], t->o.props.position[2]); new_projectile( dir, // Direction t->s.power, // Magnitude pos, // Position Missile_I // Type ); }
void move_particle(particle_type* p, GLfloat delta) { Vector accel, tempa, tempv; GLfloat deltasq = delta*delta; accel[0] = 0.0; accel[1] = -ps->gravity; accel[2] = 0.0; accel[3] = 0.0; vv_cpy(tempa, accel); vc_mul(tempa, 0.5); vc_mul(tempa, deltasq); vv_cpy(tempv, p->velocity); vc_mul(tempv, (double)delta); vv_add(tempa, tempv); vv_cpy(p->prevpos[p->begin], p->position); p->begin = (p->begin + 1) % PREVIOUS; vv_add(p->position, tempa); vv_cpy(tempa, accel); vc_mul(tempa, delta); vv_add(p->velocity, tempa); }
void initparticle(particle_type* p) { p->position[0] = ps->initpos[0]; p->position[1] = ps->initpos[1]; p->position[2] = ps->initpos[2]; p->position[3] = 0.0; v_zero(p->velocity); p->color[0] = 1.0; p->color[1] = 1.0; p->color[2] = 1.0; p->color[3] = 0.0; vv_cpy(p->prevpos[0], p->position); vv_cpy(p->prevpos[1], p->position); vv_cpy(p->prevpos[2], p->position); vv_cpy(p->prevpos[3], p->position); vv_cpy(p->prevpos[4], p->position); p->begin = 0; }
int draw_3d_tri( pVector v1p, Graph3dColor c1p, pVector n1p, pVector v2p, Graph3dColor c2p, pVector n2p, pVector v3p, Graph3dColor c3p, pVector n3p) { int j; int x1, x2, x3; int y1, y2, y3; // First, convert the colors to floats Vector c1 = { (float)c1p.r / 255.0, (float)c1p.g / 255.0, (float)c1p.b / 255.0, 1.0 }; Vector c2 = { (float)c2p.r / 255.0, (float)c2p.g / 255.0, (float)c2p.b / 255.0, 1.0 }; Vector c3 = { (float)c3p.r / 255.0, (float)c3p.g / 255.0, (float)c3p.b / 255.0, 1.0 }; Vector v1, v2, v3; Vector n1, n2, n3; Vector L1, L2, L3; // Next, apply the modelview matrix to the triangle's vertices vv_cpy(v1, v1p); vv_cpy(v2, v2p); vv_cpy(v3, v3p); vm_mul(v1, modelview); vm_mul(v2, modelview); vm_mul(v3, modelview); // And also to the normals vv_cpy(n1, n1p); vv_cpy(n2, n2p); vv_cpy(n3, n3p); vm_mul(n1, modelview); vm_mul(n2, modelview); vm_mul(n3, modelview); // Find the distance for each point from the light vv_cpy(L1, lightpos); vv_sub(L1, v1); v_norm(L1); vv_cpy(L2, lightpos); vv_sub(L2, v2); v_norm(L2); vv_cpy(L3, lightpos); vv_sub(L3, v3); v_norm(L3); // Then, apply our lighting equations // We assume that the triangle's ambient and diffuse values are the same // We also assume that for(j = 0; j < 4; j++) { c1[j] = light_transform(c1[j], n1, L1, j); c2[j] = light_transform(c2[j], n2, L2, j); c2[j] = light_transform(c3[j], n3, L3, j); } // Convert the color values to values the graphics card will accept // c1p et al were passed by value, so we can modify them c1p.r = c1[0] * 255; c1p.g = c1[1] * 255; c1p.b = c1[2] * 255; c2p.r = c2[0] * 255; c2p.g = c2[1] * 255; c2p.b = c2[2] * 255; c3p.r = c3[0] * 255; c3p.g = c3[1] * 255; c3p.b = c3[2] * 255; // Lastly, find the coordinates on the screen for each point, // and draw the triangle x1 = 800 * (depth/height) * (v1[0] / v1[2]); y1 = 600 * (depth/height) * (v1[1] / v1[2]); x2 = 800 * (depth/height) * (v2[0] / v2[2]); y2 = 600 * (depth/height) * (v2[1] / v2[2]); x3 = 800 * (depth/height) * (v3[0] / v3[2]); y3 = 600 * (depth/height) * (v3[1] / v3[2]); draw_2d_tri(x1, y1, c1p, x2, y2, c2p, x3, y3, c3p); printf("v1: %f %f %f\n", v1[0], v1[1], v1[2]); printf("v2: %f %f %f\n", v2[0], v2[1], v2[2]); printf("v2: %f %f %f\n", v3[0], v3[1], v3[2]); printf("%d %d; %d %d; %d %d\n", x1, y1, x2, y2, x3, y3); return GRAPH3D_OK; }
int graph3d_set_lightpos(pVector v) { vv_cpy(lightpos, v); return GRAPH3D_OK; }
// modify_scene modifies the global variables g_projectiles and g_explosions // during the course of an attack sequence. It takes a parameter dt which // represents the amount of time between frames. // Return: the number of items left to animate. int modify_scene(float dt) { int i, j, num_impacted; float t; struct Projectile *p; struct Explosion *e; struct Tank *tank; Vector v; float d; // Go through all the explosions and update them according to the // amount of time passed. for(j = 0; j < g_num_explosions; j++) { e = &g_explosions[j]; t = update_explosion(e, dt); } // Go through all the projectiles and handle the ones that have not yet // been impacted. for(j = 0, num_impacted = 0; j < g_num_projectiles; j++) { p = &g_projectiles[j]; if(p->o.state != STATE_IMPACTED) { t = update_projectile(p, dt); if(p->o.state == STATE_IMPACTED) { printf("Projectile %d has impacted.\n", j); // If the projectile has impacted, an explosion needs to be // created which is appropriate to the projectile which has // impacted, and which takes on properties of the former // projectile. e = new_explosion(p); // Now, using the remaining time that did not get used on the // projectile, update the new explosion. t = update_explosion(e, dt - t); // And play a sound to match sx3_play_sound(SX3_AUDIO_EXPLOSION); } } if(p->o.state == STATE_IMPACTED) num_impacted++; } // FIX ME!! These two checks don't work properly if we have a low // framerate. for(j = 0; j < g_num_explosions; j++) { e = &g_explosions[j]; for(i = 0; i < g_num_tanks; i++) { tank = &g_tanks[i]; // Don't check this tank if it's already been hit // FIX ME!! This should be on a per-projectile/explosion basis if(tank->s.temp_damage != 0.0) continue; // Find the distance between the tank and the explosion, and test vv_cpy(v, tank->o.props.position); vv_sub(v, e->props.position); d = v_mag(v); if(d < tank->o.props.radius + e->props.radius) { // A tank has been hit! sx3_play_sound(SX3_AUDIO_HIT); printf("Tank %d hit by explosion %d\n", i, j); // FIX ME!! This should not be constant damage. tank->s.temp_damage = 20.0; } } } for(j = 0; j < g_num_projectiles; j++) { p = &g_projectiles[j]; if(p->o.state == STATE_IMPACTED) continue; for(i = 0; i < g_num_tanks; i++) { tank = &g_tanks[i]; // Don't check this tank if it's already been hit // FIX ME!! This should be on a per-projectile/explosion basis if(tank->s.temp_damage != 0.0) continue; // Find the distance between the tank and the projectiles, and test vv_cpy(v, tank->o.props.position); vv_sub(v, p->o.props.position); d = v_mag(v); if(d < tank->o.props.radius + p->o.props.radius) { // A tank has been hit! sx3_play_sound(SX3_AUDIO_HIT); printf("Tank %d hit by projectile %d\n", i, j); // FIX ME!! This should not be constant damage. tank->s.temp_damage = 40.0; } } } return g_num_explosions + g_num_projectiles - num_impacted; }