SmokeParticle::SmokeParticle(Effect* _effect, ParticleMover* _mover, const Vec3 _pos, const Vec3 _velocity, const color_t hue_adjust, const color_t saturation_adjust, const coord_t _sqrt_scale, const coord_t _max_size, const coord_t size_scalar, const alpha_t alpha_scale) : Particle(_effect, _mover, _pos, _velocity, size_scalar * (0.5f + randcoord())) { sqrt_scale = _sqrt_scale; max_size = _max_size; const color_t color_scale= square(randcolor(0.6)); color_t hue, saturation, value; hue = randcolor(1.0); // saturation = 1.0 - (color_scale + 0.15) / (0.15 + color_scale + square(randcolor(0.15))); saturation = color_scale; value = square(randcolor(0.15)) + color_scale + 0.15; // color[0] = square(randcolor(0.15)) + color_scale + 0.15; // color[1] = square(randcolor(0.15)) + color_scale + 0.15; // color[2] = square(randcolor(0.15)) + color_scale + 0.15; hue += hue_adjust; if (hue > 1.0) hue -= 1.0; saturation = std::min(1.0f, saturation * saturation_adjust); hsv_to_rgb(hue, saturation, value, color[0], color[1], color[2]); alpha = std::min(1.0f, (0.05f + randcoord(0.1f)) * alpha_scale); flare_max = 1.0; flare_exp = 1.0; flare_frequency = 1.0; state = 0; }
BagParticle::BagParticle(Effect* _effect, ParticleMover* _mover, const Vec3 _pos, const Vec3 _velocity, const coord_t _size) : Particle(_effect, _mover, _pos, _velocity, _size) { color[0] = randcolor(0.3) + 0.7; color[1] = randcolor(0.3) + 0.5; color[2] = randcolor(0.3) + 0.3; alpha = 0.75; flare_max = 1.0; flare_exp = 1.0; flare_frequency = 1.0; state = 0; }
CandleParticle::CandleParticle(Effect* _effect, ParticleMover* _mover, const Vec3 _pos, const Vec3 _velocity, const color_t hue_adjust, const color_t saturation_adjust, const float _scale, const Uint16 _LOD) : Particle(_effect, _mover, _pos, _velocity) { LOD = _LOD; color_t hue, saturation, value; hue = 0.03 + randcolor(0.08); saturation = 0.78; value = 0.9; hue += hue_adjust; if (hue > 1.0) hue -= 1.0; saturation *= saturation_adjust; if (saturation > 1.0) saturation = 1.0; hsv_to_rgb(hue, saturation, value, color[0], color[1], color[2]); size = 6.0 * (2.0 + randcoord()) / (LOD + 2); alpha = 0.4 * 5 / size / (LOD + 2); if (alpha > 1.0) alpha = 1.0; size *= _scale; flare_max = 1.0; flare_exp = 0.0; flare_frequency = 2.0; state = ((rand() % 3) == 0); }
SwordParticle::SwordParticle(Effect* _effect, ParticleMover* _mover, const Vec3 _pos, const Vec3 _velocity, const coord_t _size, const alpha_t _alpha, const color_t red, const color_t green, const color_t blue, TextureEnum _texture, const Uint16 _LOD) : Particle(_effect, _mover, _pos, _velocity, std::min(1.0f, _size * (0.2f + randcoord()))) { color[0] = std::max(0.0f, std::min(1.0f, red + randcolor(0.25f) - 0.125f)); color[1] = std::max(0.0f, std::min(1.0f, green + randcolor(0.25f) - 0.125f)); color[2] = std::max(0.0f, std::min(1.0f, blue + randcolor(0.25f) - 0.125f)); texture = _texture; alpha = _alpha; velocity /= size; flare_max = 1.6; flare_exp = 0.2; flare_frequency = 2.0; LOD = _LOD; }
// rshapes draws shapes with random colors, strokes, and sizes. void rshapes(int width, int height, int n) { int i, j, np = 10; VGfloat sx, sy, cx, cy, px, py, ex, ey, pox, poy; VGfloat polyx[np], polyy[np]; rseed(); Start(width, height); for (i = 0; i < n; i++) { Fill(randcolor(), randcolor(), randcolor(), drand48()); Ellipse(randf(width), randf(height), randf(200), randf(100)); Circle(randf(width), randf(height), randf(100)); Rect(randf(width), randf(height), randf(200), randf(100)); Arc(randf(width), randf(height), randf(200), randf(200), randf(360), randf(360)); sx = randf(width); sy = randf(height); Stroke(randcolor(), randcolor(), randcolor(), 1); StrokeWidth(randf(5)); Line(sx, sy, sx + randf(200), sy + randf(100)); StrokeWidth(0); sx = randf(width); sy = randf(height); ex = sx + randf(200); ey = sy; cx = sx + ((ex - sx) / 2.0); cy = sy + randf(100); Qbezier(sx, sy, cx, cy, ex, ey); sx = randf(width); sy = randf(height); ex = sx + randf(200); ey = sy; cx = sx + ((ex - sx) / 2.0); cy = sy + randf(100); px = cx; py = sy - randf(100); Cbezier(sx, sy, cx, cy, px, py, ex, ey); pox = randf(width); poy = randf(height); for (j = 0; j < np; j++) { polyx[j] = pox + randf(200); polyy[j] = poy + randf(100); } Polygon(polyx, polyy, np); pox = randf(width); poy = randf(height); for (j = 0; j < np; j++) { polyx[j] = pox + randf(200); polyy[j] = poy + randf(100); } Polyline(polyx, polyy, np); } Fill(128, 0, 0, 1); Text(20, 20, "OpenVG on the Raspberry Pi", 32); End(); }
MissileParticle::MissileParticle(Effect* _effect, ParticleMover* _mover, const Vec3 _pos, const Vec3 _velocity, const coord_t _size, const alpha_t _alpha, const color_t red, const color_t green, #ifdef NEW_TEXTURES const color_t blue, TextureEnum _texture, const Uint16 _LOD, #else /* NEW_TEXTURES */ const color_t blue, Texture* _texture, const Uint16 _LOD, #endif /* NEW_TEXTURES */ const MissileEffect::MissileType _type) : Particle(_effect, _mover, _pos, _velocity) { color[0] = red + randcolor(0.25) - 0.125; if (color[0] > 1.0) color[0] = 1.0; else if (color[0] < 0.0) color[0] = 0.0; color[1] = green + randcolor(0.25) - 0.125; if (color[1] > 1.0) color[1] = 1.0; else if (color[1] < 0.0) color[1] = 0.0; color[2] = blue + randcolor(0.25) - 0.125; if (color[2] > 1.0) color[2] = 1.0; else if (color[2] < 0.0) color[2] = 0.0; texture = _texture; size = std::max(1.0f, (float)(_size * (0.25 + randcoord(1.25)))); // size >= 1.0 alpha = std::max(0.25f, (float)_alpha); // at least 25% alpha velocity /= size; flare_max = 1.6; flare_exp = 0.2; flare_frequency = 2.0; LOD = _LOD; type = _type; }
void render_frame(pixel* pixels, int64_t frame_index) { int64_t pixel_index = 0; int64_t x = 0, y = 0, z = 0; if (frame_index % frames_per_layer == 0) { int i; for (i = spheres - 1; i > 0; i--) { sphere_colors[i] = sphere_colors[i - 1]; } sphere_colors[0] = randcolor(); } for (y = 0; y < depth; y++) { for (x = 0; x < width; x++) { for (z = 0; z < height; z++, pixel_index++) { render_pixel(pixels + pixel_index, frame_index, pixel_index, x, y, z, x / xd, y / yd, z / zd); } } } }
TeleporterParticle::TeleporterParticle(Effect* _effect, ParticleMover* _mover, const Vec3 _pos, const Vec3 _velocity, const color_t hue_adjust, const color_t saturation_adjust, const coord_t size_scalar) : Particle(_effect, _mover, _pos, _velocity, size_scalar * (0.5 + 1.5 * randcoord())) { color_t hue, saturation, value; hue = randcolor(1.0); saturation = randfloat(0.2); value = 0.9; hue += hue_adjust; if (hue > 1.0) hue -= 1.0; saturation = std::min(1.0f, saturation * saturation_adjust); hsv_to_rgb(hue, saturation, value, color[0], color[1], color[2]); alpha = std::min(1.0f, 5.0f / size); velocity /= size; flare_max = 1.6; flare_exp = 0.2; flare_frequency = 2.0; }
ImpactEffect::ImpactEffect(EyeCandy* _base, bool* _dead, Vec3* _pos, const Vec3 _angle, const ImpactType _type, const Uint16 _LOD, const float _strength) { if (EC_DEBUG) std::cout << "ImpactEffect (" << this << ") created." << std::endl; base = _base; dead = _dead; pos = _pos; center = *pos; angle = _angle; type = _type; LOD = base->last_forced_LOD; desired_LOD = _LOD; spawner = NULL; bounds = NULL; mover = NULL; strength = _strength; const coord_t size_scalar = strength * 1.3; const coord_t vel_scalar= std::sqrt(strength) * 0.44; switch (type) { case MAGIC_PROTECTION: { angle.normalize(2.0 * vel_scalar); mover = new ParticleMover(this); for (int i = 0; i < 50 * LOD; i++) { Vec3 velocity = -angle; Vec3 offset; offset.randomize(0.3); velocity += offset; Particle * p = new ImpactParticle(this, mover, center, velocity, 0.3 * size_scalar, 1.0, 0.7, 0.2, 0.4, EC_SHIMMER, LOD, type); if (!base->push_back_particle(p)) break; } break; } case SHIELD: { angle.normalize(2.0 * vel_scalar); mover = new ParticleMover(this); for (int i = 0; i < 50 * LOD; i++) { Vec3 velocity = -angle; Vec3 offset; offset.randomize(0.3); velocity += offset; Particle * p = new ImpactParticle(this, mover, center, velocity, 0.3 * size_scalar, 1.0, 0.9, 0.9, 0.9, EC_SHIMMER, LOD, type); if (!base->push_back_particle(p)) break; } break; } case MAGIC_IMMUNITY: { angle.normalize(2.5 * vel_scalar); mover = new ParticleMover(this); for (int i = 0; i < 50 * LOD; i++) { Vec3 velocity = -angle; Vec3 offset; offset.randomize(0.4); velocity += offset; Particle * p = new ImpactParticle(this, mover, center, velocity, 0.35 * size_scalar, 1.0, randcolor(1.0), randcolor(1.0), randcolor(1.0), EC_VOID, LOD, type); if (!base->push_back_particle(p)) break; } break; } case POISON: { angle.normalize(1.0 * vel_scalar); mover = new ParticleMover(this); for (int i = 0; i < 50 * LOD; i++) { Vec3 velocity = -angle; Vec3 offset; offset.randomize(0.7); velocity += offset; Particle* p; if (randfloat() < 0.4) { p = new ImpactParticle(this, mover, center, velocity, 0.6 * size_scalar, 0.5, 0.2 + randcolor(0.2), 0.5 + randcolor(0.3), 0.2, EC_FLARE, LOD, type); p->state = 1; } else { p = new ImpactParticle(this, mover, center, velocity, 0.3 * size_scalar, 1.0, randcolor(0.1), 0.2 + randcolor(0.1), 0.2, EC_WATER, LOD, type); p->state = 0; } if (!base->push_back_particle(p)) break; } break; } case BLOOD: { angle.normalize(0.8 * vel_scalar); mover = new SimpleGravityMover(this); for (int i = 0; i < 20 * LOD; i++) { Vec3 velocity = -angle; Vec3 offset; offset.randomize(0.7); // std::cout << velocity << ", " << angle << ", " << vel_scalar << std::endl; velocity += offset; velocity.normalize(0.8 * vel_scalar); // std::cout << velocity << std::endl; Particle * p = new ImpactParticle(this, mover, center, velocity, square(square(randcoord(0.85))) * size_scalar, 0.5, 0.3 + randcolor(0.7), 0.15 + randcolor(0.1), 0.15 + randcolor(0.1), EC_WATER, LOD, type); p->state = 1; if (!base->push_back_particle(p)) break; } break; } } }
bool MissileEffect::idle(const Uint64 usec) { if (particles.size() == 0) return false; const interval_t dist = (old_pos - *pos).magnitude(); const Vec3 direction = (old_pos - *pos).normalize(0.75); if (dist < 1E-4) return true; // do not add more particles, dist < 0.0001 for (float step = 0.0; step < dist; step += (0.1 / ((1.0 + (float)hitOrMiss) / 1.5))) { const percent_t percent = step / dist; Vec3 randshift; randshift.randomize(0.025 * (1.0 + (float)hitOrMiss / 2.0)); // random particle position change const Vec3 coords = (old_pos * percent) + (*pos * (1.0 - percent)) + randshift; Vec3 velocity; velocity.randomize(0.0625 * (1.0 + (float)hitOrMiss / 2.0)); // random particle movement velocity -= direction; // follow the missile Particle* p; if (type == MAGIC && randfloat() < 0.25) { p = new MissileParticle(this, mover, coords, velocity, size / 2 + randfloat (size / 2), 1.0, randcolor(), randcolor(), randcolor(), texture, LOD, type); base->push_back_particle(p); } p = new MissileParticle(this, mover, coords, velocity, size / 2 + randfloat (size / 2), alpha / 2 + randfloat(alpha / 2), color[0], color[1], color[2], texture, LOD, type); base->push_back_particle(p); } old_pos = *pos; return true; }
bool BreathEffect::idle(const Uint64 usec) { if (particles.size() == 0) return false; if (recall) return true; const Uint64 cur_time = get_time(); const Uint64 age = cur_time - born; if (age > 1100000) return true; count += usec; while (count > 0) { count -= count_scalar * (14 - LOD); Vec3 coords; Vec3 velocity; if (type == WIND) { coords = spawner->get_new_coords() * 2 + *pos; velocity.randomize(1.0 * scale); velocity += (*target - *pos) * 10.0; } else { coords = spawner->get_new_coords() + *pos; velocity.randomize(0.5 * scale); velocity += (*target - *pos) * 2.0; } switch (type) { case FIRE: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.6, 0.8 + randcolor(0.2), 0.4 + randcolor(0.4), randcolor(0.4), EC_FLARE, LOD, type); if (!base->push_back_particle(p)) return true; break; } case ICE: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.6, randcolor(0.4), 0.4 + randcolor(0.4), 0.8 + randcolor(0.2), EC_CRYSTAL, LOD, type); if (!base->push_back_particle(p)) return true; break; } case POISON: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.1, 0.9 + randcolor(0.1), 0.8 + randcolor(0.2), 0.6 + randcolor(0.2), EC_FLARE, LOD, type); if (!base->push_back_particle(p)) return true; break; } case MAGIC: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.6, randcolor(1.0), randcolor(1.0), randcolor(1.0), EC_TWINFLARE, LOD, type); if (!base->push_back_particle(p)) return true; break; } case LIGHTNING: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.25 * size_scalar, 0.6, 0.9 + randcolor(0.1), 0.85 + randcolor(0.15), 0.8 + randcolor(0.2), EC_FLARE, LOD, type); if (!base->push_back_particle(p)) return true; break; } case WIND: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.1, 0.8 + randcolor(0.2), 0.8 + randcolor(0.2), 0.8 + randcolor(0.2), EC_FLARE, LOD, type); if (!base->push_back_particle(p)) return true; break; } } } return true; }
BreathEffect::BreathEffect(EyeCandy* _base, bool* _dead, Vec3* _pos, Vec3* _target, std::vector<ec::Obstruction*>* _obstructions, const BreathType _type, const Uint16 _LOD, const percent_t _scale) { if (EC_DEBUG) std::cout << "BreathEffect (" << this << ") created." << std::endl; base = _base; dead = _dead; pos = _pos; target = _target; obstructions = _obstructions; type = _type; LOD = base->last_forced_LOD; desired_LOD = _LOD; scale = _scale; bounds = NULL; spawner = NULL; mover = NULL; count = 0; count_scalar = 3000 / LOD; size_scalar = scale * std::sqrt(LOD) / sqrt(10.0); spawner = new FilledSphereSpawner(scale / 3.0); mover = new SmokeMover(this, 10.0); while ((int)particles.size() < LOD * 64) { const Vec3 coords = spawner->get_new_coords() + *pos; Vec3 velocity; velocity.randomize(0.5); velocity += (*target - *pos) * 2.0; switch (type) { case FIRE: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.6, 0.8 + randcolor(0.2), 0.4 + randcolor(0.4), randcolor(0.4), EC_FLARE, LOD, type); if (!base->push_back_particle(p)) return; break; } case ICE: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.6, randcolor(0.4), 0.4 + randcolor(0.4), 0.8 + randcolor(0.2), EC_CRYSTAL, LOD, type); if (!base->push_back_particle(p)) return; break; } case POISON: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.1, randcolor(0.3), 0.8 + randcolor(0.2), randcolor(0.3), EC_WATER, LOD, type); if (!base->push_back_particle(p)) return; break; } case MAGIC: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.6, randcolor(1.0), randcolor(1.0), randcolor(1.0), EC_TWINFLARE, LOD, type); if (!base->push_back_particle(p)) return; break; } case LIGHTNING: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.25 * size_scalar, 0.6, 0.9 + randcolor(0.1), 0.85 + randcolor(0.15), 0.8 + randcolor(0.2), EC_FLARE, LOD, type); if (!base->push_back_particle(p)) return; break; } case WIND: { Particle * p = new BreathParticle(this, mover, coords, velocity, 0.5 * size_scalar, 0.6, 0.8 + randcolor(0.2), 0.8 + randcolor(0.2), 0.8 + randcolor(0.2), EC_FLARE, LOD, type); if (!base->push_back_particle(p)) return; break; } } } }
BreathSmokeParticle::BreathSmokeParticle(Effect* _effect, ParticleMover* _mover, const Vec3 _pos, const Vec3 _velocity, const coord_t _size, const alpha_t _alpha, TextureEnum _texture, const Uint16 _LOD, const BreathEffect::BreathType _type) : Particle(_effect, _mover, _pos, _velocity) { texture = _texture; type = _type; switch (type) { case BreathEffect::FIRE: { const color_t color_scale= randcolor(0.1); color[0] = randcolor(0.1) + color_scale; color[1] = randcolor(0.1) + color_scale; color[2] = randcolor(0.1) + color_scale; break; } case BreathEffect::ICE: { const color_t color_scale= randcolor(0.2); color[0] = 0.3 + randcolor(0.1) + color_scale; color[1] = 0.3 + randcolor(0.1) + color_scale; color[2] = 1.0; break; } case BreathEffect::POISON: { const color_t color_scale= randcolor(0.1); color[0] = randcolor(0.0) + color_scale; color[1] = randcolor(0.0) + color_scale; color[2] = randcolor(0.0) + color_scale; texture = EC_SIMPLE; break; } case BreathEffect::MAGIC: { color[0] = randcolor(0.35); color[1] = randcolor(0.35); color[2] = randcolor(0.35); break; } case BreathEffect::LIGHTNING: // Impossible; lightning doesn't use smoke. { break; } case BreathEffect::WIND: { const color_t color_scale= randcolor(0.4); color[0] = randcolor(0.1) + color_scale; color[1] = randcolor(0.1) + color_scale; color[2] = randcolor(0.1) + color_scale; break; } } size = _size * (0.5 + randcoord()) * 10 / _LOD; alpha = _alpha; flare_max = 1.0; flare_exp = 1.0; flare_frequency = 1.0; state = 0; }
int main(int argc, char** argv) { width = 12, depth = 8, height = 60; xd = (width - 1) / 2.4; yd = (depth - 1) / 1.6; zd = (height - 1) / 2.0; xl = (width - 1) / xd; yl = (depth - 1) / yd; zl = (height - 1) / zd; total_leds = width * depth * height; channel = 0; fps = 60; period_x = xl / (2 * M_PI); speed_x = 1.0 / fps; period_y = yl / (2 * M_PI); speed_y = 0.9 / fps; period_z = zl / (2 * M_PI); speed_z = 0.8 / fps; sphere_r = .3; spheres = sqrt(pow(xl/2, 2) + pow(yl/2, 2) + pow(zl/2, 2)) / sphere_r; spheres += 2; frames_per_layer = fps / 2; pixel l_sphere_colors[spheres]; sphere_colors = l_sphere_colors; int i; for (i = 0; i < spheres; i++) { sphere_colors[i] = randcolor(); } pixel pixels[total_leds + 1]; opc_sink s; if (argc < 2) { fprintf(stderr, "Usage: %s <server>[:<port>]\n", argv[0]); return 1; } s = opc_new_sink(argv[1]); int64_t frame_index = 0; int64_t start = now(); struct fps_queue fpsq; int64_t frames[total_leds]; fpsq.samples = fps; fpsq.pos = 0; fpsq.frames = frames; while (1) { sleep_until(start + 1000000 * frame_index / fps); render_frame(pixels, frame_index); if (!opc_put_pixels(s, channel, total_leds, pixels)) { break; } record_frame(&fpsq); if (fpsq.pos == 0) { double cur_fps = (fpsq.samples - 1) / (get_elapsed(&fpsq) / 1000000.0); printf("fps: %.2f (%.2f Mbps)\n", cur_fps, total_leds * 24 * cur_fps / 1000000.0); } frame_index++; } printf("fps: %f\n", frame_index / 5.0); }
MineEffect::MineEffect(EyeCandy* _base, bool* _dead, Vec3* _pos, const MineType _type, const Uint16 _LOD) { if (EC_DEBUG) std::cout << "MineEffect (" << this << ") created (" << type << ")." << std::endl; base = _base; dead = _dead; pos = _pos; effect_center = *pos; type = _type; LOD = base->last_forced_LOD; desired_LOD = _LOD; spawner = NULL; bounds = NULL; mover = NULL; spawner2 = NULL; mover2 = NULL; switch (type) { case DETONATE_MAGIC_IMMUNITY_REMOVAL: { spawner = new FilledSphereSpawner(0.1); mover = new ParticleMover(this); while ((int)particles.size() < LOD * 150) { const Vec3 coords = spawner->get_new_coords() + effect_center; Vec3 velocity; velocity.randomize(0.5); velocity.y = 0.2; Particle * p = #ifdef NEW_TEXTURES new MineParticle(this, mover, coords, velocity, 0.2, 1.0, 3.0, 3.0, 3.0, EC_SIMPLE, LOD, type); #else /* NEW_TEXTURES */ new MineParticle(this, mover, coords, velocity, 0.2, 1.0, 3.0, 3.0, 3.0, &(base->TexSimple), LOD, type); #endif /* NEW_TEXTURES */ if (!base->push_back_particle(p)) break; } break; } case DETONATE_UNINVIZIBILIZER: { effect_center.y += 1.8; spawner = new HollowDiscSpawner(0.3); mover = new ParticleMover(this); while ((int)particles.size() < LOD * 200) { Vec3 coords = spawner->get_new_coords(); Vec3 velocity; velocity.randomize(); velocity.normalize(0.2); coords += effect_center; coords.y = randfloat(1.8); Particle * p = #ifdef NEW_TEXTURES new MineParticle(this, mover, coords, velocity, 1.2, 1.0, 3.0, 3.0, 3.0, EC_SIMPLE, LOD, type); #else /* NEW_TEXTURES */ new MineParticle(this, mover, coords, velocity, 1.2, 1.0, 3.0, 3.0, 3.0, &(base->TexSimple), LOD, type); #endif /* NEW_TEXTURES */ if (!base->push_back_particle(p)) break; } break; } case DETONATE_MANA_DRAINER: { effect_center.y += 1.6; spawner = new HollowDiscSpawner(0.3); mover = new SimpleGravityMover(this); while ((int)particles.size() < LOD * 50) { const Vec3 coords = spawner->get_new_coords() + effect_center; Vec3 velocity; velocity.randomize(); velocity.normalize(0.2); Particle * p = #ifdef NEW_TEXTURES new MineParticle(this, mover, coords, velocity, 0.3, 1.0, 0.8, 0.35, 0.7, EC_SIMPLE, LOD, type); #else /* NEW_TEXTURES */ new MineParticle(this, mover, coords, velocity, 0.3, 1.0, 0.8, 0.35, 0.7, &(base->TexSimple), LOD, type); #endif /* NEW_TEXTURES */ if (!base->push_back_particle(p)) break; } break; } case DETONATE_MANA_BURNER: { effect_center.y += 1.0; spawner = new FilledSphereSpawner(0.5); mover = new GravityMover(this, &effect_center, 8e9); while ((int)particles.size() < LOD * 100) { const Vec3 coords = spawner->get_new_coords() + effect_center; Vec3 velocity; velocity.randomize(); velocity.normalize(0.9); Particle * p = #ifdef NEW_TEXTURES new MineParticle(this, mover, coords, velocity, 0.5, 0.5, 0.8, 0.35, 0.7, EC_TWINFLARE, LOD, type); #else /* NEW_TEXTURES */ new MineParticle(this, mover, coords, velocity, 0.5, 0.5, 0.8, 0.35, 0.7, &(base->TexTwinflare), LOD, type); #endif /* NEW_TEXTURES */ if (!base->push_back_particle(p)) break; } break; } case DETONATE_CALTROP: case DETONATE_CALTROP_POISON: { effect_center.y += 0.05; mover = new SimpleGravityMover(this); spawner = new HollowSphereSpawner(0.1); for (int i = 0; i < LOD * 10; i++) { const Vec3 coords = spawner->get_new_coords() + effect_center; const Vec3 velocity(0.0, 5.0, 0.0); #ifdef NEW_TEXTURES Particle* p = new MineParticle(this, mover, coords, velocity, 0.75, 0.6, 0.4, (type == DETONATE_CALTROP ? 0.3 : 0.5), 0.3, EC_TWINFLARE, LOD, type); #else /* NEW_TEXTURES */ Particle* p = new MineParticle(this, mover, coords, velocity, 0.75, 0.6, 0.4, (type == DETONATE_CALTROP ? 0.3 : 0.5), 0.3, &(base->TexTwinflare), LOD, type); #endif /* NEW_TEXTURES */ p->state = 1; if (!base->push_back_particle(p)) break; } break; } case DETONATE_TRAP: { effect_center.y += 1.25; mover = new OrbitalMover(this, effect_center); spawner = new HollowSphereSpawner(1.25); Particle* p; for (int i = 0; i < LOD * 100; i++) { Vec3 c = effect_center; c.y = -0.3 + (i * 0.05); Vec3 vel; vel.randomize(); vel.normalize(2.0); vel *= randfloat() * 4.0; #ifdef NEW_TEXTURES p = new MineParticle(this, mover, c, vel, 0.2, 1.0, 1.0, 1.0, 1.0, EC_VOID, LOD, type); #else /* NEW_TEXTURES */ p = new MineParticle(this, mover, c, vel, 0.2, 1.0, 1.0, 1.0, 1.0, &(base->TexVoid), LOD, type); #endif /* NEW_TEXTURES */ if (!base->push_back_particle(p)) break; dynamic_cast<OrbitalMover*>(mover)->setParticleData(p, OrbitalParticleData(i, 10, 0.45, 10) ); } break; } case DETONATE_TYPE1_SMALL: case DETONATE_TYPE1_MEDIUM: case DETONATE_TYPE1_LARGE: { spawner = new FilledSphereSpawner(0.1); mover = new ParticleMover(this); const float scale = (type == DETONATE_TYPE1_SMALL ? 0.75 : type == DETONATE_TYPE1_MEDIUM ? 1.25 : 2.0); Vec3 wind; wind.randomize(); wind.normalize(0.25); wind.y = 0; for (int i = 0; i < LOD * 100 * scale; i++) { Vec3 coords = spawner->get_new_coords(); Vec3 velocity = coords * 10.0 * sqrt(scale); velocity.y = fabs(velocity.y) * 3.0f; coords += effect_center; coords.y -= 0.1; #ifdef NEW_TEXTURES Particle * p = new MineParticleFire(this, mover, coords, velocity, 0.5, 1.0, 1.0, randcolor(0.75), 0.0, EC_FLARE, LOD); #else /* NEW_TEXTURES */ Particle * p = new MineParticleFire(this, mover, coords, velocity, 0.5, 1.0, 1.0, randcolor(0.75), 0.0, &(base->TexFlare), LOD); #endif /* NEW_TEXTURES */ if (!base->push_back_particle(p)) break; } spawner = new FilledSphereSpawner(0.5 * std::sqrt(scale)); for (int i = 0; i < LOD * 32 * scale; i++) { Vec3 coords = spawner->get_new_coords(); Vec3 velocity; coords += effect_center; float grey = randcolor(0.5); velocity.randomize(); velocity.normalize(0.25 * scale); velocity.y = fabs(velocity.y) * 6.0f; velocity += wind; #ifdef NEW_TEXTURES Particle *p = new MineParticleSmoke(this, mover, coords, velocity, 3.0 + randcoord(3.0 * scale), 0.0, grey, grey, grey, EC_SIMPLE, LOD); #else /* NEW_TEXTURES */ Particle *p = new MineParticleSmoke(this, mover, coords, velocity, 3.0 + randcoord(3.0 * scale), 0.0, grey, grey, grey, &(base->TexSimple), LOD); #endif /* NEW_TEXTURES */ if (!base->push_back_particle(p)) break; } break; } } }
HarvestingEffect::HarvestingEffect(EyeCandy* _base, bool* _dead, Vec3* _pos, const HarvestingType _type, const Uint16 _LOD) { if (EC_DEBUG) std::cout << "HarvestingEffect (" << this << ") created (" << type << ")." << std::endl; base = _base; dead = _dead; pos = _pos; effect_center = *pos; type = _type; LOD = base->last_forced_LOD; desired_LOD = _LOD; spawner = NULL; bounds = NULL; mover = NULL; spawner2 = NULL; mover2 = NULL; direction = Vec3(0.0, 0.0, 0.0); switch (type) { case TOOL_BREAK: { // handled in other constructor break; } case RADON_POUCH: { effect_center.y += 0.5; spawner = new FilledSphereSpawner(0.9); mover = new GravityMover(this, &effect_center, 8e9); while ((int)particles.size() < LOD * 50) { const Vec3 coords = spawner->get_new_coords() + effect_center; Vec3 velocity; velocity.randomize(); velocity.normalize(0.8); Particle * p = new HarvestingParticle(this, mover, coords, velocity, 5.25, 0.5, 0.6, 0.7, 0.2, EC_FLARE, LOD, type); p->state = 0; if (!base->push_back_particle(p)) break; } while ((int)particles.size() < LOD * 100) { const Vec3 coords = spawner->get_new_coords() + effect_center; Vec3 velocity; velocity.randomize(); velocity.normalize(1.5); Particle * p = new HarvestingParticle(this, mover, coords, velocity, 4.5, 0.5 + randalpha(0.4), 0.7, 0.6, 0.5, EC_WATER, LOD, type); p->state = 1; if (!base->push_back_particle(p)) break; } break; } case CAVERN_WALL: { effect_center.y += 15.0; spawner = new FilledSphereSpawner(1.0); mover = new ParticleMover(this); while ((int)particles.size() < LOD * 50) { Vec3 coords = spawner->get_new_coords(); coords.y *= 8.0; Vec3 velocity; velocity.randomize(); velocity.normalize(0.2); velocity.y *= 3.0; velocity.y -= 9.0; coords += effect_center; const color_t scalar= randcolor(0.4); Particle * p = new HarvestingParticle(this, mover, coords, velocity, 8.0 + randcoord(12.0), 1.0, scalar + randcolor(0.1), scalar + randcolor(0.1), scalar + randcolor(0.1), EC_SIMPLE, LOD, type); if (!base->push_back_particle(p)) break; } while ((int)particles.size() < LOD * 100) { Vec3 coords = spawner->get_new_coords(); coords.y *= 8.0; Vec3 velocity; velocity.randomize(); velocity.normalize(0.2); velocity.y *= 3.0; velocity.y -= 9.0; coords += effect_center; Particle * p = new HarvestingParticle(this, mover, coords, velocity, 3.0 + randcoord(6.0), 0.4 + randalpha(0.4), 0.2 + randcolor(0.2), 0.2 + randcolor(0.2), 0.2 + randcolor(0.2), EC_WATER, LOD, type); if (!base->push_back_particle(p)) break; } break; } case MOTHER_NATURE: { effect_center.y += 0.2; spawner = new HollowDiscSpawner(0.1); mover = new SpiralMover(this, &effect_center, 18.0, 11.0); while ((int)particles.size() < LOD * 100) { const Vec3 coords = spawner->get_new_coords() + effect_center; Vec3 velocity; velocity.randomize(0.3); velocity.y *= 3; velocity.y += 1.4; Particle * p = new HarvestingParticle(this, mover, coords, velocity, 3.0, 0.2, 1.0, 0.5 + randcolor(0.5), 0.5, EC_TWINFLARE, LOD, type); if (!base->push_back_particle(p)) break; } break; } case QUEEN_OF_NATURE: { effect_center.y += 0.2; spawner = new FilledDiscSpawner(0.5); mover = new ParticleMover(this); while ((int)particles.size() < LOD * 100) { Vec3 coords = spawner->get_new_coords() + effect_center; coords.y += (coord_t)(randfloat(2.0) * randfloat(2.0) * randfloat(2.0)); const Vec3 velocity(0.0, 0.0, 0.0); Particle * p = new HarvestingParticle(this, mover, coords, velocity, 2.0 + randcoord(1.0), 1.0, randcolor(1.0), randcolor(1.0), randcolor(1.0), EC_SHIMMER, LOD, type); if (!base->push_back_particle(p)) break; } break; } case BEES: { spawner = new FilledSphereSpawner(0.75); mover = new GravityMover(this, &effect_center, 8e9); direction.randomize(); direction.y = 0; while ((int)particles.size() < LOD * 4) { const Vec3 coords = spawner->get_new_coords() + effect_center - direction; Vec3 velocity; velocity.randomize(); velocity.normalize(0.75); velocity.x += randfloat(direction.x); velocity.z += randfloat(direction.z); Particle * p = new HarvestingParticle(this, mover, coords, velocity, 0.5 + randfloat(0.25), 1.0, 0.9, 0.7, 0.3, EC_TWINFLARE, LOD, type); if (!base->push_back_particle(p)) break; } break; } case BAG_OF_GOLD: { mover = new GravityMover(this, &effect_center, 2e10); spawner = new HollowSphereSpawner(0.3); for (int i = 0; i < LOD * 60; i++) { Vec3 coords = spawner->get_new_coords(); const Vec3 velocity = coords / 10.0; coords += effect_center; Particle* p = new HarvestingParticle(this, mover, coords, velocity, 1.05, 0.75, randcolor(0.3) + 0.7, randcolor(0.3) + 0.5, randcolor(0.3) + 0.3, EC_FLARE, LOD, type); p->state = 1; if (!base->push_back_particle(p)) break; } Particle* p = new HarvestingParticle(this, mover, effect_center, Vec3(0.0, 0.0, 0.0), 8.0, 1.0, 0.8, 0.7, 0.3, EC_SHIMMER, LOD, type); base->push_back_particle(p); break; } case RARE_STONE: { mover = new ParticleMover(this); spawner = new HollowSphereSpawner(0.3); for (int i = 0; i < LOD * 60; i++) { Vec3 coords = spawner->get_new_coords(); const Vec3 velocity = coords / 10.0; coords += effect_center; Particle* p = new HarvestingParticle(this, mover, coords, velocity, 0.75, 0.05, randcolor(0.3) + 0.7, randcolor(0.3) + 0.5, randcolor(0.3) + 0.3, EC_FLARE, LOD, type); p->state = 1; if (!base->push_back_particle(p)) break; } Particle* p = new HarvestingParticle(this, mover, effect_center, Vec3(0.0, 0.0, 0.0), 7.5, 1.0, 1.0, 1.0, 1.0, EC_VOID, LOD, type); if (!base->push_back_particle(p)) break; p = new HarvestingParticle(this, mover, effect_center, Vec3(0.0, 0.01, 0.0), 7.5, 1.0, 1.0, 1.0, 1.0, EC_VOID, LOD, type); base->push_back_particle(p); break; } } }