ANIMATION * explosion_create(VECTOR *position) { ANIMATION *explosion = animation_new(sprites, 15); explosion->slowdown = 2; explosion->position->x = position->x - (explosion->width / 2); explosion->position->y = position->y - (explosion->height / 2); al_play_sample(sample, VOLUME, 0, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL); return explosion; }
bool ship_explode(SHIP *ship) { if(ship->explosion) return false; ANIMATION *explosion = animation_new(explosion_sprites, 60); /* explosion->slowdown = 10; */ explosion->position->x = ship->position->x - (explosion->width / 2); explosion->position->y = ship->position->y - (explosion->height / 2); ship->explosion = explosion; return true; }
animation_t * load_animation(render_manager_t *r_manager, const char * name) { int i = 0; animation_t *anim; char path_buffer[BUFFER_SIZE]; sprite_t *frames[MAX_FRAMES]; while (TRUE) { sprintf(path_buffer, "%s%s%02d%s", ASSETS_DIR, name, i, SPRITE_EXTENSION); if (!file_exists(path_buffer) || i >= MAX_FRAMES) { break; } sprintf(path_buffer, "%s%02d", name, i); frames[i] = render_manager_get_sprite(r_manager, path_buffer); ++i; } anim = animation_new(frames, i); asset_cache_add(&(r_manager->animations), anim, name); return anim; }
animation* ani_load_file(char* filename) { int state = STATE_LOAD_EMPTY; animation* a = animation_new(); skeleton* base = skeleton_new(); frame* f = NULL; SDL_RWops* file = SDL_RWFromFile(filename, "r"); if(file == NULL) { error("Could not load file %s", filename); } char line[1024]; while(SDL_RWreadline(file, line, 1024)) { if (state == STATE_LOAD_EMPTY) { int version; if (sscanf(line, "version %i", &version) > 0) { if (version != 1) { error("Can't load ani file '%s'. Don't know how to load version %i\n", filename, version); } } if (strstr(line, "nodes")) { state = STATE_LOAD_NODES; } if (strstr(line, "skeleton")) { state = STATE_LOAD_SKELETON; } } else if (state == STATE_LOAD_NODES) { char name[1024]; int id, parent; if (sscanf(line, "%i \"%[^\"]\" %i", &id, name, &parent) == 3) { skeleton_joint_add(base, name, parent); } if (strstr(line, "end")) { state = STATE_LOAD_EMPTY; } } else if (state == STATE_LOAD_SKELETON) { float time; if (sscanf(line, "time %f", &time) == 1) { f = animation_add_frame(a, base->rest_pose); } int id; float x, y, z, rx, ry, rz; if (sscanf(line, "%i %f %f %f %f %f %f", &id, &x, &y, &z, &rx, &ry, &rz) > 0) { f->joint_positions[id] = vec3_new(x, z, y); mat4 rotation = mat4_rotation_euler(rx, ry, rz); mat4 handedflip = mat4_new(1,0,0,0, 0,0,1,0, 0,1,0,0, 0,0,0,1); rotation = mat4_mul_mat4(handedflip, rotation); rotation = mat4_mul_mat4(rotation, handedflip); rotation = mat4_transpose(rotation); f->joint_rotations[id] = mat4_to_quat(rotation); } if (strstr(line, "end")) { state = STATE_LOAD_EMPTY; } } } SDL_RWclose(file); skeleton_delete(base); return a; }
/* * traverse_sprite_attributes() * Sprite attributes traversal */ int traverse_sprite_attributes(const parsetree_statement_t *stmt, void *spriteinfo) { const char *identifier; const parsetree_parameter_t *param_list; const parsetree_parameter_t *p1, *p2, *p3, *p4; spriteinfo_t *s = (spriteinfo_t*)spriteinfo; int anim_id = 0; identifier = nanoparser_get_identifier(stmt); param_list = nanoparser_get_parameter_list(stmt); if(str_icmp(identifier, "source_file") == 0) { p1 = nanoparser_get_nth_parameter(param_list, 1); nanoparser_expect_string(p1, "Must provide path to the source_file"); if(s->source_file != NULL) free(s->source_file); s->source_file = str_dup(nanoparser_get_string(p1)); } else if(str_icmp(identifier, "source_rect") == 0) { p1 = nanoparser_get_nth_parameter(param_list, 1); p2 = nanoparser_get_nth_parameter(param_list, 2); p3 = nanoparser_get_nth_parameter(param_list, 3); p4 = nanoparser_get_nth_parameter(param_list, 4); nanoparser_expect_string(p1, "Must provide four numbers to source_rect: xpos, ypos, width, height"); nanoparser_expect_string(p2, "Must provide four numbers to source_rect: xpos, ypos, width, height"); nanoparser_expect_string(p3, "Must provide four numbers to source_rect: xpos, ypos, width, height"); nanoparser_expect_string(p4, "Must provide four numbers to source_rect: xpos, ypos, width, height"); s->rect_x = max(0, atoi(nanoparser_get_string(p1))); s->rect_y = max(0, atoi(nanoparser_get_string(p2))); s->rect_w = max(1, atoi(nanoparser_get_string(p3))); s->rect_h = max(1, atoi(nanoparser_get_string(p4))); } else if(str_icmp(identifier, "frame_size") == 0) { p1 = nanoparser_get_nth_parameter(param_list, 1); p2 = nanoparser_get_nth_parameter(param_list, 2); nanoparser_expect_string(p1, "Must provide two numbers to frame_size: width, height"); nanoparser_expect_string(p2, "Must provide two numbers to frame_size: width, height"); s->frame_w = max(1, atoi(nanoparser_get_string(p1))); s->frame_h = max(1, atoi(nanoparser_get_string(p2))); } else if(str_icmp(identifier, "hot_spot") == 0) { p1 = nanoparser_get_nth_parameter(param_list, 1); p2 = nanoparser_get_nth_parameter(param_list, 2); nanoparser_expect_string(p1, "Must provide two numbers to hot_spot: xpos, ypos"); nanoparser_expect_string(p2, "Must provide two numbers to hot_spot: xpos, ypos"); s->hot_spot.x = (float)atoi(nanoparser_get_string(p1)); s->hot_spot.y = (float)atoi(nanoparser_get_string(p2)); } else if(str_icmp(identifier, "animation") == 0) { p1 = nanoparser_get_nth_parameter(param_list, 1); p2 = nanoparser_get_nth_parameter(param_list, 2); if(p1 && p2) { nanoparser_expect_string(p1, "Must provide animation number"); nanoparser_expect_program(p2, "Must provide animation attributes"); anim_id = atoi(nanoparser_get_string(p1)); if(anim_id < 0 || anim_id >= SPRITE_MAX_ANIM) fatal_error("Can't load sprites. Animation number must be in range 0..%d\nin\"%s\" near line %d", SPRITE_MAX_ANIM-1, nanoparser_get_file(stmt), nanoparser_get_line_number(stmt)); } else if(p1) { nanoparser_expect_program(p1, "Must provide animation attributes"); anim_id = 0; p2 = p1; } else fatal_error("No attributes provided to 'animation' block\nin\"%s\" near line %d", nanoparser_get_file(stmt), nanoparser_get_line_number(stmt)); if(anim_id < s->animation_count && NULL != s->animation_data[anim_id]) s->animation_data[anim_id] = animation_delete(s->animation_data[anim_id]); s->animation_count = max(s->animation_count, anim_id+1); s->animation_data = reallocx(s->animation_data, sizeof(animation_t*) * s->animation_count); /* TODO: watch this! It may generate garbage in the middle. */ s->animation_data[anim_id] = animation_new(anim_id); nanoparser_traverse_program_ex(nanoparser_get_program(p2), s->animation_data[anim_id], traverse_animation_attributes); validate_animation(s->animation_data[anim_id]); } else fatal_error("Can't load sprites. Unknown identifier '%s'\nin\"%s\" near line %d", identifier, nanoparser_get_file(stmt), nanoparser_get_line_number(stmt)); return 0; }
int main(int argc, char ** argv) { IterativeMap* map; Animation* animation; gboolean animate = FALSE; gboolean have_gtk; gboolean verbose = FALSE; gboolean hidden = FALSE; enum {INTERACTIVE, RENDER, SCREENSAVER, REMOTE} mode = INTERACTIVE; const gchar *outputFile = NULL; const gchar *pidfile = NULL; int c, option_index=0; double quality = 1.0; #ifdef HAVE_GNET int port_number = FYRE_DEFAULT_PORT; #endif GError *error = NULL; math_init(); g_type_init(); have_gtk = gtk_init_check(&argc, &argv); #ifdef HAVE_GNET gnet_init(); # ifdef WIN32 gnet_ipv6_set_policy(GIPV6_POLICY_IPV4_ONLY); # endif #endif map = ITERATIVE_MAP(de_jong_new()); animation = animation_new(); while (1) { static struct option long_options[] = { {"help", 0, NULL, 'h'}, {"read", 1, NULL, 'i'}, {"animate", 1, NULL, 'n'}, {"output", 1, NULL, 'o'}, {"param", 1, NULL, 'p'}, {"size", 1, NULL, 's'}, {"oversample", 1, NULL, 'S'}, {"quality", 1, NULL, 'q'}, {"remote", 0, NULL, 'r'}, {"verbose", 0, NULL, 'v'}, {"port", 1, NULL, 'P'}, {"cluster", 1, NULL, 'c'}, {"auto-cluster", 0, NULL, 'C'}, {"screensaver", 0, NULL, 1000}, /* Undocumented, still experimental */ {"hidden", 0, NULL, 1001}, {"chdir", 1, NULL, 1002}, /* Undocumented, used by win32 file associations */ {"pidfile", 1, NULL, 1003}, {"version", 0, NULL, 1004}, {NULL}, }; c = getopt_long(argc, argv, "hi:n:o:p:s:S:q:rvP:c:C", long_options, &option_index); if (c == -1) break; switch (c) { case 'i': { histogram_imager_load_image_file(HISTOGRAM_IMAGER(map), optarg, &error); break; } case 'n': { GtkTreeIter iter; animation_load_file(animation, optarg); animate = TRUE; gtk_tree_model_get_iter_first(GTK_TREE_MODEL(animation->model), &iter); animation_keyframe_load(animation, &iter, PARAMETER_HOLDER(map)); break; } case 'o': mode = RENDER; outputFile = optarg; break; case 'p': parameter_holder_load_string(PARAMETER_HOLDER(map), optarg); break; case 's': parameter_holder_set(PARAMETER_HOLDER(map), "size" , optarg); break; case 'S': parameter_holder_set(PARAMETER_HOLDER(map), "oversample", optarg); break; case 'q': quality = atof(optarg); break; case 'v': verbose = TRUE; break; #ifdef HAVE_GNET case 'c': { ClusterModel *cluster = cluster_model_get(map, TRUE); cluster_model_add_nodes(cluster, optarg); } break; case 'C': { ClusterModel *cluster = cluster_model_get(map, TRUE); cluster_model_enable_discovery(cluster); } break; case 'r': mode = REMOTE; break; case 'P': port_number = atol(optarg); break; #else case 'c': case 'C': case 'P': fprintf(stderr, "This Fyre binary was compiled without gnet support.\n" "Cluster support is not available.\n"); break; case 'r': fprintf(stderr, "This Fyre binary was compiled without gnet support.\n" "Cluster support is not available.\n"); exit(1); break; #endif case 1000: /* --screensaver */ mode = SCREENSAVER; break; case 1001: /* --hidden */ hidden = TRUE; break; case 1002: /* --chdir */ chdir(optarg); break; case 1003: /* --pidfile */ pidfile = optarg; break; case 1004: /* --version */ printf("%s\n", VERSION); return 0; case 'h': default: usage(argv); return 1; } } if (optind + 1 < argc) { usage(argv); return 1; } if (optind != argc) { char *ext = strrchr (argv[optind], '.'); if (ext) { if (g_strcasecmp(ext, ".png") == 0) { histogram_imager_load_image_file(HISTOGRAM_IMAGER(map), argv[optind], &error); } else if (g_strcasecmp(ext, ".fa") == 0) { GtkTreeIter iter; animation_load_file(animation, argv[optind]); animate = TRUE; gtk_tree_model_get_iter_first(GTK_TREE_MODEL(animation->model), &iter); animation_keyframe_load(animation, &iter, PARAMETER_HOLDER(map)); } else { usage(argv); return 1; } } else { usage(argv); return 1; } } switch (mode) { case INTERACTIVE: { Explorer *explorer; if (!have_gtk) { fprintf(stderr, "GTK intiailization failed, can't start in interactive mode\n"); return 1; } explorer = explorer_new (map, animation); if (error) { GtkWidget *dialog, *label; gchar *text; dialog = glade_xml_get_widget (explorer->xml, "error dialog"); label = glade_xml_get_widget (explorer->xml, "error label"); text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">Error!</span>\n\n%s", error->message); gtk_label_set_markup (GTK_LABEL (label), text); g_free (text); g_error_free (error); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_hide (dialog); } gtk_main(); break; } case RENDER: { acquire_console(); if (error) { g_print ("Error: %s\n", error->message); g_error_free (error); } if (animate) animation_render_main (map, animation, outputFile, quality); else batch_image_render (map, outputFile, quality); break; } case REMOTE: { #ifdef HAVE_GNET if (verbose) { acquire_console(); } else { daemonize_to_pidfile(pidfile); } if (!hidden) discovery_server_new(FYRE_DEFAULT_SERVICE, port_number); remote_server_main_loop(port_number, have_gtk, verbose); #else fprintf(stderr, "This Fyre binary was compiled without gnet support.\n" "Remote control mode is not available.\n"); #endif break; } case SCREENSAVER: { ScreenSaver* screensaver; GtkWidget* window; if (!have_gtk) { fprintf(stderr, "GTK intiailization failed, can't start in screensaver mode\n"); return 1; } screensaver = screensaver_new(map, animation); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); fyre_set_icon_later(window); gtk_window_set_resizable(GTK_WINDOW(window), FALSE); gtk_window_set_title(GTK_WINDOW(window), "Fyre Screensaver"); gtk_container_add(GTK_CONTAINER(window), screensaver->view); gtk_widget_show_all(window); gtk_main(); break; } } return 0; }