mirror of
https://github.com/bronson-g/pulsar.git
synced 2025-12-23 22:18:04 -05:00
1526 lines
45 KiB
C
1526 lines
45 KiB
C
|
|
/* Derived from scene.c in the The OpenGL Programming Guide */
|
|
/* Keyboard and mouse rotation taken from Swiftless Tutorials #23 Part 2 */
|
|
/* http://www.swiftless.com/tutorials/opengl/camera2.html */
|
|
|
|
/* Frames per second code taken from : */
|
|
/* http://www.lighthouse3d.com/opengl/glut/index.php?fps */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
#include "graphics.h"
|
|
|
|
/* mob controls */
|
|
extern void createMob(int, float, float, float, float);
|
|
extern void setMobPosition(int, float, float, float, float);
|
|
extern void getMobPosition(int, float*, float*, float*, float*, float*, float*);
|
|
extern int isMobVisible(int);
|
|
extern void hideMob(int);
|
|
extern void showMob(int);
|
|
extern void mobTrajectory(int, float, float);
|
|
|
|
/* viewpoint control */
|
|
extern void setViewPosition(float, float, float);
|
|
extern void getViewPosition(float *, float *, float *);
|
|
extern void getOldViewPosition(float *, float *, float *);
|
|
extern void setViewOrientation(float, float, float);
|
|
extern void getViewOrientation(float *, float *, float *);
|
|
|
|
void startLevel();
|
|
void endLevel();
|
|
|
|
typedef enum colour {
|
|
empty,
|
|
green,
|
|
blue,
|
|
red,
|
|
black,
|
|
white,
|
|
purple,
|
|
orange,
|
|
yellow
|
|
} colour;
|
|
|
|
typedef struct enemy {
|
|
int id;
|
|
int size;
|
|
int x;
|
|
int y;
|
|
int z;
|
|
int dest_x;
|
|
int dest_z;
|
|
colour*** form;
|
|
char type;
|
|
colour col;
|
|
} enemy;
|
|
|
|
colour map[WORLDX][WORLDZ] = {{empty}};
|
|
colour key[11][3] = {{empty}};
|
|
colour message[4][78] = {{empty}};
|
|
int dropBox[3] = {0};
|
|
int dest[2] = {0};
|
|
enemy* enemies = NULL;
|
|
int n_enemies = 0;
|
|
int hasKey = 0;
|
|
int dropParty = 0;
|
|
int bouncing = 0;
|
|
int shot = 0;
|
|
int level = 0;
|
|
int wall_moving = 0;
|
|
int ind = 0;
|
|
|
|
typedef struct wall_chunk {
|
|
int x;
|
|
int z;
|
|
int dir;
|
|
colour col;
|
|
} wall_chunk;
|
|
|
|
void quit() {
|
|
endLevel();
|
|
printf("You made it to level %d.\n", level);
|
|
exit(0);
|
|
}
|
|
|
|
enemy* getEnemy(int x, int y, int z) {
|
|
for(int n=0; n<n_enemies; n++) {
|
|
int off = enemies[n].size/2;
|
|
for(int i=0; i<enemies[n].size; i++) {
|
|
for(int j=0; j<enemies[n].size; j++) {
|
|
for(int k=0; k<enemies[n].size; k++) {
|
|
if(i+(enemies[n].x)-off == x && j+(enemies[n].y)-off == y && k+(enemies[n].z)-off == z) {
|
|
return &enemies[n];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
double radian(double degree) {
|
|
return degree*M_PI/180.0;
|
|
}
|
|
double degree(double radian) {
|
|
return radian*180.0/M_PI;
|
|
}
|
|
|
|
void randDestCell(enemy* mob, int dir) {
|
|
int cell = dir%4;
|
|
mob->dest_z = mob->z;
|
|
mob->dest_x = mob->x;
|
|
|
|
if(cell == 0 && mob->x < (WORLDX -16) -mob->size) {
|
|
mob->dest_x = mob->x + 16;
|
|
} else if(cell == 1 && mob->x > 16 +mob->size) {
|
|
mob->dest_x = mob->x - 16;
|
|
} else if(cell == 2 && mob->z < (WORLDZ -16) -mob->size) {
|
|
mob->dest_z = mob->z + 16;
|
|
} else if(cell == 3 && mob->z > 16 +mob->size) {
|
|
mob->dest_z = mob->z - 16;
|
|
}
|
|
}
|
|
|
|
enemy initEnemy(char type, int size, int x, int z, int temp, int dir) {
|
|
static int id = 1;
|
|
enemy ret;
|
|
|
|
if((type != 'x' && type != 'o') || size < 0 || x < 0 || z < 0) {
|
|
id = 1;
|
|
}
|
|
|
|
ret.id = id;
|
|
ret.size = size;
|
|
ret.x = x;
|
|
ret.y = (size/2)+1;
|
|
ret.z = z;
|
|
ret.type = type;
|
|
|
|
if(type == 'o') {
|
|
ret.col = yellow;
|
|
} else if(type == 'x') {
|
|
ret.col = orange;
|
|
}
|
|
|
|
ret.form = malloc(sizeof(colour**)*size);
|
|
for(int i=0; i<size; i++) {
|
|
ret.form[i] = malloc(sizeof(colour*)*size);
|
|
for(int j=0; j<size; j++) {
|
|
ret.form[i][j] = malloc(sizeof(colour)*size);
|
|
}
|
|
}
|
|
|
|
if(!temp) {
|
|
randDestCell(&ret, dir);
|
|
id++;
|
|
} else {
|
|
ret.dest_x = 0;
|
|
ret.dest_z = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void destroyEnemy(enemy mob) {
|
|
for(int i=0; i<mob.size; i++) {
|
|
for(int j=0; j<mob.size; j++) {
|
|
free(mob.form[i][j]);
|
|
}
|
|
free(mob.form[i]);
|
|
}
|
|
free(mob.form);
|
|
}
|
|
|
|
void eraseEnemy(enemy mob) {
|
|
int off = mob.size/2;
|
|
for(int i=0; i<mob.size; i++) {
|
|
for(int j=0; j<mob.size; j++) {
|
|
for(int k=0; k<mob.size; k++) {
|
|
if(world[i+(mob.x)-off][j+(mob.y)-off][k+(mob.z)-off] == mob.col) {
|
|
world[i+(mob.x)-off][j+(mob.y)-off][k+(mob.z)-off] = empty;
|
|
}
|
|
if(map[i+(mob.x)-off][k+(mob.z)-off] == mob.col) {
|
|
map[i+(mob.x)-off][k+(mob.z)-off] = empty;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void animateEnemy(enemy* mob) {
|
|
enemy temp = initEnemy(mob->type, mob->size, mob->x, mob->z, 1, 1);
|
|
int off = mob->size/2;
|
|
|
|
for(int i=0; i<mob->size; i++) {
|
|
for(int j=0; j<mob->size; j++) {
|
|
for(int k=0; k<mob->size; k++) {
|
|
if(world[i+(mob->x)-off][j+(mob->y)-off][k+(mob->z)-off] == empty) {
|
|
world[i+(mob->x)-off][j+(mob->y)-off][k+(mob->z)-off] = mob->form[i][j][k];
|
|
}
|
|
if(map[i+(mob->x)-off][k+(mob->z)-off] == empty) {
|
|
map[i+(mob->x)-off][k+(mob->z)-off] = mob->form[i][off][k];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for(int i=0; i<mob->size; i++) {
|
|
for(int j=0; j<mob->size; j++) {
|
|
for(int k=0; k<mob->size; k++) {
|
|
temp.form[i][j][k] = mob->form[k][i][j];
|
|
}
|
|
}
|
|
}
|
|
colour*** swap = mob->form;
|
|
mob->form = temp.form;
|
|
temp.form = swap;
|
|
destroyEnemy(temp);
|
|
}
|
|
|
|
void behaveEnemy(enemy* mob, int random) {
|
|
float x, y, z, rotx, roty, rotz, yrot;
|
|
int see = 1;
|
|
getViewPosition(&x, &y, &z);
|
|
getViewOrientation(&rotx, &roty, &rotz);
|
|
|
|
if(mob->x != mob->dest_x) {
|
|
int off = 0;
|
|
if(mob->dest_x > mob->x) {
|
|
off = 1;
|
|
} else {
|
|
off = -1;
|
|
}
|
|
for(int i=0; i<mob->size; i++) {
|
|
for(int j=0; j<mob->size; j++) {
|
|
if(world[mob->x+((mob->size-i)*off)][mob->y][mob->z+j-1] != empty) {
|
|
randDestCell(mob, random);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(mob->z != mob->dest_z) {
|
|
int off = 0;
|
|
if(mob->dest_z > mob->z) {
|
|
off = 1;
|
|
} else {
|
|
off = -1;
|
|
}
|
|
for(int i=0; i<mob->size; i++) {
|
|
for(int j=0; j<mob->size; j++) {
|
|
if(world[mob->x+j-1][mob->y][mob->z+((mob->size-i)*off)] != empty) {
|
|
randDestCell(mob, random);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(mob->dest_x == mob->x && mob->dest_z == mob->z) {
|
|
randDestCell(mob, random);
|
|
} else if(mob->x < mob->dest_x) {
|
|
mob->x = mob->x+1;
|
|
} else if(mob->x > mob->dest_x) {
|
|
mob->x = mob->x-1;
|
|
}
|
|
if(mob->z < mob->dest_z) {
|
|
mob->z = mob->z+1;
|
|
} else if(mob->z > mob->dest_z) {
|
|
mob->z = mob->z-1;
|
|
}
|
|
|
|
x = fabs(x);
|
|
z = fabs(z);
|
|
int zdir = 1;
|
|
int xdir = 1;
|
|
|
|
if(mob->z > z) {
|
|
zdir = -1;
|
|
}
|
|
if(mob->x > x) {
|
|
xdir = -1;
|
|
}
|
|
|
|
for(int i=0; i<abs((int)mob->x-x); i++) {
|
|
for(int j=0; j<abs((int)mob->y-y); j++) {
|
|
for(int k=0; k<abs((int)mob->z-z); k++) {
|
|
if(world[mob->x+i*xdir][mob->y+j][mob->z+k*zdir] != empty) {
|
|
see = 0;
|
|
break;
|
|
}
|
|
}
|
|
if(!see) {
|
|
break;
|
|
}
|
|
}
|
|
if(!see) {
|
|
break;
|
|
}
|
|
}
|
|
float xrot, zrot;
|
|
float mobx, moby, mobz, mobroty, mobrotx, mobrotz;
|
|
int xoff=0, zoff=0;
|
|
int origin = 0;
|
|
float opp, adj, mult = 1.0;
|
|
|
|
if(mob->x>x) {
|
|
xoff = -1*mob->size;
|
|
} else if(mob->x<x) {
|
|
xoff = mob->size;
|
|
}
|
|
if(mob->z>z) {
|
|
zoff = -1*mob->size;
|
|
} else if(mob->z<z) {
|
|
zoff = mob->size;
|
|
}
|
|
|
|
if(x > mob->x && z < mob->z) {
|
|
origin = 90;
|
|
opp = mob->z+zoff-z;
|
|
adj = mob->x+xoff-x;
|
|
} else if(z > mob->z && x > mob->x) {
|
|
origin = 180;
|
|
opp = mob->x+xoff-x;
|
|
adj = mob->z+zoff-z;
|
|
} else if(z > mob->z && x < mob->x) {
|
|
origin = 270;
|
|
opp = mob->z+zoff-z;
|
|
adj = mob->x+xoff-x;
|
|
mult = -1.0;
|
|
} else if(z < mob->z && x < mob->x) {
|
|
origin = 360;
|
|
opp = mob->x+xoff-x;
|
|
adj = mob->z+zoff-z;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
yrot = (float)origin-degree(atan(opp/adj))*mult;
|
|
if(origin == 90) {
|
|
yrot = 90-(yrot-90);
|
|
}
|
|
xrot = 0.0;
|
|
zrot = 0.0;
|
|
|
|
if(see && !isMobVisible(mob->id)) {
|
|
getMobPosition(mob->id, &mobx, &moby, &mobz, &mobroty, &mobrotx, &mobrotz);
|
|
|
|
createMob(mob->id, mob->x+xoff, mob->y, mob->z+zoff, yrot);
|
|
mobTrajectory(mob->id, xrot, zrot);
|
|
showMob(mob->id);
|
|
}
|
|
|
|
if(roty < 90-yrot+45 && roty > 90-yrot-45) {
|
|
switch(origin) {
|
|
case 90:
|
|
mob->dest_x = mob->x-random;
|
|
mob->dest_z = mob->z+random;
|
|
break;
|
|
case 180:
|
|
mob->dest_x = mob->x-random;
|
|
mob->dest_z = mob->z-random;
|
|
break;
|
|
case 270:
|
|
mob->dest_x = mob->x+random;
|
|
mob->dest_z = mob->z-random;
|
|
break;
|
|
case 360:
|
|
mob->dest_x = mob->x+random;
|
|
mob->dest_z = mob->z+random;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void teleEnemy(enemy* mob) {
|
|
int dropOff = 0;
|
|
int newx, newz;
|
|
|
|
while(!dropOff) {
|
|
newx = rand()%WORLDX;
|
|
newz = rand()%WORLDZ;
|
|
int occupied = 0;
|
|
|
|
for(int x=newx; x<newx+3; x++) {
|
|
for(int z=newz; z<newz+3; z++) {
|
|
if(map[x][z] != empty) {
|
|
occupied = 1;
|
|
break;
|
|
}
|
|
}
|
|
if(occupied) {
|
|
break;
|
|
}
|
|
}
|
|
if(!occupied) {
|
|
dropOff = 1;
|
|
}
|
|
}
|
|
|
|
mob->x = newx;
|
|
mob->z = newz;
|
|
}
|
|
|
|
GLfloat* rgb(colour col) {
|
|
static GLfloat val[4] = {0.0, 0.0, 0.0, 1.0};
|
|
for(int i=0; i<3; i++) {
|
|
val[i] = 0.0;
|
|
}
|
|
val[3] = 1.0;
|
|
switch(col) {
|
|
case red:
|
|
val[0] = 1.0;
|
|
break;
|
|
case blue:
|
|
val[2] = 1.0;
|
|
break;
|
|
case purple:
|
|
val[2] = 1.0;
|
|
val[0] = 1.0;
|
|
break;
|
|
case yellow:
|
|
val[1] = 1.0;
|
|
val[0] = 1.0;
|
|
break;
|
|
case white:
|
|
val[0] = 1.0;
|
|
val[1] = 1.0;
|
|
val[2] = 1.0;
|
|
break;
|
|
case green:
|
|
val[1] = 1.0;
|
|
break;
|
|
case orange:
|
|
val[0] = 1.0;
|
|
val[1] = 0.3;
|
|
break;
|
|
case black:
|
|
val[0] = 0.8;
|
|
val[3] = 0.4;
|
|
case empty:
|
|
default:
|
|
break;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
/* mouse function called by GLUT when a button is pressed or released */
|
|
void mouse(int, int, int, int);
|
|
|
|
extern int getMapState();
|
|
|
|
/* initialize graphics library */
|
|
extern void graphicsInit(int *, char **);
|
|
|
|
/* lighting control */
|
|
extern void setLightPosition(GLfloat, GLfloat, GLfloat);
|
|
extern GLfloat* getLightPosition();
|
|
|
|
/* add cube to display list so it will be drawn */
|
|
extern int addDisplayList(int, int, int);
|
|
|
|
/* player controls */
|
|
extern void createPlayer(int, float, float, float, float);
|
|
extern void setPlayerPosition(int, float, float, float, float);
|
|
extern void hidePlayer(int);
|
|
extern void showPlayer(int);
|
|
|
|
/* 2D drawing functions */
|
|
extern void draw2Dline(int, int, int, int, int);
|
|
extern void draw2Dbox(int, int, int, int);
|
|
extern void draw2Dtriangle(int, int, int, int, int, int);
|
|
extern void set2Dcolour(float []);
|
|
|
|
|
|
/* flag which is set to 1 when flying behaviour is desired */
|
|
extern int flycontrol;
|
|
/* flag used to indicate that the test world should be used */
|
|
extern int testWorld;
|
|
/* flag to print out frames per second */
|
|
extern int fps;
|
|
/* flag to indicate the space bar has been pressed */
|
|
extern int space;
|
|
/* flag indicates the program is a client when set = 1 */
|
|
extern int netClient;
|
|
/* flag indicates the program is a server when set = 1 */
|
|
extern int netServer;
|
|
/* size of the window in pixels */
|
|
extern int screenWidth, screenHeight;
|
|
/* flag indicates if map is to be printed */
|
|
extern int displayMap;
|
|
|
|
/* frustum corner coordinates, used for visibility determination */
|
|
extern float corners[4][3];
|
|
|
|
/* determine which cubes are visible e.g. in view frustum */
|
|
extern void ExtractFrustum();
|
|
extern void tree(float, float, float, float, float, float, int);
|
|
|
|
/********* end of extern variable declarations **************/
|
|
|
|
void getDest(int* x, int* z) {
|
|
int destX, destZ;
|
|
int found = 0;
|
|
while(!found) {
|
|
destX = (rand()%(WORLDX-6))+3;
|
|
destZ = (rand()%(WORLDZ-6))+3;
|
|
for(int i=destX-1; i<destX+2; i++) {
|
|
for(int j=destZ-1; j<destZ+2; j++) {
|
|
if(map[i][j]) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*x = destX;
|
|
*z = destZ;
|
|
}
|
|
|
|
int powerUp(colour col) {
|
|
float x,y,z;
|
|
int destX, destZ;
|
|
int ret = 1;
|
|
|
|
switch(col) {
|
|
case blue: //drop-party
|
|
getViewPosition(&x, &y, &z);
|
|
dropParty = 1;
|
|
dropBox[0] = (int)fabs(x);
|
|
dropBox[1] = (int)fabs(z);
|
|
dropBox[2] = WORLDY-1;
|
|
|
|
if(map[dropBox[0]-3][dropBox[1]-3] == empty) {
|
|
colour col = (rand()%3)+1;
|
|
map[dropBox[0]-3][dropBox[1]-3] = col;
|
|
world[dropBox[0]-3][dropBox[2]][dropBox[1]-3] = col;
|
|
}
|
|
if(map[dropBox[0]+3][dropBox[1]-3] == empty) {
|
|
colour col = (rand()%3)+1;
|
|
map[dropBox[0]+3][dropBox[1]-3] = col;
|
|
world[dropBox[0]+3][dropBox[2]][dropBox[1]-3] = col;
|
|
}
|
|
if(map[dropBox[0]-3][dropBox[1]+3] == empty) {
|
|
colour col = (rand()%3)+1;
|
|
map[dropBox[0]-3][dropBox[1]+3] = col;
|
|
world[dropBox[0]-3][dropBox[2]][dropBox[1]+3] = col;
|
|
}
|
|
if(map[dropBox[0]+3][dropBox[1]+3] == empty) {
|
|
colour col = (rand()%3)+1;
|
|
map[dropBox[0]+3][dropBox[1]+3] = col;
|
|
world[dropBox[0]+3][dropBox[2]][dropBox[1]+3] = col;
|
|
}
|
|
break;
|
|
case red: //tele-other
|
|
for(int i=0; i<n_enemies; i++) {
|
|
eraseEnemy(enemies[i]);
|
|
teleEnemy(&enemies[i]);
|
|
}
|
|
break;
|
|
case green: //bouncy-boy
|
|
getDest(&destX, &destZ);
|
|
bouncing = 1;
|
|
dest[0] = destX;
|
|
dest[1] = destZ;
|
|
|
|
break;
|
|
case white: //key
|
|
hasKey = 1;
|
|
printf("You've acquired the key.\n");
|
|
break;
|
|
default:
|
|
ret = 0;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*** collisionResponse() ***/
|
|
/* -performs collision detection and response */
|
|
/* sets new xyz to position of the viewpoint after collision */
|
|
/* -can also be used to implement gravity by updating y position of vp*/
|
|
/* note that the world coordinates returned from getViewPosition()
|
|
will be the negative value of the array indices */
|
|
void collisionResponse() {
|
|
float x=0.0;
|
|
float y=0.0;
|
|
float z=0.0;
|
|
float oldx=0.0;
|
|
float oldy=0.0;
|
|
float oldz=0.0;
|
|
float newx=0.0;
|
|
float newy=0.0;
|
|
float newz=0.0;
|
|
char dirz = '\0';
|
|
char dirx = '\0';
|
|
int i,j;
|
|
int mapx, mapy;
|
|
colour col = empty;
|
|
|
|
getViewPosition(&x, &y, &z);
|
|
getViewPosition(&newx, &newy, &newz);
|
|
getOldViewPosition(&oldx, &oldy, &oldz);
|
|
|
|
mapx = abs((int)oldx);
|
|
mapy = abs((int)oldz);
|
|
|
|
for(i=mapx-1; i<mapx+2; i++) {
|
|
for(j=mapy-1; j<mapy+2; j++) {
|
|
if(i>=0 && i<WORLDX && j>=0 && j<WORLDZ && map[i][j] == white) {
|
|
map[i][j] = empty;
|
|
}
|
|
}
|
|
}
|
|
|
|
newy = oldy;
|
|
|
|
if(oldx-x < 0) {
|
|
dirx = 'e';
|
|
} else {
|
|
dirx = 'w';
|
|
}
|
|
if(oldz-z < 0) {
|
|
dirz = 'n';
|
|
} else {
|
|
dirz = 's';
|
|
}
|
|
|
|
if(dirx == 'e') {
|
|
col = world[abs((int)(x+0.25))][abs((int)y)][abs((int)z)];
|
|
if(col > 0) {
|
|
if(world[abs((int)(x+0.25))][abs((int)(y-1))][abs((int)z)] == 0) {
|
|
newy = oldy-1;
|
|
if(powerUp(col)) {
|
|
world[abs((int)(x+0.25))][abs((int)y)][abs((int)z)] = empty;
|
|
map[abs((int)(x+0.25))][abs((int)z)] = empty;
|
|
} else {
|
|
newy = oldy-1;
|
|
}
|
|
} else {
|
|
if(col == white && world[abs((int)(x+0.25))][abs((int)(y-1))][abs((int)z)] == white && hasKey) {
|
|
printf("Congratulations, you've cleared level %d!\n", level);
|
|
endLevel();
|
|
startLevel();
|
|
return;
|
|
}
|
|
newx = oldx;
|
|
}
|
|
}
|
|
} else if(dirx == 'w') {
|
|
col = world[abs((int)(x-0.25))][abs((int)y)][abs((int)z)];
|
|
if(col > 0) {
|
|
if(world[abs((int)(x-0.25))][abs((int)(y-1))][abs((int)z)] == 0) {
|
|
if(powerUp(col)) {
|
|
world[abs((int)(x-0.25))][abs((int)y)][abs((int)z)] = empty;
|
|
map[abs((int)(x-0.25))][abs((int)z)] = empty;
|
|
} else {
|
|
newy = oldy-1;
|
|
}
|
|
} else {
|
|
if(col == white && world[abs((int)(x-0.25))][abs((int)(y-1))][abs((int)z)] == white && hasKey) {
|
|
printf("Congratulations, you've cleared level %d!\n", level);
|
|
endLevel();
|
|
startLevel();
|
|
return;
|
|
}
|
|
newx = oldx;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dirz == 'n') {
|
|
col = world[abs((int)x)][abs((int)y)][abs((int)(z+0.25))];
|
|
if(col > 0) {
|
|
if(world[abs((int)x)][abs((int)(y-1))][abs((int)(z+0.25))] == 0) {
|
|
if(powerUp(col)) {
|
|
world[abs((int)x)][abs((int)y)][abs((int)(z+0.25))] = empty;
|
|
map[abs((int)x)][abs((int)(z+0.25))] = empty;
|
|
} else {
|
|
newy = oldy-1;
|
|
}
|
|
} else {
|
|
if(col == white && world[abs((int)x)][abs((int)(y-1))][abs((int)(z+0.25))] == white && hasKey) {
|
|
printf("Congratulations, you've cleared level %d!\n", level);
|
|
endLevel();
|
|
startLevel();
|
|
return;
|
|
}
|
|
newz = oldz;
|
|
}
|
|
}
|
|
} else if(dirz == 's') {
|
|
col = world[abs((int)x)][abs((int)y)][abs((int)(z-0.25))];
|
|
if(col > 0) {
|
|
if(world[abs((int)x)][abs((int)(y-1))][abs((int)(z-0.25))] == 0) {
|
|
if(powerUp(col)) {
|
|
world[abs((int)x)][abs((int)y)][abs((int)(z-0.25))] = empty;
|
|
map[abs((int)x)][abs((int)(z-0.25))] = empty;
|
|
} else {
|
|
newy = oldy-1;
|
|
}
|
|
} else {
|
|
if(col == white && world[abs((int)x)][abs((int)(y-1))][abs((int)(z-0.25))] == white && hasKey) {
|
|
printf("Congratulations, you've cleared level %d!\n", level);
|
|
endLevel();
|
|
startLevel();
|
|
return;
|
|
}
|
|
newz = oldz;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(fabs(newx) >= WORLDX) {
|
|
newx = -1.0*(WORLDX-1);
|
|
} else if(newx > 0) {
|
|
newx = 0;
|
|
}
|
|
if(fabs(newz) >= WORLDZ) {
|
|
newz = -1.0*(WORLDZ-1);
|
|
} else if(newz > 0) {
|
|
newz = 0;
|
|
}
|
|
|
|
setViewPosition(newx, newy, newz);
|
|
|
|
mapx = abs((int)newx);
|
|
mapy = abs((int)newz);
|
|
for(i=mapx-1; i<mapx+2; i++) {
|
|
for(j=mapy-1; j<mapy+2; j++) {
|
|
if(i>=0 && i<WORLDX && j>=0 && j<WORLDZ &&map[i][j] == empty) {
|
|
map[i][j] = white;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* chooses whether or not a wall spawns from this pillar, and if so, which direction
|
|
0 for no change
|
|
1 for north
|
|
2 for east
|
|
3 for south
|
|
4 for west
|
|
r is a random integer please pass in rand()
|
|
x and z are the coords of the southeast corner of the pilar
|
|
(only used to handle edge cases)
|
|
*/
|
|
int randomWall(int r, int x, int z, colour* col) {
|
|
r = r%100;
|
|
if(r <= 44) {
|
|
if(r <= 12) {
|
|
if(z==0 || x==WORLDX-4 || z==WORLDZ-4) {
|
|
return 0;
|
|
}
|
|
if(world[x+5][(int)(WORLDY/2)][z+2] == purple) {
|
|
*col = empty;
|
|
} else {
|
|
*col = purple;
|
|
}
|
|
return 1;
|
|
} else if(r<=24) {
|
|
if(x==WORLDX-4 || x==0 || z==WORLDZ-4) {
|
|
return 0;
|
|
}
|
|
if(world[x+2][(int)(WORLDY/2)][z+5] == purple) {
|
|
*col = empty;
|
|
} else {
|
|
*col = purple;
|
|
}
|
|
return 2;
|
|
} else if(r<=36) {
|
|
if(z==0 || x==0 || z==WORLDZ-4) {
|
|
return 0;
|
|
}
|
|
if(world[x-2][(int)(WORLDY/2)][z+2] == purple) {
|
|
*col = empty;
|
|
} else {
|
|
*col = purple;
|
|
}
|
|
return 3;
|
|
} else {
|
|
if(z==0 || x==0 || x==WORLDX-4) {
|
|
return 0;
|
|
}
|
|
if(world[x+2][(int)(WORLDY/2)][z-2] == purple) {
|
|
*col = empty;
|
|
} else {
|
|
*col = purple;
|
|
}
|
|
return 4;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/******* draw2D() *******/
|
|
/* draws 2D shapes on screen */
|
|
/* use the following functions: */
|
|
/* draw2Dline(int, int, int, int, int); */
|
|
/* draw2Dbox(int, int, int, int); */
|
|
/* draw2Dtriangle(int, int, int, int, int, int); */
|
|
/* set2Dcolour(float []); */
|
|
/* colour must be set before other functions are called */
|
|
void draw2D() {
|
|
if (!testWorld) {
|
|
int i,j;
|
|
int xdis = screenWidth-WORLDX;
|
|
int ydis = screenHeight-WORLDZ;
|
|
int smallestRes = 100;
|
|
int mapInflation = 1;
|
|
|
|
if(hasKey) {
|
|
set2Dcolour(rgb(white));
|
|
for(i=0; i<11; i++) {
|
|
for(j=0; j<3; j++) {
|
|
if(key[i][j]) {
|
|
draw2Dbox(i*10+10,j*10+10,(i+1)*10+10,(j+1)*10+10);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch(getMapState()) {
|
|
case 0:
|
|
return;
|
|
case 1:
|
|
for(i=0; i<WORLDX; i++) {
|
|
for(j=0; j<WORLDZ; j++) {
|
|
set2Dcolour(rgb(map[i][j]));
|
|
draw2Dbox(j+xdis,i+ydis,j+1+xdis,i+1+ydis);
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
if(screenHeight > screenWidth) {
|
|
smallestRes = screenWidth;
|
|
} else {
|
|
smallestRes = screenHeight;
|
|
}
|
|
mapInflation = (int)((float)smallestRes/(float)WORLDZ);
|
|
|
|
xdis = (screenWidth-(WORLDX*mapInflation))/2;
|
|
ydis = (screenHeight-(WORLDZ*mapInflation))/2;
|
|
|
|
for(i=0; i<WORLDX; i++) {
|
|
for(j=0; j<WORLDZ; j++) {
|
|
set2Dcolour(rgb(map[i][j]));
|
|
draw2Dbox((j*mapInflation)+xdis,(i*mapInflation)+ydis,((j+1)*mapInflation)+xdis,((i+1)*mapInflation)+ydis);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if(shot) {
|
|
set2Dcolour(rgb(black));
|
|
for(i=0; i<screenWidth; i++) {
|
|
for(j=0; j<screenHeight; j++) {
|
|
if(rand()%20 == 0) {
|
|
draw2Dbox(i,j,i+(rand()%16),j+(rand()%16));
|
|
}
|
|
}
|
|
}
|
|
shot--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*** update() ***/
|
|
/* background process, it is called when there are no other events */
|
|
/* -used to control animations and perform calculations while the */
|
|
/* system is running */
|
|
/* -gravity must also implemented here, duplicate collisionResponse */
|
|
void update() {
|
|
int i, j, k;
|
|
static clock_t gravity_timer = 0;
|
|
static clock_t wall_timer = 0;
|
|
static clock_t inner_wall = 0;
|
|
static clock_t mob_timer = 0;
|
|
static wall_chunk chunks[WORLDX+WORLDZ];
|
|
static int num_chunks = 0;
|
|
static clock_t projectile_timer = 0;
|
|
static clock_t drop_timer = 0;
|
|
static clock_t bounce_timer = 0;
|
|
|
|
/* sample animation for the test world, don't remove this code */
|
|
/* -demo of animating mobs */
|
|
if (!testWorld) {
|
|
//do stuff to update world
|
|
srand(time(NULL));
|
|
float x=0.0;
|
|
float y=0.0;
|
|
float z=0.0;
|
|
|
|
if(gravity_timer == 0) {
|
|
gravity_timer = clock();
|
|
}
|
|
|
|
if(bounce_timer == 0) {
|
|
bounce_timer = clock();
|
|
}
|
|
|
|
if(wall_timer == 0) {
|
|
wall_timer = clock();
|
|
}
|
|
|
|
if(inner_wall == 0) {
|
|
inner_wall = clock();
|
|
}
|
|
|
|
if(projectile_timer == 0) {
|
|
projectile_timer = clock();
|
|
}
|
|
|
|
if(mob_timer == 0) {
|
|
mob_timer = clock();
|
|
}
|
|
|
|
if(drop_timer == 0) {
|
|
drop_timer = clock();
|
|
}
|
|
|
|
getViewPosition(&x, &y, &z);
|
|
|
|
time_t end = clock();
|
|
|
|
if(bouncing && (float)(end - bounce_timer) / (float)CLOCKS_PER_SEC > 0.05) {
|
|
int destX = dest[0], destZ = dest[1];
|
|
float xRatio = 0.0, zRatio = 0.0;
|
|
int xdir = 1, zdir = 1;
|
|
if((int)fabs(x) < destX) {
|
|
xRatio = (destX-fabs(x))/10.0;
|
|
} else if((int)fabs(x) > destX) {
|
|
xRatio = (fabs(x)-destX)/10.0;
|
|
xdir = -1;
|
|
}
|
|
if((int)fabs(z) < destZ) {
|
|
zRatio = (destZ-fabs(z))/10.0;
|
|
} else if((int)fabs(z) > destZ) {
|
|
zRatio = (fabs(z)-destZ)/10.0;
|
|
zdir = -1;
|
|
}
|
|
|
|
if(xRatio < 1 && zRatio < 1) {
|
|
bouncing = 0;
|
|
}
|
|
for(i=(int)fabs(x)-1; i<(int)fabs(x)+2; i++) {
|
|
for(j=(int)fabs(z)-1; j<(int)fabs(z)+2; j++) {
|
|
if(map[i][j] == white) {
|
|
map[i][j] = empty;
|
|
}
|
|
}
|
|
}
|
|
for(i=(int)fabs(x-(xRatio*xdir))-1; i<(int)fabs(x-(xRatio*xdir))+2; i++) {
|
|
for(j=(int)fabs(z-(zRatio*zdir))-1; j<(int)fabs(z-(zRatio*zdir))+2; j++) {
|
|
if(!map[i][j]) {
|
|
map[i][j] = white;
|
|
}
|
|
}
|
|
}
|
|
float yoff = sqrt(((xRatio*10)*(xRatio*10))+((zRatio*10)*(zRatio*10)));
|
|
setViewPosition(x-(xRatio*xdir), -1*yoff, z-(zRatio*zdir));
|
|
getViewPosition(&x, &y, &z);
|
|
bounce_timer = end;
|
|
}
|
|
|
|
if((float)(end - projectile_timer) / (float)CLOCKS_PER_SEC > 0.01) {
|
|
for(i=0; i<=n_enemies; i++) {
|
|
if(isMobVisible(i)) {
|
|
float mobx, moby, mobz, mobroty, mobrotx, mobrotz, difx, difz, dify;
|
|
getMobPosition(i, &mobx, &moby, &mobz, &mobroty, &mobrotx, &mobrotz);
|
|
while(mobroty >= 360.0) {
|
|
mobroty -= 360.0;
|
|
}
|
|
while(mobrotz >= 360.0) {
|
|
mobrotz -= 360.0;
|
|
}
|
|
while(mobrotx >= 360.0) {
|
|
mobrotx -= 360.0;
|
|
}
|
|
|
|
difz = fabs(cos(radian(mobroty)));
|
|
difx = fabs(sin(radian(mobroty)));
|
|
dify = fabs(sin(radian(mobrotx)));
|
|
|
|
if(mobrotx > 0 && mobrotx < 180) {
|
|
dify = -1.0*dify;
|
|
}
|
|
|
|
if(mobroty > 180 && mobroty <= 270) {
|
|
difx = -1.0*difx;
|
|
} else if(mobroty > 270 && mobroty < 360) {
|
|
difz = -1.0*difz;
|
|
difx = -1.0*difx;
|
|
} else if(mobroty >= 0 && mobroty < 90) {
|
|
difz = -1.0*difz;
|
|
}
|
|
if(map[(int)round(mobx)][(int)round(mobz)] == yellow) {
|
|
map[(int)round(mobx)][(int)round(mobz)] = empty;
|
|
}
|
|
if(mobx+difx > WORLDX || mobx+difx < 0 || mobz+difz > WORLDZ || mobz+difz < 0 || moby+dify > WORLDY || moby+dify < 0) {
|
|
hideMob(i);
|
|
} else {
|
|
setMobPosition(i, mobx+difx, moby+dify, mobz+difz, mobroty);
|
|
switch(world[(int)round(mobx+difx)][(int)round(moby+dify)][(int)round(mobz+difz)]) {
|
|
case blue:
|
|
case black:
|
|
hideMob(i);
|
|
break;
|
|
case empty:
|
|
if(map[(int)round(mobx+difx)][(int)round(mobz+difz)] == empty) {
|
|
map[(int)round(mobx+difx)][(int)round(mobz+difz)] = yellow;
|
|
} else if(map[(int)round(mobx+difx)][(int)round(mobz+difz)] == white) {
|
|
if(round(mobx+difx) == round(fabs(x)) && round(mobz+difz) == round(fabs(z))) {
|
|
if((moby+dify) < fabs(y)+1.0 && (moby+dify) > fabs(y)-1.0) {
|
|
printf("You've been shot!\n");
|
|
shot = 12;
|
|
hideMob(i);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
if((int)round(mobx+difx) > 3 && (int)round(mobx+difx) < WORLDX-3 && (int)round(mobz+difz) > 3 && (int)round(mobz+difz) < WORLDZ-3 && world[(int)round(mobx+difx)][(int)round(moby+dify)][(int)round(mobz+difz)] != white) {
|
|
world[(int)round(mobx+difx)][(int)round(moby+dify)][(int)round(mobz+difz)] = empty;
|
|
map[(int)round(mobx+difx)][(int)round(mobz+difz)] = empty;
|
|
}
|
|
hideMob(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if((float)(end - gravity_timer) / (float)CLOCKS_PER_SEC > 0.02 && !bouncing) {
|
|
if(abs((int)y)-1 >= WORLDY || world[abs((int)x)][abs((int)y)-1][abs((int)z)] == 0) {
|
|
setViewPosition(x, y+1, z);
|
|
gravity_timer = end;
|
|
}
|
|
if(y>-1.8) {
|
|
setViewPosition(x, -1.8, z);
|
|
}
|
|
}
|
|
|
|
if((float)(end - wall_timer) / (float)CLOCKS_PER_SEC > 5.0) {
|
|
int w=0;
|
|
|
|
for(w=0; w<WORLDX; w++) {
|
|
int l=0;
|
|
for(l=0; l<WORLDZ; l++) {
|
|
if(w%16==0 && l%16==0) {
|
|
wall_chunk chunk;
|
|
|
|
chunk.x = w;
|
|
chunk.z = l;
|
|
chunk.dir = randomWall(rand(), w, l, &(chunk.col));
|
|
|
|
if(chunk.dir > 0) {
|
|
chunks[num_chunks] = chunk;
|
|
num_chunks++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
wall_moving = 1;
|
|
wall_timer = end;
|
|
}
|
|
|
|
if(wall_moving && (float)(end - inner_wall) / (float)CLOCKS_PER_SEC > 0.08) {
|
|
float xpos, ypos, zpos;
|
|
|
|
for(i=0; i<num_chunks; i++) {
|
|
enemy* mob = NULL;
|
|
switch(chunks[i].dir) {
|
|
case 1: //north
|
|
for(j=chunks[i].z+1; j<chunks[i].z+3; j++) {
|
|
for(k=1; k<WORLDY; k++) {
|
|
getViewPosition(&xpos, &ypos, &zpos);
|
|
if(abs((int)xpos) == (chunks[i].x+15)-ind &&
|
|
abs((int)ypos) == k && abs((int)zpos) == j) {
|
|
if(j==chunks[i].z+1) {
|
|
setViewPosition(xpos, ypos, zpos+1.25);
|
|
} else {
|
|
setViewPosition(xpos, ypos, zpos-1.25);
|
|
}
|
|
}
|
|
if((mob = getEnemy((chunks[i].x+15)-ind, k, j))) {
|
|
eraseEnemy(*mob);
|
|
if(j==chunks[i].z+1) {
|
|
mob->z = mob->z - mob->size;
|
|
} else {
|
|
mob->z = mob->z + mob->size;
|
|
}
|
|
mob->dest_x = mob->x;
|
|
mob->dest_z = mob->z;
|
|
}
|
|
world[(chunks[i].x+15)-ind][k][j] = chunks[i].col;
|
|
}
|
|
map[(chunks[i].x+15)-ind][j] = chunks[i].col;
|
|
}
|
|
break;
|
|
case 2: //east
|
|
for(j=chunks[i].x+1; j<chunks[i].x+3; j++) {
|
|
for(k=1; k<WORLDY; k++) {
|
|
getViewPosition(&xpos, &ypos, &zpos);
|
|
if(abs((int)xpos) == j && abs((int)ypos) == k &&
|
|
abs((int)zpos) == (chunks[i].z+15)-ind) {
|
|
if(j==chunks[i].x+1) {
|
|
setViewPosition(xpos+1.25, ypos, zpos);
|
|
} else {
|
|
setViewPosition(xpos-1.25, ypos, zpos);
|
|
}
|
|
}
|
|
if((mob = getEnemy(j, k, (chunks[i].z+15)-ind))) {
|
|
eraseEnemy(*mob);
|
|
if(j==chunks[i].x+1) {
|
|
mob->x = mob->x - mob->size;
|
|
} else {
|
|
mob->x = mob->x + mob->size;
|
|
}
|
|
mob->dest_x = mob->x;
|
|
mob->dest_z = mob->z;
|
|
}
|
|
world[j][k][(chunks[i].z+15)-ind] = chunks[i].col;
|
|
}
|
|
map[j][(chunks[i].z+15)-ind] = chunks[i].col;
|
|
}
|
|
break;
|
|
case 3: //south
|
|
for(j=chunks[i].z+1; j<chunks[i].z+3; j++) {
|
|
for(k=1; k<WORLDY; k++) {
|
|
getViewPosition(&xpos, &ypos, &zpos);
|
|
if(abs((int)xpos) == (chunks[i].x-1)-ind &&
|
|
abs((int)ypos) == k && abs((int)zpos) == j) {
|
|
if(j==chunks[i].z+1) {
|
|
setViewPosition(xpos, ypos, zpos+1.25);
|
|
} else {
|
|
setViewPosition(xpos, ypos, zpos-1.25);
|
|
}
|
|
}
|
|
if((mob = getEnemy((chunks[i].x-1)-ind, k, j))) {
|
|
eraseEnemy(*mob);
|
|
if(j==chunks[i].z+1) {
|
|
mob->z = mob->z - mob->size;
|
|
} else {
|
|
mob->z = mob->z + mob->size;
|
|
}
|
|
mob->dest_x = mob->x;
|
|
mob->dest_z = mob->z;
|
|
}
|
|
world[(chunks[i].x-1)-ind][k][j] = chunks[i].col;
|
|
}
|
|
map[(chunks[i].x-1)-ind][j] = chunks[i].col;
|
|
}
|
|
break;
|
|
case 4: //west
|
|
for(j=chunks[i].x+1; j<chunks[i].x+3; j++) {
|
|
for(k=1; k<WORLDY; k++) {
|
|
getViewPosition(&xpos, &ypos, &zpos);
|
|
if(abs((int)xpos) == k && abs((int)ypos) == k &&
|
|
abs((int)zpos) == (chunks[i].z-1)-ind) {
|
|
if(j==chunks[i].x+1) {
|
|
setViewPosition(xpos+1.25, ypos, zpos);
|
|
} else {
|
|
setViewPosition(xpos-1.25, ypos, zpos);
|
|
}
|
|
}
|
|
if((mob = getEnemy(j, k, (chunks[i].z-1)-ind))) {
|
|
eraseEnemy(*mob);
|
|
if(j==chunks[i].x+1) {
|
|
mob->x = mob->x - mob->size;
|
|
} else {
|
|
mob->x = mob->x + mob->size;
|
|
}
|
|
mob->dest_x = mob->x;
|
|
mob->dest_z = mob->z;
|
|
}
|
|
world[j][k][(chunks[i].z-1)-ind] = chunks[i].col;
|
|
}
|
|
map[j][(chunks[i].z-1)-ind] = chunks[i].col;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
ind++;
|
|
if(ind == 12) {
|
|
ind = 0;
|
|
wall_moving = 0;
|
|
num_chunks = 0;
|
|
}
|
|
inner_wall = end;
|
|
}
|
|
|
|
if((float)(end - mob_timer) / (float)CLOCKS_PER_SEC > 0.1) {
|
|
for(i=0; i<n_enemies; i++) {
|
|
eraseEnemy(enemies[i]);
|
|
behaveEnemy(&enemies[i], rand());
|
|
animateEnemy(&enemies[i]);
|
|
}
|
|
mob_timer = end;
|
|
}
|
|
|
|
if((float)(end - drop_timer) / (float)CLOCKS_PER_SEC > 0.1 && dropParty) {
|
|
if(dropBox[2] > 1) {
|
|
dropBox[2] = dropBox[2]-1;
|
|
|
|
if(world[dropBox[0]-3][dropBox[2]][dropBox[1]-3] == empty) {
|
|
colour col = (rand()%3)+1;
|
|
map[dropBox[0]-3][dropBox[1]-3] = col;
|
|
world[dropBox[0]-3][dropBox[2]][dropBox[1]-3] = col;
|
|
world[dropBox[0]-3][dropBox[2]+1][dropBox[1]-3] = empty;
|
|
}
|
|
if(world[dropBox[0]+3][dropBox[2]][dropBox[1]-3] == empty) {
|
|
colour col = (rand()%3)+1;
|
|
map[dropBox[0]+3][dropBox[1]-3] = col;
|
|
world[dropBox[0]+3][dropBox[2]][dropBox[1]-3] = col;
|
|
world[dropBox[0]+3][dropBox[2]+1][dropBox[1]-3] = empty;
|
|
}
|
|
if(world[dropBox[0]-3][dropBox[2]][dropBox[1]+3] == empty) {
|
|
colour col = (rand()%3)+1;
|
|
map[dropBox[0]-3][dropBox[1]+3] = col;
|
|
world[dropBox[0]-3][dropBox[2]][dropBox[1]+3] = col;
|
|
world[dropBox[0]-3][dropBox[2]+1][dropBox[1]+3] = empty;
|
|
}
|
|
if(world[dropBox[0]+3][dropBox[2]][dropBox[1]+3] == empty) {
|
|
colour col = (rand()%3)+1;
|
|
map[dropBox[0]+3][dropBox[1]+3] = col;
|
|
world[dropBox[0]+3][dropBox[2]][dropBox[1]+3] = col;
|
|
world[dropBox[0]+3][dropBox[2]+1][dropBox[1]+3] = empty;
|
|
}
|
|
} else {
|
|
dropParty = 0;
|
|
}
|
|
drop_timer = end;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* called by GLUT when a mouse button is pressed or released */
|
|
/* -button indicates which button was pressed or released */
|
|
/* -state indicates a button down or button up event */
|
|
/* -x,y are the screen coordinates when the mouse is pressed or */
|
|
/* released */
|
|
void mouse(int button, int state, int x, int y) {
|
|
float xpos, ypos, zpos;
|
|
float xrot, yrot, zrot;
|
|
float mobx, moby, mobz, mobroty, mobrotx, mobrotz;
|
|
|
|
getViewPosition(&xpos, &ypos, &zpos);
|
|
getViewOrientation(&xrot, &yrot, &zrot);
|
|
getMobPosition(0, &mobx, &moby, &mobz, &mobroty, &mobrotx, &mobrotz);
|
|
|
|
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
|
|
map[(int)(mobx)][(int)(mobz)] = empty;
|
|
createMob(0, fabs(xpos), fabs(ypos), fabs(zpos), yrot);
|
|
mobTrajectory(0, xrot, zrot);
|
|
showMob(0);
|
|
} else if (button == GLUT_MIDDLE_BUTTON) {
|
|
} else {
|
|
}
|
|
if (state == GLUT_UP) {
|
|
} else {
|
|
}
|
|
}
|
|
|
|
void startLevel() {
|
|
int x=0;
|
|
int h=WORLDY;
|
|
int l=0, randX, randZ;
|
|
int i,j,k, keySet = 0;
|
|
|
|
level++;
|
|
|
|
for(x=0; x<WORLDX; x++) {
|
|
int z=0;
|
|
|
|
for(z=0; z<WORLDZ; z++) {
|
|
int y=0;
|
|
|
|
for(y=0; y<WORLDY; y++) {
|
|
world[x][y][z] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(l=0; l<WORLDX; l++) {
|
|
int y=0;
|
|
for(y=0; y<h; y++) {
|
|
int i=0;
|
|
for (i=1; i<3; i++) {
|
|
world[l][y][i] = purple;
|
|
world[l][y][WORLDZ-(i+1)] = purple;
|
|
map[l][i] = purple;
|
|
map[l][WORLDZ-(i+1)] = purple;
|
|
}
|
|
}
|
|
}
|
|
for(l=0; l<WORLDZ; l++) {
|
|
int y=0;
|
|
for(y=0; y<h; y++) {
|
|
int i=0;
|
|
for (i=1; i<3; i++) {
|
|
world[i][y][l] = purple;
|
|
world[WORLDX-(i+1)][y][l] = purple;
|
|
map[i][l] = purple;
|
|
map[WORLDX-(i+1)][l] = purple;
|
|
}
|
|
}
|
|
}
|
|
for(x=0; x<WORLDX; x++) {
|
|
int z=0;
|
|
colour col;
|
|
for(z=0; z<WORLDZ; z++) {
|
|
world[x][0][z] = black;
|
|
if(x%16==0 && z%16==0) {
|
|
int y=0;
|
|
int wall = randomWall(rand(), x, z, &col);
|
|
|
|
for(y=1; y<h; y++) {
|
|
int i=0;
|
|
for(i=0; i<4; i++) {
|
|
int j=0;
|
|
for(j=0; j<4; j++) {
|
|
world[x+i][y][z+j] = blue;
|
|
map[x+i][z+j] = blue;
|
|
}
|
|
}
|
|
}
|
|
switch(wall) {
|
|
int i=0;
|
|
int j=0;
|
|
int k=0;
|
|
|
|
case 1: //north
|
|
for(i=z+4; i<z+16; i++) {
|
|
for(j=x+1; j<x+3; j++) {
|
|
map[j][i] = purple;
|
|
for(k=1; k<h; k++) {
|
|
world[j][k][i] = purple;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 2: //east
|
|
for(i=z+1; i<z+3; i++) {
|
|
for(j=x+4; j<x+16; j++) {
|
|
map[j][i] = purple;
|
|
for(k=1; k<h; k++) {
|
|
world[j][k][i] = purple;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 3: //south
|
|
for(i=z-1; i>=z-12; i--) {
|
|
for(j=x+1; j<x+3; j++) {
|
|
map[j][i] = purple;
|
|
for(k=1; k<h; k++) {
|
|
world[j][k][i] = purple;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 4: //west
|
|
for(i=z+1; i<z+3; i++) {
|
|
for(j=x-1; j>=x-12; j--) {
|
|
map[j][i] = purple;
|
|
for(k=1; k<h; k++) {
|
|
world[j][k][i] = purple;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
} else if((x+7)%16==0 && (z+7)%16==0 && x > 16 && z > 16) {
|
|
if(rand() % 3 == 0 && n_enemies < MOB_COUNT-1) {
|
|
char type = 'x';
|
|
int size = 3;
|
|
if(rand()%2 == 0) {
|
|
type = 'o';
|
|
}
|
|
n_enemies++;
|
|
enemies = realloc(enemies, sizeof(enemy)*n_enemies);
|
|
enemies[n_enemies-1] = initEnemy(type, size, x, z, 0, rand());
|
|
|
|
for(i=0; i<size; i++) {
|
|
for(j=0; j<size; j++) {
|
|
for(k=0; k<size; k++) {
|
|
enemies[n_enemies-1].form[i][j][k] = empty;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(type == 'o') {
|
|
enemies[n_enemies-1].form[0][0][0] = yellow;
|
|
enemies[n_enemies-1].form[2][2][2] = yellow;
|
|
enemies[n_enemies-1].form[1][0][1] = yellow;
|
|
enemies[n_enemies-1].form[1][2][1] = yellow;
|
|
enemies[n_enemies-1].form[0][1][0] = yellow;
|
|
enemies[n_enemies-1].form[0][1][1] = yellow;
|
|
enemies[n_enemies-1].form[0][1][0] = yellow;
|
|
enemies[n_enemies-1].form[1][1][0] = yellow;
|
|
enemies[n_enemies-1].form[0][1][2] = yellow;
|
|
enemies[n_enemies-1].form[2][1][2] = yellow;
|
|
enemies[n_enemies-1].form[2][1][0] = yellow;
|
|
} else if(type == 'x') {
|
|
for(i=0; i<size; i++) {
|
|
enemies[n_enemies-1].form[i][i][i] = orange;
|
|
enemies[n_enemies-1].form[i][i][size-1-i] = orange;
|
|
enemies[n_enemies-1].form[size-1-i][i][i] = orange;
|
|
enemies[n_enemies-1].form[i][size-1-i][i] = orange;
|
|
}
|
|
enemies[n_enemies-1].form[1][1][0] = orange;
|
|
enemies[n_enemies-1].form[1][1][2] = orange;
|
|
enemies[n_enemies-1].form[2][1][1] = orange;
|
|
enemies[n_enemies-1].form[0][1][1] = orange;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
setViewPosition(-10.0, -1.8, -10.0);
|
|
setViewPosition(-10.0, -1.8, -10.0);
|
|
setViewOrientation(0.0, 90.0, 0.0);
|
|
for(i=9; i<12; i++) {
|
|
for(j=9; j<12; j++) {
|
|
map[i][j] = white;
|
|
}
|
|
}
|
|
for(i=0; i<n_enemies; i++) {
|
|
animateEnemy(&enemies[i]);
|
|
}
|
|
for(i=5; i<WORLDX-4; i++) {
|
|
for(j=5; j<WORLDZ-4; j++) {
|
|
if(!map[i][j] && rand()%20000 == 0) {
|
|
colour col = (rand()%3)+1;
|
|
map[i][j] = col;
|
|
world[i][1][j] = col;
|
|
}
|
|
}
|
|
}
|
|
while(!keySet) {
|
|
randX = (rand()%(WORLDX-10))+5;
|
|
randZ = (rand()%(WORLDZ-10))+5;
|
|
keySet = (map[randX][randZ] == empty);
|
|
}
|
|
world[randX][1][randZ] = white;
|
|
map[randX][randZ] = white;
|
|
for(i=7; i<13; i++) {
|
|
for(j=1; j<WORLDY/2; j++) {
|
|
world[i][j][WORLDZ-3] = white;
|
|
}
|
|
map[i][WORLDZ-3] = white;
|
|
}
|
|
}
|
|
}
|
|
|
|
void endLevel() {
|
|
hideMob(0);
|
|
for(int i=0; i<n_enemies; i++) {
|
|
destroyEnemy(enemies[i]);
|
|
hideMob(i+1);
|
|
}
|
|
free(enemies);
|
|
enemies = NULL;
|
|
n_enemies = 0;
|
|
|
|
initEnemy('E', -1, -1, -1, -1, -1);
|
|
|
|
for(int i=0; i<WORLDX; i++) {
|
|
for(int j=0; j<WORLDZ; j++) {
|
|
map[i][j] = empty;
|
|
}
|
|
}
|
|
hasKey = 0;
|
|
dropParty = 0;
|
|
bouncing = 0;
|
|
shot = 0;
|
|
wall_moving = 0;
|
|
ind = 0;
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
int i;
|
|
/* initialize the graphics system */
|
|
graphicsInit(&argc, argv);
|
|
|
|
/* the first part of this if statement builds a sample */
|
|
/* world which will be used for testing */
|
|
/* DO NOT remove this code. */
|
|
/* Put your code in the else statment below */
|
|
/* The testworld is only guaranteed to work with a world of
|
|
with dimensions of 100,50,100. */
|
|
if (!testWorld) {
|
|
srand(time(NULL));
|
|
for(i=0; i<3; i++) {
|
|
for(int j=0; j<3; j+=2) {
|
|
key[i][j] = white;
|
|
}
|
|
}
|
|
for(i=0; i<11; i++) {
|
|
key[i][1] = white;
|
|
}
|
|
key[1][1] = empty;
|
|
key[10][2] = white;
|
|
key[7][2] = white;
|
|
|
|
startLevel();
|
|
|
|
|
|
/* starts the graphics processing loop */
|
|
/* code after this will not run until the program exits */
|
|
glutMainLoop();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|