#include "common.h" //#link "common.c" #include "sprites.h" //#link "sprites.c" #include "rasterirq.h" //#link "rasterirq.ca65" #include "bcd.h" //#link "bcd.c" #include "sidmacros.h" ///// SPRITE DATA #define NUM_SPRITE_PATTERNS 4 /*{w:12,h:21,bpp:2,brev:1,wpimg:64,count:4,aspect:2}*/ const char SPRITE_DATA[64*NUM_SPRITE_PATTERNS] = { 0x0A,0xAA,0x80,0x0A,0xAA,0x80,0x2A,0xAA, 0xA0,0x2A,0xAA,0xA0,0xAA,0xAA,0xA8,0xFF, 0xD5,0x40,0xCD,0xD7,0x40,0x3D,0xD5,0x54, 0x37,0x55,0x54,0x37,0x54,0x50,0x05,0x55, 0x00,0x3A,0xA0,0x00,0xEA,0xA8,0x00,0xAB, 0xAA,0x00,0xAB,0xAA,0x00,0xAB,0xAA,0x80, 0xAA,0xEA,0x80,0xAA,0xAA,0x80,0x0F,0xFC, 0x00,0x0F,0xFC,0x00,0x0F,0xFF,0xC0,0x00, 0x02,0xAA,0xA0,0x02,0xAA,0xA0,0x0A,0xAA, 0xA8,0x0A,0xAA,0xA8,0x2A,0xAA,0xAA,0x01, 0x57,0xFF,0x01,0xD7,0x73,0x15,0x57,0x7C, 0x15,0x55,0xDC,0x05,0x15,0xDC,0x00,0x55, 0x50,0x00,0x0A,0xAC,0x00,0x2A,0xAB,0x00, 0xAA,0xEA,0x00,0xAA,0xEA,0x02,0xAA,0xEA, 0x02,0xAB,0xAA,0x02,0xAA,0xAA,0x00,0x3F, 0xF0,0x00,0x3F,0xF0,0x03,0xFF,0xF0,0x00, 0x03,0xFF,0xF0,0x0E,0xAA,0xAC,0x0E,0xAA,0xAC, 0x3A,0xAE,0xAB,0x3A,0xBB,0xAB,0x3A,0xBA,0xAB, 0x3A,0xBB,0xAB,0x3A,0xAE,0xAB,0x3A,0xAA,0xAB, 0x35,0xAA,0x97,0x04,0x6A,0x44,0x04,0x15,0x04, 0x01,0x04,0x10,0x01,0x04,0x10,0x01,0x04,0x10, 0x00,0x44,0x40,0x00,0x44,0x40,0x00,0xEA,0xC0, 0x00,0xD9,0xC0,0x00,0xE6,0xC0,0x00,0x3F,0x00, 0x00, 0x00,0x00,0x00,0x00,0xFF,0x00,0x03,0xAA, 0xC0,0x0E,0xAA,0xB0,0x3A,0xAA,0xAC,0xE9, 0x69,0x6B,0xEA,0x69,0xAB,0xEA,0xAA,0xAB, 0xEA,0xAA,0xAB,0x3A,0x96,0xAC,0x3A,0x69, 0xAC,0x0E,0xAA,0xB0,0x0E,0xAA,0xB0,0x0F, 0xAA,0xF0,0x3A,0xAA,0xAC,0xEE,0xAA,0xBB, 0xEE,0xAA,0xBB,0x33,0xAA,0xCC,0x03,0xAB, 0x00,0x00,0xEB,0x00,0x00,0x3F,0xC0,0x00, }; ///// DEFINES #define GAME_BASE 0x400 #define SCORE_BASE 0x2c00 #define SPRITE_SHAPE 192 // first sprite shape # #define PLAYER_SHAPE SPRITE_SHAPE #define POWERUP_SHAPE (SPRITE_SHAPE+2) #define OBSTACLE_SHAPE (SPRITE_SHAPE+3) #define PLAYER_INDEX 0 // sprite indices #define POWERUP_INDEX 1 #define OBSTACLE_INDEX 2 #define CENTER_X 172 // sprite start X coord. #define FLOOR_Y (128 << 8) // sprite start Y (fixed 8.8) #define JUMP_VELOCITY (-900) // jump velocity (fixed 8.8) #define GRAVITY 32 // gravity (fixed 8.8) #define POWERUP_Y 80 // sprite Y of power up #define OBSTACLE_Y 96 // sprite Y of obstacle #define SCROLL_TOP 8 // scroll top row #define SCROLL_ROWS 14 // scroll # of rows #define GROUND_ROW 7 // ground row (+ top row) ///// VARIABLES word player_x; // player X word player_y; // player Y (fixed 8.8) signed int player_vel_y; // player Y velocity (fixed 8.8) byte faceleft = 0; // 0 = face right, 1 = face left word scroll_x = 0; // current scroll X position word score = 0; // current player score ///// FUNCTIONS // display list used by rasterirq.h // draws scoreboard and sets scroll register void display_list() { // set x scroll register to scroll value SET_SCROLL_X(scroll_x); // set background color VIC.bgcolor[0] = COLOR_CYAN; // next interrupt is two rows from bottom DLIST_NEXT(248-16); // set background color VIC.bgcolor[0] = COLOR_BLUE; // screen memory = 0x2800 SET_VIC_SCREEN(SCORE_BASE); // clear x scroll register SET_SCROLL_X(0); // next interrupt is bottom of frame DLIST_NEXT(250); // reset screen to 0x400 SET_VIC_SCREEN(0x400); // next interrupt is above top of next frame DLIST_RESTART(40); } void update_scoreboard() { draw_bcd_word(SCRNADR(SCORE_BASE,7,24), score); } void add_score(int delta) { score = bcd_add(score, delta); update_scoreboard(); } // clear scoreboard and draw initial strings void init_scoreboard() { memset((void*)SCORE_BASE, ' ', 1024); memcpy((void*)SCRNADR(SCORE_BASE,1,24), "SCORE:", 6); update_scoreboard(); } void init_sprite_shapes() { sprite_set_shapes(SPRITE_DATA, SPRITE_SHAPE, NUM_SPRITE_PATTERNS); } void init_sprite_positions() { // setup sprite positions player_x = CENTER_X; player_y = FLOOR_Y; player_vel_y = 0; sprshad.spr_color[POWERUP_INDEX] = COLOR_YELLOW; sprshad.spr_color[OBSTACLE_INDEX] = COLOR_GRAY3; } void move_player(byte joy) { // move sprite based on joystick if (JOY_LEFT(joy)) { player_x -= 2; faceleft = 1; } if (JOY_RIGHT(joy)) { player_x += 1; faceleft = 0; } if (JOY_BTN_1(joy) && player_y == FLOOR_Y) { player_vel_y = JUMP_VELOCITY; } // apply velocity player_y += player_vel_y; // apply gravity player_vel_y += GRAVITY; // stop velocity when falling thru floor if (player_y >= FLOOR_Y) { player_y = FLOOR_Y; // reset Y position player_vel_y = 0; // reset velocity } // keep player from moving offscreen if (player_x < 36) player_x = 36; if (player_x > 300) player_x = 300; // draw player into sprite shadow buffer sprite_draw(PLAYER_INDEX, player_x, player_y >> 8, // fixed point conversion PLAYER_SHAPE + faceleft); } void move_items() { // move in sync with scrolling world // draw powerup sprite_draw(POWERUP_INDEX, ((scroll_x*2) & 0x1ff), POWERUP_Y, POWERUP_SHAPE); // draw obstacle sprite_draw(OBSTACLE_INDEX, ((scroll_x+256) & 0x1ff), OBSTACLE_Y, OBSTACLE_SHAPE); } byte get_char_for_row(byte row) { // ground? if (row >= GROUND_ROW) { return 253; } // obstacle? if (row >= GROUND_ROW-3) { // only show obstacle for certain values of scroll_x if ((scroll_x & 0b1110000) == 0) { return 247; } } // default is the sky (empty space) return 32; } void draw_right_column() { // get the top-right corner address of scroll area word addr = SCRNADR(GAME_BASE, 39, SCROLL_TOP); byte row; // draw one character per row for (row=0; row