void paddle_init_ball(float dir) { float angle = t3f_drand(&rng_state) * ALLEGRO_PI; ball.x = 320.0 - 16.0 / 2.0; ball.y = 240.0 - 16.0 / 2.0; t3f_move_collision_object_xy(ball.object, ball.x, ball.y); ball.vx = cos(angle) * EXAMPLE_START_SPEED * dir; ball.vy = sin(angle) * EXAMPLE_START_SPEED * dir; if(ball.vx > 0.0 && dir < 0.0) { ball.vx = -ball.vx; } else if(ball.vx < 0.0 && dir > 0.0) { ball.vx = -ball.vx; } ball.active = true; /* handle AI */ if(ball.vx > 0) { paddle[1].dy = paddle_ai_predict_y() - 32 + 8.0; paddle[1].dvy = t3f_drand(&rng_state) * 6.0 - 3.0; } }
/* function to set up a new level */ void dot_game_setup_level(void * data, int level) { APP_INSTANCE * app = (APP_INSTANCE *)data; int i, j; int col = 0; int num_balls = DOT_GAME_LEVEL_BASE_BALLS + level * DOT_GAME_LEVEL_BALLS_INC; int num_black_balls = DOT_GAME_LEVEL_BASE_BLACK_BALLS + (level / 2) * DOT_GAME_LEVEL_BLACK_BALLS_INC; /* initialize balls */ memset(app->game.ball, 0, sizeof(DOT_BALL) * DOT_GAME_MAX_BALLS); for(i = 0; i < num_balls && i < DOT_GAME_MAX_BALLS; i++) { app->game.ball[i].r = DOT_GAME_BALL_SIZE; app->game.ball[i].x = t3f_drand(&app->rng_state) * ((float)(DOT_GAME_PLAYFIELD_WIDTH) - app->game.ball[i].r * 2.0) + app->game.ball[i].r; app->game.ball[i].y = t3f_drand(&app->rng_state) * ((float)(DOT_GAME_PLAYFIELD_HEIGHT) - app->game.ball[i].r * 2.0) + app->game.ball[i].r; app->game.ball[i].z = 0; app->game.ball[i].a = t3f_drand(&app->rng_state) * ALLEGRO_PI * 2.0; app->game.ball[i].s = t3f_drand(&app->rng_state) * 0.75 + 0.25; app->game.ball[i].vx = cos(app->game.ball[i].a) * app->game.ball[i].s; app->game.ball[i].vy = sin(app->game.ball[i].a) * app->game.ball[i].s; app->game.ball[i].type = col; col++; if(col > 5) { col = 0; } app->game.ball[i].active = true; } /* add black balls */ for(j = i; j < i + num_black_balls && j < DOT_GAME_MAX_BALLS; j++) { app->game.ball[j].r = DOT_GAME_BALL_SIZE; app->game.ball[j].x = t3f_drand(&app->rng_state) * ((float)(DOT_GAME_PLAYFIELD_WIDTH) - app->game.ball[j].r * 2.0) + app->game.ball[i].r; app->game.ball[j].y = t3f_drand(&app->rng_state) * ((float)(DOT_GAME_PLAYFIELD_HEIGHT) - app->game.ball[j].r * 2.0) + app->game.ball[i].r; app->game.ball[j].z = 0; app->game.ball[j].a = t3f_drand(&app->rng_state) * ALLEGRO_PI * 2.0; app->game.ball[j].s = t3f_drand(&app->rng_state) * 0.75 + 0.25; app->game.ball[j].vx = cos(app->game.ball[j].a) * app->game.ball[j].s; app->game.ball[j].vy = sin(app->game.ball[j].a) * app->game.ball[j].s; app->game.ball[j].type = 6; app->game.ball[j].active = true; } /* drop the player with a random color */ dot_game_drop_player(data, t3f_rand(&app->rng_state) % 6); t3f_play_sample(app->sample[DOT_SAMPLE_START], 1.0, 0.0, 1.0); app->game.player.ball.r = 16.0; dot_game_target_balls(data, app->game.player.ball.type); app->game.level = level; app->game.speed = DOT_GAME_LEVEL_BASE_SPEED; app->game.speed_inc = DOT_GAME_LEVEL_TOP_SPEED / (float)num_balls; app->game.level_start = true; }
static void dot_game_create_splash_effect(void * data, float x, float y, float r, ALLEGRO_COLOR color) { APP_INSTANCE * app = (APP_INSTANCE *)data; int i; float ga, gx, gy; for(i = 0; i < r * 8.0; i++) { ga = t3f_drand(&app->rng_state) * ALLEGRO_PI * 2.0; gx = cos(ga) * t3f_drand(&app->rng_state) * r * t3f_drand(&app->rng_state); gy = sin(ga) * t3f_drand(&app->rng_state) * r * t3f_drand(&app->rng_state); dot_create_particle(&app->particle[app->current_particle], x + gx, y + gy, 0.0, cos(ga) * t3f_drand(&app->rng_state), sin(ga) * t3f_drand(&app->rng_state), t3f_drand(&app->rng_state) * -5.0 - 5.0, 0.5, 5.0, 30, app->bitmap[DOT_BITMAP_PARTICLE], color); app->current_particle++; if(app->current_particle >= DOT_MAX_PARTICLES) { app->current_particle = 0; } } }
int main(int argc, char * argv[]) { int i; char fn[1024] = {0}; if(!t3f_initialize("ex_atlas", 640, 480, 60.0, logic, render, T3F_USE_KEYBOARD | T3F_USE_MOUSE, NULL)) { return 1; } t3f_srand(&rng_state, time(0)); /* load bitmaps into sprite sheet */ atlas = t3f_create_atlas(512, 512); if(!atlas) { printf("Failed to create atlas!\n"); return 0; } for(i = 0; i < 8; i++) { sprintf(fn, "data/%d.png", i); bitmap[i] = al_load_bitmap(fn); if(!bitmap[i]) { return 1; } t3f_add_bitmap_to_atlas(atlas, &bitmap[i], T3F_ATLAS_SPRITE); } for(i = 0; i < 1024; i++) { object[i].x = t3f_drand(&rng_state) * 640.0; object[i].y = t3f_drand(&rng_state) * 480.0; object[i].vx = t3f_drand(&rng_state) * 4.0 - 2.0; object[i].vy = t3f_drand(&rng_state) * 4.0 - 2.0; object[i].bitmap = t3f_rand(&rng_state) % 8; } t3f_run(); return 0; }
void dot_setup_bg_objects(void * data) { APP_INSTANCE * app = (APP_INSTANCE *)data; int i; float s, a; t3f_srand(&dot_bg_rng_state, time(0)); /* initialize background objects */ memset(app->bg_object, 0, sizeof(DOT_BG_OBJECT) * DOT_MAX_BG_OBJECTS); a = ALLEGRO_PI / 8.0; // angle slightly toward the player for(i = 0; i < DOT_MAX_BG_OBJECTS; i++) { s = t3f_drand(&dot_bg_rng_state) * 0.5 + 0.25; s = 0.25; app->bg_object[i].x = t3f_drandom(&dot_bg_rng_state, DOT_GAME_PLAYFIELD_WIDTH + DOT_GAME_BALL_SIZE) - DOT_GAME_BALL_SIZE; app->bg_object[i].y = t3f_drandom(&dot_bg_rng_state, DOT_GAME_PLAYFIELD_HEIGHT + DOT_GAME_BALL_SIZE) - DOT_GAME_BALL_SIZE; app->bg_object[i].z = -t3f_drandom(&dot_bg_rng_state, 320.0); app->bg_object[i].vx = -cos(a) * s; app->bg_object[i].vy = 0.0; app->bg_object[i].vz = -sin(a) * s; } }
/* render routines, passed to T^3 Framework */ void paddle_render(void * data) { /* render switch, render graphics according to which state we are in */ switch(paddle_state) { case EXAMPLE_STATE_TITLE: { /* draw background */ al_draw_bitmap(paddle_bitmap[EXAMPLE_BITMAP_BG], 0.0, 0.0, 0); /* center logo */ al_draw_bitmap(paddle_bitmap[EXAMPLE_BITMAP_LOGO], al_get_display_width(t3f_display) / 2 - al_get_bitmap_width(paddle_bitmap[EXAMPLE_BITMAP_LOGO]) / 2, 32.0, 0); /* draw menu */ t3f_render_gui(paddle_menu); break; } case EXAMPLE_STATE_GAME: { int i; /* draw background */ al_draw_bitmap(paddle_bitmap[EXAMPLE_BITMAP_BG], 0.0, 0.0, 0); /* draw game objects */ for(i = 0; i < 2; i++) { if(paddle[i].active) { al_draw_bitmap(paddle_bitmap[EXAMPLE_BITMAP_PADDLE], paddle[i].x, paddle[i].y, 0); } if(ball.active) { al_draw_bitmap(paddle_bitmap[EXAMPLE_BITMAP_BALL], ball.x, ball.y, 0); } } /* draw scores */ al_draw_textf(paddle_font[EXAMPLE_FONT_GAME], al_map_rgba(0, 0, 0, 255), 10.0, 0.0, 0, "Player 1: %d", score[0]); al_draw_textf(paddle_font[EXAMPLE_FONT_GAME], al_map_rgba(0, 0, 0, 255), 540.0, 0.0, 0, "Player 2: %d", score[1]); break; } case EXAMPLE_STATE_GAME_OVER: { /* draw background */ al_draw_bitmap(paddle_bitmap[EXAMPLE_BITMAP_BG], 0.0, 0.0, 0); /* draw results */ al_draw_filled_circle(640.0 * t3f_drand(&rng_state), 480.0 * t3f_drand(&rng_state), 10.0 + 32.0 * t3f_drand(&rng_state), al_map_rgba(0, 0, 192, 128)); al_draw_filled_rectangle(220.0, 192.0, 420.0, 280.0, al_map_rgba(0, 192, 0, 128)); al_draw_rectangle(220.0, 192.0, 420.0, 280.0, al_map_rgba(0, 0, 0, 255), 2.0); al_draw_textf(paddle_font[EXAMPLE_FONT_MENU], al_map_rgba(0, 0, 0, 255), 320.0, 200.0, ALLEGRO_ALIGN_CENTRE, "Player %d Wins!", score[0] > score[1] ? 1 : 2); al_draw_textf(paddle_font[EXAMPLE_FONT_GAME], al_map_rgba(0, 0, 0, 255), 320.0, 240.0, ALLEGRO_ALIGN_CENTRE, "Click to continue..."); break; } } }
/* logic routines, passed to T^3 Framework */ void paddle_logic(void * data) { /* logic switch, use different logic for each state */ switch(paddle_state) { case EXAMPLE_STATE_TITLE: { t3f_process_gui(paddle_menu, data); break; } case EXAMPLE_STATE_GAME: { /* return to menu if Escape pressed */ if(t3f_key[ALLEGRO_KEY_ESCAPE]) { paddle_game_exit(); } /* store old paddle positions */ paddle[0].oy = paddle[0].y; paddle[1].oy = paddle[1].y; /* move paddle */ paddle[0].y = t3f_mouse_y - 32; if(paddle[0].y < 0) { paddle[0].y = 0; } if(paddle[0].y > 480.0 - 64.0) { paddle[0].y = 480.0 - 64.0; } t3f_move_collision_object_xy(paddle[0].object, paddle[0].x, paddle[0].y); /* move CPU paddle */ if(ball.vx > 0.0) { if(ball.x > paddle[1].x - 24) { paddle[1].y += paddle[1].dvy; } else { if(paddle[1].y < paddle[1].dy - 2.0) { paddle[1].y += 2.0; if(paddle[1].y > 480.0 - 64.0) { paddle[1].y = 480.0 - 64.0; } } else if(paddle[1].y > paddle[1].dy + 2.0) { paddle[1].y -= 2.0; if(paddle[1].y < 0.0) { paddle[1].y = 0.0; } } } /* correct paddle position so it doesn't go past edge */ if(paddle[1].y > 480.0 - 64.0) { paddle[1].y = 480.0 - 64.0; } if(paddle[1].y < 0.0) { paddle[1].y = 0.0; } } t3f_move_collision_object_xy(paddle[1].object, paddle[1].x, paddle[1].y); /* move ball */ ball.x += ball.vx; t3f_move_collision_object_xy(ball.object, ball.x, ball.y); if(ball.vx < 0 && t3f_check_object_collision(paddle[0].object, ball.object)) { al_play_sample(paddle_sample[EXAMPLE_SAMPLE_HIT], 0.5, 0.5, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL); ball.x = paddle[0].x + 16.0; ball.vx = -ball.vx; ball.vx += EXAMPLE_SPEED_INCREASE; ball.vy -= (paddle[0].oy - paddle[0].y) / 4.0; if(ball.vy < -3.0) { ball.vy = -3.0; } if(ball.vy > 3.0) { ball.vy = 3.0; } paddle[1].dy = paddle_ai_predict_y() - 32 + 8.0; paddle[1].dvy = t3f_drand(&rng_state) * 6.0 - 3.0; } else if(ball.vx > 0 && t3f_check_object_collision(paddle[1].object, ball.object)) { al_play_sample(paddle_sample[EXAMPLE_SAMPLE_HIT], 0.5, 0.5, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL); ball.x = paddle[1].x - 16.0 - 1.0; ball.vx = -ball.vx; ball.vx -= EXAMPLE_SPEED_INCREASE; ball.vy -= (paddle[1].oy - paddle[1].y) / 4.0; if(ball.vy < -3.0) { ball.vy = -3.0; } if(ball.vy > 3.0) { ball.vy = 3.0; } } if(ball.x < -16.0) { al_play_sample(paddle_sample[EXAMPLE_SAMPLE_SCORE], 0.5, 0.5, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL); score[1]++; if(score[1] >= 5) { t3f_stop_music(); paddle_state = EXAMPLE_STATE_GAME_OVER; } paddle_init_ball(1.0); } else if(ball.x > 640.0) { al_play_sample(paddle_sample[EXAMPLE_SAMPLE_SCORE], 0.5, 0.5, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL); score[0]++; if(score[0] >= 5) { t3f_stop_music(); paddle_state = EXAMPLE_STATE_GAME_OVER; } paddle_init_ball(-1.0); } ball.y += ball.vy; if(ball.y < 0.0) { ball.y = 0.0; ball.vy = -ball.vy; } else if(ball.y > 480.0 - 16.0) { ball.y = 480.0 - 16.0; ball.vy = -ball.vy; } break; } case EXAMPLE_STATE_GAME_OVER: { /* return to menu if Escape pressed */ if(t3f_mouse_button[0] || t3f_key[ALLEGRO_KEY_ESCAPE]) { paddle_game_exit(); } break; } } }