static void move_mouse(void) { if ((MOUINFO->xpos != MSCURSOR->xcord) || (MOUINFO->ypos != MSCURSOR->ycord)) { int check = MOUINFO->docheck; int dospec = SPECIALMODE && MSCURSOR->displayed; MOUINFO->docheck = FALSE; if (dospec) draw_special(); GrMoveCursor(MSCURSOR, MOUINFO->xpos, MOUINFO->ypos); if (dospec) draw_special(); MOUINFO->docheck = check; } }
static void erase_mouse(void) { int check = MOUINFO->docheck; MOUINFO->docheck = FALSE; if(SPECIALMODE) draw_special(); GrEraseCursor(MSCURSOR); MOUINFO->docheck = check; }
static void draw_mouse(void) { int check = MOUINFO->docheck; MOUINFO->docheck = FALSE; GrDisplayCursor(MSCURSOR); if(SPECIALMODE) draw_special(); MOUINFO->docheck = check; }
/* Animate special objects */ void animate_specials (void) { struct dllist *list = special_list,*next; while (list) { struct SpecialObj *obj=list->data; /* Check for collisions */ if(obj->hitship) ship_hit_special (obj); if(obj->hitprojectile) projectile_hit_special(obj); /* Animate */ if(obj->animate) obj->animate(obj); if (obj->timer > 0) obj->timer--; /* Draw the object on all viewports */ draw_special (obj); /* Check if the object has expired. * If life < 0, the object has no time limit */ next = list->next; if(obj->life > 0) obj->life--; else if (obj->life == 0) { if(obj->destroy) obj->destroy(obj); free (obj); if(list==special_list) special_list=dllist_remove(list); else dllist_remove(list); } list = next; } }
/* The main game loop */ static void do_game(game_t *p_game) { uint8_t exit=FALSE; while(!exit) { uint16_t input = get_input(p_game); uint16_t fire; int i; exit = input & FE_EVENT_EXIT; fire = input & FE_EVENT_SELECT; /* Move the paddle (according to input) */ update_paddle(&p_game->paddle, input & FE_EVENT_LEFT ? 4:0, input & FE_EVENT_RIGHT ? 4:0); /* Handle the ball(s) */ p_game->free_ball = -1; for (i=0; i<MAX_BALLS; i++) { /* Unused balls are skipped */ if (!(p_game->p_balls[i].state & BALL_STATE_ACTIVE)) { draw_ball(&p_game->p_balls[i]); p_game->free_ball = i; continue; } /* The player is holding the ball */ if (p_game->p_balls[i].state & BALL_STATE_HOLDING) { p_game->p_balls[i].lastx = p_game->p_balls[i].x; p_game->p_balls[i].x += p_game->paddle.x-p_game->paddle.lastx; if (fire) { /* The player relases the ball. The following will * clear the HOLDING-bit. It will also shoot the * ball away upwards. */ p_game->p_balls[i].dx = 1; p_game->p_balls[i].state &= (0xff ^ BALL_STATE_HOLDING); bounce_ball_paddle(p_game, &p_game->p_balls[i]); } } else if (paddle_ball_collide(&p_game->paddle, &p_game->p_balls[i])) { /* Hold the ball if the pad is sticky */ if (p_game->paddle.type & SPECIAL_STICKY) { p_game->p_balls[i].dy = 0; p_game->p_balls[i].dx = 0; p_game->p_balls[i].state |= BALL_STATE_HOLDING; p_game->paddle.type--; /* Sticky for maximum 3 rounds */ } else bounce_ball_paddle(p_game, &p_game->p_balls[i]); } /* Check collisions against blocks */ block_ball_collide(p_game, &p_game->p_balls[i]); draw_ball(&p_game->p_balls[i]); /* Update the ball (and check if it moves out of the playfield) */ if (update_ball(p_game, &p_game->p_balls[i])) { /* Ball is out of bounds - Remove it */ init_ball(&p_game->p_balls[i], 0, 0, 0); p_game->nr_balls--; } } /* Handle the specials */ p_game->free_special = -1; for (i=0; i<MAX_SPECIALS; i++) { int res; /* Always draw the specials for timing-reasons */ draw_special(&p_game->p_specials[i]); /* Inactive special - continue */ if (!p_game->p_specials[i].type) { p_game->free_special = i; continue; } /* This moves the special and also checks if it collides with the paddle */ res = update_special(p_game, &p_game->p_specials[i]); switch(res) { case 1: /* Player took the special */ switch(p_game->p_specials[i].type) { case SPECIAL_EXTRA_BALL: if (p_game->free_ball != -1) /* Check if there is free space for the ball */ { p_game->nr_balls++; init_ball(&p_game->p_balls[p_game->free_ball], p_game->paddle.x+PADDLE_WIDTH/2, PADDLE_Y-PADDLE_HEIGHT, BALL_STATE_ACTIVE); } break; case SPECIAL_LONG_PADDLE: p_game->paddle.width = PADDLE_LONG_WIDTH; break; case SPECIAL_SHORT_PADDLE: p_game->paddle.width = PADDLE_SHORT_WIDTH; break; case SPECIAL_EXTRA_LIFE: if (p_game->lives < MAX_LIVES) { p_game->lives++; draw_lives(p_game); } break; case SPECIAL_STICKY: /* * For the sticky and destroyers, we use the bits * from the flag and downwards as counters. * * i.e: SPECIAL_STICKY is the third bit, which means * that type becomes 0b00000111. type is then * lowered when the ball hits the paddle and after * zeroing the lower bits, the SPECIAL_STICKY bit is * finally cleared. This gives a maximum of three * sticky rounds. * * These two only adds 30 bytes to the binary :-) */ p_game->paddle.type = (SPECIAL_STICKY | (SPECIAL_STICKY-1)); break; case SPECIAL_DESTROYER: p_game->p_balls[0].state |= (BALL_STATE_DESTROYER | (BALL_STATE_DESTROYER-1)); break; case SPECIAL_FLOOR: p_game->state |= (SPECIAL_FLOOR | 2); /* Three times */ fe_fill_area(0, SCREEN_HEIGHT-FLOOR_HEIGHT, SCREEN_WIDTH, FLOOR_HEIGHT); break; } /* Fall through */ case -1: /* Remove the special */ p_game->nr_specials--; fe_clear_area(p_game->p_specials[i].x, p_game->p_specials[i].y-1, SPECIAL_WIDTH, SPECIAL_HEIGHT+1); p_game->p_specials[i].type = SPECIAL_NONE; break; } } /* No balls left in play */ if (!p_game->nr_balls) { if (--p_game->lives == 0) exit = TRUE; /* No lives left! */ else { /* Restart the game */ p_game->nr_balls = 1; draw_screen(p_game); init_paddle(&p_game->paddle, SPECIAL_NONE, SCREEN_WIDTH/2-PADDLE_WIDTH/2); init_ball(&p_game->p_balls[0], p_game->paddle.x+p_game->paddle.width/2, PADDLE_Y-PADDLE_HEIGHT, BALL_STATE_HOLDING | BALL_STATE_ACTIVE); } } /* No blocks left to remove */ if (!p_game->nr_blocks) { fe_sleep(LEVEL_SLEEP_PERIOD); if (handle_level_finished(p_game) < 0) exit = TRUE; /* Last level */ } draw_paddle(&p_game->paddle); /* Sleep for a short while. */ #if !defined(TARGET_REX) fe_sleep(SLEEP_PERIOD); #endif /* TARGET_REX */ } }