// Create some particle fire void create_fire(VECT pos) { VECT ppos = pos; // Create some particle fire for(int i=0; i<RAND(3,7); i++) { ppos = pos; ppos.x += RANDF(-0.4f, 0.4f); ppos.y += RANDF(-0.3f, 0.3f); ppos.z += RANDF(-0.4f, 0.4f); VECT dir(RANDF(-0.01f,0.01f), RANDF(0.05f,0.15f), RANDF(-0.01f,0.01f)); float c1[4] = { 1, 0.5f, 0.1f, 1 }; float c2[4] = { 1, 0.1f, 0.1f, 0.1f }; add_particle(ppos, dir, RAND(20,35), 0.3f, 0.1f, c1, c2, part_fire); } // Create smoke if(RAND(0,100) > 50) { pos.y += 0.2f; pos.x += RANDF(-0.3f, 0.3f); pos.y += RANDF(0.1f, 0.5f); pos.z += RANDF(-0.3f, 0.3f); VECT dir(RANDF(-0.01f,0.01f), RANDF(0.05f,0.1f), RANDF(-0.01f,0.01f)); float c1[4] = { 0.5f, 0.1f, 0.1f, 1 }; float c2[4] = { 0.1f, 0.1f, 0.1f, 0 }; add_particle(pos, dir, RAND(20,35), 0.2f, 0.4f, c1, c2, part_smoke, true); } }
// Create the teleport effect void create_teleport_effect(int x, int y) { // Add the big glow particle VECT pos(x + 0.5f, 0.5f, y + 0.5f); VECT dir = 0.0f; float c1[4] = { 1.0f, 1.0f, 0.3f, 1.0f }; float c2[4] = { 1, 1, 0, 0 }; // float c1[4] = { 0.3f, 0.8f, 1.0f, 1.0f }; // float c2[4] = { 0, 0, 1, 0 }; add_particle(pos, dir, 60, 2.0f, 1.0f, c1, c2, part_glow); // Create those "fire lines" for(int f=0; f < RAND(5,6); f++) { // Choose the direction VECT dir; dir.x = RANDF(-0.5f, 0.5f); dir.y = RANDF(0.05f, 0.5f); dir.z = RANDF(-0.5f, 0.5f); normalize(dir); // Create the particles int max = RAND(25, 50); for(int i=0; i < max; i++) { VECT p(x + 0.5f, 0.0f, y + 0.5f); p += (dir * (float)i * 0.1f); VECT d = 0.0f; float s = (float)i / (float)max; add_particle(p, d, RAND(40,80), 0.5f * (1.0f-s), 0.00f, c1, c2, part_glow); } } }
void add_particle(Node* n, Particle* p) { // Occupy empty node if (n->c1 == NULL && n->p == NULL) { n->p = p; n->child_mass = p->mass; n->com = p->pos; } // Traverse internal node else if (n->c1 != NULL) { n->child_mass += p->mass; n->com += p->pos*p->mass/n->child_mass; Node* insert_node = which_octant(n, p); add_particle(insert_node, p); } // Split external node else { split_external_node(n); Particle* pt = n->p; n->p = NULL; n->child_mass = p->mass + pt->mass; n->com = (p->pos*p->mass+pt->pos*pt->mass)/n->child_mass; Node* insert_node_original = which_octant(n, pt); Node* insert_node_new = which_octant(n, p); insert_node_original->child_mass = pt->mass; insert_node_original->com = pt->pos; insert_node_original->p = pt; add_particle(insert_node_new, p); } }
//funkce obstara vybuch raketky pri 0 hp void player_explosion(float posx, float posy) { int i; for (i=0;i<160;i++) add_particle(posx, posy, 50*DFRAND, 50*DFRAND, 2*FRAND, 1, FRAND, 0.1, 1); for (i=0;i<110;i++) add_particle(posx, posy, 150*DFRAND, 150*DFRAND, 3*FRAND, 1, FRAND, 0.5, 2); for (i=0;i<115;i++) add_particle(posx+10*DFRAND, posy+10*DFRAND, 10*DFRAND, 10*DFRAND, 6*FRAND, 0.5, 0.5, 0.5, 3); for (i=0;i<160;i++) add_particle(posx, posy, 50*DFRAND, 50*DFRAND, 2*FRAND, 1, 0.5*FRAND, 0.1, 3); }
void insert (Node* root, Particle *p ) { if (root->is_leaf) { if (root->particle) { Node * child; while (1) { child = split (root, p); if (child->particle) root = child; else break; } add_particle (child, p); } else { add_particle (root, p); } } else { switch (child_alternative (root, p)) { case ONE: insert (root->one, p); break; case TWO: insert (root->two, p); break; case THREE: insert (root->three, p); break; case FOUR: insert (root->four, p); break; default: printf ("ERROR: Bad number of children\n"); finalize (); exit (1); } } }
static void foe_add_trail(const vector2 *pos, const vector2 *dir, int palette) { const int nparticles = 3 + irand(7); int i; vector2 tp = *pos, e = *dir; vec2_mul_scalar(&e, 1.02f); vec2_sub_from(&tp, &e); for (i = 0; i < nparticles; i++) { particle *p = add_particle(); if (!p) break; p->ttl = 15 + irand(15); p->t = 0; p->palette = palette; p->width = p->height = .2f + .1f*frand(); p->pos.x = tp.x + .2f*frand() - .1f; p->pos.y = tp.y + .2f*frand() - .1f; vec2_set(&p->dir, 1, 0); p->speed = 0.f; p->friction = .9f; } }
void SPHSystem::init_system() { float3 pos; float3 vel=make_float3(0.0f); for(pos.x=world_size.x*0.0f; pos.x<world_size.x*0.6f; pos.x+=(kernel[LEVEL1]*0.5f)) { for(pos.y=world_size.y*0.0f; pos.y<world_size.y*1.0f; pos.y+=(kernel[LEVEL1]*0.5f)) { for(pos.z=world_size.z*0.0f; pos.z<world_size.z*1.0f; pos.z+=(kernel[LEVEL1]*0.5f)) { add_particle(pos, vel, LEVEL1); } } } /*for(pos.x=world_size.x*0.7f; pos.x<world_size.x*1.0f; pos.x+=(kernel[LEVEL2]*0.5f)) { for(pos.y=world_size.y*0.0f; pos.y<world_size.y*1.0f; pos.y+=(kernel[LEVEL2]*0.5f)) { for(pos.z=world_size.z*0.0f; pos.z<world_size.z*1.0f; pos.z+=(kernel[LEVEL2]*0.5f)) { add_particle(pos, vel, 1); } } }*/ printf("Init Particle: %u\n", num_particle); }
void SpringSystem::add_cloth(const vec3& center, const vec3& x, const vec3& y, size_t size, float particleMass, int attach) { assert(size > 1); size_t p0 = particles.size(); cloths.push_back(ClothInfo(p0, size)); // particles // 0 1 2 3 4 5 // 6 7 8 9 ... for(size_t i=0; i<size; i++) { for(size_t j=0; j<size; j++) { bool attached = false; if (attach == 1) attached = (i == 0); else if (attach == 2) attached = (i == 0 || i == size-1 || j == 0 || j == size-1); add_particle(center + x * ((float)i / size) + y * ((float)j / size), vec3(0.0, 0.0, 0.0), particleMass, attached); } } // horizontal springs for(size_t i=0; i<size; i++) { for(size_t j=0; j<size-1; j++) { int from = p0 + i*size + j; int to = from + 1; add_spring(from, to); } } // lateral springs for(size_t i=0; i<size-1; i++) { for(size_t j=0; j<size; j++) { int from = p0 + i*size + j; int to = from + size; add_spring(from, to); } } // diagonal upper left to lower right for(size_t i=0; i<size-1; i++) { for(size_t j=0; j<size-1; j++) { int from = p0 + i*size + j; int to = from + size + 1; add_spring(from, to); } } // diagonal upper right to lower left for(size_t i=0; i<size-1; i++) { for(size_t j=1; j<size; j++) { int from = p0 + i*size + j; int to = from + size - 1; add_spring(from, to); } } }
//指定雪花区域与雪花数量,大小,缓存大小,片段大小 P244 SNOW::SNOW(BOUNDINGBOX *box,int num_particles):_box(*box) { _size = 50.0f; //雪花的大小 _vertexbuf_size = 2048; //粒子系统对GPU的可用大小 _vertexbuf_offset = 0; //顶点缓存的偏移量 _vertexbuf_num = 512; //每次填充顶点缓存顶点数 for(int i = 0;i < num_particles;i++) //根据所需数量添加雪花 add_particle(); }
FIRE::FIRE(D3DXVECTOR3 *origin,int num_particles) { _origin = *origin; _size = 0.9f; _vertexbuf_size = 2048; _vertexbuf_offset = 0; _vertexbuf_num = 512; for(int i = 0; i < num_particles; i++) add_particle(); }
Tree::Tree(Particle* p, int _n_particles, double _theta, Physics* _physics) { n_particles = _n_particles; theta = _theta; physics = _physics; double box_length = max_boxsize(p, n_particles); std::cout << "Constructing tree of boxsize " << box_length << std::endl; root = new Node(-box_length, box_length, -box_length, box_length, -box_length, box_length); int i; for (i = 0; i < n_particles; i++) { add_particle(root, &p[i]); } std::cout << "Tree finished" << std::endl; }
void SPHSystem::init_system() { srand((unsigned int)time(NULL)); float2 pos; float2 vel=make_float2(0.0f, 0.0f); for(pos.x=hParam->world_size.x*0.0f; pos.x<hParam->world_size.x*0.4f; pos.x+=(hParam->kernel*0.6f)) { for(pos.y=hParam->world_size.y*0.0f; pos.y<hParam->world_size.y*0.9f; pos.y+=(hParam->kernel*0.6f)) { add_particle(pos, vel); } } copy_array(dMem, hMem, sizeof(Particle)*hParam->num_particle, CUDA_HOST_TO_DEV); printf("Init Particle: %u\n", hParam->num_particle); }
void run_simulation(particle_t* ps, int n, FILE* fsave){ //Create partition and set active partition* p = alloc_partition(n); set_active_partition(p); //Add all particles for(int i=0; i<n; i++) add_particle(&ps[i]); //For each step for(int step = 0; step < NSTEPS; step++ ){ update_particles(); //=== Save state to file === if( fsave && (step%SAVEFREQ) == 0 ) save( fsave, n, particles ); } }
void SPHSystem::init_system() { float3 pos; float3 vel; vel.x=0.0f; vel.y=0.0f; vel.z=0.0f; for(pos.x=world_size.x*0.0f; pos.x<world_size.x*0.6f; pos.x+=(kernel*0.5f)) { for(pos.y=world_size.y*0.0f; pos.y<world_size.y*0.9f; pos.y+=(kernel*0.5f)) { for(pos.z=world_size.z*0.0f; pos.z<world_size.z*0.6f; pos.z+=(kernel*0.5f)) { add_particle(pos, vel); } } } printf("Init Particle: %u\n", num_particle); }
static void gen_explosion(float x, float y) { int i, n, c; particle *p; n = 150 + irand(150); c = irand(NUM_PALETTES); for (i = 0; i < n; i++) { vector2 offs; p = add_particle(); if (!p) break; p->ttl = 20 + irand(20); p->t = 0; p->width = .3f*(.6f + .1f*frand()); p->height = .3f*(2.8f + .4f*frand()); p->pos.x = x; p->pos.y = y; p->palette = c; vec2_set(&p->dir, frand() - .5f, frand() - .5f); vec2_normalize(&p->dir); offs = p->dir; vec2_mul_scalar(&offs, 1.3f*frand()); vec2_add_to(&p->pos, &offs); p->speed = PARTICLE_SPEED + .05f*frand(); p->friction = .96f; } }
/* track backwards */ double trackback_c (tracking_run *run_info, int step) { int i, j, h, in_volume = 0; int philf[4][MAX_CANDS]; int count1 = 0, count2 = 0, num_added = 0; int quali = 0; double angle, acc, dl; vec3d diff_pos, X[6]; /* 6 reference points used in the algorithm */ vec2d n[4], v2[4]; // replaces xn,yn, x2[4], y2[4], double rr, Ymin = 0, Ymax = 0; double npart = 0, nlinks = 0; foundpix *w; sequence_par *seq_par; track_par *tpar; volume_par *vpar; control_par *cpar; framebuf *fb; Calibration **cal; /* Shortcuts to inside current frame */ P *curr_path_inf, *ref_path_inf; /* shortcuts */ cal = run_info->cal; seq_par = run_info->seq_par; tpar = run_info->tpar; vpar = run_info->vpar; cpar = run_info->cpar; fb = run_info->fb; /* Prime the buffer with first frames */ for (step = seq_par->last; step > seq_par->last - 4; step--) { fb_read_frame_at_end(fb, step, 1); fb_next(fb); } fb_prev(fb); /* sequence loop */ for (step = seq_par->last - 1; step > seq_par->first; step--) { printf ("Time step: %d, seqnr: %d:\n", step - seq_par->first, step); for (h = 0; h < fb->buf[1]->num_parts; h++) { curr_path_inf = &(fb->buf[1]->path_info[h]); /* We try to find link only if the forward search failed to. */ if ((curr_path_inf->next < 0) || (curr_path_inf->prev != -1)) continue; for (j = 0; j < 6; j++) vec_init(X[j]); curr_path_inf->inlist = 0; /* 3D-position of current particle */ vec_copy(X[1], curr_path_inf->x); /* use information from previous to locate new search position and to calculate values for search area */ ref_path_inf = &(fb->buf[0]->path_info[curr_path_inf->next]); vec_copy(X[0], ref_path_inf->x); search_volume_center_moving(ref_path_inf->x, curr_path_inf->x, X[2]); for (j = 0; j < fb->num_cams; j++) { point_to_pixel (n[j], X[2], cal[j], cpar); } /* calculate searchquader and reprojection in image space */ w = sorted_candidates_in_volume(X[2], n, fb->buf[2], run_info); if (w != NULL) { count2++; i = 0; while (w[i].ftnr != TR_UNUSED) { ref_path_inf = &(fb->buf[2]->path_info[w[i].ftnr]); vec_copy(X[3], ref_path_inf->x); vec_subt(X[1], X[3], diff_pos); if (pos3d_in_bounds(diff_pos, tpar)) { angle_acc(X[1], X[2], X[3], &angle, &acc); /* *********************check link *****************************/ if ((acc < tpar->dacc && angle < tpar->dangle) || \ (acc < tpar->dacc/10)) { dl = (vec_diff_norm(X[1], X[3]) + vec_diff_norm(X[0], X[1]) )/2; quali = w[i].freq; rr = (dl/run_info->lmax + acc/tpar->dacc + \ angle/tpar->dangle)/quali; register_link_candidate(curr_path_inf, rr, w[i].ftnr); } } i++; } } free(w); /* if old wasn't found try to create new particle position from rest */ if (tpar->add) { if ( curr_path_inf->inlist == 0) { quali = assess_new_position(X[2], v2, philf, fb->buf[2], run_info); if (quali>=2) { //vec_copy(X[3], X[2]); in_volume = 0; point_position(v2, fb->num_cams, cpar->mm, cal, X[3]); /* volume check */ if ( vpar->X_lay[0] < X[3][0] && X[3][0] < vpar->X_lay[1] && Ymin < X[3][1] && X[3][1] < Ymax && vpar->Zmin_lay[0] < X[3][2] && X[3][2] < vpar->Zmax_lay[1]) {in_volume = 1;} vec_subt(X[1], X[3], diff_pos); if (in_volume == 1 && pos3d_in_bounds(diff_pos, tpar)) { angle_acc(X[1], X[2], X[3], &angle, &acc); if ( (acc<tpar->dacc && angle<tpar->dangle) || \ (acc<tpar->dacc/10) ) { dl = (vec_diff_norm(X[1], X[3]) + vec_diff_norm(X[0], X[1]) )/2; rr = (dl/run_info->lmax+acc/tpar->dacc + angle/tpar->dangle)/(quali); register_link_candidate(curr_path_inf, rr, fb->buf[2]->num_parts); add_particle(fb->buf[2], X[3], philf); } } in_volume = 0; } } } /* end of if old wasn't found try to create new particle position from rest */ } /* end of h-loop */ for (h = 0; h < fb->buf[1]->num_parts; h++) { curr_path_inf = &(fb->buf[1]->path_info[h]); if(curr_path_inf->inlist > 0 ) { sort(curr_path_inf->inlist, (float *)curr_path_inf->decis, curr_path_inf->linkdecis); } } /* create links with decision check */ count1 = 0; num_added = 0; for (h = 0; h < fb->buf[1]->num_parts; h++) { curr_path_inf = &(fb->buf[1]->path_info[h]); if (curr_path_inf->inlist > 0 ) { /* if old/new and unused prev == -1 and next == -2 link is created */ ref_path_inf = &(fb->buf[2]->path_info[curr_path_inf->linkdecis[0]]); if ( ref_path_inf->prev == PREV_NONE && \ ref_path_inf->next == NEXT_NONE ) { curr_path_inf->finaldecis = curr_path_inf->decis[0]; curr_path_inf->prev = curr_path_inf->linkdecis[0]; fb->buf[2]->path_info[curr_path_inf->prev].next = h; num_added++; } /* old which link to prev has to be checked */ if ((ref_path_inf->prev != PREV_NONE) && \ (ref_path_inf->next == NEXT_NONE) ) { vec_copy(X[0], fb->buf[0]->path_info[curr_path_inf->next].x); vec_copy(X[1], curr_path_inf->x); vec_copy(X[3], ref_path_inf->x); vec_copy(X[4], fb->buf[3]->path_info[ref_path_inf->prev].x); for (j = 0; j < 3; j++) X[5][j] = 0.5*(5.0*X[3][j] - 4.0*X[1][j] + X[0][j]); angle_acc(X[3], X[4], X[5], &angle, &acc); if ( (acc<tpar->dacc && angle<tpar->dangle) || (acc<tpar->dacc/10) ) { curr_path_inf->finaldecis = curr_path_inf->decis[0]; curr_path_inf->prev = curr_path_inf->linkdecis[0]; fb->buf[2]->path_info[curr_path_inf->prev].next = h; num_added++; } } } if (curr_path_inf->prev != PREV_NONE ) count1++; } /* end of creation of links with decision check */ printf ("step: %d, curr: %d, next: %d, links: %d, lost: %d, add: %d", step, fb->buf[1]->num_parts, fb->buf[2]->num_parts, count1, fb->buf[1]->num_parts - count1, num_added); /* for the average of particles and links */ npart = npart + fb->buf[1]->num_parts; nlinks = nlinks + count1; fb_next(fb); fb_write_frame_from_start(fb, step); if(step > seq_par->first + 2) { fb_read_frame_at_end(fb, step - 3, 1); } } /* end of sequence loop */ /* average of all steps */ npart /= (seq_par->last - seq_par->first - 1); nlinks /= (seq_par->last - seq_par->first - 1); printf ("Average over sequence, particles: %5.1f, links: %5.1f, lost: %5.1f\n", npart, nlinks, npart-nlinks); fb_next(fb); fb_write_frame_from_start(fb, step); fb_free(fb); free(fb); free(tpar); return nlinks; }
/* trackcorr_c_loop is the main tracking subroutine that scans the 3D particle position * data from rt_is.* files and the 2D particle positions in image space in _targets and * constructs trajectories (links) of the particles in 3D in time. * the basic concepts of the tracking procedure are from the following publication by * Jochen Willneff: "A New Spatio-Temporal Matching Algorithm For 3D-Particle Tracking Velocimetry" * https://www.mendeley.com/catalog/new-spatiotemporal-matching-algorithm-3dparticle-tracking-velocimetry/ * or http://e-collection.library.ethz.ch/view/eth:26978 * this method is an extension of the previously used tracking method described in details in * Malik et al. 1993: "Particle tracking velocimetry in three-dimensional flows: Particle tracking" * http://mnd.ly/2dCt3um * * Arguments: * tracking_run *run_info pointer to the (sliding) frame dataset of 4 frames of particle positions * and all the needed parameters underneath: control, volume, etc. * integer step number or the frame number from the sequence * Note: step is not really setting up the step to track, the buffer provided to the trackcoor_c_loop * is already preset by 4 frames buf[0] to buf[3] and we track particles in buf[1], i.e. one "previous" * one present and two future frames. * * Returns: function does not return an argument, the tracks are updated within the run_info dataset */ void trackcorr_c_loop (tracking_run *run_info, int step) { /* sequence loop */ int j, h, mm, kk, in_volume = 0; int philf[4][MAX_CANDS]; int count1 = 0, count2 = 0, count3 = 0, num_added = 0; int quali = 0; vec3d diff_pos, X[6]; /* 7 reference points used in the algorithm, TODO: check if can reuse some */ double angle, acc, angle0, acc0, dl; double angle1, acc1; vec2d v1[4], v2[4]; /* volume center projection on cameras */ double rr; /* Shortcuts to inside current frame */ P *curr_path_inf, *ref_path_inf; corres *curr_corres; target **curr_targets; int _ix; /* For use in any of the complex index expressions below */ int orig_parts; /* avoid infinite loop with particle addition set */ /* Shortcuts into the tracking_run struct */ Calibration **cal; framebuf *fb; track_par *tpar; volume_par *vpar; control_par *cpar; foundpix *w, *wn; count1 = 0; num_added = 0; fb = run_info->fb; cal = run_info->cal; tpar = run_info->tpar; vpar = run_info->vpar; cpar = run_info->cpar; curr_targets = fb->buf[1]->targets; /* try to track correspondences from previous 0 - corp, variable h */ orig_parts = fb->buf[1]->num_parts; for (h = 0; h < orig_parts; h++) { for (j = 0; j < 6; j++) vec_init(X[j]); curr_path_inf = &(fb->buf[1]->path_info[h]); curr_corres = &(fb->buf[1]->correspond[h]); curr_path_inf->inlist = 0; /* 3D-position */ vec_copy(X[1], curr_path_inf->x); /* use information from previous to locate new search position and to calculate values for search area */ if (curr_path_inf->prev >= 0) { ref_path_inf = &(fb->buf[0]->path_info[curr_path_inf->prev]); vec_copy(X[0], ref_path_inf->x); search_volume_center_moving(ref_path_inf->x, curr_path_inf->x, X[2]); for (j = 0; j < fb->num_cams; j++) { point_to_pixel (v1[j], X[2], cal[j], cpar); } } else { vec_copy(X[2], X[1]); for (j = 0; j < fb->num_cams; j++) { if (curr_corres->p[j] == -1) { point_to_pixel (v1[j], X[2], cal[j], cpar); } else { _ix = curr_corres->p[j]; v1[j][0] = curr_targets[j][_ix].x; v1[j][1] = curr_targets[j][_ix].y; } } } /* calculate search cuboid and reproject it to the image space */ w = sorted_candidates_in_volume(X[2], v1, fb->buf[2], run_info); if (w == NULL) continue; /* Continue to find candidates for the candidates. */ count2++; mm = 0; while (w[mm].ftnr != TR_UNUSED) { /* counter1-loop */ /* search for found corr of current the corr in next with predicted location */ /* found 3D-position */ ref_path_inf = &(fb->buf[2]->path_info[w[mm].ftnr]); vec_copy(X[3], ref_path_inf->x); if (curr_path_inf->prev >= 0) { for (j = 0; j < 3; j++) X[5][j] = 0.5*(5.0*X[3][j] - 4.0*X[1][j] + X[0][j]); } else { search_volume_center_moving(X[1], X[3], X[5]); } for (j = 0; j < fb->num_cams; j++) { point_to_pixel (v1[j], X[5], cal[j], cpar); } /* end of search in pix */ wn = sorted_candidates_in_volume(X[5], v1, fb->buf[3], run_info); if (wn != NULL) { count3++; kk = 0; while (wn[kk].ftnr != TR_UNUSED) { ref_path_inf = &(fb->buf[3]->path_info[wn[kk].ftnr]); vec_copy(X[4], ref_path_inf->x); vec_subt(X[4], X[3], diff_pos); if ( pos3d_in_bounds(diff_pos, tpar)) { angle_acc(X[3], X[4], X[5], &angle1, &acc1); if (curr_path_inf->prev >= 0) { angle_acc(X[1], X[2], X[3], &angle0, &acc0); } else { acc0 = acc1; angle0 = angle1; } acc = (acc0+acc1)/2; angle = (angle0+angle1)/2; quali = wn[kk].freq+w[mm].freq; if ((acc < tpar->dacc && angle < tpar->dangle) || \ (acc < tpar->dacc/10)) { dl = (vec_diff_norm(X[1], X[3]) + vec_diff_norm(X[4], X[3]) )/2; rr = (dl/run_info->lmax + acc/tpar->dacc + \ angle/tpar->dangle)/(quali); register_link_candidate( curr_path_inf, rr, w[mm].ftnr); } } kk++; } /* End of searching 2nd-frame candidates. */ } /* creating new particle position, * reset img coord because of num_cams < 4 * fix distance of 3 pixels to define xl,xr,yu,yd instead of searchquader * and search for unused candidates in next time step */ quali = assess_new_position(X[5], v2, philf, fb->buf[3], run_info); /* quali >=2 means at least in two cameras * we found a candidate */ if ( quali >= 2) { in_volume = 0; //inside volume dl = point_position(v2, cpar->num_cams, cpar->mm, cal, X[4]); /* volume check */ if ( vpar->X_lay[0] < X[4][0] && X[4][0] < vpar->X_lay[1] && run_info->ymin < X[4][1] && X[4][1] < run_info->ymax && vpar->Zmin_lay[0] < X[4][2] && X[4][2] < vpar->Zmax_lay[1]) { in_volume = 1; } vec_subt(X[3], X[4], diff_pos); if ( in_volume == 1 && pos3d_in_bounds(diff_pos, tpar) ) { angle_acc(X[3], X[4], X[5], &angle, &acc); if ((acc < tpar->dacc && angle < tpar->dangle) || \ (acc < tpar->dacc/10)) { dl = (vec_diff_norm(X[1], X[3]) + vec_diff_norm(X[4], X[3]) )/2; rr = (dl/run_info->lmax + acc/tpar->dacc + angle/tpar->dangle) / (quali+w[mm].freq); register_link_candidate(curr_path_inf, rr, w[mm].ftnr); if (tpar->add) { add_particle(fb->buf[3], X[4], philf); num_added++; } } } in_volume = 0; } quali = 0; /* end of creating new particle position */ /* *************************************************************** */ /* try to link if kk is not found/good enough and prev exist */ if ( curr_path_inf->inlist == 0 && curr_path_inf->prev >= 0 ) { vec_subt(X[3], X[1], diff_pos); if (pos3d_in_bounds(diff_pos, tpar)) { angle_acc(X[1], X[2], X[3], &angle, &acc); if ( (acc < tpar->dacc && angle < tpar->dangle) || \ (acc < tpar->dacc/10) ) { quali = w[mm].freq; dl = (vec_diff_norm(X[1], X[3]) + vec_diff_norm(X[0], X[1]) )/2; rr = (dl/run_info->lmax + acc/tpar->dacc + angle/tpar->dangle)/(quali); register_link_candidate(curr_path_inf, rr, w[mm].ftnr); } } } free(wn); mm++; } /* end of loop over first-frame candidates. */ /* begin of inlist still zero */ if (tpar->add) { if ( curr_path_inf->inlist == 0 && curr_path_inf->prev >= 0 ) { quali = assess_new_position(X[2], v2, philf, fb->buf[2], run_info); if (quali>=2) { vec_copy(X[3], X[2]); in_volume = 0; dl = point_position(v2, fb->num_cams, cpar->mm, cal, X[3]); /* in volume check */ if ( vpar->X_lay[0] < X[3][0] && X[3][0] < vpar->X_lay[1] && run_info->ymin < X[3][1] && X[3][1] < run_info->ymax && vpar->Zmin_lay[0] < X[3][2] && X[3][2] < vpar->Zmax_lay[1]) { in_volume = 1; } vec_subt(X[2], X[3], diff_pos); if ( in_volume == 1 && pos3d_in_bounds(diff_pos, tpar) ) { angle_acc(X[1], X[2], X[3], &angle, &acc); if ( (acc < tpar->dacc && angle < tpar->dangle) || \ (acc < tpar->dacc/10) ) { dl = (vec_diff_norm(X[1], X[3]) + vec_diff_norm(X[0], X[1]) )/2; rr = (dl/run_info->lmax + acc/tpar->dacc + angle/tpar->dangle)/(quali); register_link_candidate(curr_path_inf, rr, fb->buf[2]->num_parts); add_particle(fb->buf[2], X[3], philf); num_added++; } } in_volume = 0; } // if quali >= 2 } } /* end of inlist still zero */ /***********************************/ free(w); } /* end of h-loop */ /* sort decis and give preliminary "finaldecis" */ for (h = 0; h < fb->buf[1]->num_parts; h++) { curr_path_inf = &(fb->buf[1]->path_info[h]); if(curr_path_inf->inlist > 0 ) { sort(curr_path_inf->inlist, (float *) curr_path_inf->decis, curr_path_inf->linkdecis); curr_path_inf->finaldecis = curr_path_inf->decis[0]; curr_path_inf->next = curr_path_inf->linkdecis[0]; } } /* create links with decision check */ for (h = 0; h < fb->buf[1]->num_parts; h++) { curr_path_inf = &(fb->buf[1]->path_info[h]); if(curr_path_inf->inlist > 0 ) { ref_path_inf = &(fb->buf[2]->path_info[curr_path_inf->next]); if (ref_path_inf->prev == PREV_NONE) { /* best choice wasn't used yet, so link is created */ ref_path_inf->prev = h; } else { /* best choice was already used by mega[2][mega[1][h].next].prev */ /* check which is the better choice */ if ( fb->buf[1]->path_info[ref_path_inf->prev].finaldecis > \ curr_path_inf->finaldecis) { /* remove link with prev */ fb->buf[1]->path_info[ref_path_inf->prev].next = NEXT_NONE; ref_path_inf->prev = h; } else { curr_path_inf->next = NEXT_NONE; } } } if (curr_path_inf->next != NEXT_NONE ) count1++; } /* end of creation of links with decision check */ printf ("step: %d, curr: %d, next: %d, links: %d, lost: %d, add: %d\n", step, fb->buf[1]->num_parts, fb->buf[2]->num_parts, count1, fb->buf[1]->num_parts - count1, num_added); /* for the average of particles and links */ run_info->npart = run_info->npart + fb->buf[1]->num_parts; run_info->nlinks = run_info->nlinks + count1; fb_next(fb); fb_write_frame_from_start(fb, step); if(step < run_info->seq_par->last - 2) { fb_read_frame_at_end(fb, step + 3, 0); } } /* end of sequence loop */
// Move the enemy void ENEMY::move() { // Advance the animation if(!chase && !burning) anim += 0.10f; else anim += 0.20f; if((int)anim > 3 || kicked) anim = 0.0f; // Advance the dying animation if we're actually dying if(dying) { die_anim -= 0.03f; // Create the blue "burning down" effect float px = get_real_x(); float py = get_real_y(); for(int f=0; f < RAND(2,10); f++) { float rnd = RANDF(-0.3f, 0.3f); VECT pos(px, 2*size - 0.05f - (2.5f*size*(1-die_anim)), py); pos.x += rnd; pos.z -= rnd; if(pos.y < 0.0f) pos.y = 0.0f; if(turning) pos.y += (turning_raise * 0.85f); VECT dir = 0.0f; float c1[4] = { 0.1f, 0.7f, 1, 1 }; float c2[4] = { 0.1f, 0.7f, 1, 0 }; add_particle(pos, dir, RAND(20,35), 0.1f, 0.4f, c1, c2, part_star); } if(die_anim < 0.0f) { die_anim = 0.0f; alive = false; } return; } // Create some particle fire from the burning enemies if(burning) { VECT ppos(get_real_x(), 0.5f, get_real_y()); create_fire(ppos); } // Advance the turning animation if(turning) { // Raise up if(turning == 1) { turning_raise += 0.035f; if(turning_raise >= 1.0f) { turning_raise = 1.0f; turning++; } } // Turn else if(turning == 2) { turning_counter++; if(turning_counter == 5) { dir = nextdir; nextdir = dir + 1; if(nextdir > DIR_W) nextdir = DIR_N; } else if(turning_counter == 10) { dir = nextdir; turning++; } } // Go down else if(turning == 3) { turning_raise -= 0.035f; if(turning_raise <= 0.0f) { turning_raise = 0.0f; turning = 0; } } // Check the collision between the player #1 if(p1.alive && !p1.jumping) { float dx = get_real_x() - p1.get_real_x(); float dy = get_real_y() - p1.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Kill the player and die p1.die(); die(); } } // Check the collision between the player #2 if(alive && two_players && p2.alive && !p2.jumping) { float dx = get_real_x() - p2.get_real_x(); float dy = get_real_y() - p2.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Kill the player and die p2.die(); die(); } } return; } // If there is the lightning special power in progress, don't move the enemies which are // suffering from the lightning strikes if(special_power_pause && which_special_power == BLUE_POWER_LIGHTNING) { // Check if we're a target for(int f=0; f<ENEMY_AMOUNT; f++) { if(sp_lightning.targets[f] == this) { anim += 0.30f; if((int)anim > 3) anim = 0.0f; return; } } } // Don't move if the level is finished if(level_pause) return; // Check the traps if(traplist.size() > 0) { list<TRAP>::iterator t; for(t = traplist.begin(); t != traplist.end(); ++t) { if(x == (*t).x && y == (*t).y) { die(); return; } } } // Handle the burning, that is run around aimlessly if(burning) { if(!kicked) { // Reduce the burning time burn_time--; if(burn_time == 0) { die(); return; } // Choose a random direction if(RAND(0,100) > 50 && offset == 0.0f) { if(RAND(0,100) > 50) dir++; else dir--; if(dir > DIR_W) dir = DIR_N; else if(dir < DIR_N) dir = DIR_W; } // Move one step if(tx == x && ty == y) { offset = 0.0f; // Don't stop until there's a wall. switch(dir) { default: case DIR_N: tx = x; ty = y - 1; break; case DIR_E: tx = x + 1; ty = y; break; case DIR_S: tx = x; ty = y + 1; break; case DIR_W: tx = x - 1; ty = y; break; } // Check if the target is passable? if(map_solid(tx, ty)) { // Stop and choose a new dir tx = x; ty = y; dir += RAND(-1,1); if(dir < DIR_N) dir = DIR_W; else if(dir > DIR_W) dir = DIR_N; return; } } // Move towards the target tile if(offset < 1.0f && (tx != x || ty != y)) { offset += speed; // Check the collision between the player #1 if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) { float dx = get_real_x() - p1.get_real_x(); float dy = get_real_y() - p1.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Turn around and run tx = x; ty = y; offset = 0.0f; dir += 2; if(dir > DIR_W) dir -= 4; } } // Check the collision between the player #2 if(two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) { float dx = get_real_x() - p2.get_real_x(); float dy = get_real_y() - p2.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Turn around and run tx = x; ty = y; offset = 0.0f; dir += 2; if(dir > DIR_W) dir -= 4; } } // Check the collision between the potato men if(potatoman.collide_with(this) && !kicked) { // Potatoman "kicked" us potatoman.kick(this); } // If we're reached the target tile, move again if(offset >= 1.0f) { x = tx; y = ty; offset = 0.0f; } } } // Check collisions with other enemies and spread the fire bool burnt_somebody = false; list<ENEMY>::iterator e; for(e = enemylist.begin(); e != enemylist.end(); ++e) { if(this != &(*e) && !(*e).burning) { // Check the distance float dx = get_real_x() - (*e).get_real_x(); float dy = get_real_y() - (*e).get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Burn the other enemy (*e).burning = true; (*e).burn_time = enemy_burn_time; (*e).speed += 0.06f; burnt_somebody = true; } } } // Play the burning sound if(burnt_somebody) play_sound(SND_WILDFIRE, false); if(!kicked) return; } // Not burning below here // Choose a random destination if(path_pos == -1) { // Choose a valid target int dx = RAND(0, MAP_W-1); int dy = RAND(0, MAP_H-1); while(map_solid(dx, dy) || dx == x || dy == y) { dx = RAND(0, MAP_W-1); dy = RAND(0, MAP_H-1); } // Calculate the path if(pf.find_path(x, y, dx, dy) == PATH_FAILED) { // Well, tough luck. We'll just wait and try again later. return; } // Now we've got a nice path for us! path_pos = 0; offset = 0.0f; tx = pf.path[0].x; ty = pf.path[0].y; dir = get_dir(tx - x, ty - y); look_player(); } // Move one step if(tx == x && ty == y && path_pos > -1) { offset = 0.0f; // Follow the path if we're not chasing if(chase == 0 && !kicked) { path_pos++; tx = pf.path[path_pos].x; ty = pf.path[path_pos].y; dir = get_dir(tx - x, ty - y); look_player(); } else if(chase && !kicked) { // We are chasing. Don't stop until there's a wall. switch(dir) { default: case DIR_N: tx = x; ty = y - 1; break; case DIR_E: tx = x + 1; ty = y; break; case DIR_S: tx = x; ty = y + 1; break; case DIR_W: tx = x - 1; ty = y; break; } // Check if the target is passable? if(map_solid(tx, ty)) { // Stop and choose a new path tx = x; ty = y; path_pos = -1; chase = 0; speed -= 0.03f; } } else if(kicked) { // Potatoman has kicked us. "Fly" straight until we hit a wall. switch(dir) { default: case DIR_N: tx = x; ty = y - 1; break; case DIR_E: tx = x + 1; ty = y; break; case DIR_S: tx = x; ty = y + 1; break; case DIR_W: tx = x - 1; ty = y; break; } // Check for the wall if(map_solid(tx, ty)) { die(); return; } } } // Move towards the target tile if(offset < 1.0f && (tx != x || ty != y) && path_pos > -1) { offset += speed; // Check the collision between the player #1 if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) { float dx = get_real_x() - p1.get_real_x(); float dy = get_real_y() - p1.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Kill the player and die p1.die(); die(); } } // Check the collision between the player #2 if(alive && two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) { float dx = get_real_x() - p2.get_real_x(); float dy = get_real_y() - p2.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Kill the player and die p2.die(); die(); } } // Check the collision between the potato men if(potatoman.collide_with(this) && !kicked) { // Potatoman "kicked" us potatoman.kick(this); } // If we're reached the target tile, move again if(offset >= 1.0f) { x = tx; y = ty; offset = 0.0f; // If this is the final destination, stay put and choose a new path // on the next cycle if(x == pf.dx && y == pf.dy && !chase && !kicked) path_pos = -1; } } }
// Move the player void PLAYER::move() { #ifndef EDITOR int who = (this == &p1) ? 1 : 2; int who2 = who-1; // Used for array indices // Reduce the icon alpha if(p_icon_alpha[who2]) { p_icon_alpha[who2] -= 0.005f; if(p_icon_alpha[who2] < 0.0f) p_icon_alpha[who2] = 0.0f; } // If we're dead, reduce the death counter and respawn if(!alive) { death_counter--; if(death_counter == 0) { // Respawn to a block int ox, oy; get_respawn_position((int)get_real_x(), (int)get_real_y(), ox, oy); int odir = dir; //clear(); alive = true; x = ox; y = oy; dir = odir; nextdir = dir; tx = x; ty = y; walking = false; jumping = false; dying = false; offset = 0.0f; create_teleport_effect(x, y); show_icon(who2); // Play the appear sound play_sound(SND_APPEAR, false); } return; } // Advance the dying animation if we're actually dying if(dying) { die_anim -= 0.03f; // Create the blue "burning down" effect float px = get_real_x(); float py = get_real_y(); for(int f=0; f < RAND(2,10); f++) { float rnd = RANDF(-0.3f, 0.3f); VECT pos(px, 2*size - 0.05f - (2.5f*size*(1-die_anim)), py); pos.x += rnd; pos.z -= rnd; if(pos.y < 0.0f) pos.y = 0.0f; VECT dir = 0.0f; float c1[4] = { 0.1f, 0.7f, 1, 1 }; float c2[4] = { 0.1f, 0.7f, 1, 0 }; add_particle(pos, dir, RAND(20,35), 0.1f, 0.4f, c1, c2, part_star); } if(die_anim < 0.0f) { die_anim = 0.0f; alive = false; // Explode the player bombs if(num_bombs > 0) { list<BOMB>::iterator b; for(b = bomblist.begin(); b != bomblist.end(); ++b) if((*b).owner == who && (*b).time > 1) (*b).time = 1; // Makes the bomb explode on the next cycle } } return; } // Jumping stuff if(jumping) { jump_pos += jump_speed; if(jump_pos >= 1.0f) { jump_pos = 1.0f; // We're now on the target tile x = jump_tx; y = jump_ty; tx = x; ty = y; offset = 0.0f; jumping = false; } // Create some particles if we're teleporting if(in_teleport && jumping) { VECT pos(get_real_x(), 0.25f, get_real_y()); pos += jump_dir * jump_pos * jump_dist; pos.y += jump_height * SIN(180.0f * jump_pos); VECT dir; for(int f=0; f<5; f++) { VECT ppos = pos + VECT(RANDF(-0.5f,0.5f),RANDF(-0.5f,0.5f),RANDF(-0.5f,0.5f)); dir.x = dir.y = dir.z = 0.0f; float c1[4] = { 0.3, 0.7f, 1, 1 }; float c2[4] = { 0, 0, 1, 0 }; add_particle(ppos, dir, RAND(10,30), 0.1f, 0.3f, c1, c2, part_teleport); } } // This is a dirty hack. Read the comments from the beginning of this file. if(map[jump_tx][jump_ty][1] && jump_pos > 0.9f) { players_on_block_x[who2] = jump_tx; players_on_block_y[who2] = jump_ty; } return; } // This is a dirty hack. Read the comments from the beginning of this file. if(map[x][y][1]) { players_on_block_x[who2] = x; players_on_block_y[who2] = y; //return; } else { players_on_block_x[who2] = -1; } // Don't move if we're using the napalm or the teleport power if(using_special_power && (which_special_power == RED_POWER_NAPALM)) return; if(using_special_power == who && (which_special_power == BLUE_POWER_TELEPORT)) return; // Don't move if the level is finished if(level_pause) return; // Advance the animation anim += 0.20f; if((int)anim > 3) anim = 0.0f; // Advance the turning animation if(turning) { turning_counter++; if(turning_counter == 5) { dir = nextdir; nextdir = dir + 1; if(nextdir > DIR_W) nextdir = DIR_N; } else if(turning_counter == 10) { dir = nextdir; turning = false; } } if(!walking && ((config.moving_style[who2] == MOV_RELATIVE && !key[config.key_up[who2]]) || (config.moving_style[who2] == MOV_ABSOLUTE && !key[config.key_up[who2]] && !key[config.key_down[who2]] && !key[config.key_left[who2]] && !key[config.key_right[who2]]))) anim = 0.0f; // Check if we're on a block bool on_block = false; if(map_solid(x,y)) on_block = true; // Don't move if we're using the flower power (absolute) if(on_block && config.moving_style[who2] == MOV_ABSOLUTE && (p1.num_flower_bombs > 0 || p2.num_flower_bombs > 0)) return; // Check for turning input if(key[config.key_left[who2]]) { if(config.moving_style[who2] == MOV_RELATIVE) { // Relative moving if(!turn_key_down[0] && !turning) { // Turn left nextdir = dir - 1; if(nextdir < DIR_N) nextdir = DIR_W; if(!walking) dir = nextdir; turn_key_down[0] = true; } } else if(config.moving_style[who2] == MOV_ABSOLUTE && !walking) { // Absolute moving dir = DIR_W; walking = true; offset = 0.0f; tx = x - 1; ty = y; // Check if the target is passable? if(map_solid(tx, ty)) { tx = x; ty = y; walking = false; } if(on_block) { // We're on a block, jump down from it jump(tx, ty, 2.0f, 0.05f); tx = x; ty = y; anim = 0; on_block = true; // Play the jumping sound if(jumping) play_sound(SND_JUMP, false); } } } else turn_key_down[0] = false; if(key[config.key_right[who2]]) { if(config.moving_style[who2] == MOV_RELATIVE) { // Relative moving if(!turn_key_down[1] && !turning) { // Turn right nextdir = dir + 1; if(nextdir > DIR_W) nextdir = DIR_N; if(!walking) dir = nextdir; turn_key_down[1] = true; } } else if(config.moving_style[who2] == MOV_ABSOLUTE && !walking) { // Absolute moving dir = DIR_E; walking = true; offset = 0.0f; tx = x + 1; ty = y; // Check if the target is passable? if(map_solid(tx, ty)) { tx = x; ty = y; walking = false; } if(on_block) { // We're on a block, jump down from it jump(tx, ty, 2.0f, 0.05f); tx = x; ty = y; anim = 0; on_block = true; // Play the jumping sound if(jumping) play_sound(SND_JUMP, false); } } } else turn_key_down[1] = false; // Check for 180 degree turning if(key[config.key_down[who2]]) { if(config.moving_style[who2] == MOV_RELATIVE) { // Relative moving if(!turn_key_down[2] && !turning && !walking && !key[config.key_up[who2]]) { nextdir = dir + 1; if(nextdir > DIR_W) nextdir = DIR_N; turning = true; turning_counter = 0; turn_key_down[2] = true; } } else if(config.moving_style[who2] == MOV_ABSOLUTE && !walking) { // Absolute moving dir = DIR_S; walking = true; offset = 0.0f; tx = x; ty = y + 1; // Check if the target is passable? if(map_solid(tx, ty)) { tx = x; ty = y; walking = false; } if(on_block) { // We're on a block, jump down from it jump(tx, ty, 2.0f, 0.05f); tx = x; ty = y; anim = 0; on_block = true; // Play the jumping sound if(jumping) play_sound(SND_JUMP, false); } } } else turn_key_down[2] = false; // Don't move if we're using the flower power (relative) if(on_block && config.moving_style[who2] == MOV_RELATIVE && (p1.num_flower_bombs > 0 || p2.num_flower_bombs > 0)) return; // Check for walking input if(key[config.key_up[who2]] && !walking && !turning) { if(config.moving_style[who2] == MOV_RELATIVE) { // Relative moving walking = true; offset = 0.0f; dir = nextdir; switch(dir) { default: case DIR_N: tx = x; ty = y - 1; break; case DIR_E: tx = x + 1; ty = y; break; case DIR_S: tx = x; ty = y + 1; break; case DIR_W: tx = x - 1; ty = y; break; } // Check if the target is passable? if(map_solid(tx, ty)) { tx = x; ty = y; walking = false; } if(on_block) { // We're on a block, jump down from it jump(tx, ty, 2.0f, 0.05f); tx = x; ty = y; anim = 0; on_block = true; // Play the jumping sound if(jumping) play_sound(SND_JUMP, false); } } else { // Absolute moving dir = DIR_N; walking = true; offset = 0.0f; tx = x; ty = y - 1; // Check if the target is passable? if(map_solid(tx, ty)) { tx = x; ty = y; walking = false; } if(on_block) { // We're on a block, jump down from it jump(tx, ty, 2.0f, 0.05f); tx = x; ty = y; anim = 0; on_block = true; // Play the jumping sound if(jumping) play_sound(SND_JUMP, false); } } } // Move towards the target tile if(offset < 1.0f && (tx != x || ty != y)) { offset += 0.1f; // If we're reached the target tile, move again if(offset >= 1.0f) { x = tx; y = ty; offset = 0.0f; walking = false; in_teleport = 0; } } // Reload the weapons if(reload > 0) reload--; // Dropping bombs if(key[config.key_shoot[who2]] && reload == 0 && num_bombs < 3 && !on_block && !icon_menu.wait) { reload = 30; // Plant the bomb add_bomb(x, y, BTYP_NORMAL, who); num_bombs++; // Play the sound play_sound(SND_BOMB, false); } // Invoke the special powers if(key[config.key_special[who2]]) { open_icon_menu(who, on_block); show_icon(0); show_icon(1); } #endif }
//funkce obstara efekt pri ztrate zivota (power levelu) void player_injury(float posx, float posy) { int i; for (i=0;i<110;i++) add_particle(posx, posy, 50*DFRAND, 50*DFRAND, FRAND, 1, FRAND, 0.5, 2); }
static void foe_common_gen_explosion(struct foe_common *f, float scale) { int i; particle *p; int ndebris, nballs; ndebris = scale*(40 + irand(30)); /* debris */ for (i = 0; i < ndebris; i++) { p = add_particle(); if (!p) break; p->ttl = 20 + irand(15); p->t = 0; p->width = scale*.4f*(.6f + .15f*frand()); p->height = scale*.3f*(2.8f + .4f*frand()); p->pos = f->pos; p->palette = PAL_YELLOW; p->friction = .9; vec2_set(&p->dir, frand() - .5f, frand() - .5f); vec2_normalize(&p->dir); p->speed = scale*(PARTICLE_SPEED + .05f*frand()); } #define RADIUS .4f /* fireballs */ nballs = scale*(8 + irand(8)); for (i = 0; i < nballs; i++) { vector2 pos; float r, l; l = 1.2*scale; pos.x = f->pos.x + l*frand() - .5f*l; pos.y = f->pos.y + l*frand() - .5f*l; r = scale*(.2f + .15f*frand()); add_explosion(&pos, r, EFF_EXPLOSION, 13 + irand(4)); } /* shockwave */ add_explosion(&f->pos, scale*.3f, EFF_RING, 18); /* p = add_particle(); if (p) { p->t = 0; p->ttl = 20; p->width = p->height = scale*.3f; p->pos = f->pos; p->palette = PAL_RED; p->type = PT_SHOCKWAVE; } */ perturb_water(&f->pos, scale*1200.f); play_fx(FX_EXPLOSION_1); }
Node * split (Node *root, Particle *p) { Node * new_node; Particle * old_particle; double x3 = (root->tl.x + root->br.x) / 2; double y3 = (root->tl.y + root->br.y) / 2; old_particle = root->particle; root->particle = NULL; root->is_leaf = 0; new_node = (Node *) malloc (sizeof (Node)); new_node->one = new_node->two = new_node->three = new_node->four = NULL; new_node->particle = NULL; new_node->is_leaf = 1; new_node->tl.x= root->tl.x; new_node->tl.y= root->tl.y; new_node->br.x= x3; new_node->br.y= y3; new_node->parent = root; new_node->total_mass = 0; new_node->cm.x = new_node->cm.y = -1.0; root->one = new_node; new_node = (Node *) malloc (sizeof (Node)); new_node->one = new_node->two = new_node->three = new_node->four = NULL; new_node->particle = NULL; new_node->is_leaf = 1; new_node->tl.x= x3; new_node->tl.y= root->tl.y; new_node->br.x= root->br.x; new_node->br.y= y3; new_node->parent = root; new_node->total_mass = 0; new_node->cm.x = new_node->cm.y = -1.0; root->two = new_node; new_node = (Node *) malloc (sizeof (Node)); new_node->one = new_node->two = new_node->three = new_node->four = NULL; new_node->particle = NULL; new_node->is_leaf = 1; new_node->tl.x= root->tl.x; new_node->tl.y= y3; new_node->br.x= x3; new_node->br.y= root->br.y; new_node->parent = root; new_node->total_mass = 0; new_node->cm.x = new_node->cm.y = -1.0; root->three = new_node; new_node = (Node *) malloc (sizeof (Node)); new_node->one = new_node->two = new_node->three = new_node->four = NULL; new_node->particle = NULL; new_node->is_leaf = 1; new_node->tl.x= x3; new_node->tl.y= y3; new_node->br.x= root->br.x; new_node->br.y= root->br.y; new_node->parent = root; new_node->total_mass = 0; new_node->cm.x = new_node->cm.y = -1.0; root->four = new_node; switch (child_alternative (root, old_particle)) { case ONE: add_particle (root->one, old_particle); break; case TWO: add_particle (root->two, old_particle); break; case THREE: add_particle (root->three, old_particle); break; case FOUR: add_particle (root->four, old_particle); break; default: printf ("ERROR: Bad number of children\n"); finalize (); exit (1); } switch (child_alternative (root, p)) { case ONE: return root->one ; case TWO: return root->two ; case THREE: return root->three ; case FOUR: return root->four ; default: return NULL; } }
// Create an explosion to a tile void create_explosion(int x, int y, int type) { int p; if(type == EXP_BOMB_NORMAL) { for(p = 0; p < RAND(20,40); p++) { // Add the explosion flames VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.01f, 0.01f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.01f, 0.01f); float c1[4] = { 1, 0.3f, 0.2f, 1 }; float c2[4] = { 1, 0, 0, 0 }; add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo); } for(p = 0; p < RAND(10,30); p++) { // Add the sparks VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.05f, 0.05f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.05f, 0.05f); float c1[4] = { 1, 0.7f, 0.3f, 1 }; float c2[4] = { 0, 0, 1, 0 }; add_particle(pos, dir, RAND(20,70), 0.05f, 0.01f, c1, c2, part_spark); } } if(type == EXP_BOMB_FLOWER) { for(p = 0; p < RAND(10,30); p++) { // Add the explosion flames VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.01f, 0.01f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.01f, 0.01f); float c1[4] = { 0.5f, 0, 1, 1 }; float c2[4] = { 0.2f, 1, 0.2f, 0 }; add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo); } for(p = 0; p < RAND(1,5); p++) { // Add the flowers VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.05f, 0.05f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.05f, 0.05f); float c1[4] = { 1, 1, 1, 1 }; float c2[4] = { 1, 1, 1, 0 }; add_particle(pos, dir, RAND(50,100), 0.5f, 0.1f, c1, c2, part_flower, true); } } else if(type == EXP_BOMB_CENTER) { for(p = 0; p < RAND(30,70); p++) { // Add the explosion flames VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.01f, 0.01f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.01f, 0.01f); float c1[4] = { 1, 0.7f, 0.3f, 1 }; float c2[4] = { 1, 0, 0, 0 }; add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo); } for(p = 0; p < RAND(10,40); p++) { // Add the sparks VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.05f, 0.05f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.05f, 0.05f); float c1[4] = { 1, 0.7f, 0.3f, 1 }; float c2[4] = { 0, 0, 1, 0 }; add_particle(pos, dir, RAND(20,70), 0.05f, 0.01f, c1, c2, part_spark); } } else if(type == EXP_BOMB_CENTER_FLOWER) { for(p = 0; p < RAND(20,30); p++) { // Add the explosion flames VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.01f, 0.01f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.01f, 0.01f); float c1[4] = { 0.3f, 1, 0.3f, 1 }; float c2[4] = { .5f, 0, 1, 0 }; add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo); } for(p = 0; p < RAND(1,5); p++) { // Add the flowers VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.05f, 0.05f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.05f, 0.05f); float c1[4] = { 1, 1, 1, 1 }; float c2[4] = { 1, 1, 1, 0 }; add_particle(pos, dir, RAND(50,100), 0.5f, 0.1f, c1, c2, part_flower, true); } } else if(type == EXP_NAPALM) { for(p = 0; p < RAND(20,50); p++) { // Add the explosion flames VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.01f, 0.01f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.01f, 0.01f); float c1[4] = { 1, 0.3f, 0.2f, 1 }; float c2[4] = { 1, 0, 0, 0 }; add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo); } for(p = 0; p < RAND(10,30); p++) { // Add the sparks VECT pos(x + 0.5f, 0.0f, y + 0.5f); VECT dir; dir.x = RANDF(-0.05f, 0.05f); dir.y = RANDF(0.0f, 0.1f); dir.z = RANDF(-0.05f, 0.05f); float c1[4] = { 1, 0.7f, 0.3f, 1 }; float c2[4] = { 0, 0, 1, 0 }; add_particle(pos, dir, RAND(20,70), 0.05f, 0.01f, c1, c2, part_spark); } } }
void process_message_from_server(unsigned char *in_data, int data_lenght) { //see what kind of data we got switch (in_data[PROTOCOL]) { case RAW_TEXT: { // do filtering and ignoring data_lenght=filter_or_ignore_text(&in_data[3],data_lenght-3)+3; if(data_lenght > 3) { //how to display it if(interface_mode!=interface_opening) put_text_in_buffer(&in_data[3],data_lenght-3,0); else put_text_in_buffer(&in_data[3],data_lenght-3,54); //lets log it write_to_log(&in_data[3],data_lenght-3); } } break; case SMALL_WINDOW_TEXT: { add_text_to_small_text_buffer(in_data+3, data_lenght-3); display_small_text_window(); } break; case ADD_NEW_ACTOR: { add_actor_from_server(&in_data[3]); } break; case ADD_NEW_ENHANCED_ACTOR: { add_enhanced_actor_from_server(&in_data[3]); } break; case ADD_ACTOR_COMMAND: { add_command_to_actor(*((short *)(in_data+3)),in_data[5]); } break; case REMOVE_ACTOR: { destroy_actor(*((short *)(in_data+3))); } break; case KILL_ALL_ACTORS: { destroy_all_actors(); } break; case NEW_MINUTE: { game_minute=*((short *)(in_data+3)); new_minute(); } break; case LOG_IN_OK: { interface_mode=interface_game; previously_logged_in=1; } break; case HERE_YOUR_STATS: { get_the_stats((Sint16 *)(in_data+3)); } break; case SEND_PARTIAL_STAT: { get_partial_stat(*((Uint8 *)(in_data+3)),*((Sint32 *)(in_data+4))); } break; case GET_KNOWLEDGE_LIST: { get_knowledge_list(*(Uint16 *)(in_data+1)-1, in_data+3); } break; case GET_NEW_KNOWLEDGE: { get_new_knowledge(*(Uint16 *)(in_data+3)); } break; case HERE_YOUR_INVENTORY: { get_your_items(in_data+3); } break; case GET_NEW_INVENTORY_ITEM: { get_new_inventory_item(in_data+3); } break; case REMOVE_ITEM_FROM_INVENTORY: { remove_item_from_inventory(*((Uint8 *)(in_data+3))); } break; case INVENTORY_ITEM_TEXT: { put_small_text_in_box(&in_data[3],data_lenght-3,6*51+100,items_string); if(!(get_show_window(items_win)||get_show_window(trade_win))) { put_text_in_buffer(&in_data[3],data_lenght-3,0); } } break; case GET_KNOWLEDGE_TEXT: { put_small_text_in_box(&in_data[3],data_lenght-3,6*51+150,knowledge_string); } break; case CHANGE_MAP: { current_sector=-1; if(map_file_name[0]!=0) save_map(map_file_name); object_under_mouse=-1;//to prevent a nasty crash, while looking for bags, when we change the map close_dialogue(); // close the dialogue window if open destroy_all_particles(); if(!load_map(&in_data[4])){ // creating map if it does not exist int size=(in_data[3]&0x1f)<<4; new_map(size,size); dungeon=(in_data[3]&0x20)?1:0; strcpy(map_file_name,&in_data[4]); save_map(map_file_name); } kill_local_sounds(); #ifndef NO_MUSIC playing_music=0; #endif //NO_MUSIC get_map_playlist(); have_a_map=1; //also, stop the rain seconds_till_rain_starts=-1; seconds_till_rain_stops=-1; is_raining=0; rain_sound=0;//kill local sounds also kills the rain sound weather_light_offset=0; rain_light_offset=0; } break; case GET_TELEPORTERS_LIST: { add_teleporters_from_list(&in_data[3]); } break; case PLAY_MUSIC: { if(!no_sound)play_music(*((short *)(in_data+3))); } break; case PLAY_SOUND: { if(!no_sound)add_sound_object(*((short *)(in_data+3)),*((short *)(in_data+5)),*((short *)(in_data+7)),*((char *)(in_data+9)),*((short *)(in_data+10))); } break; case TELEPORT_OUT: { add_particle_sys_at_tile("./particles/teleport_in.part",*((short *)(in_data+3)),*((short *)(in_data+5))); if(!no_sound)add_sound_object(snd_tele_out,*((short *)(in_data+3)),*((short *)(in_data+5)),1,0); } break; case TELEPORT_IN: { add_particle_sys_at_tile("./particles/teleport_in.part",*((short *)(in_data+3)),*((short *)(in_data+5))); if(!no_sound)add_sound_object(snd_tele_in,*((short *)(in_data+3)),*((short *)(in_data+5)),1,0); } break; case LOG_IN_NOT_OK: { sprintf(log_in_error_str,"%s: %s",reg_error_str,invalid_pass); } break; case REDEFINE_YOUR_COLORS: { strcpy(log_in_error_str,redefine_your_colours); } break; case YOU_DONT_EXIST: { sprintf(log_in_error_str,"%s: %s",reg_error_str,char_dont_exist); } break; case CREATE_CHAR_NOT_OK: { sprintf(create_char_error_str,"%s: %s",reg_error_str,char_name_in_use); return; } break; case CREATE_CHAR_OK: { login_from_new_char(); } break; case YOU_ARE: { yourself=*((short *)(in_data+3)); } break; case START_RAIN: { seconds_till_rain_starts=*((Uint8 *)(in_data+3)); seconds_till_rain_stops=-1; } break; case STOP_RAIN: { seconds_till_rain_stops=*((Uint8 *)(in_data+3)); seconds_till_rain_starts=-1; } break; case THUNDER: { add_thunder(rand()%5,*((Uint8 *)(in_data+3))); } break; case SYNC_CLOCK: { server_time_stamp=*((int *)(in_data+3)); client_time_stamp=SDL_GetTicks(); client_server_delta_time=server_time_stamp-client_time_stamp; } break; case PONG: { Uint8 str[160]; sprintf(str,"%s: %i MS",server_latency, SDL_GetTicks()-*((Uint32 *)(in_data+3))); log_to_console(c_green1,str); } break; case UPGRADE_NEW_VERSION: { log_to_console(c_red1,update_your_client); log_to_console(c_red1,(char*)web_update_address); } break; case UPGRADE_TOO_OLD: { log_to_console(c_red1,client_ver_not_supported); log_to_console(c_red1,(char*)web_update_address); this_version_is_invalid=1; } break; case GET_NEW_BAG: { put_bag_on_ground(*((Uint16 *)(in_data+3)),*((Uint16 *)(in_data+5)),*((Uint8 *)(in_data+7))); } break; case GET_BAGS_LIST: { add_bags_from_list(&in_data[3]); } break; case SPAWN_BAG_PARTICLES: { add_particle_sys_at_tile("./particles/bag_in.part",*((Uint16 *)(in_data+3)),*((Uint16 *)(in_data+5))); } break; case GET_NEW_GROUND_ITEM: { get_bag_item(in_data+3); } break; case HERE_YOUR_GROUND_ITEMS: { get_bags_items_list(&in_data[3]); } break; case CLOSE_BAG: { hide_window(ground_items_win); } break; case REMOVE_ITEM_FROM_GROUND: { remove_item_from_ground(in_data[3]); } break; case DESTROY_BAG: { remove_bag(in_data[3]); } break; case NPC_TEXT: { put_small_text_in_box(&in_data[3],data_lenght-3,dialogue_menu_x_len-70,dialogue_string); display_dialogue(); if(in_data[3]>=127 && in_data[4]>=127) { add_questlog(&in_data[4],data_lenght-4); } } break; case SEND_NPC_INFO: { my_strcp(npc_name,&in_data[3]); cur_portrait=in_data[23]; } break; case NPC_OPTIONS_LIST: { build_response_entries(&in_data[3],*((Uint16 *)(in_data+1))); } break; case GET_TRADE_ACCEPT: { if(!in_data[3])trade_you_accepted=1; else trade_other_accepted=1; } break; case GET_TRADE_REJECT: { if(!in_data[3])trade_you_accepted=0; else trade_other_accepted=0; } break; case GET_TRADE_EXIT: { hide_window(trade_win); } break; case GET_YOUR_TRADEOBJECTS: { get_your_trade_objects(in_data+3); } break; case GET_TRADE_OBJECT: { put_item_on_trade(in_data+3); } break; case REMOVE_TRADE_OBJECT: { remove_item_from_trade(in_data+3); } break; case GET_TRADE_PARTNER_NAME: { get_trade_partner_name(&in_data[3],*((Uint16 *)(in_data+1))-1); } break; case GET_ACTOR_DAMAGE: { get_actor_damage(*((Uint16 *)(in_data+3)),in_data[5]); } break; case GET_ACTOR_HEAL: { get_actor_heal(*((Uint16 *)(in_data+3)),in_data[5]); } break; case ACTOR_UNWEAR_ITEM: { unwear_item_from_actor(*((Uint16 *)(in_data+3)),in_data[5]); } break; case ACTOR_WEAR_ITEM: { actor_wear_item(*((Uint16 *)(in_data+3)),in_data[5],in_data[6]); } break; case NPC_SAY_OVERTEXT: { add_displayed_text_to_actor( get_actor_ptr_from_id( *((Uint16 *)(in_data+3)) ), in_data+5 ); } break; case BUDDY_EVENT: { if(in_data[3]==1) add_buddy(&in_data[5],in_data[4],data_lenght-5); else if(in_data[3]==0) del_buddy(&in_data[4],data_lenght-4); } break; // BARREN MOON NEW MESSAGES case THIS_IS_ACTIVE_SECTOR: active_sector=*((Uint16 *)(in_data+3)); break; case GET_TILE_DATA: get_tile_data(in_data+3); break; case GET_3D_OBJECTS: get_3d_objects(in_data+3); break; case GET_2D_OBJECTS: get_2d_objects(in_data+3); break; case GET_LIGHT_OBJECTS: get_light_objects(in_data+3); break; case GET_PARTICLE_OBJECTS: get_particle_objects(in_data+3); break; case GET_3D_OBJECTS_FULL_ROTATION: get_3d_objects_full_rotation(in_data+3); break; case GET_CHECKSUMS: { actor *actor=pf_get_our_actor(); get_checksums(in_data+3, sector_get(actor->x_pos,actor->y_pos)); break; } case ADD_3D_OBJECT: add_3d_object(in_data+3); break; case ADD_3D_OBJECT_FULL_ROTATION: add_3d_object_fullrotation(in_data+3); break; case DELETE_3D_OBJECT: delete_3d_object(in_data+3); break; case REPLACE_3D_OBJECT: replace_3d_object(in_data+3); break; case ADD_2D_OBJECT: add_2d_object(in_data+3); break; case DELETE_2D_OBJECT: delete_2d_object(in_data+3); break; case REPLACE_2D_OBJECT: replace_2d_object(in_data+3); break; case ADD_LIGHT: add_lights(in_data+3); break; case DELETE_LIGHT: delete_light(in_data+3); break; case ADD_PARTICLE: add_particle(in_data+3); break; case DELETE_PARTICLE: delete_particle(in_data+3); break; case REPLACE_PARTICLE: replace_particle(in_data+3); break; default: { /* Unknown data type?? */; } break; } }
int main(void) { t_gravity_particles gravity_particles; t_particle_system* particle_system; t_particle* p; int i; show_msgbox( "Ndless - Particle System Demo", "------------------------\n" " Particle System Demo\n" \ "© 2010-2011 by the Ndless Team\n" "------------------------\n" "+ Add a particle\n" "- Remove a particle\n" "* Increase gravity\n" "/ Decrease gravity\n" "C Enable/Disable collision detection\n" "T Enable/Disable trace mode\n" "S Clear screen\n" "ESC - Exit" ); if (is_classic) { // programs are started with the screen cleared on non-classic void *scrbuf = malloc(SCREEN_BYTES_SIZE); memcpy(scrbuf, SCREEN_BASE_ADDRESS, SCREEN_BYTES_SIZE); for (i = 0; i < 0x0F; ++i) { fade(scrbuf, 1); sleep(70); if (isKeyPressed(KEY_NSPIRE_ESC)) { free(scrbuf); return 0; } } free(scrbuf); } clrscr(); lcd_ingray(); gravity_particles_construct(&gravity_particles, 0.00006672f, 100); particle_system = &(gravity_particles.particleSystem); particle_system->detectCol = false; particle_system->trace = false; particle_system_start(particle_system); p = particle_construct3(&(t_vector){0.f, 0.f, 0.f}, &(t_vector){0.f, 0.f, 0.f}, 1500.f, 4, BLACK); (void) particle_system_addParticle(particle_system, p); add_particle(&gravity_particles); while (!isKeyPressed(KEY_NSPIRE_ESC)) { gravity_particles_draw(&gravity_particles); // Add a particule (+) if (isKeyPressed(KEY_NSPIRE_PLUS)) { if (particle_system->nParticles == 0) { p = particle_construct3(&(t_vector){0.f, 0.f, 0.f}, &(t_vector){0.f, 0.f, 0.f}, 1500.f, 4, BLACK); (void) particle_system_addParticle(particle_system, p); } add_particle(&gravity_particles); while (isKeyPressed(KEY_NSPIRE_PLUS)); } // Remove a particle (-) if (isKeyPressed(KEY_NSPIRE_MINUS)) { remove_particle(&gravity_particles); while (isKeyPressed(KEY_NSPIRE_MINUS)); } // High gravity (*) if (isKeyPressed(KEY_NSPIRE_MULTIPLY)) { gravity_particles.gravitationalConstant *= 10.f; while (isKeyPressed(KEY_NSPIRE_MULTIPLY)); } // Low gravity (/) if (isKeyPressed(KEY_NSPIRE_DIVIDE)) { gravity_particles.gravitationalConstant /= 10.f; while (isKeyPressed(KEY_NSPIRE_DIVIDE)); } // Collision (C) if (isKeyPressed(KEY_NSPIRE_C)) { particle_system->detectCol = !particle_system->detectCol; while (isKeyPressed(KEY_NSPIRE_C)); } // Collision (T) if (isKeyPressed(KEY_NSPIRE_T)) { particle_system->trace = !particle_system->trace; while (isKeyPressed(KEY_NSPIRE_T)); } // Collision (S) if (isKeyPressed(KEY_NSPIRE_S)) { clearScreen(); while (isKeyPressed(KEY_NSPIRE_S)); } } gravity_particles_destruct(&gravity_particles); return 0; }