Files
CTheEscape/!TheEsc/c/Mission1
T
2021-03-31 21:08:48 +01:00

1092 lines
31 KiB
C

#include "Graphics.h"
#define PLAYER_Y_START 100
#define PLAYER_X_SPEED 10
#define MAX_NPCS 5
#define MAX_STARS 10
#define MAX_PROJECTILES 15
//#defene PROFILE(X) lastprofile = clock(); X; printf("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t%s %i\n", #X, (clock() - lastprofile))
#define PROFILE(X) X
enum sprite_e{player_ship, durno_ship, ship_trgt, durno_ship2, ship2_trgt, player_shipl,player_shipr,explode_start,explode_shp2,explode_shp3,explode_end,photon1,photon2,plasma1,plasma2};
char *sprites[] = {"player_ship","durno_ship","ship_trgt","durno_ship2","ship2_trgt","player_shipl","player_shipr","explode_shp1","explode_shp2","explode_shp3","explode_shp4","photon1","photon2","plasma1","plasma2"};
char hudbuffer[63];
struct EntityLocation_s {
short signed int X,Y;
};
enum npctype_e{bigdurno, littledurno,maxnpctype};
struct NPC_s {
struct EntityLocation_s location;
enum sprite_e idlesprite;
enum sprite_e sprite;
enum sprite_e weaponspritestart;
enum sprite_e weaponspriteend;
enum npctype_e npctype;
struct EntityLocation_s velocity;
int health;
struct EntityLocation_s hitbox_bl;
struct EntityLocation_s hitbox_tr;
int collideforce;
int collidable;
int explodenextframe;
int nextfire;
int fireinterval;
int firewidth;
};
struct Star_s {
struct EntityLocation_s location;
unsigned char length;
};
struct Player_s {
struct EntityLocation_s location;
enum sprite_e idlesprite;
enum sprite_e sprite;
unsigned char velocity;
int nextidlesprite;
int shields;
int nextshieldheal;
int integrity;
int remainingdistance;
struct EntityLocation_s hitbox_bl;
struct EntityLocation_s hitbox_tr;
struct EntityLocation_s phaser1;
struct EntityLocation_s phaser2;
int targetleft;
int targetright;
short int firingleft;
short int firingright;
int phaserdamage;
};
struct Projectile_s {
struct EntityLocation_s location;
enum sprite_e sprite;
enum sprite_e spritestart;
enum sprite_e spriteend;
struct EntityLocation_s velocity;
int collidable;
int nextframe;
short int active;
int damage;
};
struct Star_s Stars[MAX_STARS];
struct NPC_s NPCS[MAX_NPCS];
struct Projectile_s Projectiles[MAX_PROJECTILES];
struct Player_s Player;
extern void game_respawn_npc(int id);
extern int tick;
extern int lasttick;
enum debugs_e{dbbase,dbhitbox,dbweapons,dbinput,dbperformance,dbnpcs,dbprojectiles,dbmax};
int debugs[dbmax];
enum colour_e{lcars_black,lcars_violet1,debugpink,stargrey,debuggreen,phaserorange1,phaserorange2,tractor1,tractor2,tractor3,tractormax};
int colours[] = {0x11111100,0xc4727200,0xcc00ff00,0x66666600,0x00ff0000,0x0053ff00,0x00d5ff00,0x2e120600,0x1c100a00,0x75250000,0xbf430a00};
void game_spawn_projectile(int id, int Px, int Py, int Vx, int Vy, enum sprite_e spritestart, enum sprite_e spriteend, int damage)
{
int i;
if(id < 0)
{
for(i = 0; i < MAX_PROJECTILES; i++)
{
if(Projectiles[i].active == 0)
id = i;
}
}
// If no velocity X specified we're targetting the player
if(Vx == 0)
{
int V;
int Xdistance = abs((Player.location.X + (Player.hitbox_tr.X/2)) - Px);
int Ydistance = abs((Player.location.Y + (Player.hitbox_tr.Y/2)) - Py);
int distance = sqrt((Xdistance^2) + (Ydistance^2));
V = Vy;
Vx = Xdistance / (distance / Vy);
Vy = Ydistance / (distance / Vy);
if(Player.location.X > Px)
Vx = 0 - Vx;
}
// If it's too close to horizontal you can't dodge
if(Py < (Player.location.X + 100))
id = -1;
//If no free IDs then we go without
if(id >= 0)
{
Projectiles[id].location.X = Px;
Projectiles[id].location.Y = Py;
Projectiles[id].velocity.X = Vx;
Projectiles[id].velocity.Y = Vy;
Projectiles[id].active = 1;
Projectiles[id].sprite = spritestart;
Projectiles[id].spritestart = spritestart;
Projectiles[id].spriteend = spriteend;
Projectiles[id].nextframe = tick + 10;
Projectiles[id].damage = damage;
Projectiles[id].collidable = 1;
}
}
void game_draw_player()
{
draw_sprite(sprites[Player.sprite], Player.location.X, Player.location.Y);
if(debugs[dbhitbox])
{
graphics_colour(colours[debugpink]);
// Bounding box debug
draw_rectangle(
Player.location.X + Player.hitbox_bl.X,
Player.location.Y + Player.hitbox_bl.Y,
Player.location.X + Player.hitbox_tr.X,
Player.location.Y + Player.hitbox_tr.Y
);
}
if((Player.firingleft) && (Player.targetleft >= 0))
{
graphics_colour(colours[phaserorange1]);
draw_line(
Player.location.X + Player.phaser1.X,
Player.location.Y + Player.phaser1.Y,
NPCS[Player.targetleft].location.X + ((NPCS[Player.targetleft].hitbox_bl.X + NPCS[Player.targetleft].hitbox_tr.X)/2),
NPCS[Player.targetleft].location.Y + NPCS[Player.targetleft].hitbox_bl.Y
);
graphics_colour(colours[phaserorange2]);
draw_dotted_line(
Player.location.X + Player.phaser1.X + 1,
Player.location.Y + Player.phaser1.Y,
NPCS[Player.targetleft].location.X + ((NPCS[Player.targetleft].hitbox_bl.X + NPCS[Player.targetleft].hitbox_tr.X)/2) + 1,
NPCS[Player.targetleft].location.Y + NPCS[Player.targetleft].hitbox_bl.Y
);
draw_dotted_line(
Player.location.X + Player.phaser1.X - 1,
Player.location.Y + Player.phaser1.Y,
NPCS[Player.targetleft].location.X + ((NPCS[Player.targetleft].hitbox_bl.X + NPCS[Player.targetleft].hitbox_tr.X)/2) - 1,
NPCS[Player.targetleft].location.Y + NPCS[Player.targetleft].hitbox_bl.Y
);
}
if((Player.firingright) && (Player.targetright >= 0))
{
graphics_colour(colours[phaserorange1]);
draw_line(
Player.location.X + Player.phaser2.X,
Player.location.Y + Player.phaser2.Y,
NPCS[Player.targetright].location.X + ((NPCS[Player.targetright].hitbox_bl.X + NPCS[Player.targetright].hitbox_tr.X)/2),
NPCS[Player.targetright].location.Y + NPCS[Player.targetright].hitbox_bl.Y
);
graphics_colour(colours[phaserorange2]);
draw_dotted_line(
Player.location.X + Player.phaser2.X + 1,
Player.location.Y + Player.phaser2.Y,
NPCS[Player.targetright].location.X + ((NPCS[Player.targetright].hitbox_bl.X + NPCS[Player.targetright].hitbox_tr.X)/2) + 1,
NPCS[Player.targetright].location.Y + NPCS[Player.targetright].hitbox_bl.Y
);
draw_dotted_line(
Player.location.X + Player.phaser2.X - 1,
Player.location.Y + Player.phaser2.Y,
NPCS[Player.targetright].location.X + ((NPCS[Player.targetright].hitbox_bl.X + NPCS[Player.targetright].hitbox_tr.X)/2) - 1,
NPCS[Player.targetright].location.Y + NPCS[Player.targetright].hitbox_bl.Y
);
}
if(debugs[dbweapons])
{
graphics_colour(colours[debuggreen]);
// Draw phaser banks
draw_line(
Player.location.X + Player.phaser1.X,
Player.location.Y + Player.phaser1.Y -5,
Player.location.X + Player.phaser1.X,
Player.location.Y + Player.phaser1.Y + 5
);
draw_line(
Player.location.X + Player.phaser1.X -5,
Player.location.Y + Player.phaser1.Y,
Player.location.X + Player.phaser1.X +5,
Player.location.Y + Player.phaser1.Y
);
draw_line(
Player.location.X + Player.phaser2.X,
Player.location.Y + Player.phaser2.Y -5,
Player.location.X + Player.phaser2.X,
Player.location.Y + Player.phaser2.Y + 5
);
draw_line(
Player.location.X + Player.phaser2.X -5,
Player.location.Y + Player.phaser2.Y,
Player.location.X + Player.phaser2.X +5,
Player.location.Y + Player.phaser2.Y
);
}
}
void game_draw_npcs()
{
int i;
for(i = 0; i < MAX_NPCS; i++)
{
// Don't bother if they are off the screen
if(NPCS[i].location.Y < DISPLAY_Y)
{
draw_sprite(sprites[NPCS[i].sprite], NPCS[i].location.X, NPCS[i].location.Y);
// Next sprite up in index is the appropriate target icon
if(Player.targetleft == i)
draw_sprite(sprites[NPCS[i].sprite + 1], NPCS[i].location.X, NPCS[i].location.Y);
if(Player.targetright == i)
draw_sprite(sprites[NPCS[i].sprite + 1], NPCS[i].location.X, NPCS[i].location.Y);
if(tick > NPCS[i].explodenextframe)
{
if((NPCS[i].sprite >= explode_start) && (NPCS[i].sprite <= explode_end))
{
NPCS[i].sprite++;
if(NPCS[i].sprite > explode_end)
game_respawn_npc(i);
}
NPCS[i].explodenextframe = tick + 4;
}
if(debugs[dbhitbox])
{
graphics_colour(colours[debugpink]);
// Bounding box debug
draw_rectangle(
NPCS[i].location.X + NPCS[i].hitbox_bl.X,
NPCS[i].location.Y + NPCS[i].hitbox_bl.Y,
NPCS[i].location.X + NPCS[i].hitbox_tr.X,
NPCS[i].location.Y + NPCS[i].hitbox_tr.Y
);
}
}
}
}
void game_draw_projectiles()
{
int i;
for(i = 0; i < MAX_PROJECTILES; i++)
{
if(Projectiles[i].active == 0)
continue;
draw_sprite(sprites[Projectiles[i].sprite], Projectiles[i].location.X,Projectiles[i].location.Y);
Projectiles[i].sprite++;
if(Projectiles[i].sprite > Projectiles[i].spriteend)
Projectiles[i].sprite = Projectiles[i].spritestart;
}
}
void game_draw_stars()
{
unsigned char i;
graphics_colour(colours[stargrey]);
for(i = 0; i < MAX_STARS; i++)
{
draw_line(Stars[i].location.X,Stars[i].location.Y,Stars[i].location.X,Stars[i].location.Y+Stars[i].length);
}
}
void game_setup_player()
{
Player.location.X = DISPLAY_X/2;
Player.location.Y = PLAYER_Y_START;
Player.sprite = player_ship;
Player.idlesprite = player_ship;
Player.velocity = 100;
Player.shields = 100;
Player.integrity = 100;
Player.remainingdistance = 1500000;
Player.hitbox_bl.X = 0;
Player.hitbox_bl.Y = 0;
Player.hitbox_tr.X = 60;
Player.hitbox_tr.Y = 81;
Player.phaser1.X = 20;
Player.phaser1.Y = 75;
Player.phaser2.X = 41;
Player.phaser2.Y = 75;
Player.targetleft = -1;
Player.targetright = -1;
Player.firingleft = 0;
Player.firingright = 0;
Player.phaserdamage = 10;
}
void game_tick_stars()
{
int i;
for(i = 0; i < MAX_STARS; i++)
{
Stars[i].location.Y -= (tick - lasttick) * 4;
if((Stars[i].location.Y + Stars[i].length) <= 0)
{
Stars[i].length = 20 + (rand() % 10);
Stars[i].location.X = rand() % DISPLAY_X;
Stars[i].location.Y = DISPLAY_Y + Stars[i].length;
}
}
}
void game_setup_stars()
{
int i;
for(i = 0; i < MAX_STARS; i++)
{
Stars[i].length = 20 + (rand() % 10);
Stars[i].location.X = rand() % DISPLAY_X;
Stars[i].location.Y = rand() % DISPLAY_Y;
}
}
void game_setup_input()
{
/*
inreg.r[0] = 4;
inreg.r[1] = 1;
_kernel_swi(OS_Byte,&inreg,&outreg);
*/
}
void game_respawn_npc(int id)
{
if(Player.remainingdistance <= 120000)
return;
NPCS[id].location.X = rand() % DISPLAY_X;
NPCS[id].location.Y = DISPLAY_Y + (rand() % (DISPLAY_Y/2));
if((rand() % 10) > 3)
NPCS[id].npctype = littledurno;
else
NPCS[id].npctype = bigdurno;
NPCS[id].collidable = 1;
NPCS[id].nextfire = tick + (rand() % 100);
switch(NPCS[id].npctype)
{
case bigdurno:
NPCS[id].idlesprite = durno_ship;
NPCS[id].sprite = durno_ship;
NPCS[id].velocity.X = 0;
NPCS[id].velocity.Y = (rand() % 6) + 1;
NPCS[id].health = 1000;
NPCS[id].hitbox_bl.X = 0;
NPCS[id].hitbox_bl.Y = 0;
NPCS[id].hitbox_tr.X = 48;
NPCS[id].hitbox_tr.Y = 74;
NPCS[id].collideforce = 1000;
NPCS[id].weaponspritestart = photon1;
NPCS[id].weaponspriteend = photon2;
NPCS[id].fireinterval = 100;
NPCS[id].firewidth = 400;
break;
case littledurno:
NPCS[id].idlesprite = durno_ship2;
NPCS[id].sprite = durno_ship2;
NPCS[id].velocity.X = (rand() % 4) + 2;
NPCS[id].velocity.Y = (rand() % 4) + 2;
NPCS[id].health = 300;
NPCS[id].hitbox_bl.X = 0;
NPCS[id].hitbox_bl.Y = 0;
NPCS[id].hitbox_tr.X = 38;
NPCS[id].hitbox_tr.Y = 56;
NPCS[id].collideforce = 50;
NPCS[id].weaponspritestart = plasma1;
NPCS[id].weaponspriteend = plasma2;
NPCS[id].fireinterval = 80;
NPCS[id].firewidth = 30;
break;
};
}
void game_setup_npcs()
{
int i;
for(i = 0; i < MAX_NPCS; i++)
{
game_respawn_npc(i);
NPCS[i].location.Y += 400;
}
}
void game_tick_npcs()
{
int i;
for(i = 0; i < MAX_NPCS; i++)
{
NPCS[i].location.Y -= (tick - lasttick) * NPCS[i].velocity.Y;
NPCS[i].location.X -= (tick - lasttick) * NPCS[i].velocity.X;
if(NPCS[i].npctype == littledurno)
{
if(NPCS[i].location.Y > (Player.location.Y + 500))
{
if(abs(NPCS[i].location.X - Player.location.X) > 100)
{
if(NPCS[i].location.X < Player.location.X)
NPCS[i].velocity.X = 0 - abs(NPCS[i].velocity.X);
else
NPCS[i].velocity.X = abs(NPCS[i].velocity.X);
}
}else{
if(NPCS[i].velocity.X > 0)
NPCS[i].velocity.X = 1;
else
NPCS[i].velocity.X = -1;
// Make the accelerate if they're close
NPCS[i].location.Y -= (tick - lasttick) * NPCS[i].velocity.Y;
}
}
if(NPCS[i].location.Y + NPCS[i].hitbox_tr.Y <= 0)
game_respawn_npc(i);
if((NPCS[i].location.X + NPCS[i].hitbox_tr.X) > DISPLAY_X)
game_respawn_npc(i);
if((NPCS[i].location.X + NPCS[i].hitbox_bl.X) < 0)
game_respawn_npc(i);
if(tick > NPCS[i].nextfire)
{
// Dont fire if off screen
if((NPCS[i].location.Y < DISPLAY_Y))
{
if((NPCS[i].firewidth == -1) || (abs(Player.location.X - NPCS[i].location.X) < NPCS[i].firewidth))
{
if(NPCS[i].weaponspritestart == photon1)
game_spawn_projectile(-1,NPCS[i].location.X, NPCS[i].location.Y, 0, 10, NPCS[i].weaponspritestart, NPCS[i].weaponspriteend, 60);
else
game_spawn_projectile(-1,NPCS[i].location.X, NPCS[i].location.Y, 0, 10, NPCS[i].weaponspritestart, NPCS[i].weaponspriteend, 20);
NPCS[i].nextfire = tick + NPCS[i].fireinterval;
}
}
}
if(NPCS[i].health <= 0)
{
if(NPCS[i].sprite == NPCS[i].idlesprite)
{
NPCS[i].collidable = 0;
NPCS[i].sprite = explode_start;
NPCS[i].explodenextframe = tick + 4;
sound_play(1,-5,0,100);
sound_play(3,-15,0,1000);
sound_play(2,-10,1,100);
}
}
}
}
void game_draw_debugmenu()
{
/* int i;
if(debugs[dbbase])
{
font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
draw_text("Debug List",DISPLAY_X-200,DISPLAY_Y-40,font[sys_12_8]);
font_colour(colours[debugs[dbhitbox]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
draw_text("1: hitbox",DISPLAY_X-200,DISPLAY_Y-60,font[sys_12_8]);
font_colour(colours[debugs[dbweapons]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
draw_text("2: weapons",DISPLAY_X-200,DISPLAY_Y-80,font[sys_12_8]);
font_colour(colours[debugs[dbinput]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
draw_text("3: input",DISPLAY_X-200,DISPLAY_Y-100,font[sys_12_8]);
font_colour(colours[debugs[dbperformance]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
draw_text("4: performance",DISPLAY_X-200,DISPLAY_Y-120,font[sys_12_8]);
font_colour(colours[debugs[dbnpcs]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
draw_text("5: NPCs",DISPLAY_X-200,DISPLAY_Y-140,font[sys_12_8]);
font_colour(colours[debugs[dbprojectiles]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
draw_text("6: Projectiles",DISPLAY_X-200,DISPLAY_Y-160,font[sys_12_8]);
}
if(debugs[dbperformance])
{
font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
sprintf(hudbuffer,"CPF: %i",(tick-lasttick));
draw_text(hudbuffer,DISPLAY_X-500,DISPLAY_Y-60,font[sys_12_8]);
}
if(debugs[dbnpcs])
{
font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
for(i = 0; i < MAX_NPCS; i++)
{
sprintf(hudbuffer,"NPCS[%i] %i%i,%i %i,%i %i",i,NPCS[i].health,NPCS[i].velocity.X,NPCS[i].velocity.Y,NPCS[i].location.X,NPCS[i].location.Y);
draw_text(hudbuffer,DISPLAY_X-800,DISPLAY_Y-60-(i * 20),font[sys_12_8]);
}
}
if(debugs[dbprojectiles])
{
font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
for(i = 0; i < MAX_PROJECTILES; i++)
{
sprintf(hudbuffer,"Projectiles[%i] %i %i,%i %i,%i",i,Projectiles[i].active,Projectiles[i].velocity.X,Projectiles[i].velocity.Y,Projectiles[i].location.X,Projectiles[i].location.Y);
draw_text(hudbuffer,DISPLAY_X-800,DISPLAY_Y-60-(i * 20),font[sys_12_8]);
}
}*/
}
void game_tick_collider()
{
int i;
for(i = 0; i < MAX_NPCS; i++)
{
if(!NPCS[i].collidable)
continue;
// Excuse this formatting
if(
game_hitbox_collide(
(Player.location.X + Player.hitbox_bl.X),(Player.location.Y + Player.hitbox_bl.Y),
(Player.hitbox_tr.X - Player.hitbox_bl.X),(Player.hitbox_tr.Y - Player.hitbox_bl.Y),
(NPCS[i].location.X + NPCS[i].hitbox_bl.X),(NPCS[i].location.Y + NPCS[i].hitbox_bl.Y),
(NPCS[i].hitbox_tr.X - NPCS[i].hitbox_bl.X),(NPCS[i].hitbox_tr.Y - NPCS[i].hitbox_bl.Y)
)
)
{
/*if(debugs[dbhitbox])
{
font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
sprintf(hudbuffer,"NPCS[%i] hits player",i,NPCS[i].location.X,NPCS[i].location.Y);
draw_text(hudbuffer,DISPLAY_X-900,DISPLAY_Y-260-(i * 20),font[sys_12_8]);
}*/
NPCS[i].health -= 300;
NPCS[i].collidable = 0;
NPCS[i].velocity.Y = NPCS[i].velocity.Y / 2;
NPCS[i].velocity.X = NPCS[i].velocity.X * 4;
Player.shields -= NPCS[i].collideforce;
if(Player.shields < 0)
{
Player.integrity += Player.shields;
Player.shields = 0;
}
}
}
for(i = 0; i < MAX_PROJECTILES; i++)
{
if(!Projectiles[i].active)
continue;
if(!Projectiles[i].collidable)
continue;
// Excuse this formatting
if(
game_hitbox_collide(
(Player.location.X + Player.hitbox_bl.X),(Player.location.Y + Player.hitbox_bl.Y),
(Player.hitbox_tr.X - Player.hitbox_bl.X),(Player.hitbox_tr.Y - Player.hitbox_bl.Y),
Projectiles[i].location.X,Projectiles[i].location.Y,
10,10
)
)
{
sound_play(2,-5, 20,1);
Projectiles[i].active = 0;
Player.shields -= Projectiles[i].damage;
if(Player.shields < 0)
{
Player.integrity += Player.shields;
Player.shields = 0;
}
}
}
}
void game_tick_player_targets()
{
int i;
int NoseX = Player.location.X + Player.hitbox_bl.X + (Player.hitbox_tr.X/2);
int NoseXLeft = Player.location.X + Player.hitbox_bl.X;
int NoseXRight = Player.location.X + Player.hitbox_bl.X + Player.hitbox_tr.X;
int NoseY = Player.location.Y + + Player.hitbox_bl.Y + Player.hitbox_tr.Y;
int LeftDistance = 1000;
int RightDistance = 1000;
int LeftCornerX, LeftCornerY, RightCornerX,DistanceX,DistanceY;
Player.targetleft = -1;
Player.targetright = -1;
for(i = 0; i < MAX_NPCS; i++)
{
if(!NPCS[i].collidable)
continue;
if(NPCS[i].location.Y > (DISPLAY_Y-50))
continue;
LeftCornerX = NPCS[i].location.X + NPCS[i].hitbox_bl.X;
LeftCornerY = NPCS[i].location.Y + NPCS[i].hitbox_bl.Y;
RightCornerX = NPCS[i].location.X + NPCS[i].hitbox_tr.X;
if(LeftCornerY > NoseY)
{
DistanceY = LeftCornerY - NoseY;
DistanceX = abs(NoseX - ((LeftCornerX + RightCornerX) / 2));
if((DistanceY/5) > DistanceX)
{
if((NoseXRight - ((LeftCornerX + RightCornerX) / 2)) > 0)
{
if(DistanceY < LeftDistance)
{
LeftDistance = DistanceY;
Player.targetleft = i;
}
}
if((NoseXLeft - ((LeftCornerX + RightCornerX) / 2)) < 0)
{
if(DistanceY < RightDistance)
{
RightDistance = DistanceY;
Player.targetright = i;
}
}
}
}
}
}
void game_tick_projectiles()
{
int i;
for(i = 0; i < MAX_PROJECTILES; i++)
{
if(!Projectiles[i].active)
continue;
if(tick > Projectiles[i].nextframe)
{
if((Projectiles[i].sprite >= photon1) && (Projectiles[i].sprite <= photon2))
{
Projectiles[i].sprite++;
if(Projectiles[i].sprite > photon2)
Projectiles[i].sprite = photon1;
}
Projectiles[i].nextframe = tick + 10;
}
Projectiles[i].location.Y -= (tick - lasttick) * Projectiles[i].velocity.Y;
Projectiles[i].location.X -= (tick - lasttick) * Projectiles[i].velocity.X;
if((Projectiles[i].location.Y) <= 0)
{
Projectiles[i].active = 0;
}
}
}
void game_tick_input()
{
if(debugs[dbbase])
{
// 1
if(input_readkey(17))
debugs[dbinput] = 1;
// 2
if(input_readkey(48))
debugs[dbhitbox] = 1;
// 3
if(input_readkey(49))
debugs[dbweapons] = 1;
// 4
if(input_readkey(18))
debugs[dbperformance] = 1;
// 5
if(input_readkey(19))
debugs[dbnpcs] = 1;
// 6
if(input_readkey(24))
debugs[dbprojectiles] = 1;
}
/*if(debugs[dbinput])
{
font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
sprintf(hudbuffer,"Keycode: %i",input_readanykey());
draw_text(hudbuffer,DISPLAY_X-500,DISPLAY_Y-40,font[sys_12_8]);
}*/
// Q
if(input_readkey(16))
Player.remainingdistance = 0;
// debugs[dbbase] = 1;
// E
if(input_readkey(33))
{
Player.remainingdistance = 120000;
}
// Right arrow
if(input_readkey(121))
{
Player.location.X += PLAYER_X_SPEED * (tick - lasttick);
Player.sprite = player_shipr;
Player.nextidlesprite = tick + 15;
if((Player.location.X + Player.hitbox_tr.X) > DISPLAY_X)
{
Player.location.X = DISPLAY_X - Player.hitbox_tr.X;
}
}
// Left arrow
if(input_readkey(25))
{
Player.location.X -= PLAYER_X_SPEED * (tick - lasttick);
Player.sprite = player_shipl;
Player.nextidlesprite = tick + 15;
if((Player.location.X + Player.hitbox_bl.X) < 0)
{
Player.location.X = 0 - Player.hitbox_bl.X;
}
}
// Space
if(input_readkey(98))
{
Player.firingleft = 1;
Player.firingright = 1;
Player.nextshieldheal = tick + 100;
}else{
Player.firingleft = 0;
Player.firingright = 0;
}
}
void game_setup_audio()
{
sound_voices(4);
sound_set_voice(1,"WaveSynth-Beep");
sound_set_voice(2,"Percussion-Noise");
sound_set_voice(3,"Percussion-Soft");
sound_set_voice(4,"Percussion-Noise");
}
void game_draw_hud()
{
draw_sprite("lcars",4,DISPLAY_Y-164);
draw_sprite("pointer",141+(Player.shields*2),DISPLAY_Y - 164 + 84);
draw_sprite("pointer",141+(Player.integrity*2),DISPLAY_Y - 164 + 44);
draw_sprite("pointer",141+(Player.remainingdistance/7500),DISPLAY_Y - 164 + 4);
}
void game1_setup()
{
game_setup_input();
game_setup_audio();
game_setup_stars();
game_setup_player();
game_setup_npcs();
tick = clock();
}
void game_tick_player()
{
if(tick > Player.nextidlesprite)
Player.sprite = Player.idlesprite;
Player.remainingdistance -= Player.velocity * (tick - lasttick);
if(Player.shields < 100)
{
if(tick > Player.nextshieldheal)
{
Player.shields += 1;
Player.nextshieldheal = tick + 10;
}
}
if((Player.firingleft) && (Player.targetleft >= 0))
{
NPCS[Player.targetleft].health -= (tick - lasttick) * Player.phaserdamage;
}
if((Player.firingright) && (Player.targetright >= 0))
{
NPCS[Player.targetright].health -= (tick - lasttick) * Player.phaserdamage;
}
}
void game1_death()
{
int currentstart = 0;
int introframe = 0;
sound_voices(4);
sound_set_voice(1,"WaveSynth-Beep");
sound_set_voice(2,"WaveSynth-Beep");
sound_set_voice(3,"WaveSynth-Beep");
sound_set_voice(4,"WaveSynth-Beep");
sound_composition_init();
currentstart += 100;
sound_composition_element_add(currentstart,1,sound_note("D2"),150);
currentstart += 100;
sound_composition_element_add(currentstart,2,sound_note("G2"),200);
currentstart += 200;
sound_composition_element_add(currentstart,3,sound_note("B3"),75);
currentstart += 40;
sound_composition_element_add(currentstart,4,sound_note("G2"),75);
currentstart += 50;
sound_composition_element_add(currentstart,2,sound_note("B3"),200);
currentstart += 200;
sound_composition_element_add(currentstart,1,sound_note("A3"),100);
currentstart += 100;
sound_composition_element_add(currentstart,3,sound_note("G2"),150);
currentstart += 150;
sound_composition_element_add(currentstart,2,sound_note("E2"),100);
currentstart += 100;
sound_composition_element_add(currentstart,1,sound_note("D2"),150);
currentstart += 150;
sound_composition_element_add(currentstart,3,sound_note("D2"),150);
currentstart += 100;
sound_composition_element_add(currentstart,4,sound_note("G2"),150);
currentstart += 150;
sound_composition_element_add(currentstart,1,sound_note("B3"),75);
currentstart += 40;
sound_composition_element_add(currentstart,2,sound_note("G2"),75);
currentstart += 40;
sound_composition_element_add(currentstart,3,sound_note("B3"),150);
currentstart += 150;
sound_composition_element_add(currentstart,4,sound_note("A3"),130);
currentstart += 100;
sound_composition_element_add(currentstart,1,sound_note("G2"),200);
currentstart += 300;
tick = clock();
sound_composition_start(clock());
draw_sprite("spacebar",(DISPLAY_X/2)-106,50);
draw_sprite("kia",(DISPLAY_X/2)-300,500);
screen_flipbuffer();
while(sound_composition_incomplete())
{
sound_composition_tick(clock());
if(clock() > (tick + 100))
{
if(input_readkey(98))
sound_composition_stop();
}
}
}
void game_tick_npcs_scatter()
{
int i;
for(i = 0; i < MAX_NPCS; i++)
{
NPCS[i].location.Y -= (tick - lasttick) * NPCS[i].velocity.Y;
if(NPCS[i].velocity.X == 0)
{
if(NPCS[i].location.X > Player.location.X)
NPCS[i].velocity.X = 1;
else
NPCS[i].velocity.X = -1;
}
NPCS[i].location.X += (tick - lasttick) * ((NPCS[i].velocity.X * 3));
if(NPCS[i].health <= 0)
{
if(NPCS[i].sprite == NPCS[i].idlesprite)
{
NPCS[i].collidable = 0;
NPCS[i].sprite = explode_start;
NPCS[i].explodenextframe = tick + 4;
sound_play(1,-5,0,100);
sound_play(3,-15,0,1000);
sound_play(2,-10,1,100);
}
}
}
}
void game_draw_tractor()
{
int tractorx;
int colour;
Player.location.Y += PLAYER_X_SPEED * (tick - lasttick) / 6;
for(tractorx = 0; tractorx <= (Player.hitbox_tr.X - Player.hitbox_bl.X); tractorx++)
{
colour = tractor1;
colour += rand() % (tractormax - tractor1);
graphics_colour(colours[colour]);
if(tractorx % 2 == 0)
{
draw_line(
(Player.location.X + Player.hitbox_bl.X) + tractorx,
Player.location.Y + (Player.hitbox_tr.Y/2),
DISPLAY_X/2,
DISPLAY_Y + 500
);
}else{
draw_dotted_line(
(Player.location.X + Player.hitbox_bl.X) + tractorx,
Player.location.Y + (Player.hitbox_tr.Y/2),
DISPLAY_X/2,
DISPLAY_Y + 200
);
}
}
}
void game_tick_endingcentre()
{
if((Player.location.X + Player.hitbox_bl.X + (Player.hitbox_tr.X/2)) < ((DISPLAY_X/2)-50))
{
Player.location.X += PLAYER_X_SPEED * (tick - lasttick);
Player.sprite = player_shipr;
Player.nextidlesprite = tick + 15;
}
else if((Player.location.X + Player.hitbox_bl.X + (Player.hitbox_tr.X/2)) > ((DISPLAY_X/2)+50))
{
Player.location.X -= PLAYER_X_SPEED * (tick - lasttick);
Player.sprite = player_shipr;
Player.nextidlesprite = tick + 15;
}
else
{
Player.location.X = (DISPLAY_X/2);
}
}
void game1_briefing()
{
screen_clear();
draw_spritetext(
"~~~~~~~~{chief engineers log - uss archimedes - stardate 1234567890 ~~==========~~===============}\n\n\nthe federation has begun diplomatic relations with the planet korell. their unusual position within an asteroid belt \nmeans their planet has to be protected by a deflector shield. the federation has offered to help enhance this shield. \nonce this upgrade was completed we were preparing to leave when we recieved a priority one transmission from the \narchimedes saying a fleet of fighters from the neighbouring planet of durnovaria was en route to torell. it transpires \nthat the deflector shield may also have some military value that was concealed from the federation. the durnovarians \nhave said our shuttle is now considered a military target and will be treated as such. must to get back to the archimedes \nbefore we get dragged further into the conflict between the two planets.\n\n\n\n\n\n\n\n\n\n\n\n\n\n~~~~~~~~{==========================================~~~~~~~~=======}"
, 50, 950);
draw_sprite("spacebar",(DISPLAY_X/2)-106,50);
screen_flipbuffer();
tick = clock();
while(1)
{
if(clock() > (tick + 100))
{
if(input_readkey(98))
return;
}
}
}
void game1_victory()
{
screen_clear();
draw_spritetext(
"~~~~~~~~{chief engineers log - uss archimedes - stardate 1234567890 ~~==========~~===============}\n\n\nour shuttlepod has been rescued by the uss archimedes - but our job here isn't done. the archimedes is now under attack \nfrom the durnovarians, and recoverying the shuttle has come at a cost. Several major systems are now offline.\n\n\n\n\n\n\n\n\n\n\n\n\n\n~~~~~~~~{==========================================~~~~~~~~=======}"
, 50, 950);
draw_sprite("spacebar",(DISPLAY_X/2)-106,50);
screen_flipbuffer();
tick = clock();
while(1)
{
if(clock() > (tick + 100))
{
if(input_readkey(98))
return;
}
}
}
void game_draw_comms(char* msg)
{
draw_sprite("commspanel",4,DISPLAY_Y-164);
draw_spritetext(
msg
, 80, DISPLAY_Y-80);
}
int game1_tick()
{
lasttick = tick;
tick = clock();
screen_flipbuffer();
screen_clear();
if(Player.remainingdistance <= 0)
{
return 2;
}else if (Player.remainingdistance <= 120000)
{
if(Player.remainingdistance <= 80000)
{
PROFILE(game_draw_tractor());
}
game_tick_endingcentre();
// Run a smaller subset of the norm near the ending
PROFILE(game_tick_stars());
PROFILE(game_tick_player());
PROFILE(game_tick_npcs_scatter());
PROFILE(game_tick_projectiles());
PROFILE(game_draw_stars());
PROFILE(game_draw_player());
PROFILE(game_draw_npcs());
PROFILE(game_draw_projectiles());
game_draw_comms("Shuttlepod Phoebe - this is the USS Archimedes.\nPower down your engines and stand by for\nimmediate tractor beam recovery.");
return 0;
}
else if(Player.integrity > 0)
{
PROFILE(game_tick_stars());
PROFILE(game_tick_input());
PROFILE(game_tick_player());
PROFILE(game_tick_npcs());
PROFILE(game_tick_collider());
PROFILE(game_tick_player_targets());
PROFILE(game_tick_projectiles());
PROFILE(game_draw_stars());
PROFILE(game_draw_player());
PROFILE(game_draw_npcs());
PROFILE(game_draw_projectiles());
PROFILE(game_draw_hud());
PROFILE(game_draw_debugmenu());
return 0;
}else{
screen_flipbuffer();
screen_clear();
game1_death();
return 1;
}
}