322 lines
10 KiB
C++
322 lines
10 KiB
C++
#include "sdlpp_renderobject.hpp"
|
|
#include <cmath>
|
|
|
|
namespace SDLPP {
|
|
/* wheter to use entire texture rather than just a part of it */
|
|
bool RenderObject::entireTexture() {
|
|
return src_rect.x == -1 || src_rect.y == -1 || src_rect.w == -1 ||
|
|
src_rect.h == -1;
|
|
}
|
|
void RenderObject::render() {
|
|
if ( !getHidden() ) {
|
|
if ( polygon )
|
|
polygon->render( *renderer );
|
|
if ( texture != NULL ) {
|
|
SDL_Rect *src = NULL;
|
|
if ( animation.empty() || !animating ) {
|
|
if ( !entireTexture() )
|
|
src = &src_rect;
|
|
} else {
|
|
src = &animation[animation_index];
|
|
}
|
|
SDL_Point *rotation_point = NULL;
|
|
if ( rotation_center.getX() != -1 ) {
|
|
rotation_point = &rotation_center_point;
|
|
}
|
|
SDL_RenderCopyEx( renderer->getRendererPtr(),
|
|
texture->getTexturePtr(), src, &rect,
|
|
rotation_angle, rotation_point, flip );
|
|
}
|
|
if ( hasCollisions() && renderer->getRenderColiders() ) {
|
|
for ( const auto &col : getCollisions() )
|
|
col->render( *renderer, colider_color );
|
|
}
|
|
}
|
|
}
|
|
void RenderObject::setPos( double x, double y ) {
|
|
setPos( Vec2D< double >( x, y ) );
|
|
}
|
|
void RenderObject::setPos( const std::pair< double, double > &pos ) {
|
|
setPos( Vec2D< double >( pos.first, pos.second ) );
|
|
}
|
|
void RenderObject::setPos( const Vec2D< double > &vec ) {
|
|
original = vec;
|
|
// updateSizeAndPosition();
|
|
}
|
|
Vec2D< double > RenderObject::getPos() const {
|
|
return original;
|
|
}
|
|
std::vector< uint64_t >
|
|
RenderObject::colidesWith( const RenderObject &other ) const {
|
|
if ( !hasCollisions() || !other.hasCollisions() || getHidden() ||
|
|
other.getHidden() ) {
|
|
return {};
|
|
}
|
|
std::vector< uint64_t > ret = {};
|
|
for ( const auto &x : collisions ) {
|
|
for ( const auto &y : other.getCollisions() ) {
|
|
if ( x->colidesWith( *y ) ) {
|
|
ret.push_back( x->getId() );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
void RenderObject::removeCollisions() {
|
|
collisions.clear();
|
|
}
|
|
bool RenderObject::hasCollisions() const {
|
|
return !collisions.empty();
|
|
}
|
|
const std::vector< std::shared_ptr< CollisionPolygon > > &
|
|
RenderObject::getCollisions() const {
|
|
return collisions;
|
|
}
|
|
void RenderObject::setTexture( const std::shared_ptr< Texture > &t,
|
|
const SDL_Rect &source_rect ) {
|
|
texture = t;
|
|
src_rect = source_rect;
|
|
}
|
|
void RenderObject::setTextureKeepSRC( const std::shared_ptr< Texture > &t ) {
|
|
setTexture(t, src_rect);
|
|
}
|
|
void RenderObject::setTexture( const std::shared_ptr< Texture > &t,
|
|
int source_x, int source_y, int source_width,
|
|
int source_height ) {
|
|
setTexture( t, { source_x, source_y, source_width, source_height } );
|
|
}
|
|
void RenderObject::setTexture( const std::string &img_path,
|
|
const SDL_Rect &source_rect ) {
|
|
texture = std::make_shared< Texture >( renderer, img_path );
|
|
src_rect = source_rect;
|
|
}
|
|
void RenderObject::setTexture( const std::string &img_path, int source_x,
|
|
int source_y, int source_width,
|
|
int source_height ) {
|
|
setTexture( img_path, { source_x, source_y, source_width, source_height } );
|
|
}
|
|
void RenderObject::setTexture( Font &font, const std::string &text,
|
|
const std::string &color,
|
|
const std::string &outline_color,
|
|
int outline_size ) {
|
|
texture = std::make_shared< Texture >( renderer, font, text, color,
|
|
outline_color, outline_size );
|
|
src_rect = { -1, -1, -1, -1 };
|
|
}
|
|
void RenderObject::unsetTexture() {
|
|
texture.reset();
|
|
}
|
|
void RenderObject::unsetColor() {
|
|
polygon.reset();
|
|
}
|
|
// per second, relative to window width
|
|
void RenderObject::setMovementSpeed( double speed ) {
|
|
movementSpeed = speed;
|
|
}
|
|
void RenderObject::addMovement( double x, double y ) {
|
|
movementDirection += { x, y };
|
|
}
|
|
void RenderObject::setMovement( double x, double y ) {
|
|
movementDirection = { x, y };
|
|
}
|
|
Vec2D< double > RenderObject::getMovement() {
|
|
return movementDirection;
|
|
}
|
|
void RenderObject::resetMovementX() {
|
|
movementDirection = { 0, movementDirection.getY() };
|
|
}
|
|
void RenderObject::resetMovementY() {
|
|
movementDirection = { movementDirection.getX(), 0 };
|
|
}
|
|
void RenderObject::clearColided() {
|
|
colidedWith.clear();
|
|
}
|
|
void RenderObject::addColided( std::shared_ptr< RenderObject > &obj ) {
|
|
colidedWith.push_back( obj );
|
|
}
|
|
std::vector< std::shared_ptr< RenderObject > > &RenderObject::getColidedWith() {
|
|
return colidedWith;
|
|
}
|
|
void RenderObject::setId( uint64_t input_id ) {
|
|
id = input_id;
|
|
}
|
|
uint64_t RenderObject::getId() const {
|
|
return id;
|
|
}
|
|
void RenderObject::setHidden( bool hid ) {
|
|
hidden = hid;
|
|
}
|
|
bool RenderObject::getHidden() const {
|
|
return hidden;
|
|
}
|
|
void RenderObject::destroy() {
|
|
setHidden( true );
|
|
kill = true;
|
|
}
|
|
bool RenderObject::getKilled() {
|
|
return kill;
|
|
}
|
|
void RenderObject::setColiderColor( const std::string &color ) {
|
|
colider_color = getSDLColorHEX( color );
|
|
}
|
|
|
|
void RenderObject::animate( int ticks ) {
|
|
if ( animating && !animation.empty() ) {
|
|
animation_next_frame -= ticks;
|
|
if ( animation_next_frame <= 0 ) {
|
|
animation_index = ( animation_index + 1 ) % animation.size();
|
|
animation_next_frame =
|
|
animation_next_frame_base + animation_next_frame;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RenderObject::move( int ticks ) {
|
|
if ( permanent )
|
|
return;
|
|
auto addx = movementSpeed * movementDirection.getX() * ticks / 1000.0;
|
|
auto addy = movementSpeed * movementDirection.getY() * ticks / 1000.0;
|
|
if ( std::isnan( addx ) || std::isnan( addy ) )
|
|
return;
|
|
|
|
original += { addx, addy };
|
|
|
|
custom_move( ticks );
|
|
|
|
updateSizeAndPosition();
|
|
}
|
|
void RenderObject::setPermanent( bool perm ) {
|
|
permanent = perm;
|
|
setStatic( perm );
|
|
}
|
|
bool RenderObject::getPermanent() const {
|
|
return permanent;
|
|
}
|
|
bool RenderObject::isStatic() {
|
|
return is_static;
|
|
}
|
|
void RenderObject::setStatic( bool stat ) {
|
|
is_static = stat;
|
|
}
|
|
std::shared_ptr< Renderer > RenderObject::getRenderer() const {
|
|
return renderer;
|
|
}
|
|
void RenderObject::setSceneID( int id ) {
|
|
scene_id = id;
|
|
}
|
|
void RenderObject::copyTo( std::shared_ptr< RenderObject > other ) {
|
|
other->collisions.clear();
|
|
for ( auto &colider : collisions ) {
|
|
other->collisions.push_back( colider->copySelf() );
|
|
}
|
|
other->texture.reset();
|
|
if ( texture ) {
|
|
other->texture = std::make_shared< Texture >( *texture );
|
|
}
|
|
other->polygon.reset();
|
|
if ( polygon ) {
|
|
other->polygon = polygon->copySelf();
|
|
}
|
|
other->colidedWith.clear();
|
|
}
|
|
void RenderObject::setTextureAlpha( uint8_t alpha ) {
|
|
texture->setAlpha( alpha );
|
|
}
|
|
void RenderObject::setTextureSourceRect( const SDL_Rect &source_rect ) {
|
|
src_rect = source_rect;
|
|
}
|
|
void RenderObject::setTextureSourceRect( int x, int y, int w, int h ) {
|
|
setTextureSourceRect( { x, y, w, h } );
|
|
}
|
|
SDL_Rect RenderObject::getTextureSourceRect() const {
|
|
return src_rect;
|
|
}
|
|
void RenderObject::setAnimationFrames( const std::vector< SDL_Rect > &frames ) {
|
|
animation = frames;
|
|
}
|
|
void RenderObject::addAnimationFrame( const SDL_Rect &frame ) {
|
|
animation.push_back( frame );
|
|
}
|
|
void RenderObject::addAnimationFrame( const int x, const int y, const int w,
|
|
const int h ) {
|
|
addAnimationFrame( { x, y, w, h } );
|
|
}
|
|
void RenderObject::pauseAnimation() {
|
|
animating = false;
|
|
}
|
|
void RenderObject::resumeAnimation() {
|
|
animating = true;
|
|
}
|
|
void RenderObject::removeAnimation() {
|
|
animation.clear();
|
|
}
|
|
void RenderObject::setAnimationSpeed( const double fps ) {
|
|
animation_fps = fps;
|
|
animation_next_frame = animation_next_frame_base = 1000 / fps;
|
|
}
|
|
void RenderObject::visit( Visitor &visitor ) {
|
|
visitor.visit( *this );
|
|
}
|
|
void RenderObject::setAlignment( ObjectAlignment horizontal,
|
|
ObjectAlignment vertical ) {
|
|
_horizontal = horizontal;
|
|
_vertical = vertical;
|
|
}
|
|
void RenderObject::flipHorizontally() {
|
|
if ( flip & SDL_FLIP_HORIZONTAL ) {
|
|
flip = static_cast< SDL_RendererFlip >( flip & ~SDL_FLIP_HORIZONTAL );
|
|
} else {
|
|
flip = static_cast< SDL_RendererFlip >( flip | SDL_FLIP_HORIZONTAL );
|
|
}
|
|
}
|
|
void RenderObject::flipVertically() {
|
|
if ( flip & SDL_FLIP_VERTICAL ) {
|
|
flip = static_cast< SDL_RendererFlip >( flip & ~SDL_FLIP_VERTICAL );
|
|
} else {
|
|
flip = static_cast< SDL_RendererFlip >( flip | SDL_FLIP_VERTICAL );
|
|
}
|
|
}
|
|
void RenderObject::setRotationCenter( const Vec2D< double > ¢er ) {
|
|
rotation_center = center;
|
|
rotation_center_point = { static_cast< int >( center.getX() * rect.w ),
|
|
static_cast< int >( center.getY() * rect.h ) };
|
|
}
|
|
void RenderObject::rotateClockwise( int angle ) {
|
|
rotation_angle = ( rotation_angle + angle ) % 360;
|
|
}
|
|
void RenderObject::rotateCounterClockwise( int angle ) {
|
|
rotateClockwise( 360 - ( angle % 360 ) );
|
|
}
|
|
Vec2D< double > RenderObject::computeAlignmentAdditions() {
|
|
double x_addition = 0, y_addition = 0;
|
|
auto dimensions = renderer->getDoubleDimensions();
|
|
auto width_diff = dimensions.getX() - 1;
|
|
auto height_diff = dimensions.getY() - 1;
|
|
switch ( _horizontal ) {
|
|
case OBJ_CENTER:
|
|
x_addition = width_diff / 2;
|
|
break;
|
|
case OBJ_END:
|
|
x_addition = width_diff;
|
|
default:
|
|
break;
|
|
}
|
|
switch ( _vertical ) {
|
|
case OBJ_CENTER:
|
|
y_addition = height_diff / 2;
|
|
break;
|
|
case OBJ_END:
|
|
y_addition = height_diff;
|
|
default:
|
|
break;
|
|
}
|
|
return { x_addition, y_addition };
|
|
}
|
|
void RenderObject::updateXY() {
|
|
auto additions = computeAlignmentAdditions();
|
|
current = { original.getX() + additions.getX(),
|
|
original.getY() + additions.getY() };
|
|
}
|
|
} // namespace SDLPP
|