Show exstars.c syntax highlighted
/*
* Example program for the Allegro library, by Dave Thomson.
*
* This program draws a 3D starfield (depth-cued) and a al_draw_polygon
* starship (controllable), using the Allegro math functions.
*/
#include <stdio.h>
#include "allegro.h"
/* starfield system */
typedef struct VECTOR
{
fixed x, y, z;
} VECTOR;
#define NUM_STARS 512
#define Z_NEAR 24
#define Z_FAR 1024
#define XY_CUBE 2048
#define SPEED_LIMIT 20
VECTOR stars[NUM_STARS];
fixed star_x[NUM_STARS];
fixed star_y[NUM_STARS];
VECTOR delta;
/* polygonal models */
#define NUM_VERTS 4
#define NUM_FACES 4
#define ENGINE 3 /* which face is the engine */
#define ENGINE_ON 64 /* colour index */
#define ENGINE_OFF 32
typedef struct FACE /* for triangular models */
{
int v1, v2, v3;
int colour, range;
VECTOR normal, rnormal;
} FACE;
typedef struct MODEL
{
VECTOR points[NUM_VERTS];
FACE faces[NUM_FACES];
fixed x, y, z;
fixed rx, ry, rz;
int minx, miny, maxx, maxy;
VECTOR aim;
int velocity;
} MODEL;
MODEL ship;
VECTOR direction;
AL_BITMAP *buffer;
/* initialises the starfield system */
void init_stars(void)
{
int i;
for (i=0; i<NUM_STARS; i++) {
stars[i].x = al_int_to_fix((rand() % XY_CUBE) - (XY_CUBE >> 1));
stars[i].y = al_int_to_fix((rand() % XY_CUBE) - (XY_CUBE >> 1));
stars[i].z = al_int_to_fix((rand() % (Z_FAR - Z_NEAR)) + Z_NEAR);
}
delta.x = 0;
delta.y = 0;
delta.z = 0;
}
/* draws the starfield */
void draw_stars(void)
{
int i, c;
AL_MATRIX m;
VECTOR outs[NUM_STARS];
for (i=0; i<NUM_STARS; i++) {
al_get_translation_matrix(&m, delta.x, delta.y, delta.z);
al_apply_matrix(&m, stars[i].x, stars[i].y, stars[i].z, &outs[i].x, &outs[i].y, &outs[i].z);
al_persp_project(outs[i].x, outs[i].y, outs[i].z, &star_x[i], &star_y[i]);
c = (al_fix_to_int(outs[i].z) >> 8) + 16;
al_put_pixel(buffer, al_fix_to_int(star_x[i]), al_fix_to_int(star_y[i]), al_palette_color[c]);
}
}
/* deletes the stars from the al_screen */
void erase_stars(void)
{
int i;
for (i=0; i<NUM_STARS; i++)
al_put_pixel(buffer, al_fix_to_int(star_x[i]), al_fix_to_int(star_y[i]), al_palette_color[0]);
}
/* moves the stars */
void move_stars(void)
{
int i;
for (i=0; i<NUM_STARS; i++) {
stars[i].x += delta.x;
stars[i].y += delta.y;
stars[i].z += delta.z;
if (stars[i].x > al_int_to_fix(XY_CUBE >> 1))
stars[i].x = al_int_to_fix(-(XY_CUBE >> 1));
else if (stars[i].x < al_int_to_fix(-(XY_CUBE >> 1)))
stars[i].x = al_int_to_fix(XY_CUBE >> 1);
if (stars[i].y > al_int_to_fix(XY_CUBE >> 1))
stars[i].y = al_int_to_fix(-(XY_CUBE >> 1));
else if (stars[i].y < al_int_to_fix(-(XY_CUBE >> 1)))
stars[i].y = al_int_to_fix(XY_CUBE >> 1);
if (stars[i].z > al_int_to_fix(Z_FAR))
stars[i].z = al_int_to_fix(Z_NEAR);
else if (stars[i].z < al_int_to_fix(Z_NEAR))
stars[i].z = al_int_to_fix(Z_FAR);
}
}
/* initialises the ship model */
void init_ship(void)
{
VECTOR v1, v2, *pts;
FACE *face;
int i;
ship.points[0].x = al_int_to_fix(0);
ship.points[0].y = al_int_to_fix(0);
ship.points[0].z = al_int_to_fix(32);
ship.points[1].x = al_int_to_fix(16);
ship.points[1].y = al_int_to_fix(-16);
ship.points[1].z = al_int_to_fix(-32);
ship.points[2].x = al_int_to_fix(-16);
ship.points[2].y = al_int_to_fix(-16);
ship.points[2].z = al_int_to_fix(-32);
ship.points[3].x = al_int_to_fix(0);
ship.points[3].y = al_int_to_fix(16);
ship.points[3].z = al_int_to_fix(-32);
ship.faces[0].v1 = 3;
ship.faces[0].v2 = 0;
ship.faces[0].v3 = 1;
pts = &ship.points[0];
face = &ship.faces[0];
v1.x = (pts[face->v2].x - pts[face->v1].x);
v1.y = (pts[face->v2].y - pts[face->v1].y);
v1.z = (pts[face->v2].z - pts[face->v1].z);
v2.x = (pts[face->v3].x - pts[face->v1].x);
v2.y = (pts[face->v3].y - pts[face->v1].y);
v2.z = (pts[face->v3].z - pts[face->v1].z);
al_cross_product(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, &(face->normal.x), &(face->normal.y), &(face->normal.z));
ship.faces[1].v1 = 2;
ship.faces[1].v2 = 0;
ship.faces[1].v3 = 3;
face = &ship.faces[1];
v1.x = (pts[face->v2].x - pts[face->v1].x);
v1.y = (pts[face->v2].y - pts[face->v1].y);
v1.z = (pts[face->v2].z - pts[face->v1].z);
v2.x = (pts[face->v3].x - pts[face->v1].x);
v2.y = (pts[face->v3].y - pts[face->v1].y);
v2.z = (pts[face->v3].z - pts[face->v1].z);
al_cross_product(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, &(face->normal.x), &(face->normal.y), &(face->normal.z));
ship.faces[2].v1 = 1;
ship.faces[2].v2 = 0;
ship.faces[2].v3 = 2;
face = &ship.faces[2];
v1.x = (pts[face->v2].x - pts[face->v1].x);
v1.y = (pts[face->v2].y - pts[face->v1].y);
v1.z = (pts[face->v2].z - pts[face->v1].z);
v2.x = (pts[face->v3].x - pts[face->v1].x);
v2.y = (pts[face->v3].y - pts[face->v1].y);
v2.z = (pts[face->v3].z - pts[face->v1].z);
al_cross_product(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, &(face->normal.x), &(face->normal.y), &(face->normal.z));
ship.faces[3].v1 = 2;
ship.faces[3].v2 = 3;
ship.faces[3].v3 = 1;
face = &ship.faces[3];
v1.x = (pts[face->v2].x - pts[face->v1].x);
v1.y = (pts[face->v2].y - pts[face->v1].y);
v1.z = (pts[face->v2].z - pts[face->v1].z);
v2.x = (pts[face->v3].x - pts[face->v1].x);
v2.y = (pts[face->v3].y - pts[face->v1].y);
v2.z = (pts[face->v3].z - pts[face->v1].z);
al_cross_product(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, &(face->normal.x), &(face->normal.y), &(face->normal.z));
for (i=0; i<NUM_FACES; i++) {
ship.faces[i].colour = 32;
ship.faces[i].range = 15;
al_normalize_vector(&ship.faces[i].normal.x, &ship.faces[i].normal.y, &ship.faces[i].normal.z);
ship.faces[i].rnormal.x = ship.faces[i].normal.x;
ship.faces[i].rnormal.y = ship.faces[i].normal.y;
ship.faces[i].rnormal.z = ship.faces[i].normal.z;
}
ship.x = ship.y = 0;
ship.z = al_int_to_fix(192);
ship.rx = ship.ry = ship.rz = 0;
ship.aim.x = direction.x = 0;
ship.aim.y = direction.y = 0;
ship.aim.z = direction.z = al_int_to_fix(-1);
ship.velocity = 0;
}
/* draws the ship model */
void draw_ship(void)
{
VECTOR outs[NUM_VERTS];
AL_MATRIX m;
int i, col;
ship.minx = AL_SCREEN_W;
ship.miny = AL_SCREEN_H;
ship.maxx = ship.maxy = 0;
al_get_rotation_matrix(&m, ship.rx, ship.ry, ship.rz);
al_apply_matrix(&m, ship.aim.x, ship.aim.y, ship.aim.z, &outs[0].x, &outs[0].y, &outs[0].z);
direction.x = outs[0].x;
direction.y = outs[0].y;
direction.z = outs[0].z;
for (i=0; i<NUM_FACES; i++)
al_apply_matrix(&m, ship.faces[i].normal.x, ship.faces[i].normal.y, ship.faces[i].normal.z, &ship.faces[i].rnormal.x, &ship.faces[i].rnormal.y, &ship.faces[i].rnormal.z);
al_get_transformation_matrix(&m, al_int_to_fix(1), ship.rx, ship.ry, ship.rz, ship.x, ship.y, ship.z);
for (i=0; i<NUM_VERTS; i++) {
al_apply_matrix(&m, ship.points[i].x, ship.points[i].y, ship.points[i].z, &outs[i].x, &outs[i].y, &outs[i].z);
al_persp_project(outs[i].x, outs[i].y, outs[i].z, &outs[i].x, &outs[i].y);
if (al_fix_to_int(outs[i].x) < ship.minx)
ship.minx = al_fix_to_int(outs[i].x);
if (al_fix_to_int(outs[i].x) > ship.maxx)
ship.maxx = al_fix_to_int(outs[i].x);
if (al_fix_to_int(outs[i].y) < ship.miny)
ship.miny = al_fix_to_int(outs[i].y);
if (al_fix_to_int(outs[i].y) > ship.maxy)
ship.maxy = al_fix_to_int(outs[i].y);
}
for (i=0; i<NUM_FACES; i++) {
if (al_fix_to_(ship.faces[i].rnormal.z) < 0.0) {
col = al_fix_to_int(al_fix_mul(dot_product(ship.faces[i].rnormal.x, ship.faces[i].rnormal.y, ship.faces[i].rnormal.z, 0, 0, al_int_to_fix(1)), al_int_to_fix(ship.faces[i].range)));
if (col < 0)
col = -col + ship.faces[i].colour;
else
col = col + ship.faces[i].colour;
al_draw_triangle(buffer, al_fix_to_int(outs[ship.faces[i].v1].x), al_fix_to_int(outs[ship.faces[i].v1].y),
al_fix_to_int(outs[ship.faces[i].v2].x), al_fix_to_int(outs[ship.faces[i].v2].y),
al_fix_to_int(outs[ship.faces[i].v3].x), al_fix_to_int(outs[ship.faces[i].v3].y),
al_palette_color[col]);
}
}
}
/* removes the ship model from the al_screen */
void erase_ship(void)
{
al_draw_rect_fill(buffer, ship.minx, ship.miny, ship.maxx, ship.maxy, al_palette_color[0]);
}
int main(int argc, char *argv[])
{
AL_PALETTE pal;
char buf[64];
int i;
allegro_init();
al_install_keyboard();
al_install_timer();
if (al_set_gfx_mode(AL_GFX_SAFE, 320, 200, 0, 0) != 0) {
al_set_gfx_mode(AL_GFX_NONE, 0, 0, 0, 0);
al_show_message("Unable to set any graphic mode\n%s\n", al_error);
return 1;
}
for (i=0; i<16; i++)
pal[i].r = pal[i].g = pal[i].b = 0;
/* greyscale */
pal[16].r = pal[16].g = pal[16].b = 63;
pal[17].r = pal[17].g = pal[17].b = 48;
pal[18].r = pal[18].g = pal[18].b = 32;
pal[19].r = pal[19].g = pal[19].b = 16;
pal[20].r = pal[20].g = pal[20].b = 8;
/* red range */
for (i=0; i<16; i++) {
pal[i+32].r = 31 + i*2;
pal[i+32].g = 15;
pal[i+32].b = 7;
}
/* a nice fire orange */
for (i=64; i<68; i++) {
pal[i].r = 63;
pal[i].g = 17 + (i-64)*3;
pal[i].b = 0;
}
al_set_palette(pal);
buffer = al_create_bitmap(AL_SCREEN_W, AL_SCREEN_H);
al_clear_bitmap(buffer);
al_set_projection_viewport(0, 0, AL_SCREEN_W, AL_SCREEN_H);
init_stars();
draw_stars();
init_ship();
draw_ship();
for (;;) {
erase_stars();
erase_ship();
move_stars();
draw_stars();
sprintf(buf, " direction: [%f] [%f] [%f] ", al_fix_to_(direction.x), al_fix_to_(direction.y), al_fix_to_(direction.z));
al_put_text_centre(buffer, al_font_8x8, buf, AL_SCREEN_W / 2, AL_SCREEN_H-10, al_palette_color[17]);
sprintf(buf, " delta: [%f] [%f] [%f] ", al_fix_to_(delta.x), al_fix_to_(delta.y), al_fix_to_(delta.z));
al_put_text_centre(buffer, al_font_8x8, buf, AL_SCREEN_W / 2, AL_SCREEN_H-20, al_palette_color[17]);
sprintf(buf, " velocity: %d ", ship.velocity);
al_put_text_centre(buffer, al_font_8x8, buf, AL_SCREEN_W / 2, AL_SCREEN_H-30, al_palette_color[17]);
al_put_text_centre(buffer, al_font_8x8, "Press ESC to exit", AL_SCREEN_W/2, 16, al_palette_color[18]);
al_put_text_centre(buffer, al_font_8x8, "Press CTRL to fire engine", AL_SCREEN_W/2, 32, al_palette_color[18]);
draw_ship();
al_vsync();
al_blit(buffer, al_screen, 0, 0, 0, 0, AL_SCREEN_W, AL_SCREEN_H);
al_poll_keyboard();
/* exit program */
if (al_key[AL_KEY_ESC])
break;
/* rotates */
if (al_key[AL_KEY_UP])
ship.rx -= al_int_to_fix(5);
else if (al_key[AL_KEY_DOWN])
ship.rx += al_int_to_fix(5);
if (al_key[AL_KEY_LEFT])
ship.ry -= al_int_to_fix(5);
else if (al_key[AL_KEY_RIGHT])
ship.ry += al_int_to_fix(5);
if (al_key[AL_KEY_PGUP])
ship.rz -= al_int_to_fix(5);
else if (al_key[AL_KEY_PGDN])
ship.rz += al_int_to_fix(5);
/* thrust */
if ((al_key[AL_KEY_LCONTROL]) || (al_key[AL_KEY_RCONTROL])) {
ship.faces[ENGINE].colour = ENGINE_ON;
ship.faces[ENGINE].range = 3;
if (ship.velocity < SPEED_LIMIT)
ship.velocity += 2;
}
else {
ship.faces[ENGINE].colour = ENGINE_OFF;
ship.faces[ENGINE].range = 15;
if (ship.velocity > 0)
ship.velocity -= 2;
}
ship.rx &= al_int_to_fix(255);
ship.ry &= al_int_to_fix(255);
ship.rz &= al_int_to_fix(255);
delta.x = al_fix_mul(direction.x, al_int_to_fix(ship.velocity));
delta.y = al_fix_mul(direction.y, al_int_to_fix(ship.velocity));
delta.z = al_fix_mul(direction.z, al_int_to_fix(ship.velocity));
}
al_destroy_bitmap(buffer);
return 0;
}
AL_END_OF_MAIN();
See more files for this project here