Files
CTheEscape/!TheEsc/c/Mission2
T

628 lines
16 KiB
C

#include "Graphics.h"
#include "swis.h"
#include <kernel.h>
#include "Sound.h"
extern int tick;
extern int lasttick;
extern int screen;
extern _kernel_swi_regs inreg;
extern _kernel_swi_regs outreg;
#define TILESX 10
#define TILESY 10
#define SMARTTILES 200
#define AREAS 20
// map[0] is the 'master', [1] and [2] represents what is currently
// believed to be displayed in the corresponding (+1) screen buffer
// and we run a compare to see if re-drawing is needed. 0xFF is used
// for a re-draw being required (so it's set on the tile under the player
unsigned char map[3][TILESX][TILESY];
unsigned char fullmap[10000];
unsigned char areaname[13];
char tilenamebuffer[4];
char textbuffer[63];
struct EntityLocation_s {
short signed int X,Y;
};
struct Area_s {
unsigned char name[16];
};
struct Area_s Areas[AREAS];
#define DIRECTION_NONE 0
#define DIRECTION_N 0
#define DIRECTION_E 1
#define DIRECTION_S 2
#define DIRECTION_W 3
struct TilePlayer_s {
struct EntityLocation_s location;
struct EntityLocation_s lastlocation;
struct EntityLocation_s hitbox_bl;
struct EntityLocation_s hitbox_tr;
struct EntityLocation_s drawbox_bl;
struct EntityLocation_s drawbox_tr;
struct EntityLocation_s mapoffset;
struct EntityLocation_s lastmapoffset;
struct EntityLocation_s localtile;
int rawtile;
int lastrawtile;
unsigned char direction;
unsigned char facedirection;
unsigned char sprite[13];
unsigned char basesprite[13];
unsigned char animframe;
int nextanimframe;
int nextanimidle;
};
struct TilePlayer_s TilePlayer;
struct SmartTile_s {
int Tile;
int ActionTarget;
unsigned char Action;
unsigned char ActionValue;
};
struct SmartTile_s SmartTiles[SMARTTILES];
void game2_loadsmarttiles(char* filename)
{
int length;
// Attempt to get file info
inreg.r[0] = 5;
inreg.r[1] = (int) filename;
_kernel_swi(OS_File,&inreg,&outreg);
// Length will be in R4 if it exists
length = outreg.r[4];
if(length > sizeof(SmartTiles))
{
screen_nobuffer();
while (1)
printf("Smarttiles exceeds %d bytes (%d bytes) object type is %d\n",sizeof(SmartTiles),length,outreg.r[0]);
}
// Attempt to get file info
inreg.r[0] = 16;
inreg.r[1] = (int) filename;
inreg.r[2] = (int) SmartTiles;
inreg.r[3] = 0;
_kernel_swi(OS_File,&inreg,&outreg);
}
void game2_loadareanames(char* filename)
{
int length;
// Attempt to get file info
inreg.r[0] = 5;
inreg.r[1] = (int) filename;
_kernel_swi(OS_File,&inreg,&outreg);
// Length will be in R4 if it exists
length = outreg.r[4];
if(length > sizeof(Areas))
{
screen_nobuffer();
while (1)
printf("Areas exceeds %d bytes (%d bytes) object type is %d\n",sizeof(Areas),length,outreg.r[0]);
}
// Attempt to get file info
inreg.r[0] = 16;
inreg.r[1] = (int) filename;
inreg.r[2] = (int) Areas;
inreg.r[3] = 0;
_kernel_swi(OS_File,&inreg,&outreg);
}
void game2_loadmap(char* filename)
{
int length,i;
// Attempt to get file info
inreg.r[0] = 5;
inreg.r[1] = (int) filename;
_kernel_swi(OS_File,&inreg,&outreg);
// Length will be in R4 if it exists
length = outreg.r[4];
if(length > sizeof(fullmap))
{
screen_nobuffer();
while(1)
printf("Map exceeds %d bytes (%d bytes) object type is %d\n",sizeof(fullmap),length,outreg.r[0]);
}
// Attempt to get file info
inreg.r[0] = 16;
inreg.r[1] = (int) filename;
inreg.r[2] = (int) fullmap;
inreg.r[3] = 0;
_kernel_swi(OS_File,&inreg,&outreg);
for(i = 0; i < SMARTTILES; i++)
SmartTiles[i].Tile = -1;
}
void game2_death()
{
int currentstart = 0;
int introframe = 0;
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();
sound_composition_load("music.cmpagrac");
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 game2_briefing()
{
screen_clear();
draw_spritetext(
"~~~~~~~~{ chief engineers log - uss archimedes - stardate 1234567890 ==}\n\n\ndo stuff on the ship. not sure what yet. go for a wander. \n\n\n\n\n\n\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 game2_fillmap(int xoffset, int yoffset)
{
memcpy(map[0][0],fullmap+yoffset+(xoffset*100),10);
memcpy(map[0][1],fullmap+yoffset+(xoffset*100)+100,10);
memcpy(map[0][2],fullmap+yoffset+(xoffset*100)+200,10);
memcpy(map[0][3],fullmap+yoffset+(xoffset*100)+300,10);
memcpy(map[0][4],fullmap+yoffset+(xoffset*100)+400,10);
memcpy(map[0][5],fullmap+yoffset+(xoffset*100)+500,10);
memcpy(map[0][6],fullmap+yoffset+(xoffset*100)+600,10);
memcpy(map[0][7],fullmap+yoffset+(xoffset*100)+700,10);
memcpy(map[0][8],fullmap+yoffset+(xoffset*100)+800,10);
memcpy(map[0][9],fullmap+yoffset+(xoffset*100)+900,10);
}
void game2_setup_audio()
{
sound_pcm_loadsample(PCMSAMPLE_HAIL,"sounds.commbdg");
sound_pcm_loadsample(PCMSAMPLE_DOOR,"sounds.door");
}
void game2_setup()
{
screen_flipbuffer();
screen_clear();
screen_flipbuffer();
screen_clear();
TilePlayer.location.X = 102;
TilePlayer.location.Y = 102;
TilePlayer.hitbox_bl.X = 10;
TilePlayer.hitbox_bl.Y = 10;
TilePlayer.hitbox_tr.X = 70;
TilePlayer.hitbox_tr.Y = 70;
TilePlayer.drawbox_bl.X = 0;
TilePlayer.drawbox_bl.Y = 0;
TilePlayer.drawbox_tr.X = 80;
TilePlayer.drawbox_tr.Y = 80;
TilePlayer.direction = DIRECTION_NONE;
TilePlayer.facedirection = 1;
TilePlayer.animframe = 0;
TilePlayer.nextanimframe = 0;
TilePlayer.nextanimidle = 0;
TilePlayer.lastrawtile = -1;
memset(map[0],0xFF,100);
memset(map[1],0xFF,100);
memset(map[2],0xFF,100);
game2_loadmap("m2_map");
game2_loadsmarttiles("m2_smart");
game2_loadareanames("m2_areas");
game2_setup_audio();
game2_fillmap(TilePlayer.mapoffset.X,TilePlayer.mapoffset.Y);
}
int game2_check_collide()
{
int x,y,hit;
hit = 0;
for(x = 0; x < TILESX; x++)
{
for(y = 0; y < TILESY; y++)
{
// Finds any tile we collide with
if(game_hitbox_collide(
(TilePlayer.location.X + TilePlayer.hitbox_bl.X),(TilePlayer.location.Y + TilePlayer.hitbox_bl.Y),
(TilePlayer.hitbox_tr.X - TilePlayer.hitbox_bl.X),(TilePlayer.hitbox_tr.Y - TilePlayer.hitbox_bl.Y),
x*100,y*100,
100,100
))
{
if(((map[0][x][y] >> 7) & 0x01))
{
hit = 1;
}
}
}
}
return hit;
}
void game2_tick_input()
{
int movex = 0;
int movey = 0;
TilePlayer.direction = 0;
if(input_readkey(57)) // UP
TilePlayer.direction |= 1 << DIRECTION_N;
if(input_readkey(41)) // DOWN
TilePlayer.direction |= 1 << DIRECTION_S;
if(input_readkey(121)) // RIGHT
TilePlayer.direction |= 1 << DIRECTION_E;
if(input_readkey(25)) // LEFT
TilePlayer.direction |= 1 << DIRECTION_W;
// If Up & Down then cancel both
if((TilePlayer.direction & (1 << DIRECTION_N)) && (TilePlayer.direction & (1 << DIRECTION_S)))
TilePlayer.direction -= 5;
// If Left & Right then cancel both
if((TilePlayer.direction & (1 << DIRECTION_E)) && (TilePlayer.direction & (1 << DIRECTION_W)))
TilePlayer.direction -= 10;
// If N
if(TilePlayer.direction & (1 << DIRECTION_N))
movey += 3;
// If S
if(TilePlayer.direction & (1 << DIRECTION_S))
movey -= 3;
// If W
if(TilePlayer.direction & (1 << DIRECTION_W))
movex -= 3;
// If E
if(TilePlayer.direction & (1 << DIRECTION_E))
movex += 3;
// Handle diagonals by reducing to sin(45) * 3 (conveniently about 2)
if((movex == 3) && (movey == 3)) // NE
{
movex = 2;
movey = 2;
}else if((movex == 3) && (movey == -3)) // SW
{
movex = 2;
movey = -2;
}else if((movex == -3) && (movey == 3)) // NW
{
movex = -2;
movey = 3;
}else if((movex == -3) && (movey == -3)) // SE
{
movex = -2;
movey = -2;
}
// Store the last movement so we know where to face an idle player
if(TilePlayer.direction > 0)
{
TilePlayer.facedirection = TilePlayer.direction;
if(tick > TilePlayer.nextanimframe)
{
TilePlayer.animframe++;
TilePlayer.nextanimframe = tick + 10;
TilePlayer.nextanimidle = tick + 20;
}
if(TilePlayer.animframe > 3)
TilePlayer.animframe = 0;
}else{
if(tick > TilePlayer.nextanimidle)
TilePlayer.animframe = 0;
}
// Store in case we have a vertical collide
TilePlayer.lastlocation.X = TilePlayer.location.X;
TilePlayer.lastlocation.Y = TilePlayer.location.Y;
TilePlayer.lastmapoffset.X = TilePlayer.mapoffset.X;
TilePlayer.lastmapoffset.Y = TilePlayer.mapoffset.Y;
if(movey > 0)
{
TilePlayer.location.Y += movey * (tick - lasttick);
if(TilePlayer.location.Y > (910))
{
TilePlayer.location.Y = 100;
TilePlayer.mapoffset.Y += 10;
game2_fillmap(TilePlayer.mapoffset.X,TilePlayer.mapoffset.Y);
}
}
else if(movey < 0)
{
TilePlayer.location.Y += movey * (tick - lasttick);
if(TilePlayer.location.Y < (10))
{
if(TilePlayer.mapoffset.Y > 0)
{
TilePlayer.location.Y = 900;
TilePlayer.mapoffset.Y -= 10;
game2_fillmap(TilePlayer.mapoffset.X,TilePlayer.mapoffset.Y);
}else{
TilePlayer.location.Y = TilePlayer.lastlocation.Y;
}
}
}
if(game2_check_collide())
{
TilePlayer.location.X = TilePlayer.lastlocation.X;
TilePlayer.location.Y = TilePlayer.lastlocation.Y;
TilePlayer.mapoffset.X = TilePlayer.lastmapoffset.X;
TilePlayer.mapoffset.Y = TilePlayer.lastmapoffset.Y;
}
// Store in case we have a horizontal collide
TilePlayer.lastlocation.X = TilePlayer.location.X;
TilePlayer.lastlocation.Y = TilePlayer.location.Y;
if(movex > 0)
{
TilePlayer.location.X += movex * (tick - lasttick);
if(TilePlayer.location.X > (910))
{
TilePlayer.location.X = 100;
TilePlayer.mapoffset.X += 10;
game2_fillmap(TilePlayer.mapoffset.X,TilePlayer.mapoffset.Y);
}
}
else if(movex < 0)
{
TilePlayer.location.X += movex * (tick - lasttick);
if(TilePlayer.location.X < (10))
{
if(TilePlayer.mapoffset.X > 0)
{
TilePlayer.location.X = 900;
TilePlayer.mapoffset.X -= 10;
game2_fillmap(TilePlayer.mapoffset.X,TilePlayer.mapoffset.Y);
}else{
TilePlayer.location.X = TilePlayer.lastlocation.X;
}
}
}
if(game2_check_collide())
{
TilePlayer.location.X = TilePlayer.lastlocation.X;
TilePlayer.location.Y = TilePlayer.lastlocation.Y;
}
}
int game2_tick()
{
int x;
int y;
int i;
char flipv = 0;
char fliph = 0;
lasttick = tick;
tick = clock();
screen_flipbuffer();
if(1)
{
// Fill the map0 with our chunk of the full map
game2_fillmap(TilePlayer.mapoffset.X,TilePlayer.mapoffset.Y);
draw_spritetext("#############", 1020, 950);
draw_spritetext(areaname, 1020, 950);
for(x = 0; x < TILESX; x++)
{
for(y = 0; y < TILESY; y++)
{
// Finds any tile we collide with
if(game_hitbox_collide(
(TilePlayer.location.X + TilePlayer.drawbox_bl.X),(TilePlayer.location.Y + TilePlayer.drawbox_bl.Y),
(TilePlayer.hitbox_tr.X - TilePlayer.drawbox_bl.X),(TilePlayer.drawbox_tr.Y - TilePlayer.drawbox_bl.Y),
x*100,y*100,
100,100
))
{
map[1][x][y] = 255;
map[2][x][y] = 255;
}
// Find the tile under our centre of mass
if(game_hitbox_collide(
(TilePlayer.location.X + TilePlayer.hitbox_bl.X + (TilePlayer.hitbox_tr.X/2)),(TilePlayer.location.Y + TilePlayer.hitbox_bl.Y + (TilePlayer.hitbox_tr.Y/2)),
(1),(1),
x*100,y*100,
100,100
))
{
TilePlayer.localtile.X = x;
TilePlayer.localtile.Y = y;
}
// Redraw any tiles we're overlapping
if(map[0][x][y] ^ map[screen+1][x][y])
{
map[screen+1][x][y] = map[0][x][y];
if(map[screen+1][x][y] < 128)
sprintf(tilenamebuffer,"%i",map[screen+1][x][y]);
else
sprintf(tilenamebuffer,"%i",(map[screen+1][x][y]-128));
draw_tile(tilenamebuffer,x*100,y*100);
}
}
}
TilePlayer.lastrawtile = TilePlayer.rawtile;
TilePlayer.rawtile = (TilePlayer.mapoffset.Y) + TilePlayer.localtile.Y + (TilePlayer.mapoffset.X * 100) + (TilePlayer.localtile.X * 100);
if(TilePlayer.rawtile != TilePlayer.lastrawtile)
{
// Trigger any smart tiles for our centre of mass
for(i = 0; i < SMARTTILES; i++)
{
if(SmartTiles[i].Tile == TilePlayer.rawtile)
{
if(SmartTiles[i].Action == 0) // Change tile sprite
fullmap[SmartTiles[i].ActionTarget] = SmartTiles[i].ActionValue;
else if(SmartTiles[i].Action == 1) // Change area name
sprintf(areaname,"%s",Areas[SmartTiles[i].ActionValue].name);
}
}
}
game2_tick_input();
if((TilePlayer.facedirection & (1 << DIRECTION_N)) && (TilePlayer.facedirection & (1 << DIRECTION_E))) //NE
{
fliph = 1;
sprintf(TilePlayer.basesprite, "man_se");
}else if((TilePlayer.facedirection & (1 << DIRECTION_S)) && (TilePlayer.facedirection & (1 << DIRECTION_E))) // SE
{
sprintf(TilePlayer.basesprite, "man_se");
}else if((TilePlayer.facedirection & (1 << DIRECTION_S)) && (TilePlayer.facedirection & (1 << DIRECTION_W))) // SW
{
flipv = 1;
sprintf(TilePlayer.basesprite, "man_se");
}else if((TilePlayer.facedirection & (1 << DIRECTION_N)) && (TilePlayer.facedirection & (1 << DIRECTION_W))) // NW
{
flipv = 1;
fliph = 1;
sprintf(TilePlayer.basesprite, "man_se");
}else if(TilePlayer.facedirection & (1 << DIRECTION_N)) // N
{
fliph = 1;
sprintf(TilePlayer.basesprite, "man_s");
}else if(TilePlayer.facedirection & (1 << DIRECTION_S)) // S
{
sprintf(TilePlayer.basesprite, "man_s");
}else if(TilePlayer.facedirection & (1 << DIRECTION_E)) // E
{
sprintf(TilePlayer.basesprite, "man_e");
}else if(TilePlayer.facedirection & (1 << DIRECTION_W)) // W
{
flipv = 1;
sprintf(TilePlayer.basesprite, "man_e");
}
if(TilePlayer.animframe == 0)
sprintf(TilePlayer.sprite, "%s",TilePlayer.basesprite);
if(TilePlayer.animframe == 1)
sprintf(TilePlayer.sprite, "%s_l",TilePlayer.basesprite);
if(TilePlayer.animframe == 2)
sprintf(TilePlayer.sprite, "%s",TilePlayer.basesprite);
if(TilePlayer.animframe == 3)
{
// Use 'right' for diagonals, otherwise we flip
if(strlen(TilePlayer.basesprite) > 5)
{
sprintf(TilePlayer.sprite, "%s_r",TilePlayer.basesprite);
}
else
{
if((TilePlayer.facedirection & (1 << DIRECTION_N)) || (TilePlayer.facedirection & (1 << DIRECTION_S)))
flipv = 1;
if((TilePlayer.facedirection & (1 << DIRECTION_E)) || (TilePlayer.facedirection & (1 << DIRECTION_W)))
fliph = 1;
sprintf(TilePlayer.sprite, "%s_l",TilePlayer.basesprite);
}
}
if(fliph && flipv)
draw_sprite_flippedhv(TilePlayer.sprite,TilePlayer.location.X,TilePlayer.location.Y);
else if(fliph)
draw_sprite_flippedh(TilePlayer.sprite,TilePlayer.location.X,TilePlayer.location.Y);
else if(flipv)
draw_sprite_flippedv(TilePlayer.sprite,TilePlayer.location.X,TilePlayer.location.Y);
else
draw_sprite(TilePlayer.sprite,TilePlayer.location.X,TilePlayer.location.Y);
#ifdef M2_DEBUG_HITBOXES
draw_rectangle(
(TilePlayer.location.X + TilePlayer.hitbox_bl.X),
(TilePlayer.location.Y + TilePlayer.hitbox_bl.Y),
(TilePlayer.location.X + TilePlayer.hitbox_tr.X),
(TilePlayer.location.Y + TilePlayer.hitbox_tr.Y)
);
draw_rectangle(
(TilePlayer.location.X + TilePlayer.drawbox_bl.X),
(TilePlayer.location.Y + TilePlayer.drawbox_bl.Y),
(TilePlayer.location.X + TilePlayer.drawbox_tr.X),
(TilePlayer.location.Y + TilePlayer.drawbox_tr.Y)
);
#endif
return 0;
}else{
/* screen_flipbuffer();
screen_clear();
game2_death();
return 1;*/
}
}