A bunch of progress on collectable occlusion
This commit is contained in:
parent
d009ef328c
commit
c49d937e20
21 changed files with 388 additions and 42 deletions
|
@ -126,7 +126,10 @@ set(SOURCES
|
||||||
src/game/physics/holes/ground/collectable_sim_ground.cpp
|
src/game/physics/holes/ground/collectable_sim_ground.cpp
|
||||||
src/game/physics/holes/ground/collectable_sim_ground.hpp
|
src/game/physics/holes/ground/collectable_sim_ground.hpp
|
||||||
src/game/physics/body_adapter.cpp
|
src/game/physics/body_adapter.cpp
|
||||||
src/game/physics/body_adapter.hpp)
|
src/game/physics/body_adapter.hpp
|
||||||
|
src/sprites/masked_sprite.cpp
|
||||||
|
src/sprites/masked_sprite.hpp
|
||||||
|
src/sprites/configs/masked_sprite_config.hpp src/sprites/masked_sprite_hole.hpp)
|
||||||
|
|
||||||
set(PHYSICS_00_SOURCES
|
set(PHYSICS_00_SOURCES
|
||||||
src/prototypes/physics_00.cpp)
|
src/prototypes/physics_00.cpp)
|
||||||
|
|
BIN
assets/collectables/bike.png
Normal file
BIN
assets/collectables/bike.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 849 B |
BIN
assets/collectables/rose.png
Normal file
BIN
assets/collectables/rose.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 517 B |
BIN
assets/collectables/rosebush.png
Normal file
BIN
assets/collectables/rosebush.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 578 B |
BIN
assets/collectables/small-tree.png
Normal file
BIN
assets/collectables/small-tree.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 835 B |
BIN
assets/collectables/stone.png
Normal file
BIN
assets/collectables/stone.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 617 B |
BIN
assets/collectables/tram.png
Normal file
BIN
assets/collectables/tram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 967 B |
|
@ -6,7 +6,7 @@
|
||||||
#include "game/collectables/collectable_config.hpp"
|
#include "game/collectables/collectable_config.hpp"
|
||||||
|
|
||||||
std::map<std::string, CollectableConfig> const all_collectables = {
|
std::map<std::string, CollectableConfig> const all_collectables = {
|
||||||
{"box", CollectableConfig("numbers")}
|
{"box", CollectableConfig("rosebush")}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //HOLESOME_COLLECTABLES_HPP
|
#endif //HOLESOME_COLLECTABLES_HPP
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#define ISOMETRIC_SKEW (16.f/32.f)
|
#define ISOMETRIC_SKEW (16.f/32.f)
|
||||||
#define MOVEMENT_SKEW sf::Vector2f(1.f, 1/ISOMETRIC_SKEW/2.f)
|
#define MOVEMENT_SKEW sf::Vector2f(1.f, 1/ISOMETRIC_SKEW/2.f)
|
||||||
#define WORLD_TO_ISO_SCALE 50.0f // 50.f, don't change. Rather adjust the zoom of the camera
|
#define WORLD_TO_ISO_SCALE 50.0f // 50.f, don't change. Rather adjust the zoom of the camera
|
||||||
|
#define MASKED_HOLE_BORDER_TRANSITION_SIZE 0.2f
|
||||||
|
|
||||||
// Tracking view defaults
|
// Tracking view defaults
|
||||||
#define DEF_TV_IS_ABSOLUTE_FREE_MOVE_THRESHOLD false
|
#define DEF_TV_IS_ABSOLUTE_FREE_MOVE_THRESHOLD false
|
||||||
|
|
22
src/sprites/configs/masked_sprite_config.hpp
Normal file
22
src/sprites/configs/masked_sprite_config.hpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef HOLESOME_MASKED_SPRITE_CONFIG_HPP
|
||||||
|
#define HOLESOME_MASKED_SPRITE_CONFIG_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
#include "sprite_config.hpp"
|
||||||
|
|
||||||
|
struct MaskedSpriteConfig
|
||||||
|
{
|
||||||
|
SpriteConfig spriteConfig;
|
||||||
|
|
||||||
|
MaskedSpriteConfig(std::string sheetName, int sheetIndex, sf::Vector2f size = sf::Vector2f(0, 0))
|
||||||
|
: spriteConfig(std::move(sheetName), sheetIndex, size)
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit MaskedSpriteConfig(std::string textureName, sf::Vector2f size = sf::Vector2f(0, 0))
|
||||||
|
: spriteConfig(std::move(textureName), size)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //HOLESOME_MASKED_SPRITE_CONFIG_HPP
|
144
src/sprites/masked_sprite.cpp
Normal file
144
src/sprites/masked_sprite.cpp
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
#include "masked_sprite.hpp"
|
||||||
|
#include "../config.h"
|
||||||
|
#include "../logging/easylogging++.h"
|
||||||
|
#include "../game/player/player_collection.hpp"
|
||||||
|
|
||||||
|
MaskedSprite::MaskedSprite(const std::shared_ptr<sf::Texture> &sheetTexture, sf::IntRect textureRext, sf::Vector2f size)
|
||||||
|
: texture(sheetTexture), textureRect(textureRext)
|
||||||
|
{
|
||||||
|
image = std::make_shared<sf::Image>(sheetTexture->copyToImage());
|
||||||
|
sprite = std::make_shared<sf::Sprite>(*texture, textureRect);
|
||||||
|
setSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaskedSprite::MaskedSprite(const std::shared_ptr<sf::Texture> &texture, sf::Vector2f size)
|
||||||
|
: texture(texture)
|
||||||
|
{
|
||||||
|
image = std::make_shared<sf::Image>(texture->copyToImage());
|
||||||
|
textureRect = sf::IntRect(0, 0, texture->getSize().x, texture->getSize().y);
|
||||||
|
sprite = std::make_shared<sf::Sprite>(*texture, textureRect);
|
||||||
|
setSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaskedSprite::preRenderUpdate()
|
||||||
|
{
|
||||||
|
GameObject::preRenderUpdate();
|
||||||
|
|
||||||
|
// TODO: Did anything change? Is update of masked sprite necessary?
|
||||||
|
|
||||||
|
if (angle == 0)
|
||||||
|
{
|
||||||
|
renderPosition = coordinates->isometric().toScreen();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
auto position = coordinates->isometric().toScreen();
|
||||||
|
renderPosition = calculateRotatedCornerPosition(position, angle);
|
||||||
|
}
|
||||||
|
sprite->setPosition(renderPosition);
|
||||||
|
sprite->setRotation(angle);
|
||||||
|
|
||||||
|
updateFreshMaskedSprite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaskedSprite::draw(sf::RenderWindow *window)
|
||||||
|
{
|
||||||
|
GameObject::draw(window);
|
||||||
|
|
||||||
|
window->draw(*sprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaskedSprite::updateFreshMaskedSprite()
|
||||||
|
{
|
||||||
|
// TODO: Calculate depth per pixel
|
||||||
|
auto maskedImage = std::make_shared<sf::Image>();
|
||||||
|
maskedImage->create(textureRect.width, textureRect.height, sf::Color::Transparent);
|
||||||
|
|
||||||
|
// todo: or use sf::RenderTexture?
|
||||||
|
|
||||||
|
maskedImage->copy(*image, 0, 0);
|
||||||
|
|
||||||
|
// Calculate world coordinates for each pixel
|
||||||
|
auto topLeftCorner = sf::Vector2f(coordinates->diagonalWorld().horizontal, coordinates->diagonalWorld().vertical);
|
||||||
|
auto xAxis = rotateVectorByAngle(sf::Vector2f(1, 0), angle);
|
||||||
|
auto yAxis = rotateVectorByAngle(sf::Vector2f(0, -1), angle);
|
||||||
|
float xFactorPerPixel = sprite->getScale().x / WORLD_TO_ISO_SCALE;
|
||||||
|
float yFactorPerPixel = sprite->getScale().y / WORLD_TO_ISO_SCALE;
|
||||||
|
for (int yOffset = 0; yOffset < textureRect.height; yOffset++)
|
||||||
|
{
|
||||||
|
for (int xOffset = 0; xOffset < textureRect.width; xOffset++)
|
||||||
|
{
|
||||||
|
int y = yOffset + textureRect.top;
|
||||||
|
int x = xOffset + textureRect.left;
|
||||||
|
|
||||||
|
auto pixelPosition =
|
||||||
|
topLeftCorner + xAxis * (xOffset * xFactorPerPixel) + yAxis * (yOffset * yFactorPerPixel);
|
||||||
|
if (pixelPosition.y >= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pixelColor = image->getPixel(x, y);
|
||||||
|
auto newPixelColor = calculateNewPixelColor(pixelColor, pixelPosition);
|
||||||
|
maskedImage->setPixel(x, y, newPixelColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maskedTexture = std::make_shared<sf::Texture>();
|
||||||
|
maskedTexture->loadFromImage(*maskedImage);
|
||||||
|
|
||||||
|
sprite->setTexture(*maskedTexture);
|
||||||
|
sprite->setTextureRect(sf::IntRect(0, 0, textureRect.width, textureRect.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaskedSprite::setSize(const sf::Vector2f &size)
|
||||||
|
{
|
||||||
|
if (size == sf::Vector2f(0, 0))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite->setScale(size.x / textureRect.width, size.y / textureRect.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Vector2f MaskedSprite::getSize() const
|
||||||
|
{
|
||||||
|
return {textureRect.width * sprite->getScale().x, textureRect.height * sprite->getScale().y};
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Sprite MaskedSprite::getSprite() const
|
||||||
|
{
|
||||||
|
return *sprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaskedSprite::setRotation(float angle)
|
||||||
|
{
|
||||||
|
this->angle = restrictAngle(angle);
|
||||||
|
sprite->setRotation(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Color MaskedSprite::calculateNewPixelColor(sf::Color currentColor, sf::Vector2<float> position)
|
||||||
|
{
|
||||||
|
if (position.y >= 0)
|
||||||
|
{
|
||||||
|
// Pixel is above ground
|
||||||
|
return currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change color based on height and hole
|
||||||
|
// Cut off pixels that are hidden in the ground, beyond the hole
|
||||||
|
float depth = coordinates->diagonalWorld().depth;
|
||||||
|
auto pixelCoordinates = TranslatedCoordinates(DiagonalWorldCoordinates(position.x, position.y, depth));
|
||||||
|
|
||||||
|
std::vector<float> holeAlphaFactors{};
|
||||||
|
auto players = PlayerCollection::getInstance()->getPlayers();
|
||||||
|
for (auto &player: players)
|
||||||
|
{
|
||||||
|
auto holeMask = MaskedSpriteHole(player);
|
||||||
|
float holeAlphaFactor = holeMask.isPointInHoleFactor(pixelCoordinates);
|
||||||
|
holeAlphaFactors.push_back(holeAlphaFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
float biggestHoleAlphaFactor = *std::max_element(holeAlphaFactors.begin(), holeAlphaFactors.end());
|
||||||
|
currentColor.a *= biggestHoleAlphaFactor;
|
||||||
|
return currentColor;
|
||||||
|
}
|
45
src/sprites/masked_sprite.hpp
Normal file
45
src/sprites/masked_sprite.hpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef HOLESOME_MASKED_SPRITE_HPP
|
||||||
|
#define HOLESOME_MASKED_SPRITE_HPP
|
||||||
|
|
||||||
|
|
||||||
|
#include <SFML/Graphics/Texture.hpp>
|
||||||
|
#include "../game/game_object.h"
|
||||||
|
#include "versatile_sprite.hpp"
|
||||||
|
#include "masked_sprite_hole.hpp"
|
||||||
|
|
||||||
|
class MaskedSprite : public Sprite, public GameObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MaskedSprite(const std::shared_ptr<sf::Texture>& texture, sf::Vector2f size = sf::Vector2f(0, 0));
|
||||||
|
|
||||||
|
MaskedSprite(const std::shared_ptr<sf::Texture> &sheetTexture, sf::IntRect textureRext,
|
||||||
|
sf::Vector2f size = sf::Vector2f(0, 0));
|
||||||
|
|
||||||
|
void preRenderUpdate() override;
|
||||||
|
|
||||||
|
void draw(sf::RenderWindow *window) override;
|
||||||
|
|
||||||
|
void setSize(const sf::Vector2f &size) override;
|
||||||
|
|
||||||
|
sf::Vector2f getSize() const override;
|
||||||
|
|
||||||
|
sf::Sprite getSprite() const override;
|
||||||
|
|
||||||
|
void setRotation(float angle) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<sf::Sprite> sprite;
|
||||||
|
std::shared_ptr<sf::Texture> maskedTexture;
|
||||||
|
std::shared_ptr<sf::Texture> texture;
|
||||||
|
std::shared_ptr<sf::Image> image;
|
||||||
|
sf::IntRect textureRect;
|
||||||
|
float angle = 0;
|
||||||
|
sf::Vector2f renderPosition;
|
||||||
|
|
||||||
|
void updateFreshMaskedSprite();
|
||||||
|
|
||||||
|
sf::Color calculateNewPixelColor(sf::Color currentColor, sf::Vector2<float> position);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //HOLESOME_MASKED_SPRITE_HPP
|
51
src/sprites/masked_sprite_hole.hpp
Normal file
51
src/sprites/masked_sprite_hole.hpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef HOLESOME_MASKED_SPRITE_HOLE_HPP
|
||||||
|
#define HOLESOME_MASKED_SPRITE_HOLE_HPP
|
||||||
|
|
||||||
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
#include "../coordinates/translated_coordinates.h"
|
||||||
|
#include "../game/player/player.hpp"
|
||||||
|
|
||||||
|
struct MaskedSpriteHole
|
||||||
|
{
|
||||||
|
sf::Vector2f center = sf::Vector2f(0, 0);
|
||||||
|
float majorRadiusSquared = 0;
|
||||||
|
float minorRadiusSquared = 0;
|
||||||
|
|
||||||
|
MaskedSpriteHole() = default;
|
||||||
|
|
||||||
|
MaskedSpriteHole(const std::shared_ptr<Player> &player)
|
||||||
|
{
|
||||||
|
auto iso = player->coordinates->isometric();
|
||||||
|
this->center = sf::Vector2f(iso.x, iso.y);
|
||||||
|
|
||||||
|
float radius = player->getWorldRadius() * WORLD_TO_ISO_SCALE * sqrt(2);
|
||||||
|
this->majorRadiusSquared = pow(radius, 2);
|
||||||
|
this->minorRadiusSquared = pow(radius * ISOMETRIC_SKEW, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
float isPointInHoleFactor(TranslatedCoordinates point) const
|
||||||
|
{
|
||||||
|
if (majorRadiusSquared == 0 || minorRadiusSquared == 0)
|
||||||
|
return 1.f;
|
||||||
|
|
||||||
|
// Calculate the value of the ellipse equation
|
||||||
|
auto iso = point.isometric();
|
||||||
|
auto relativeCoordinates = center - sf::Vector2f(iso.x, iso.y);
|
||||||
|
float L = pow(relativeCoordinates.x, 2) / majorRadiusSquared + pow(relativeCoordinates.y, 2) / minorRadiusSquared;
|
||||||
|
|
||||||
|
// Compare the value of L to 1
|
||||||
|
float lowerBound = 1 - MASKED_HOLE_BORDER_TRANSITION_SIZE / 2.f;
|
||||||
|
float upperBound = 1 + MASKED_HOLE_BORDER_TRANSITION_SIZE / 2.f;
|
||||||
|
if (L <= lowerBound)
|
||||||
|
// Inside
|
||||||
|
return 1.f;
|
||||||
|
else if (L < upperBound)
|
||||||
|
// Linear transition for anti-aliasing
|
||||||
|
return (upperBound - L) / MASKED_HOLE_BORDER_TRANSITION_SIZE;
|
||||||
|
else
|
||||||
|
// Outside
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //HOLESOME_MASKED_SPRITE_HOLE_HPP
|
|
@ -1,6 +1,7 @@
|
||||||
#include "sprite_factory.hpp"
|
#include "sprite_factory.hpp"
|
||||||
#include "../texture_config.h"
|
#include "../texture_config.h"
|
||||||
#include "texture_manager.hpp"
|
#include "texture_manager.hpp"
|
||||||
|
#include "masked_sprite.hpp"
|
||||||
|
|
||||||
std::shared_ptr<SingleSprite> SpriteFactory::createSingleSprite(const std::string &name, sf::Vector2f size)
|
std::shared_ptr<SingleSprite> SpriteFactory::createSingleSprite(const std::string &name, sf::Vector2f size)
|
||||||
{
|
{
|
||||||
|
@ -136,3 +137,45 @@ std::shared_ptr<TileMap> SpriteFactory::createTileMap(TileMapConfig config)
|
||||||
|
|
||||||
return std::make_shared<TileMap>(tileSet, config.tiles);
|
return std::make_shared<TileMap>(tileSet, config.tiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MaskedSprite> SpriteFactory::createMaskedSprite(const std::string &name, sf::Vector2f size)
|
||||||
|
{
|
||||||
|
// Get sprite config
|
||||||
|
auto masked_sprite_config = all_masked_sprites.find(name);
|
||||||
|
|
||||||
|
if (masked_sprite_config == all_masked_sprites.end())
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "MaskedSprite " << name << " not found. Could not create masked sprite.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct sprite
|
||||||
|
auto spriteConfig = masked_sprite_config->second.spriteConfig;
|
||||||
|
|
||||||
|
// Construct simply from texture
|
||||||
|
if (!spriteConfig.isFromSheet)
|
||||||
|
{
|
||||||
|
auto texture = TextureManager::getInstance()->getTexture(spriteConfig.resourceName);
|
||||||
|
if (texture == nullptr)
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "Texture " << spriteConfig.resourceName << " not found. Could not create masked sprite.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Creating masked sprite from texture " << spriteConfig.resourceName;
|
||||||
|
return std::make_shared<MaskedSprite>(texture, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct from sheet
|
||||||
|
auto sheet = createSheet(spriteConfig.resourceName);
|
||||||
|
if (sheet == nullptr)
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "Sheet " << spriteConfig.resourceName << " not found. Could not create masked sprite.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Creating single masked from sheet " << spriteConfig.resourceName;
|
||||||
|
auto texture = sheet->getTexture();
|
||||||
|
auto rect = sheet->getTextureRect(spriteConfig.sheetIndex);
|
||||||
|
return std::make_shared<MaskedSprite>(texture, rect, size);
|
||||||
|
}
|
||||||
|
|
|
@ -11,11 +11,13 @@
|
||||||
#include "tiling/tilemap.hpp"
|
#include "tiling/tilemap.hpp"
|
||||||
#include "tiling/tileset.hpp"
|
#include "tiling/tileset.hpp"
|
||||||
#include "tiling/tilemap_config.hpp"
|
#include "tiling/tilemap_config.hpp"
|
||||||
|
#include "masked_sprite.hpp"
|
||||||
|
|
||||||
class SpriteFactory
|
class SpriteFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<SingleSprite> createSingleSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0));
|
static std::shared_ptr<SingleSprite> createSingleSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0));
|
||||||
|
static std::shared_ptr<MaskedSprite> createMaskedSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0));
|
||||||
static std::shared_ptr<AnimatedSprite> createAnimatedSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0));
|
static std::shared_ptr<AnimatedSprite> createAnimatedSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0));
|
||||||
static std::shared_ptr<SpriteSheet> createSheet(const std::string& name);
|
static std::shared_ptr<SpriteSheet> createSheet(const std::string& name);
|
||||||
static std::shared_ptr<TileSet> createTileSet(const std::string &name);
|
static std::shared_ptr<TileSet> createTileSet(const std::string &name);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "sprite_sheet.hpp"
|
#include "sprite_sheet.hpp"
|
||||||
#include "single_sprite.hpp"
|
#include "single_sprite.hpp"
|
||||||
|
|
||||||
SpriteSheet::SpriteSheet(const std::shared_ptr<sf::Texture>& texture, int columns, int rows)
|
SpriteSheet::SpriteSheet(const std::shared_ptr<sf::Texture> &texture, int columns, int rows)
|
||||||
{
|
{
|
||||||
this->texture = texture;
|
this->texture = texture;
|
||||||
this->columns = columns;
|
this->columns = columns;
|
||||||
|
@ -17,12 +17,15 @@ SpriteSheet::SpriteSheet(const std::shared_ptr<sf::Texture>& texture, int column
|
||||||
{
|
{
|
||||||
sf::Sprite sprite;
|
sf::Sprite sprite;
|
||||||
sprite.setTexture(*texture);
|
sprite.setTexture(*texture);
|
||||||
sprite.setTextureRect(sf::IntRect(x * spriteWidth, y * spriteHeight, spriteWidth, spriteHeight));
|
sprite.setTextureRect(getRect(spriteWidth, spriteHeight, y, x));
|
||||||
sprites.push_back(sprite);
|
sprites.push_back(sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sf::Rect<int> SpriteSheet::getRect(int spriteWidth, int spriteHeight, int row, int column) const
|
||||||
|
{ return sf::IntRect(column * spriteWidth, row * spriteHeight, spriteWidth, spriteHeight); }
|
||||||
|
|
||||||
std::shared_ptr<SingleSprite> SpriteSheet::getSprite(int sequenceIndex) const
|
std::shared_ptr<SingleSprite> SpriteSheet::getSprite(int sequenceIndex) const
|
||||||
{
|
{
|
||||||
if (sequenceIndex < 0 || sequenceIndex >= sprites.size())
|
if (sequenceIndex < 0 || sequenceIndex >= sprites.size())
|
||||||
|
@ -66,3 +69,12 @@ std::shared_ptr<sf::Texture> SpriteSheet::getTexture() const
|
||||||
{
|
{
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sf::IntRect SpriteSheet::getTextureRect(int sequenceIndex) const
|
||||||
|
{
|
||||||
|
int column = sequenceIndex % columns;
|
||||||
|
int row = sequenceIndex / columns;
|
||||||
|
int spriteWidth = texture->getSize().x / columns;
|
||||||
|
int spriteHeight = texture->getSize().y / rows;
|
||||||
|
return getRect(spriteWidth, spriteHeight, row, column);
|
||||||
|
}
|
||||||
|
|
|
@ -13,20 +13,24 @@ class SpriteSheet
|
||||||
public:
|
public:
|
||||||
SpriteSheet(const std::shared_ptr<sf::Texture>& texture, int columns, int rows);
|
SpriteSheet(const std::shared_ptr<sf::Texture>& texture, int columns, int rows);
|
||||||
|
|
||||||
std::shared_ptr<SingleSprite> getSprite(int sequenceIndex) const;
|
[[nodiscard]] std::shared_ptr<SingleSprite> getSprite(int sequenceIndex) const;
|
||||||
|
|
||||||
std::shared_ptr<AnimatedSprite> getAnimation(int startingSequenceIndex, int numberOfFrames) const;
|
[[nodiscard]] std::shared_ptr<AnimatedSprite> getAnimation(int startingSequenceIndex, int numberOfFrames) const;
|
||||||
|
|
||||||
std::shared_ptr<sf::Texture> getTexture() const;
|
[[nodiscard]] std::shared_ptr<sf::Texture> getTexture() const;
|
||||||
|
|
||||||
int getColumns() const;
|
[[nodiscard]] sf::IntRect getTextureRect(int sequenceIndex) const;
|
||||||
int getRows() const;
|
|
||||||
|
[[nodiscard]] int getColumns() const;
|
||||||
|
[[nodiscard]] int getRows() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int columns;
|
int columns;
|
||||||
int rows;
|
int rows;
|
||||||
std::shared_ptr<sf::Texture> texture;
|
std::shared_ptr<sf::Texture> texture;
|
||||||
std::vector<sf::Sprite> sprites;
|
std::vector<sf::Sprite> sprites;
|
||||||
|
|
||||||
|
[[nodiscard]] sf::Rect<int> getRect(int spriteWidth, int spriteHeight, int row, int column) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,19 @@ VersatileSprite::VersatileSprite(const std::string &name, sf::Vector2f size)
|
||||||
// Try to find in sprites
|
// Try to find in sprites
|
||||||
if (all_sprites.find(name) != all_sprites.end())
|
if (all_sprites.find(name) != all_sprites.end())
|
||||||
{
|
{
|
||||||
singleSprite = SpriteFactory::createSingleSprite(name, size);
|
auto spriteObject = SpriteFactory::createSingleSprite(name, size);
|
||||||
addChild(singleSprite);
|
addChild(spriteObject);
|
||||||
|
sprite = spriteObject;
|
||||||
} else if (all_animations.find(name) != all_animations.end())
|
} else if (all_animations.find(name) != all_animations.end())
|
||||||
{
|
{
|
||||||
animatedSprite = SpriteFactory::createAnimatedSprite(name, size);
|
auto spriteObject = SpriteFactory::createAnimatedSprite(name, size);
|
||||||
addChild(animatedSprite);
|
addChild(spriteObject);
|
||||||
|
sprite = spriteObject;
|
||||||
|
} else if (all_masked_sprites.find(name) != all_masked_sprites.end())
|
||||||
|
{
|
||||||
|
auto spriteObject = SpriteFactory::createMaskedSprite(name, size);
|
||||||
|
addChild(spriteObject);
|
||||||
|
sprite = spriteObject;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "Sprite " << name << " not found. Could not create versatile sprite.";
|
LOG(ERROR) << "Sprite " << name << " not found. Could not create versatile sprite.";
|
||||||
|
@ -22,34 +29,20 @@ VersatileSprite::VersatileSprite(const std::string &name, sf::Vector2f size)
|
||||||
|
|
||||||
void VersatileSprite::setSize(const sf::Vector2f &size)
|
void VersatileSprite::setSize(const sf::Vector2f &size)
|
||||||
{
|
{
|
||||||
getUsedSpritePtr()->setSize(size);
|
sprite->setSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
sf::Vector2f VersatileSprite::getSize() const
|
sf::Vector2f VersatileSprite::getSize() const
|
||||||
{
|
{
|
||||||
return getUsedSpritePtr()->getSize();
|
return sprite->getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
sf::Sprite VersatileSprite::getSprite() const
|
sf::Sprite VersatileSprite::getSprite() const
|
||||||
{
|
{
|
||||||
return getUsedSpritePtr()->getSprite();
|
return sprite->getSprite();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersatileSprite::setRotation(float angle)
|
void VersatileSprite::setRotation(float angle)
|
||||||
{
|
{
|
||||||
getUsedSpritePtr()->setRotation(angle);
|
sprite->setRotation(angle);
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Sprite> VersatileSprite::getUsedSpritePtr() const
|
|
||||||
{
|
|
||||||
if (singleSprite != nullptr)
|
|
||||||
{
|
|
||||||
return singleSprite;
|
|
||||||
} else if (animatedSprite != nullptr)
|
|
||||||
{
|
|
||||||
return animatedSprite;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Versatile sprite has no sprite");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,7 @@ public:
|
||||||
void setRotation(float angle) override;
|
void setRotation(float angle) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<SingleSprite> singleSprite = nullptr;
|
std::shared_ptr<Sprite> sprite = nullptr;
|
||||||
std::shared_ptr<AnimatedSprite> animatedSprite = nullptr;
|
|
||||||
|
|
||||||
std::shared_ptr<Sprite> getUsedSpritePtr() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "sprites/configs/sheet_config.hpp"
|
#include "sprites/configs/sheet_config.hpp"
|
||||||
#include "sprites/configs/sprite_config.hpp"
|
#include "sprites/configs/sprite_config.hpp"
|
||||||
#include "sprites/tiling/tileset_config.hpp"
|
#include "sprites/tiling/tileset_config.hpp"
|
||||||
|
#include "sprites/configs/masked_sprite_config.hpp"
|
||||||
|
|
||||||
#define PLAYER_SKIN "hole"
|
#define PLAYER_SKIN "hole"
|
||||||
|
|
||||||
|
@ -21,6 +22,12 @@ std::map<std::string, std::string> const all_textures = {
|
||||||
{"ring", "assets/ring.png"},
|
{"ring", "assets/ring.png"},
|
||||||
{"grasses", "assets/grass_plus.png"},
|
{"grasses", "assets/grass_plus.png"},
|
||||||
{"hole", "assets/hole.png"},
|
{"hole", "assets/hole.png"},
|
||||||
|
{"bike", "assets/collectables/bike.png"},
|
||||||
|
{"rose", "assets/collectables/rose.png"},
|
||||||
|
{"rosebush", "assets/collectables/rosebush.png"},
|
||||||
|
{"small-tree", "assets/collectables/small-tree.png"},
|
||||||
|
{"stone", "assets/collectables/stone.png"},
|
||||||
|
{"tram", "assets/collectables/tram.png"},
|
||||||
{"iso-tiles", "assets/isometric-tiles.png"}
|
{"iso-tiles", "assets/isometric-tiles.png"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,6 +60,19 @@ std::map<std::string, SpriteConfig> const all_sprites = {
|
||||||
{"hole", SpriteConfig("hole")}
|
{"hole", SpriteConfig("hole")}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All masked sprites used in the game.
|
||||||
|
* The key is the name of the MaskedSprite, the value is the MaskedSprite config.
|
||||||
|
*/
|
||||||
|
std::map<std::string, MaskedSpriteConfig> const all_masked_sprites = {
|
||||||
|
{"bike", MaskedSpriteConfig("bike")},
|
||||||
|
{"rose", MaskedSpriteConfig("rose")},
|
||||||
|
{"rosebush", MaskedSpriteConfig("rosebush")},
|
||||||
|
{"stone", MaskedSpriteConfig("stone")},
|
||||||
|
{"tram", MaskedSpriteConfig("tram")},
|
||||||
|
{"small-tree", MaskedSpriteConfig("small-tree")}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All tilesets used in the game.
|
* All tilesets used in the game.
|
||||||
* The key is the name of the tileset, the value is the tileset config.
|
* The key is the name of the tileset, the value is the tileset config.
|
||||||
|
|
|
@ -35,4 +35,13 @@ T sum(sf::Vector2<T> v)
|
||||||
return v.x + v.y;
|
return v.x + v.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
sf::Vector2<T> rotateVectorByAngle(sf::Vector2<T> v, float angle)
|
||||||
|
{
|
||||||
|
float radians = -angle * M_PI / 180;
|
||||||
|
auto x = v.x * std::cos(radians) - v.y * std::sin(radians);
|
||||||
|
auto y = v.x * std::sin(radians) + v.y * std::cos(radians);
|
||||||
|
return sf::Vector2<T>(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
#endif //HOLESOME_VECTOR_UTILS_HPP
|
#endif //HOLESOME_VECTOR_UTILS_HPP
|
||||||
|
|
Loading…
Reference in a new issue