Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - TheSpaceEvader

Pages: [1]
1
General / How to build a project that relies on relative paths
« on: July 06, 2018, 05:14:31 pm »
So I recently made a post asking why, when I built my project using CMake, none of my resources (images, sounds, fonts etc) were loading: https://en.sfml-dev.org/forums/index.php?topic=24218.msg163942
I now know, as eXpl0it3r rightfully pointed out, that the cause of my problem was due to my over-reliance on relative files and how, once the project is built, this is meaningless to the built program when executed. It's my understanding that there (atleast) two solutions to this for me:
  • Convert my resources to RGBA's, which are then stored in their own respective C source files, as seen here: https://en.sfml-dev.org/forums/index.php?topic=17256.msg124792#msg124792. However, my problems with this option are:
    • What tool would I use to convert image files into a string of RGBA values? I have attempted to use both sites such as convertio.co and tools like ImageMagick, but none of these appear to allow me to extract the values as a string?
    • As some of these images are relatively large, surely the RGBA string they are converted into would be absolutely massive? I attempted to convert one of my larger JPG's into a C source file using Gimp to test this and exported file was 20MB! Is this really the most feasible way of doing this?
  • An alternative that I have seen suggested is to have CMake copy these resources into my build directory. Then, where I would previously load from a relative path, have the project determine the actual, absolute path to the program using something like this: https://stackoverflow.com/questions/143174/how-do-i-get-the-directory-that-a-program-is-running-from
So, my question is, which of these, or perhaps another, solution is most often used/considered best practice by the community? #1 seems like the more portable solution but does not seem to allow for regular image sizes?

2
Why are you adding resource files to the source file listing? Why do you need resource files when building your application?
Just to be clear, my initial thinking was that I would not have to, as these resources are directly called to in my code. However, when the project is built by CMake, these resource files do not appear to have been packaged along with all the other project files. This results in a built program which, when run, show's a black screen with only any SFML objects being drawn, along with all the exceptions being raised in terminal, as can be seen here:


I am really unsure what the next step, and I apologise if this is not the place to ask questions like this, but I'm quite desperate to get this working and am now running out of ideas to potentially fix it. Thanks in advance if anyone can provide any suggestions or even just point me in the right direction!

3
I agree that this seems unnecessary, I did initially forgo mentioning any assets in the source files section, given that they were already directly mentioned in their respective files in the project:
// Title & Score Font assignment:
    if(!font.loadFromFile("Font/Arial_Unicode.ttf"))
        std::cout << "ERROR: Could not load font file." << std::endl;
but for whatever reason, when I attempt to run the build (whether it is mentioned or not in SOURCE_FILES section of CMakeLists.txt), all assets fail to load:
/Users/TheSpaceEvader/Documents/C++\ Projects/Sk-iver/SK_IVER ; exit;
Failed to open sound file "Resources/Sounds/nice_music.ogg" (couldn't open stream)
ERROR: could not load audio file from file path
Failed to load font "Font/Arial_Unicode.ttf" (failed to create the font face)
ERROR: Could not load font file.
Failed to load image "newDiver_spritesheet3.png". Reason: Unable to open file
ERROR: Could not load diver texture from file path.
Failed to load image "Resources/Images/skydiving_placeholder.jpg". Reason: Unable to open file
ERROR: Could not load diver texture from file path.
Window Active

[Process completed]

4
This is my first time attempting to build my game with CMake, and i've followed the steps on this (https://github.com/SFML/SFML/wiki/Tutorial%3A-Build-your-SFML-project-with-CMake) tutorial up til now. However, once it came to the very final steps ("cmake CMakeLists.txt", "cmake --build .") my build appears to have failed loading any of my assets. This includes, pictures, sounds & fonts, while all SFML assets appear to be drawing as usual, I cant seem to figure it out. I've attempted to directly reference their file paths in the CMakeLists.txt file, in the hopes that even one variation of the different file paths would work, but no luck. It might go without saying, but run from within my IDE (CLion) the project runs perfectly. Just incase it's relevant (and as there's not really much code I can show here), I've included my CMakeLists.txt code, just incase that might help:

cmake_minimum_required(VERSION 3.8)

# Enable debug symbols by default
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build (Debug or Release)" FORCE)
endif()

project(Sk_iver)

set(CMAKE_CXX_STANDARD 11)

# Set version information in a config.h file
set(myproject_VERSION_MAJOR 1)
set(myproject_VERSION_MINOR 0)
configure_file(
        "${PROJECT_SOURCE_DIR}/config.h.in"
        "${PROJECT_BINARY_DIR}/config.h"
)
include_directories("${PROJECT_BINARY_DIR}")

set(SOURCE_FILES
        Font
        Resources
        newDiver_spritesheet3.png
        Font/Arial_Unicode.ttf
        main.cpp
        Diver.cpp
        Diver.h
        README.md Ring.cpp Ring.h HandleEvents.cpp HandleEvents.h Background.cpp Background.h Particle.cpp Particle.h Particles.cpp Particles.h Game.cpp Game.h)

# Define sources and executable
set(EXECUTABLE_NAME "SK_IVER")
add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES})

# Detect and add SFML
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(SFML REQUIRED system window graphics network audio)
if (SFML_FOUND)
    include_directories(${SFML_INCLUDE_DIR})
    target_link_libraries(SK_IVER ${SFML_LIBRARIES})
endif()

# Install target
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)

# CPack packagin
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
set(CPACK_PACKAGE_VERSION_MAJOR "${myproject_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${myproject_VERSION_MINOR}")
include(CPack)
 

5
Yes, that was it! Thank you so so much, i've been banging my head against this for days now!  ;D

6
In an effort to refactor, I recently moved the majority of the code in my main method into it's own Game class. However, upon doing so I appear to have broken a number of my window.draw() statements, without having them give any particular error, but rather, raising a EXC_BAD_ACCESS (code: EXC_I386_GPFLT) exception when I step through them in debug. Further research (https://bit.ly/2tXDEV3) indicates that this could mean that I'm using a "non-canonical pointer", but I'm relatively new to C++ development so I would not know where to even begin with this?

main.cpp:
#include "Game.h"


Game *game = nullptr;

int main()
{
    game = new Game;

    game->setUp();
    game->update();

    return 0;
}

Game.h:
#include <SFML/Graphics.hpp>

class Game {
public:
    void setUp();
    void update();

private:
    sf::RenderWindow window;
    sf::Vector2u screenDimensions;
    sf::Sound music;
    sf::Text title, score;
    int textAlpha = 256, playerScore = 0;
    std::vector<Ring> rings;
    sf::View backgroundView, playerView;
    bool quitGame = false;

    void textSetUp(sf::Text &text, std::string string, sf::Font font, unsigned int characterSize, sf::Color fillColour, sf::Text::Style style, sf::Vector2f position);
    void textSetUp(sf::Text &text, std::string string, sf::Font font, unsigned int characterSize, sf::Color fillColour, sf::Text::Style style, sf::Vector2f position, sf::Color outlineColour, float outlineThickness);
};

Game.cpp:
#include "Game.h"

void Game::setUp() {
    screenDimensions.x = 1920;
    screenDimensions.y = 1280;

    // Window:
    window.create(sf::VideoMode(screenDimensions.x, screenDimensions.y), "Sk-iver", sf::Style::Titlebar | sf::Style::Close | sf::Style::Resize);
    window.setPosition(sf::Vector2i(200, 150));
    window.setKeyRepeatEnabled(false); // TODO investigate
    window.setVerticalSyncEnabled(true);
    window.setFramerateLimit(60);

    // Music:
    sf::SoundBuffer musicBuffer;
    if(!musicBuffer.loadFromFile("Resources/Sounds/nice_music.ogg"))
        std::cout << "ERROR: could not load audio file from file path" << std::endl;

    music.setBuffer(musicBuffer);
    music.setLoop(true);
    music.setVolume(20);
    music.play();

    // Title & Score Font assignment:
    sf::Font font;
    if(!font.loadFromFile("Font/Arial_Unicode.ttf"))
        std::cout << "ERROR: Could not load font file." << std::endl;

    // Title & Score Colour assignment:
    sf::Color scoreColour = titleColour = sf::Color::White;
    scoreColour.a = 150;

    // Title:
    std::string titleString = "Sk-iver";
    sf::Vector2f titlePosition((screenDimensions.x - title.getGlobalBounds().width) / 2,
                               (screenDimensions.y - title.getGlobalBounds().height) / 2);
    textSetUp(title, titleString, font, 500, titleColour, sf::Text::Bold, titlePosition);

    // Score:
    sf::Vector2f scorePosition(screenDimensions.x - score.getGlobalBounds().width, 0);
    textSetUp(score, std::to_string(playerScore), font, 80, scoreColour, sf::Text::Italic, scorePosition, sf::Color::Black, 5);

    // Background View:
    backgroundView.reset(sf::FloatRect(0, 0, screenDimensions.x, screenDimensions.y));
    backgroundView.setViewport(sf::FloatRect(0, 0, 1.0f, 1.0f));

    // Player View:
    playerView.reset(sf::FloatRect(0, 0, screenDimensions.x, screenDimensions.y));
    playerView.setViewport(sf::FloatRect(0, 0, 1.0f, 1.0f));
}

// text set up for title Text
void Game::textSetUp(sf::Text &text, std::string string, sf::Font font, unsigned int characterSize, sf::Color fillColour, sf::Text::Style style, sf::Vector2f position) {
    text.setString(string);
    text.setFont(font);
    text.setCharacterSize(characterSize);
    text.setFillColor(fillColour);
    text.setStyle(style);
    text.setPosition(position);
}

// text set up for score Text
void Game::textSetUp(sf::Text &text, std::string string, sf::Font font, unsigned int characterSize, sf::Color fillColour, sf::Text::Style style, sf::Vector2f position, sf::Color outlineColour, float outlineThickness) {
    text.setString(string);
    text.setFont(font);
    text.setCharacterSize(characterSize);
    text.setFillColor(fillColour);
    text.setStyle(style);
    text.setPosition(position);
    text.setOutlineColor(outlineColour);
    text.setOutlineThickness(outlineThickness);
}

void Game::update() {
    // todo find a more elegant solution for this
    Diver player = Diver(window.getSize());
    Background background = Background(window.getSize());

    while(!quitGame) // beginning of game loop
    {
        // Get player inputs:
        quitGame = HandleEvents(music, window);
       
        window.setView(backgroundView);

        // Background (update & draw):
        background.update();
        background.draw(window);

        // Rings (generate, update & draw):
        if (clock.getElapsedTime().asSeconds() > 9)
        {
            Ring ring = Ring(window.getSize());
            rings.emplace_back(ring);
            clock.restart();
        }

        // todo make two vectors, one for all rings where getStage()<= 1, and those that == 2
        for (auto &ring : rings)
        {
            if(ring.getStage() <= 1)
            {
                int tempScore = ring.update(player);

                // Score update
                if(tempScore)  // i.e. if tempScore != 0
                {
                    playerScore += tempScore;

                    score.setString(std::to_string(playerScore));
                    score.setPosition(screenDimensions.x - score.getGlobalBounds().width, 0);
                }

                ring.draw(window);
            }
        }

        // The Player (update & draw):
        window.setView(playerView);

        player.getInputs();
        frameCounter = player.update(clock, frameCounter, frameSpeed);
        player.draw(window);

        // slowly fades out title - todo: needs to be in it's own title object
        if (textAlpha > 5) // means that title is no longer drawn once no longer visible
        {
            if (clock.getElapsedTime().asSeconds() > 5)
            {
                titleColour.a = static_cast<sf::Uint8>(textAlpha--);
                title.setFillColor(titleColour);
            }

            window.draw(title);
        }
        else
        {
            window.draw(score);
        }

        window.display();
        window.clear();
    }
}
 

Note: music is also not working, which I have also not altered and believe may be related, but cannot prove this atm. Otherwise, most other sprites/shapes called in their own draw functions are drawing as normal.

Any help with this would be greatly GREATLY appreciated!

Pages: [1]