/* main loop */ static void mainLoop(void) { ARUint8 *dataPtr; ARMarkerInfo *marker_info; int marker_num; float curPaddlePos[3]; int i; double err; double angle; err=0.; /* grab a video frame */ if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) { arUtilSleep(2); return; } if( count == 0 ) arUtilTimerReset(); count++; /* detect the markers in the video frame */ if( arDetectMarkerLite(dataPtr, thresh, &marker_info, &marker_num) < 0 ) { cleanup(); exit(0); } argDrawMode2D(); if( !arDebug ) { argDispImage( dataPtr, 0,0 ); } else { argDispImage( dataPtr, 1, 1 ); if( arImageProcMode == AR_IMAGE_PROC_IN_HALF ) argDispHalfImage( arImage, 0, 0 ); else argDispImage( arImage, 0, 0); glColor3f( 1.0, 0.0, 0.0 ); glLineWidth( 1.0 ); for( i = 0; i < marker_num; i++ ) { argDrawSquare( marker_info[i].vertex, 0, 0 ); } glLineWidth( 1.0 ); } arVideoCapNext(); for( i = 0; i < marker_num; i++ ) marker_flag[i] = 0; /* get the paddle position */ paddleGetTrans(paddleInfo, marker_info, marker_flag, marker_num, &cparam); /* draw the 3D models */ glClearDepth( 1.0 ); glClear(GL_DEPTH_BUFFER_BIT); /* get the translation from the multimarker pattern */ if( (err=arMultiGetTransMat(marker_info, marker_num, config)) < 0 ) { argSwapBuffers(); return; } // printf("err = %f\n", err); if(err > 100.0 ) { argSwapBuffers(); return; } //draw a red ground grid drawGroundGrid( config->trans, 15, 150.0, 110.0, 0.0); /* find the paddle position relative to the base */ if (paddleInfo->active) findPaddlePosition(curPaddlePos,paddleInfo->trans,config->trans); /* checking for paddle gesture */ if( paddleInfo->active) { int findItem=-1; if (myPaddleItem.item!=-1) { if( check_incline(paddleInfo->trans, config->trans, &angle) ) { myPaddleItem.x += 2.0 * cos(angle); myPaddleItem.y += 2.0 * sin(angle); if( myPaddleItem.x*myPaddleItem.x + myPaddleItem.y*myPaddleItem.y > 900.0 ) { myPaddleItem.x -= 2.0 * cos(angle); myPaddleItem.y -= 2.0 * sin(angle); myListItem.item[myPaddleItem.item].onpaddle=0; myListItem.item[myPaddleItem.item].pos[0]=curPaddlePos[0]; myListItem.item[myPaddleItem.item].pos[1]=curPaddlePos[1]; myPaddleItem.item = -1; } } } else { if ((findItem=check_pickup(paddleInfo->trans, config->trans,&myListItem, &angle))!=-1) { myPaddleItem.item=findItem; myPaddleItem.x =0.0; myPaddleItem.y =0.0; myPaddleItem.angle = 0.0; myListItem.item[myPaddleItem.item].onpaddle=1; } } } /* draw the item */ drawItems(config->trans,&myListItem); /* draw the paddle */ if( paddleInfo->active ){ draw_paddle(paddleInfo,&myPaddleItem); } argSwapBuffers(); }
/* 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 */ } }