shithub: musw

ref: e095f65376894dcdef067b63103f2e17e55a1f14
dir: /universe.c/

View raw version
#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);
}