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     _surfaceRenderer = _gfx->createSurfaceRenderer();
00044 }
00045 
00046 VisualExplodingImage::~VisualExplodingImage() {
00047     if (_surface) {
00048         _surface->free();
00049     }
00050     delete _surface;
00051     delete _texture;
00052     delete _surfaceRenderer;
00053 }
00054 
00055 void VisualExplodingImage::initFromSurface(const Graphics::Surface *surface) {
00056     assert(!_surface && !_texture);
00057 
00058     // Decode the XMG
00059     _surface = new Graphics::Surface();
00060     _surface->copyFrom(*surface);
00061 
00062     _texture = _gfx->createTexture(_surface);
00063     _texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
00064 
00065     // Create an explosion unit for each pixel in the surface
00066     _units.resize(_surface->w * _surface->h);
00067 
00068     Common::Point explosionCenter(_surface->w / 2, _surface->h / 2);
00069     Common::Point explosionAmplitude(48, 16);
00070 
00071     uint index = 0;
00072     for (uint y = 0; y < _surface->h; y++) {
00073         for (uint x = 0; x < _surface->w; x++, index++) {
00074             _units[index].setPosition(x, y);
00075             _units[index].setExplosionSettings(explosionCenter, explosionAmplitude);
00076             _units[index].setColor(*static_cast<uint32 *>(_surface->getBasePtr(x, y)), _surface->format);
00077         }
00078     }
00079 }
00080 
00081 void VisualExplodingImage::render(const Common::Point &position) {
00082     // Fill with transparent color
00083     _surface->fillRect(Common::Rect(_surface->w, _surface->h), 0);
00084 
00085     for (uint i = 0; i < _units.size(); i++) {
00086         _units[i].update();
00087         _units[i].draw(_surface);
00088     }
00089 
00090     _texture->update(_surface);
00091     _surfaceRenderer->render(_texture, position);
00092 }
00093 
00094 VisualExplodingImage::ExplosionUnit::ExplosionUnit() :
00095         _stillImageTimeRemaining(33 * 33),
00096         _explosionFastAccelerationTimeRemaining(25 * 33),
00097         _mainColor(0),
00098         _darkColor(0) {
00099 
00100 }
00101 
00102 void VisualExplodingImage::ExplosionUnit::setPosition(int x, int y) {
00103     _position = Math::Vector2d(x, y);
00104 }
00105 
00106 void VisualExplodingImage::ExplosionUnit::setExplosionSettings(const Common::Point &center, const Common::Point &amplitude) {
00107     _center = Math::Vector2d(center.x, center.y);
00108 
00109     _speed.setX(cos(StarkRandomSource->getRandomNumber(M_PI * 100)) * (float)amplitude.x);
00110     _speed.setY(sin(StarkRandomSource->getRandomNumber(M_PI * 100)) * (float)amplitude.y);
00111 
00112     // WTF, ensuring all fragments go in the same direction?
00113     float magnitude = _position.getDistanceTo(_speed);
00114     _speed -= _position;
00115     _speed = _speed / _speed.getMagnitude() * -magnitude;
00116 }
00117 
00118 void VisualExplodingImage::ExplosionUnit::setColor(uint32 color, const Graphics::PixelFormat &format) {
00119     _mainColor = color;
00120 
00121     byte a, r, g, b;
00122     format.colorToARGB(color, a, r, g, b);
00123     r >>= 1;
00124     g >>= 1;
00125     b >>= 1;
00126 
00127     _darkColor = format.ARGBToColor(a, r, g, b);
00128 }
00129 
00130 void VisualExplodingImage::ExplosionUnit::update() {
00131     if (_stillImageTimeRemaining > 0) {
00132         _stillImageTimeRemaining -= StarkGlobal->getMillisecondsPerGameloop();
00133         return;
00134     }
00135 
00136     if (_position.getDistanceTo(_center) <= 1.f) {
00137         // Units near the center stay there (to make it look like they enter the chest)
00138         return;
00139     }
00140 
00141     Math::Vector2d speed = _speed.getNormalized() * 0.6f;
00142     _position += speed;
00143 
00144     // Update the acceleration to units move towards the center
00145     Math::Vector2d acceleration = _center - _position;
00146     if (_explosionFastAccelerationTimeRemaining > 0) {
00147         acceleration *= 3.0f;
00148         _explosionFastAccelerationTimeRemaining -= StarkGlobal->getMillisecondsPerGameloop();
00149     }
00150 
00151     _speed += acceleration;
00152     _speed -= speed * 2.5f;
00153 }
00154 
00155 void VisualExplodingImage::ExplosionUnit::draw(Graphics::Surface *surface) {
00156     if (_position.getX() <= 1.f || _position.getX() >= surface->w - 1
00157             || _position.getY() <= 1.f || _position.getY() >= surface->h - 1) {
00158         return; // Ignore units outside of the surface
00159     }
00160 
00161     if (_stillImageTimeRemaining <= 0 && _position.getDistanceTo(_center) <= 2.f) {
00162         return; // Ignore units close to the center (to make it look like they enter the chest)
00163     }
00164 
00165     uint32 *pixel = static_cast<uint32 *>(surface->getBasePtr(_position.getX(), _position.getY() - 1));
00166     *pixel = _darkColor;
00167 
00168     pixel = static_cast<uint32 *>(surface->getBasePtr(_position.getX() - 1, _position.getY()));
00169     *pixel++ = _darkColor;
00170     *pixel++ = _mainColor;
00171     *pixel = _darkColor;
00172 
00173     pixel = static_cast<uint32 *>(surface->getBasePtr(_position.getX(), _position.getY() + 1));
00174     *pixel = _darkColor;
00175 }
00176 
00177 } // End of namespace Stark


Generated on Sat Mar 16 2019 05:01:30 for ResidualVM by doxygen 1.7.1
curved edge   curved edge