mirror of https://github.com/dirtbags/tanks.git
Finally got sensors debugged
This commit is contained in:
parent
4720524639
commit
74b9e8e455
7
Makefile
7
Makefile
|
@ -1,6 +1,11 @@
|
||||||
|
LDFLAGS = -lm
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
test: test-tanks
|
test: test-tanks
|
||||||
./test-tanks
|
./test-tanks | m4 round.html.m4 - > round.html
|
||||||
|
|
||||||
test-tanks: test-tanks.o ctanks.o
|
test-tanks: test-tanks.o ctanks.o
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f test-tanks *.o
|
207
ctanks.c
207
ctanks.c
|
@ -2,9 +2,22 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "trig.h"
|
|
||||||
#include "ctanks.h"
|
#include "ctanks.h"
|
||||||
|
|
||||||
|
/* Debugging help */
|
||||||
|
#define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args)
|
||||||
|
#define DUMP() DUMPf("")
|
||||||
|
#define DUMP_d(v) DUMPf("%s = %d", #v, v)
|
||||||
|
#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v)
|
||||||
|
#define DUMP_s(v) DUMPf("%s = %s", #v, v)
|
||||||
|
#define DUMP_c(v) DUMPf("%s = %c", #v, v)
|
||||||
|
#define DUMP_f(v) DUMPf("%s = %f", #v, v)
|
||||||
|
#define DUMP_xy(v) DUMPf("%s = (%f, %f)", #v, v[0], v[1]);
|
||||||
|
#define DUMP_angle(v) DUMPf("%s = %.3fπ", #v, (v/PI));
|
||||||
|
|
||||||
|
#define sq(x) ((x) * (x))
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
tank_init(struct tank *tank, tank_run_func *run, void *udata)
|
tank_init(struct tank *tank, tank_run_func *run, void *udata)
|
||||||
{
|
{
|
||||||
|
@ -32,16 +45,16 @@ tank_set_speed(struct tank *tank, float left, float right)
|
||||||
tank->speed.desired[1] = right;
|
tank->speed.desired[1] = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
float
|
||||||
tank_get_turret(struct tank *tank)
|
tank_get_turret(struct tank *tank)
|
||||||
{
|
{
|
||||||
return tank->turret.current;
|
return tank->turret.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tank_set_turret(struct tank *tank, int angle)
|
tank_set_turret(struct tank *tank, float angle)
|
||||||
{
|
{
|
||||||
tank->turret.desired = angle;
|
tank->turret.desired = fmodf(angle, 2*PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -50,7 +63,7 @@ tank_get_sensor(struct tank *tank, int sensor_num)
|
||||||
if ((sensor_num < 0) || (sensor_num > TANK_MAX_SENSORS)) {
|
if ((sensor_num < 0) || (sensor_num > TANK_MAX_SENSORS)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return tank->sensor[sensor_num].triggered;
|
return tank->sensors[sensor_num].triggered;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -60,16 +73,19 @@ tank_set_led(struct tank *tank, int active)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rotate_point(int angle, float point[2])
|
rotate_point(float angle, float point[2])
|
||||||
{
|
{
|
||||||
float cos_, sin_;
|
float cos_, sin_;
|
||||||
float new[2];
|
float new[2];
|
||||||
|
|
||||||
cos_ = trig_cos(angle);
|
cos_ = cosf(angle);
|
||||||
sin_ = trig_sin(angle);
|
sin_ = sinf(angle);
|
||||||
|
|
||||||
new[0] = point[0]*cos_ + point[1]*sin_;
|
new[0] = point[0]*cos_ - point[1]*sin_;
|
||||||
new[1] = point[0]*sin_ + point[1]*cos_;
|
new[1] = point[0]*sin_ + point[1]*cos_;
|
||||||
|
|
||||||
|
point[0] = new[0];
|
||||||
|
point[1] = new[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,7 +111,7 @@ tank_sensor_calc(struct tanks_game *game,
|
||||||
|
|
||||||
rpos[0] = tpos[0];
|
rpos[0] = tpos[0];
|
||||||
rpos[1] = tpos[1];
|
rpos[1] = tpos[1];
|
||||||
rotate_point(theta, rpos);
|
rotate_point(-theta, rpos);
|
||||||
if (fabsf(rpos[1]) < TANK_RADIUS) {
|
if (fabsf(rpos[1]) < TANK_RADIUS) {
|
||||||
that->killer = this;
|
that->killer = this;
|
||||||
that->cause_death = "shot";
|
that->cause_death = "shot";
|
||||||
|
@ -103,50 +119,59 @@ tank_sensor_calc(struct tanks_game *game,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate sensors */
|
/* Calculate sensors */
|
||||||
for (i = 0; i < this->num_sensors; i += 1) {
|
for (i = 0; i < TANK_MAX_SENSORS; i += 1) {
|
||||||
int theta;
|
float theta;
|
||||||
float rpos[2];
|
float rpos[2];
|
||||||
float m_r, m_s;
|
float m_r, m_s;
|
||||||
|
|
||||||
/* No need to re-check this sensor if it's already firing */
|
/* No need to re-check this sensor if it's already firing */
|
||||||
if (this->sensor[i].triggered) {
|
if (this->sensors[i].triggered) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the tank is out of range, don't bother */
|
/* If the tank is out of range, don't bother */
|
||||||
if (dist2 < this->sensor[i].range_adj2) {
|
if (dist2 > sq(this->sensors[i].range + TANK_RADIUS)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* What is the angle of our sensor? */
|
/* What is the angle of our sensor? */
|
||||||
theta = this->angle;
|
theta = this->angle + this->sensors[i].angle;
|
||||||
if (this->sensor[i].turret) {
|
if (this->sensors[i].turret) {
|
||||||
theta += this->turret.current;
|
theta += this->turret.current;
|
||||||
}
|
}
|
||||||
|
theta = fmodf(theta, 2*PI);
|
||||||
|
|
||||||
/* Rotate tpos by theta */
|
/* Rotate tpos by theta */
|
||||||
rpos[0] = tpos[0];
|
rpos[0] = tpos[0];
|
||||||
rpos[1] = tpos[1];
|
rpos[1] = tpos[1];
|
||||||
rotate_point(theta, rpos);
|
rotate_point(-theta, rpos);
|
||||||
|
|
||||||
/* Sensor is symmetrical, we can consider only first quadrant */
|
/* Sensor is symmetrical, we can consider only top quadrants */
|
||||||
rpos[1] = fabsf(rpos[1]);
|
rpos[1] = fabsf(rpos[1]);
|
||||||
|
|
||||||
/* Compute slopes to tank and of our sensor */
|
/* Compute inverse slopes to tank and of our sensor */
|
||||||
m_s = tan(theta);
|
m_s = 1 / tanf(this->sensors[i].width / 2);
|
||||||
m_r = rpos[1] / rpos[0];
|
m_r = rpos[0] / rpos[1];
|
||||||
|
|
||||||
/* If their slope is greater than ours, they're inside the arc */
|
if (1 == i) {
|
||||||
|
DUMP();
|
||||||
|
DUMP_angle(this->angle);
|
||||||
|
DUMP_angle(theta);
|
||||||
|
DUMP_xy(tpos);
|
||||||
|
DUMP_xy(rpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If our inverse slope is less than theirs, they're inside the arc */
|
||||||
if (m_r >= m_s) {
|
if (m_r >= m_s) {
|
||||||
this->sensor[i].triggered = 1;
|
this->sensors[i].triggered = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now check if the edge of the arc intersects the tank. Do this
|
/* Now check if the edge of the arc intersects the tank. Do this
|
||||||
just like with firing. */
|
just like with firing. */
|
||||||
rotate_point(this->sensor[i].width / 2, rpos);
|
rotate_point(this->sensors[i].width / -2, rpos);
|
||||||
if (fabsf(rpos[1]) < TANK_RADIUS) {
|
if (fabsf(rpos[1]) < TANK_RADIUS) {
|
||||||
this->sensor[i].triggered = 1;
|
this->sensors[i].triggered = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,12 +181,14 @@ do_shit_with(struct tanks_game *game,
|
||||||
struct tank *this,
|
struct tank *this,
|
||||||
struct tank *that)
|
struct tank *that)
|
||||||
{
|
{
|
||||||
float vector[2];
|
float vector[2];
|
||||||
int dist2; /* Integer to avoid overflow! */
|
float dist2; /* distance squared */
|
||||||
float tpos; /* Translated position */
|
float tpos; /* Translated position */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Don't bother if one is dead */
|
/* Don't bother if that is dead */
|
||||||
|
/* XXX: If three tanks occupy the same space at the same time, only
|
||||||
|
the first two will collide. */
|
||||||
if ((this->killer) || (that->killer)) {
|
if ((this->killer) || (that->killer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -171,16 +198,11 @@ do_shit_with(struct tanks_game *game,
|
||||||
for (i = 0; i < 2; i += 1) {
|
for (i = 0; i < 2; i += 1) {
|
||||||
float halfsize = game->size[i] / 2;
|
float halfsize = game->size[i] / 2;
|
||||||
|
|
||||||
/* XXX: is there a more elegant way to do this? */
|
vector[i] = halfsize - fabsf(that->position[i] - this->position[i] - halfsize);
|
||||||
vector[i] = that->position[i] - this->position[i];
|
|
||||||
if (2*vector[i] > game->size[i]) {
|
|
||||||
vector[i] -= game->size[i];
|
|
||||||
} else if (2*vector[i] < game->size[i]) {
|
|
||||||
vector[i] += game->size[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute distance^2 for range comparisons */
|
/* Compute distance^2 for range comparisons */
|
||||||
dist2 = ((vector[0] * vector[0]) + (vector[1] * vector[1]));
|
dist2 = sq(vector[0]) + sq(vector[1]);
|
||||||
|
|
||||||
/* If they're not within sensor range, there's nothing to do. */
|
/* If they're not within sensor range, there's nothing to do. */
|
||||||
if (dist2 > TANK_SENSOR_ADJ2) {
|
if (dist2 > TANK_SENSOR_ADJ2) {
|
||||||
|
@ -193,7 +215,7 @@ do_shit_with(struct tanks_game *game,
|
||||||
this->cause_death = "collision";
|
this->cause_death = "collision";
|
||||||
|
|
||||||
that->killer = this;
|
that->killer = this;
|
||||||
this->cause_death = "collision";
|
that->cause_death = "collision";
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -203,43 +225,51 @@ do_shit_with(struct tanks_game *game,
|
||||||
tank_sensor_calc(game, that, this, dist2);
|
tank_sensor_calc(game, that, this, dist2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
tanks_print_tank(struct tanks_game *game,
|
|
||||||
struct tank *tank)
|
|
||||||
{
|
|
||||||
printf("%p\n", tank);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
tanks_move_tank(struct tanks_game *game,
|
tanks_move_tank(struct tanks_game *game,
|
||||||
struct tank *tank)
|
struct tank *tank)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float movement[2];
|
float movement;
|
||||||
int angle;
|
float angle;
|
||||||
|
|
||||||
|
/* Rotate the turret */
|
||||||
|
{
|
||||||
|
float rot_angle; /* Quickest way there */
|
||||||
|
|
||||||
|
/* Constrain rot_angle to between -PI and PI */
|
||||||
|
rot_angle = tank->turret.desired - tank->turret.current;
|
||||||
|
while (rot_angle < 0) {
|
||||||
|
rot_angle += 2*PI;
|
||||||
|
}
|
||||||
|
rot_angle = fmodf(PI + rot_angle, 2*PI) - PI;
|
||||||
|
|
||||||
|
rot_angle = min(TANK_MAX_TURRET_ROT, rot_angle);
|
||||||
|
rot_angle = max(-TANK_MAX_TURRET_ROT, rot_angle);
|
||||||
|
tank->turret.current = fmodf(tank->turret.current + rot_angle, 2*PI);
|
||||||
|
}
|
||||||
|
|
||||||
/* Fakey acceleration */
|
/* Fakey acceleration */
|
||||||
for (i = 0; i < 2; i += 1) {
|
for (i = 0; i < 2; i += 1) {
|
||||||
if (tank->speed.current[i] == tank->speed.desired[i]) {
|
if (tank->speed.current[i] == tank->speed.desired[i]) {
|
||||||
/* Do nothing */
|
/* Do nothing */
|
||||||
} else if (tank->speed.current[i] < tank->speed.desired[i]) {
|
} else if (tank->speed.current[i] < tank->speed.desired[i]) {
|
||||||
tank->speed.current[i] = max(tank->speed.current[i] - TANK_MAX_ACCEL,
|
tank->speed.current[i] = min(tank->speed.current[i] + TANK_MAX_ACCEL,
|
||||||
tank->speed.desired[i]);
|
tank->speed.desired[i]);
|
||||||
} else {
|
} else {
|
||||||
tank->speed.current[i] = min(tank->speed.current[i] + TANK_MAX_ACCEL,
|
tank->speed.current[i] = max(tank->speed.current[i] - TANK_MAX_ACCEL,
|
||||||
tank->speed.desired[i]);
|
tank->speed.desired[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The simple case */
|
/* The simple case */
|
||||||
if (tank->speed.current[0] == tank->speed.current[1]) {
|
if (tank->speed.current[0] == tank->speed.current[1]) {
|
||||||
movement[0] = tank->speed.current[0];
|
movement = tank->speed.current[0] * (TANK_TOP_SPEED / 100.0);
|
||||||
movement[1] = tank->speed.current[1];
|
angle = 0;
|
||||||
angle = tank->angle;
|
|
||||||
} else {
|
} else {
|
||||||
/* pflarr's original comment:
|
/* pflarr's original comment:
|
||||||
*
|
*
|
||||||
* The tank drives around in a circle of radius r, which is some *
|
* The tank drives around in a circle of radius r, which is some
|
||||||
* offset on a line perpendicular to the tank. The distance it
|
* offset on a line perpendicular to the tank. The distance it
|
||||||
* travels around the circle varies with the speed of each tread,
|
* travels around the circle varies with the speed of each tread,
|
||||||
* and is such that each side of the tank moves an equal angle
|
* and is such that each side of the tank moves an equal angle
|
||||||
|
@ -250,29 +280,25 @@ tanks_move_tank(struct tanks_game *game,
|
||||||
float friction;
|
float friction;
|
||||||
float v[2];
|
float v[2];
|
||||||
float So, Si;
|
float So, Si;
|
||||||
float w, r;
|
float r;
|
||||||
int theta;
|
float theta;
|
||||||
int dir;
|
int dir;
|
||||||
|
|
||||||
/* The first thing Paul's code does is find "friction", which seems
|
/* The first thing Paul's code does is find "friction", which seems
|
||||||
to be a penalty for having the treads go in opposite directions.
|
to be a penalty for having the treads go in opposite directions.
|
||||||
This probably plays hell with precisely-planned tanks, which I
|
This probably plays hell with precisely-planned tanks, which I
|
||||||
find very ha ha. */
|
find very ha ha. */
|
||||||
friction = .25 * (fabsf(tank->speed.current[0] - tank->speed.current[1]) / 200);
|
friction = .75 * (fabsf(tank->speed.current[0] - tank->speed.current[1]) / 200);
|
||||||
|
v[0] = tank->speed.current[0] * (1 - friction) * (TANK_TOP_SPEED / 100.0);
|
||||||
v[0] = tank->speed.current[0] * friction;
|
v[1] = tank->speed.current[1] * (1 - friction) * (TANK_TOP_SPEED / 100.0);
|
||||||
v[1] = tank->speed.current[1] * friction;
|
|
||||||
|
|
||||||
/* Outside and inside speeds */
|
/* Outside and inside speeds */
|
||||||
So = max(v[0], v[1]);
|
So = max(v[0], v[1]);
|
||||||
Si = min(v[0], v[1]);
|
Si = min(v[0], v[1]);
|
||||||
dir = (v[0] > v[1]) ? 1 : -1;
|
dir = (v[0] > v[1]) ? 1 : -1;
|
||||||
|
|
||||||
/* Width of tank */
|
|
||||||
w = TANK_RADIUS * 2;
|
|
||||||
|
|
||||||
/* Radius of circle to outside tread (use similar triangles) */
|
/* Radius of circle to outside tread (use similar triangles) */
|
||||||
r = So * w / (So - Si);
|
r = So * (TANK_RADIUS * 2) / (So - Si);
|
||||||
|
|
||||||
/* pflarr:
|
/* pflarr:
|
||||||
|
|
||||||
|
@ -285,28 +311,25 @@ tanks_move_tank(struct tanks_game *game,
|
||||||
theta = So/r
|
theta = So/r
|
||||||
We multiply it by dir to adjust for the direction of rotation
|
We multiply it by dir to adjust for the direction of rotation
|
||||||
*/
|
*/
|
||||||
theta = rad2deg(So/r) * dir;
|
theta = So/r * dir;
|
||||||
|
|
||||||
/* Translate so the circle's center is 0,0, rotate the point by
|
movement = r * tanf(theta);
|
||||||
theta, then add back in. */
|
|
||||||
v[0] = trig_cos(tank->angle + 90*dir) * (TANK_RADIUS - r);
|
|
||||||
v[1] = trig_sin(tank->angle + 90*dir) * (TANK_RADIUS - r);
|
|
||||||
|
|
||||||
movement[0] = v[0];
|
|
||||||
movement[1] = v[1];
|
|
||||||
rotate_point(theta, movement);
|
|
||||||
|
|
||||||
movement[0] -= v[0];
|
|
||||||
movement[1] -= v[1];
|
|
||||||
angle = theta;
|
angle = theta;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now move the tank */
|
/* Now move the tank */
|
||||||
for (i = 0; i < 2; i += 1) {
|
tank->angle = fmodf(tank->angle + angle + 2*PI, 2*PI);
|
||||||
tank->position[i] = fmodf(tank->position[i] + movement[i] + game->size[i],
|
{
|
||||||
game->size[i]);
|
float m[2];
|
||||||
|
|
||||||
|
m[0] = cosf(tank->angle) * movement;
|
||||||
|
m[1] = sinf(tank->angle) * movement;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i += 1) {
|
||||||
|
tank->position[i] = fmodf(tank->position[i] + m[i] + game->size[i],
|
||||||
|
game->size[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tank->angle = (tank->angle + angle + 360) % 360;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -314,11 +337,31 @@ tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
|
/* Run programs */
|
||||||
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
|
if (! tanks[i].killer) {
|
||||||
|
tanks[i].run(&tanks[i], &tanks[i].udata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear sensors */
|
||||||
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
|
for (j = 0; j < TANK_MAX_SENSORS; j += 1) {
|
||||||
|
tanks[i].sensors[j].triggered = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move */
|
||||||
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
|
if (! tanks[i].killer) {
|
||||||
|
tanks_move_tank(game, &(tanks[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sense and fire */
|
||||||
for (i = 0; i < ntanks; i += 1) {
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
for (j = i + 1; j < ntanks; j += 1) {
|
for (j = i + 1; j < ntanks; j += 1) {
|
||||||
do_shit_with(game, &(tanks[i]), &(tanks[j]));
|
do_shit_with(game, &(tanks[i]), &(tanks[j]));
|
||||||
}
|
}
|
||||||
tanks_print_tank(game, &(tanks[i]));
|
|
||||||
tanks_move_tank(game, &(tanks[i]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
45
ctanks.h
45
ctanks.h
|
@ -2,11 +2,15 @@
|
||||||
#define __CTANKS_H__
|
#define __CTANKS_H__
|
||||||
|
|
||||||
/* Some useful constants */
|
/* Some useful constants */
|
||||||
#define TANK_MAX_SENSORS 10
|
#define PI 3.14159265358979323846
|
||||||
#define TANK_RADIUS 7.5
|
|
||||||
#define TANK_SENSOR_RANGE 100
|
#define TANK_MAX_SENSORS 10
|
||||||
#define TANK_CANNON_RANGE (TANK_SENSOR_RANGE / 2)
|
#define TANK_RADIUS 7.5
|
||||||
#define TANK_MAX_ACCEL 35
|
#define TANK_SENSOR_RANGE 100
|
||||||
|
#define TANK_CANNON_RANGE (TANK_SENSOR_RANGE / 2)
|
||||||
|
#define TANK_MAX_ACCEL 35
|
||||||
|
#define TANK_MAX_TURRET_ROT (PI/3)
|
||||||
|
#define TANK_TOP_SPEED 7
|
||||||
|
|
||||||
/* (tank radius + tank radius)^2 */
|
/* (tank radius + tank radius)^2 */
|
||||||
#define TANK_COLLISION_ADJ2 \
|
#define TANK_COLLISION_ADJ2 \
|
||||||
|
@ -18,6 +22,16 @@
|
||||||
#define TANK_SENSOR_ADJ2 \
|
#define TANK_SENSOR_ADJ2 \
|
||||||
((TANK_SENSOR_RANGE + TANK_RADIUS) * (TANK_SENSOR_RANGE + TANK_RADIUS))
|
((TANK_SENSOR_RANGE + TANK_RADIUS) * (TANK_SENSOR_RANGE + TANK_RADIUS))
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef rad2deg
|
||||||
|
#define rad2deg(r) ((int)(180*(r)/PI))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef max
|
||||||
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
struct tanks_game {
|
struct tanks_game {
|
||||||
float size[2]; /* dimensions of playing field */
|
float size[2]; /* dimensions of playing field */
|
||||||
};
|
};
|
||||||
|
@ -25,10 +39,10 @@ struct tanks_game {
|
||||||
struct tank;
|
struct tank;
|
||||||
|
|
||||||
struct sensor {
|
struct sensor {
|
||||||
int angle;
|
float angle;
|
||||||
int width;
|
float width;
|
||||||
float range;
|
int range;
|
||||||
float range_adj2; /* (range + TANK_RADIUS)^2 */
|
int range_adj2; /* (range + TANK_RADIUS)^2 */
|
||||||
int turret; /* Mounted to turret? */
|
int turret; /* Mounted to turret? */
|
||||||
int triggered;
|
int triggered;
|
||||||
};
|
};
|
||||||
|
@ -37,19 +51,18 @@ typedef void tank_run_func(struct tank *, void *);
|
||||||
|
|
||||||
struct tank {
|
struct tank {
|
||||||
float position[2]; /* Current position on the board */
|
float position[2]; /* Current position on the board */
|
||||||
int angle; /* Current orientation */
|
float angle; /* Current orientation */
|
||||||
struct {
|
struct {
|
||||||
float current[2]; /* Current tread speed */
|
float current[2]; /* Current tread speed */
|
||||||
float desired[2]; /* Desired tread speed */
|
float desired[2]; /* Desired tread speed */
|
||||||
} speed;
|
} speed;
|
||||||
struct {
|
struct {
|
||||||
int current; /* Current turret angle */
|
float current; /* Current turret angle */
|
||||||
int desired; /* Desired turret angle */
|
float desired; /* Desired turret angle */
|
||||||
int firing; /* True if firing this turn */
|
int firing; /* True if firing this turn */
|
||||||
int recharge; /* Turns until gun is recharged */
|
int recharge; /* Turns until gun is recharged */
|
||||||
} turret;
|
} turret;
|
||||||
struct sensor sensor[TANK_MAX_SENSORS]; /* Sensor array */
|
struct sensor sensors[TANK_MAX_SENSORS]; /* Sensor array */
|
||||||
int num_sensors; /* Number of sensors */
|
|
||||||
int led; /* State of the LED */
|
int led; /* State of the LED */
|
||||||
struct tank *killer; /* Killer, or NULL if alive */
|
struct tank *killer; /* Killer, or NULL if alive */
|
||||||
char *cause_death; /* Cause of death */
|
char *cause_death; /* Cause of death */
|
||||||
|
@ -76,10 +89,10 @@ void tank_fire(struct tank *tank);
|
||||||
void tank_set_speed(struct tank *tank, float left, float right);
|
void tank_set_speed(struct tank *tank, float left, float right);
|
||||||
|
|
||||||
/** Get the current turret angle */
|
/** Get the current turret angle */
|
||||||
int tank_get_turret(struct tank *tank);
|
float tank_get_turret(struct tank *tank);
|
||||||
|
|
||||||
/** Set the desired turret angle */
|
/** Set the desired turret angle */
|
||||||
void tank_set_turret(struct tank *tank, int angle);
|
void tank_set_turret(struct tank *tank, float angle);
|
||||||
|
|
||||||
/** Is a sensor active? */
|
/** Is a sensor active? */
|
||||||
int tank_get_sensor(struct tank *tank, int sensor_num);
|
int tank_get_sensor(struct tank *tank, int sensor_num);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tank Game</title>
|
||||||
|
<script type="application/javascript" src="tanks.js"></script>
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
background-color: #444444;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="application/javascript">
|
||||||
|
function go() {
|
||||||
|
start(
|
||||||
|
// Start JSON data
|
||||||
|
divert(1)
|
||||||
|
// end JSON data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
window.onload = go;
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="game_box"><canvas id="battlefield"></canvas></div>
|
||||||
|
<p><span id="fps">0</span> fps</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
divert(0)
|
|
@ -0,0 +1,219 @@
|
||||||
|
function dbg(o) {
|
||||||
|
e = document.getElementById("debug");
|
||||||
|
e.innerHTML = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
function torgba(color, alpha) {
|
||||||
|
var r = parseInt(color.substring(1,3), 16);
|
||||||
|
var g = parseInt(color.substring(3,5), 16);
|
||||||
|
var b = parseInt(color.substring(5,7), 16);
|
||||||
|
|
||||||
|
return "rgba(" + r + "," + g + "," + b + "," + alpha + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
function Tank(ctx, width, height, color, sensors) {
|
||||||
|
var craterStroke = torgba(color, 0.5);
|
||||||
|
var craterFill = torgba(color, 0.2);
|
||||||
|
var sensorStroke = torgba(color, 0.4);
|
||||||
|
var maxlen = 0;
|
||||||
|
|
||||||
|
this.x = 0;
|
||||||
|
this.y = 0;
|
||||||
|
this.rotation = 0;
|
||||||
|
this.turret = 0;
|
||||||
|
|
||||||
|
// Do all the yucky math up front
|
||||||
|
this.sensors = new Array();
|
||||||
|
for (i in sensors) {
|
||||||
|
var s = sensors[i];
|
||||||
|
// r, angle, width, turret
|
||||||
|
this.sensors[i] = new Array();
|
||||||
|
this.sensors[i][0] = s[0];
|
||||||
|
this.sensors[i][1] = s[1] - s[2]/2;
|
||||||
|
this.sensors[i][2] = s[1] + s[2]/2;
|
||||||
|
this.sensors[i][3] = s[3]?1:0;
|
||||||
|
if (s[0] > maxlen) {
|
||||||
|
maxlen = s[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up our state, for later interleaved draw requests
|
||||||
|
this.set_state = function(x, y, rotation, turret, flags, sensor_state) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.rotation = rotation;
|
||||||
|
this.turret = turret;
|
||||||
|
if (flags & 1) {
|
||||||
|
this.fire = 5;
|
||||||
|
}
|
||||||
|
this.led = flags & 2;
|
||||||
|
this.sensor_state = sensor_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.draw_crater = function() {
|
||||||
|
var points = 7;
|
||||||
|
var angle = Math.PI / points;
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(this.x, this.y);
|
||||||
|
ctx.rotate(this.rotation);
|
||||||
|
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.strokeStyle = craterStroke;
|
||||||
|
ctx.fillStyle = craterFill;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(12, 0);
|
||||||
|
for (i = 0; i < points; i += 1) {
|
||||||
|
ctx.rotate(angle);
|
||||||
|
ctx.lineTo(6, 0);
|
||||||
|
ctx.rotate(angle);
|
||||||
|
ctx.lineTo(12, 0);
|
||||||
|
}
|
||||||
|
ctx.closePath()
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.draw_sensors = function() {
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(this.x, this.y);
|
||||||
|
ctx.rotate(this.rotation);
|
||||||
|
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
for (i in this.sensors) {
|
||||||
|
var s = this.sensors[i];
|
||||||
|
var adj = this.turret * s[3];
|
||||||
|
|
||||||
|
if (this.sensor_state & (1 << i)) {
|
||||||
|
// Sensor is triggered
|
||||||
|
ctx.strokeStyle = "#000";
|
||||||
|
} else {
|
||||||
|
ctx.strokeStyle = sensorStroke;
|
||||||
|
}
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(0, 0);
|
||||||
|
ctx.arc(0, 0, s[0], s[1] + adj, s[2] + adj, false);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.draw_tank = function() {
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(this.x, this.y);
|
||||||
|
ctx.rotate(this.rotation);
|
||||||
|
|
||||||
|
ctx.fillStyle = color;
|
||||||
|
ctx.fillRect(-5, -4, 10, 8);
|
||||||
|
ctx.fillStyle = "#777";
|
||||||
|
ctx.fillRect(-7, -9, 15, 5);
|
||||||
|
ctx.fillRect(-7, 4, 15, 5);
|
||||||
|
ctx.rotate(this.turret);
|
||||||
|
if (this.fire) {
|
||||||
|
ctx.fillStyle = ("rgba(68,204,68," + this.fire/5 +")");
|
||||||
|
ctx.fillRect(0, -1, 45, 2);
|
||||||
|
this.fire -= 1;
|
||||||
|
} else {
|
||||||
|
if (this.led) {
|
||||||
|
ctx.fillStyle = "#f00";
|
||||||
|
} else {
|
||||||
|
ctx.fillStyle = "#000";
|
||||||
|
}
|
||||||
|
ctx.fillRect(0, -1, 10, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.draw_wrap_sensors = function() {
|
||||||
|
var orig_x = this.x;
|
||||||
|
var orig_y = this.y;
|
||||||
|
for (x = this.x - width; x < width + maxlen; x += width) {
|
||||||
|
for (y = this.y - height; y < height + maxlen; y += height) {
|
||||||
|
if ((-maxlen < x) && (x < width + maxlen) &&
|
||||||
|
(-maxlen < y) && (y < height + maxlen)) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.draw_sensors();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.x = orig_x;
|
||||||
|
this.y = orig_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function start(game) {
|
||||||
|
var canvas = document.getElementById('battlefield');
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
var loop_id;
|
||||||
|
|
||||||
|
canvas.width = game[0][0];
|
||||||
|
canvas.height = game[0][1];
|
||||||
|
// game[2] is tank descriptions
|
||||||
|
var turns = game[2];
|
||||||
|
|
||||||
|
// Set up tanks
|
||||||
|
var tanks = new Array();
|
||||||
|
for (i in game[1]) {
|
||||||
|
var desc = game[1][i];
|
||||||
|
tanks[i] = new Tank(ctx, game[0][0], game[0][1], desc[0], desc[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var frame = 0;
|
||||||
|
var lastframe = 0;
|
||||||
|
var fps = document.getElementById('fps');
|
||||||
|
|
||||||
|
function update_fps() {
|
||||||
|
fps.innerHTML = (frame - lastframe);
|
||||||
|
lastframe = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var idx = frame % (turns.length + 20);
|
||||||
|
var turn;
|
||||||
|
|
||||||
|
frame += 1;
|
||||||
|
if (idx >= turns.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.width = canvas.width;
|
||||||
|
turn = turns[idx];
|
||||||
|
|
||||||
|
// Draw craters first
|
||||||
|
for (i in turn) {
|
||||||
|
t = turn[i];
|
||||||
|
if (! t) {
|
||||||
|
tanks[i].draw_crater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Then sensors
|
||||||
|
for (i in turn) {
|
||||||
|
t = turn[i];
|
||||||
|
if (t) {
|
||||||
|
// Surely there's a better way to do this.
|
||||||
|
tanks[i].set_state(t[0], t[1], t[2], t[3], t[4], t[5]);
|
||||||
|
tanks[i].draw_wrap_sensors();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Then tanks
|
||||||
|
for (i in turn) {
|
||||||
|
t = turn[i];
|
||||||
|
if (t) {
|
||||||
|
tanks[i].draw_tank()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//loop_id = setInterval(update, 66);
|
||||||
|
loop_id = setInterval(update, 200);
|
||||||
|
if (fps) {
|
||||||
|
setInterval(update_fps, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
122
test-tanks.c
122
test-tanks.c
|
@ -2,24 +2,128 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "ctanks.h"
|
#include "ctanks.h"
|
||||||
|
|
||||||
|
#define NTANKS 2
|
||||||
|
|
||||||
void
|
void
|
||||||
test_run(struct tank *tank, void *unused)
|
test_run(struct tank *tank, void *unused)
|
||||||
{
|
{
|
||||||
tank_set_speed(tank, 30, 50);
|
tank_set_speed(tank, 61, 60);
|
||||||
tank_set_turret(tank, fmod(tank->turret.desired + 0.2, 2*PI));
|
tank_set_turret(tank, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sitting_duck(struct tank *tank, void *unused)
|
||||||
|
{
|
||||||
|
tank_set_turret(tank, tank->turret.desired + PI/15);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct tank mytank;
|
struct tanks_game game;
|
||||||
int i;
|
struct tank mytanks[NTANKS];
|
||||||
|
int i;
|
||||||
|
|
||||||
tank_init(&mytank, test_run, NULL);
|
game.size[0] = 600;
|
||||||
printf("hi\n");
|
game.size[1] = 600;
|
||||||
for (i = 0; i < 4; i += 1) {
|
|
||||||
printf("%f\n", mytank.turret.desired);
|
printf("[\n");
|
||||||
mytank.run(&mytank, mytank.udata);
|
printf("[%d, %d, %d],\n",
|
||||||
|
(int)game.size[0], (int)game.size[1], TANK_CANNON_RANGE);
|
||||||
|
printf("[\n");
|
||||||
|
for (i = 0; i < NTANKS; i += 1) {
|
||||||
|
if (i == 1) {
|
||||||
|
printf(" [\"#888888\",[");
|
||||||
|
tank_init(&mytanks[i], sitting_duck, NULL);
|
||||||
|
} else {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
printf(" [\"#ff4444\",[");
|
||||||
|
tank_init(&mytanks[i], test_run, NULL);
|
||||||
|
|
||||||
|
mytanks[i].sensors[0].angle = 0;
|
||||||
|
mytanks[i].sensors[0].width = PI/10;
|
||||||
|
mytanks[i].sensors[0].range = 50;
|
||||||
|
mytanks[i].sensors[0].turret = 1;
|
||||||
|
|
||||||
|
mytanks[i].sensors[1].angle = 0*PI/2;
|
||||||
|
mytanks[i].sensors[1].width = PI/3;
|
||||||
|
mytanks[i].sensors[1].range = 100;
|
||||||
|
mytanks[i].sensors[1].turret = 1;
|
||||||
|
|
||||||
|
mytanks[i].sensors[2].angle = 1*PI/2;
|
||||||
|
mytanks[i].sensors[2].width = PI/3;
|
||||||
|
mytanks[i].sensors[2].range = 100;
|
||||||
|
mytanks[i].sensors[2].turret = 1;
|
||||||
|
|
||||||
|
mytanks[i].sensors[3].angle = 2*PI/2;
|
||||||
|
mytanks[i].sensors[3].width = PI/3;
|
||||||
|
mytanks[i].sensors[3].range = 100;
|
||||||
|
mytanks[i].sensors[3].turret = 1;
|
||||||
|
|
||||||
|
mytanks[i].sensors[4].angle = 3*PI/2;
|
||||||
|
mytanks[i].sensors[4].width = PI/3;
|
||||||
|
mytanks[i].sensors[4].range = 100;
|
||||||
|
mytanks[i].sensors[4].turret = 1;
|
||||||
|
|
||||||
|
for (j = 0; j < TANK_MAX_SENSORS; j += 1) {
|
||||||
|
struct sensor *s = &(mytanks[i].sensors[j]);
|
||||||
|
|
||||||
|
if (s->range) {
|
||||||
|
printf("[%d, %.2f, %.2f, %d],",
|
||||||
|
(int)(s->range),
|
||||||
|
s->angle,
|
||||||
|
s->width,
|
||||||
|
s->turret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mytanks[i].position[0] = (game.size[0] / NTANKS) * i + 50;
|
||||||
|
mytanks[i].position[1] = 50;
|
||||||
|
/* XXX: print sensors */
|
||||||
|
printf("]],\n");
|
||||||
}
|
}
|
||||||
|
printf("],\n");
|
||||||
|
printf("// Rounds\n");
|
||||||
|
printf("[\n");
|
||||||
|
|
||||||
|
for (i = 0; i < 200; i += 1) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
tanks_run_turn(&game, mytanks, NTANKS);
|
||||||
|
printf("[\n");
|
||||||
|
for (j = 0; j < NTANKS; j += 1) {
|
||||||
|
struct tank *t = &(mytanks[j]);
|
||||||
|
|
||||||
|
if (t->killer) {
|
||||||
|
printf(" 0,\n");
|
||||||
|
} else {
|
||||||
|
int k;
|
||||||
|
int flags = 0;
|
||||||
|
int sensors = 0;
|
||||||
|
|
||||||
|
for (k = 0; k < TANK_MAX_SENSORS; k += 1) {
|
||||||
|
if (t->sensors[k].triggered) {
|
||||||
|
sensors |= (1 << k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t->turret.firing) {
|
||||||
|
flags |= 1;
|
||||||
|
}
|
||||||
|
if (t->led) {
|
||||||
|
flags |= 2;
|
||||||
|
}
|
||||||
|
printf(" [%d,%d,%.2f,%.2f,%d,%d],\n",
|
||||||
|
(int)(t->position[0]),
|
||||||
|
(int)(t->position[1]),
|
||||||
|
t->angle,
|
||||||
|
t->turret.current,
|
||||||
|
flags,
|
||||||
|
sensors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("],\n");
|
||||||
|
}
|
||||||
|
printf("]]\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
93
trig.c
93
trig.c
|
@ -1,93 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include "trig.h"
|
|
||||||
|
|
||||||
#ifndef max
|
|
||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static float trig_cos_table[] = {
|
|
||||||
1.000000, 0.999848, 0.999391, 0.998630, 0.997564, 0.996195,
|
|
||||||
0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627,
|
|
||||||
0.978148, 0.974370, 0.970296, 0.965926, 0.961262, 0.956305,
|
|
||||||
0.951057, 0.945519, 0.939693, 0.933580, 0.927184, 0.920505,
|
|
||||||
0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.874620,
|
|
||||||
0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152,
|
|
||||||
0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.754710,
|
|
||||||
0.743145, 0.731354, 0.719340, 0.707107, 0.694658, 0.681998,
|
|
||||||
0.669131, 0.656059, 0.642788, 0.629320, 0.615661, 0.601815,
|
|
||||||
0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038,
|
|
||||||
0.500000, 0.484810, 0.469472, 0.453990, 0.438371, 0.422618,
|
|
||||||
0.406737, 0.390731, 0.374607, 0.358368, 0.342020, 0.325568,
|
|
||||||
0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951,
|
|
||||||
0.207912, 0.190809, 0.173648, 0.156434, 0.139173, 0.121869,
|
|
||||||
0.104528, 0.087156, 0.069756, 0.052336, 0.034899, 0.017452,
|
|
||||||
0.000000,
|
|
||||||
};
|
|
||||||
|
|
||||||
float
|
|
||||||
trig_cos(int angle)
|
|
||||||
{
|
|
||||||
int a;
|
|
||||||
float ret;
|
|
||||||
|
|
||||||
a = abs(angle) % 180;
|
|
||||||
if (a > 90) {
|
|
||||||
a = 180 - a;
|
|
||||||
}
|
|
||||||
ret = trig_cos_table[a];
|
|
||||||
a = abs(angle) % 360;
|
|
||||||
if ((a > 90) && (a < 270)) {
|
|
||||||
ret = -ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
|
||||||
trig_sin(int angle)
|
|
||||||
{
|
|
||||||
return trig_cos(90 - angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
|
||||||
trig_tan(int angle)
|
|
||||||
{
|
|
||||||
return trig_sin(angle) / trig_cos(angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
trig_asin(float x)
|
|
||||||
{
|
|
||||||
return rad2deg(asinf(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
trig_acos(float x)
|
|
||||||
{
|
|
||||||
return rad2deg(acosf(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
trig_atan2(float y, float x)
|
|
||||||
{
|
|
||||||
return rad2deg(atan2f(y, x));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main()
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
float f;
|
|
||||||
int t;
|
|
||||||
|
|
||||||
for (i = 0; i < 600; i += 1) {
|
|
||||||
printf("%-04d %-0.6f %-0.6f\n", i, trig_cos(i), cosf(deg2rad(i)));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
25
trig.h
25
trig.h
|
@ -1,25 +0,0 @@
|
||||||
#ifndef __TRIG_H__
|
|
||||||
#define __TRIG_H__
|
|
||||||
|
|
||||||
/** Trigonometry in degrees
|
|
||||||
*
|
|
||||||
* It's just a library to do discrete(-ish) trig, using degrees. It
|
|
||||||
* uses a lookup table to make sin, cos, and tan really fast.
|
|
||||||
* Everything is as slow as normal :)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Just to make it clear what scale these functions are dealing with */
|
|
||||||
#define PI 3.14159265358979323846
|
|
||||||
|
|
||||||
#define rad2deg(rad) ((int)(rad * 180 / PI))
|
|
||||||
#define deg2rad(deg) ((float)(deg * PI / 180))
|
|
||||||
|
|
||||||
float trig_cos(int angle);
|
|
||||||
float trig_sin(int angle);
|
|
||||||
float trig_atan(int angle);
|
|
||||||
|
|
||||||
int trig_acos(float angle);
|
|
||||||
int trig_asin(float angle);
|
|
||||||
int trig_atan2(float y, float x);
|
|
||||||
|
|
||||||
#endif /* __TRIG_H__ */
|
|
Loading…
Reference in New Issue