#include "sdlpp_renderobject.hpp" #include 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; } Vec2D< double > RenderObject::getAbsolutePos() const { return current; } 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() const { 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 ) ); } void RenderObject::setRotationSpeed(int speed) { rotation_speed = speed; } void RenderObject::startRotation() { rotating = true; } void RenderObject::stopRotation() { rotating = false; } Vec2D< double > RenderObject::computeAlignmentAdditions() { double x_addition = 0; double 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() }; } void RenderObject::custom_move(int ticks) { if(isRotating()) { auto angle = ticks * rotation_speed / 1000; // tick = millisecond rotateCounterClockwise(angle); } } } // namespace SDLPP