ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

explodingimage.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/visual/explodingimage.h"
00024 
00025 #include "common/random.h"
00026 #include "graphics/surface.h"
00027 
00028 #include "engines/stark/gfx/driver.h"
00029 #include "engines/stark/gfx/surfacerenderer.h"
00030 #include "engines/stark/gfx/texture.h"
00031 
00032 #include "engines/stark/services/global.h"
00033 #include "engines/stark/services/services.h"
00034 #include "engines/stark/services/settings.h"
00035 
00036 namespace Stark {
00037 
00038 VisualExplodingImage::VisualExplodingImage(Gfx::Driver *gfx) :
00039         Visual(TYPE),
00040         _gfx(gfx),
00041         _texture(nullptr),
00042         _surface(nullptr),
00043         _originalWidth(0),
00044         _originalHeight(0) {
00045     _surfaceRenderer = _gfx->createSurfaceRenderer();
00046 }
00047 
00048 VisualExplodingImage::~VisualExplodingImage() {
00049     if (_surface) {
00050         _surface->free();
00051     }
00052     delete _surface;
00053     delete _texture;
00054     delete _surfaceRenderer;
00055 }
00056 
00057 void VisualExplodingImage::initFromSurface(const Graphics::Surface *surface, uint originalWidth, uint originalHeight) {
00058     assert(!_surface && !_texture);
00059 
00060     _surface = new Graphics::Surface();
00061     _surface->copyFrom(*surface);
00062     _originalWidth  = originalWidth;
00063     _originalHeight = originalHeight;
00064 
00065     _texture = _gfx->createTexture(_surface);
00066     _texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
00067 
00068     // Create an explosion unit for each pixel in the surface
00069     _units.resize(_surface->w * _surface->h);
00070 
00071     Common::Point explosionCenter(_surface->w / 2, _surface->h / 2);
00072     Common::Point explosionAmplitude(48, 16);
00073     explosionAmplitude.x *= _surface->w / (float)originalWidth;
00074     explosionAmplitude.y *= _surface->h / (float)originalHeight;
00075 
00076     uint index = 0;
00077     for (uint y = 0; y < _surface->h; y++) {
00078         for (uint x = 0; x < _surface->w; x++, index++) {
00079             _units[index].setPosition(x, y);
00080             _units[index].setExplosionSettings(explosionCenter, explosionAmplitude, _surface->w / (float)originalWidth);
00081             _units[index].setColor(*static_cast<uint32 *>(_surface->getBasePtr(x, y)), _surface->format);
00082         }
00083     }
00084 }
00085 
00086 void VisualExplodingImage::render(const Common::Point &position) {
00087     // Fill with transparent color
00088     _surface->fillRect(Common::Rect(_surface->w, _surface->h), 0);
00089 
00090     for (uint i = 0; i < _units.size(); i++) {
00091         _units[i].update();
00092         _units[i].draw(_surface);
00093     }
00094 
00095     _texture->update(_surface);
00096     _surfaceRenderer->render(_texture, position, _originalWidth, _originalHeight);
00097 }
00098 
00099 VisualExplodingImage::ExplosionUnit::ExplosionUnit() :
00100         _scale(1.f),
00101         _stillImageTimeRemaining(33 * 33),
00102         _explosionFastAccelerationTimeRemaining(25 * 33),
00103         _mainColor(0),
00104         _darkColor(0) {
00105 
00106 }
00107 
00108 void VisualExplodingImage::ExplosionUnit::setPosition(int x, int y) {
00109     _position = Math::Vector2d(x, y);
00110 }
00111 
00112 void VisualExplodingImage::ExplosionUnit::setExplosionSettings(const Common::Point &center, const Common::Point &amplitude, float scale) {
00113     _center = Math::Vector2d(center.x, center.y);
00114 
00115     _speed.setX(cos(StarkRandomSource->getRandomNumber(M_PI * 100)) * (float)amplitude.x);
00116     _speed.setY(sin(StarkRandomSource->getRandomNumber(M_PI * 100)) * (float)amplitude.y);
00117 
00118     // WTF, ensuring all fragments go in the same direction?
00119     float magnitude = _position.getDistanceTo(_speed);
00120     _speed -= _position;
00121     _speed = _speed / _speed.getMagnitude() * -magnitude;
00122     _scale = scale;
00123 }
00124 
00125 void VisualExplodingImage::ExplosionUnit::setColor(uint32 color, const Graphics::PixelFormat &format) {
00126     _mainColor = color;
00127 
00128     byte a, r, g, b;
00129     format.colorToARGB(color, a, r, g, b);
00130     r >>= 1;
00131     g >>= 1;
00132     b >>= 1;
00133 
00134     _darkColor = format.ARGBToColor(a, r, g, b);
00135 }
00136 
00137 void VisualExplodingImage::ExplosionUnit::update() {
00138     if (_stillImageTimeRemaining > 0) {
00139         _stillImageTimeRemaining -= StarkGlobal->getMillisecondsPerGameloop();
00140         return;
00141     }
00142 
00143     if (_position.getDistanceTo(_center) <= 1.f * _scale) {
00144         // Units near the center stay there (to make it look like they enter the chest)
00145         return;
00146     }
00147 
00148     Math::Vector2d speed = _speed.getNormalized() * 0.6f * _scale;
00149     _position += speed;
00150 
00151     // Update the acceleration to units move towards the center
00152     Math::Vector2d acceleration = _center - _position;
00153     if (_explosionFastAccelerationTimeRemaining > 0) {
00154         acceleration *= 3.0f;
00155         _explosionFastAccelerationTimeRemaining -= StarkGlobal->getMillisecondsPerGameloop();
00156     }
00157 
00158     _speed += acceleration;
00159     _speed -= speed * 2.5f;
00160 }
00161 
00162 void VisualExplodingImage::ExplosionUnit::draw(Graphics::Surface *surface) {
00163     if (_position.getX() <= 1.f || _position.getX() >= surface->w - 1
00164             || _position.getY() <= 1.f || _position.getY() >= surface->h - 1) {
00165         return; // Ignore units outside of the surface
00166     }
00167 
00168     if (_stillImageTimeRemaining <= 0 && _position.getDistanceTo(_center) <= 2.f) {
00169         return; // Ignore units close to the center (to make it look like they enter the chest)
00170     }
00171 
00172     uint32 *pixel = static_cast<uint32 *>(surface->getBasePtr(_position.getX(), _position.getY() - 1));
00173     *pixel = _darkColor;
00174 
00175     pixel = static_cast<uint32 *>(surface->getBasePtr(_position.getX() - 1, _position.getY()));
00176     *pixel++ = _darkColor;
00177     *pixel++ = _mainColor;
00178     *pixel = _darkColor;
00179 
00180     pixel = static_cast<uint32 *>(surface->getBasePtr(_position.getX(), _position.getY() + 1));
00181     *pixel = _darkColor;
00182 }
00183 
00184 } // End of namespace Stark


Generated on Sat Aug 17 2019 05:00:43 for ResidualVM by doxygen 1.7.1
curved edge   curved edge