#include "Graphics.h" #include "swis.h" #include 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; 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_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(); 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() { 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; 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_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.rawtile = (TilePlayer.mapoffset.Y) + TilePlayer.localtile.Y + (TilePlayer.mapoffset.X * 100) + (TilePlayer.localtile.X * 100); // Trigger any smart tiles for our centre of mass for(i = 0; i < SMARTTILES; i++) { if(SmartTiles[i].Tile == TilePlayer.rawtile) { // Change tile sprite if(SmartTiles[i].Action == 0) fullmap[SmartTiles[i].ActionTarget] = SmartTiles[i].ActionValue; else if(SmartTiles[i].Action == 1) 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;*/ } }