ref: e095f65376894dcdef067b63103f2e17e55a1f14
dir: /universe.c/
#include <u.h>
#include <libc.h>
#include <ip.h>
#include <mp.h>
#include <libsec.h>
#include <draw.h>
#include <geometry.h>
#include "dat.h"
#include "fns.h"
/* Ship */
static void
ship_forward(Ship *s, double Δt)
{
Point2 v;
Matrix R = {
cos(s->θ), -sin(s->θ), 0,
sin(s->θ), cos(s->θ), 0,
0, 0, 1,
};
v = mulpt2(xform(Vec2(1,0), R), THRUST*Δt);
s->v = addpt2(s->v, v);
}
static void
ship_rotate(Ship *s, int dir, double Δt)
{
s->θ += PI*dir*Δt;
}
static void
ship_hyperjump(Ship *s)
{
USED(s);
return;
}
static void
ship_fire(Ship *s)
{
int i;
Point2 bv;
Matrix R = {
cos(s->θ), -sin(s->θ), 0,
sin(s->θ), cos(s->θ), 0,
0, 0, 1,
};
bv = mulpt2(xform(Vec2(1,0), R), 10*THRUST);
for(i = 0; i < nelem(s->rounds); i++)
if(!s->rounds[i].fired){
s->rounds[i].p = s->p;
s->rounds[i].v = addpt2(s->v, bv);
s->rounds[i].θ = s->θ;
s->rounds[i].ttl = 5;
s->rounds[i].fired++;
break;
}
}
/* Universe */
static void
universe_step(Universe *u, double Δt)
{
Ship *s;
Bullet *b;
integrate(u, u->t, Δt);
for(s = u->ships; s < u->ships+nelem(u->ships); s++)
for(b = s->rounds; b < s->rounds+nelem(s->rounds); b++)
if(b->fired)
b->ttl -= Δt;
u->timeacc -= Δt;
u->t += Δt;
}
static void
warp(Particle *p)
{
Rectangle r;
r = Rect(-SCRW/2, -SCRH/2, SCRW/2, SCRH/2);
if(p->p.x < r.min.x)
p->p.x = r.max.x;
if(p->p.y < r.min.y)
p->p.y = r.max.y;
if(p->p.x > r.max.x)
p->p.x = r.min.x;
if(p->p.y > r.max.y)
p->p.y = r.min.y;
}
/* collision detection and resolution */
static void
universe_collide(Universe *u)
{
Ship *s;
Bullet *b;
for(s = u->ships; s < u->ships+nelem(u->ships); s++){
for(b = s->rounds; b < s->rounds+nelem(s->rounds); b++)
if(b->fired){
if(b->ttl <= 0){
b->fired = 0;
continue;
}
warp(b);
}
warp(s);
}
}
static void
universe_reset(Universe *u)
{
int i, j;
for(i = 0; i < nelem(u->ships); i++){
for(j = 0; j < nelem(u->ships[i].rounds); j++)
memset(&u->ships[i].rounds[j], 0, sizeof(Bullet));
memset(&u->ships[i].Particle, 0, sizeof(Particle));
}
memset(&u->star.Particle, 0, sizeof(Particle));
inituniverse(u);
}
void
inituniverse(Universe *u)
{
int i;
double θ;
Point2 aimstar;
u->star.p = Pt2(0,0,1);
u->star.mass = 5.97e24; /* earth's mass */
θ = ntruerand(360)*DEG;
for(i = 0; i < nelem(u->ships); i++){
θ += i*180*DEG;
Matrix R = {
cos(θ), -sin(θ), 0,
sin(θ), cos(θ), 0,
0, 0, 1
};
u->ships[i].p = addpt2(Pt2(0,0,1), mulpt2(xform(Vec2(1,0), R), 200));
aimstar = subpt2(u->star.p, u->ships[i].p);
u->ships[i].θ = atan2(aimstar.y, aimstar.x);
}
u->ships[0].mass = 10e3; /* 10 tons */
u->ships[0].fuel = 100;
u->ships[1].mass = 40e3; /* 40 tons */
u->ships[1].fuel = 200;
u->ships[0].forward = u->ships[1].forward = ship_forward;
u->ships[0].rotate = u->ships[1].rotate = ship_rotate;
u->ships[0].hyperjump = u->ships[1].hyperjump = ship_hyperjump;
u->ships[0].fire = u->ships[1].fire = ship_fire;
}
Universe *
newuniverse(void)
{
Universe *u;
u = emalloc(sizeof(Universe));
memset(u, 0, sizeof *u);
u->step = universe_step;
u->collide = universe_collide;
u->reset = universe_reset;
return u;
}
void
deluniverse(Universe *u)
{
free(u);
}