/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: hdavid, amaechler */ #include "rain_effect.h" #include "util/loading/load_param.h" #include "util/loading/factory.h" #include "util/loading/resource_manager.h" #include "glincl.h" #include "p_node.h" #include "state.h" #include "spark_particles.h" #include "plane_emitter.h" #include "shell_command.h" #include "light.h" #include "parser/tinyxml/tinyxml.h" SHELL_COMMAND(activate, RainEffect, activateRain); SHELL_COMMAND(deactivate, RainEffect, deactivateRain); SHELL_COMMAND(startraining, RainEffect, startRaining); SHELL_COMMAND(stopraining, RainEffect, stopRaining); using namespace std; CREATE_FACTORY(RainEffect, CL_RAIN_EFFECT); // TODO: Dim Light with Rain, Finish preCaching, check out if multiple rain emitters work, Think about what happens with building poss. to hang movewithcam off, benchmark, possible to activate lightening, turn off visibility when in a building, variable emitter size depending on playable, also rain velocity RainEffect::RainEffect(const TiXmlElement* root) { this->setClassID(CL_RAIN_EFFECT, "RainEffect"); this->init(); if (root != NULL) this->loadParams(root); //load rain sound if (this->rainBuffer != NULL) ResourceManager::getInstance()->unload(this->rainBuffer); this->rainBuffer = (OrxSound::SoundBuffer*)ResourceManager::getInstance()->load("sound/atmosphere/rain.wav", WAV); //load wind sound if (this->rainWindForce != 0) { if (this->windBuffer != NULL) ResourceManager::getInstance()->unload(this->windBuffer); this->windBuffer = (OrxSound::SoundBuffer*)ResourceManager::getInstance()->load("sound/atmosphere/wind.wav", WAV); } if(rainActivate) this->activate(); } RainEffect::~RainEffect() { this->deactivate(); if (this->rainBuffer != NULL) ResourceManager::getInstance()->unload(this->rainBuffer); if (this->windBuffer != NULL) ResourceManager::getInstance()->unload(this->windBuffer); } void RainEffect::loadParams(const TiXmlElement* root) { WeatherEffect::loadParams(root); LoadParam(root, "coord", this, RainEffect, setRainCoord); LoadParam(root, "size", this, RainEffect, setRainSize); LoadParam(root, "rate", this, RainEffect, setRainRate); LoadParam(root, "velocity", this, RainEffect, setRainVelocity); LoadParam(root, "life", this, RainEffect, setRainLife); LoadParam(root, "wind", this, RainEffect, setRainWind); LoadParam(root, "fadeinduration", this, RainEffect, setRainFadeIn); LoadParam(root, "fadeoutduration", this, RainEffect, setRainFadeOut); LOAD_PARAM_START_CYCLE(root, element); { LoadParam_CYCLE(element, "option", this, RainEffect, setRainOption); } LOAD_PARAM_END_CYCLE(element); } bool RainEffect::init() { //Default values this->rainActivate = false; this->rainMove = false; this->rainCoord = Vector(500, 500, 500); this->rainSize = Vector2D(1000, 1000); this->rainRate = 4000; this->rainVelocity = -300; this->rainLife = 4; this->rainMaxParticles = this->rainRate * this->rainLife; this->rainWindForce = 0; this->rainFadeInDuration = 0; this->rainFadeOutDuration = 0; this->localTimer = 0; this->soundRainVolume = 0.8f; this->emitter = new PlaneEmitter(this->rainSize); lightMan = LightManager::getInstance(); this->rainAmbient = lightMan->getAmbientColor(); return 0; } SparkParticles* RainEffect::rainParticles = NULL; bool RainEffect::activate() { PRINTF(0)( "Activating RainEffect, coord: %f, %f, %f, size: %f, %f, rate: %f, velocity: %f, moveRain: %s\n", this->rainCoord.x, this->rainCoord.y, this->rainCoord.z, this->rainSize.x, this-> rainSize.y, this->rainRate, this->rainVelocity, this->rainMove ? "true" : "false" ); this->rainActivate = true; if (unlikely(RainEffect::rainParticles == NULL)) { RainEffect::rainParticles = new SparkParticles((int) this->rainMaxParticles); RainEffect::rainParticles->setName("RainParticles"); RainEffect::rainParticles->precache((int)this->rainLife); RainEffect::rainParticles->setLifeSpan(this->rainLife, 2); RainEffect::rainParticles->setRadius(0, 0.03); RainEffect::rainParticles->setRadius(0.2, 0.02); RainEffect::rainParticles->setRadius(1, 0.01); RainEffect::rainParticles->setColor(0, 0.3, 0.3, 0.5, 0.2); // grey blue 1 RainEffect::rainParticles->setColor(0.5, 0.4, 0.4, 0.5, 0.2); // grey blue 2 RainEffect::rainParticles->setColor(1, 0.7, 0.7, 0.7, 0.2); // light grey } this->emitter->setSystem(RainEffect::rainParticles); this->emitter->setRelCoor(this->rainCoord); this->emitter->setEmissionRate(this->rainRate); this->emitter->setEmissionVelocity(this->rainVelocity); this->emitter->setSpread(this->rainWindForce / 50, 0.2); this->soundSource.loop(this->rainBuffer, this->soundRainVolume); if (this->rainWindForce != 0) this->soundSource.loop(this->windBuffer, 0.1f * this->rainWindForce); lightMan->setAmbientColor(.1,.1,.1); return 0; } bool RainEffect::deactivate() { PRINTF(0)("Deactivating RainEffect\n"); this->rainActivate = false; this->emitter->setSystem(NULL); // Stop Sound this->soundSource.stop(); // Restore Light Ambient lightMan->setAmbientColor(this->rainAmbient, this->rainAmbient, this->rainAmbient); return 0; } void RainEffect::tick (float dt) { if (!this->rainActivate) return; if (this->rainMove) { this->rainCoord = State::getCameraNode()->getAbsCoor(); this->emitter->setRelCoor(this->rainCoord.x , this->rainCoord.y+800, this->rainCoord.z); } if (this->rainFadeInDuration != 0 && this->localTimer < this->rainFadeInDuration) { this->localTimer += dt; float progress = this->localTimer / this->rainFadeInDuration; // Dim Light lightMan->setAmbientColor(1.1 - progress, 1.1 - progress, 1.1 - progress); // use alpha in color to fade in RainEffect::rainParticles->setColor(0, 0.3, 0.3, 0.5, 0.2 * progress); // grey blue 1 RainEffect::rainParticles->setColor(0.5, 0.4, 0.4, 0.5, 0.2 * progress); // grey blue 2 RainEffect::rainParticles->setColor(1, 0.7, 0.7, 0.7, 0.2 * progress); // light grey // increase radius for more "heavy" rain RainEffect::rainParticles->setRadius(0, 0.03 * progress); RainEffect::rainParticles->setRadius(0.2, 0.02 * progress); RainEffect::rainParticles->setRadius(1, 0.01 * progress); // increase sound volume // this->soundSource.fadein(this->rainBuffer, 10); } else if (this->rainFadeOutDuration != 0 && this->localTimer < this->rainFadeOutDuration) { this->localTimer += dt; float progress = 1 - (this->localTimer / this->rainFadeOutDuration); // Dim Light lightMan->setAmbientColor(1.1 - progress, 1.1 - progress, 1.1 - progress); // use alpha in color to fade in RainEffect::rainParticles->setColor(0, 0.3, 0.3, 0.5, 0.2 * progress); // grey blue 1 RainEffect::rainParticles->setColor(0.5, 0.4, 0.4, 0.5, 0.2 * progress); // grey blue 2 RainEffect::rainParticles->setColor(1, 0.7, 0.7, 0.7, 0.2 * progress); // light grey // increase radius for more "heavy" rain RainEffect::rainParticles->setRadius(0, 0.03 * progress); RainEffect::rainParticles->setRadius(0.2, 0.02 * progress); RainEffect::rainParticles->setRadius(1, 0.01 * progress); // increase sound volume // this->soundSource.fadein(this->rainBuffer, 10); } } void RainEffect::startRaining() { if (this->rainActivate) this->deactivate(); if (!this->rainFadeInDuration > 0) this->rainFadeInDuration = 20; this->localTimer = 0; this->activate(); } void RainEffect::stopRaining() { if (this->rainActivate) this->deactivate(); if (!this->rainFadeOutDuration > 0) this->rainFadeOutDuration = 20; this->localTimer = 0; this->activate(); }