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 - anthonyy

Pages: [1]
1
I've fixed it now, thanks :)

2
Oh my god. I ported this code from pure C, I had no idea. Thanks so much for your help. I can't believe I didn't realise  :'(

3
This is as compact as I think I can get it.

#include <stdlib.h>

#include <map>
#include <string>

#include <SFML/Graphics.hpp>

typedef int Id;

/* This crap basically gets the unique ID for each component type */
Id
_unique_id() {
    static Id lastId = 0;
    return lastId++;
}

template<typename T>
Id type_id() {
    static Id typeId = _unique_id();
    return typeId;
}
/* ---------------------------------- */

/* Entity stuff */
/* ------------ */
struct Entity {
    Id id {0};

    std::map<Id, void *> components {};
};

template <typename T> void
add_component(Entity& e, T *c) {
    e.components[type_id<T>()] = c;
}

template <typename T> T *
get_component(Entity& e) {
    return static_cast<T *>(e.components[type_id<T>()]);
}
/* ------------ */

/* Util */
void
load_sprite(sf::Sprite& sprite, std::string file) {
    auto texture = (sf::Texture *)malloc(sizeof(sf::Texture));
    sprite.setTexture(*texture);
}
/* ---- */

struct RenderableComponent {
    sf::Sprite sprite;
};

int
main(int argc, char **argv) {
    sf::VideoMode videoMode {640, 480};
    sf::RenderWindow window {videoMode, "debug"};

    auto rc = (RenderableComponent *)malloc(sizeof(RenderableComponent));
    load_sprite(rc->sprite, "whatever.png");
    rc->sprite.setPosition(10, 30);

    Entity entity;
    add_component(entity, rc);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }

        window.clear();

        /* Try and use the sf::Sprite on RenderableComponent */
        window.draw(get_component<RenderableComponent>(entity)->sprite);
        /* aaaaaand it segfaults ;-; */

        window.display();
    }

    free(rc);
}
 

Thanks for helping out :)

4
Honestly I can't find anything. "this" is not null. The sprite is not null. The sf::Drawable passed into the draw method casted to an sf::Sprite is not null and it's texture isn't either. The render component is not null. The transform component is not null.

Valgrind run with --track-origins=yes doesn't tell me where the error originates either.

I don't know what to do ;-;

5
Okay I wiped SFML off my system again, built with debug symbols and the resulting call stack isn't much different.

sf::RenderTarget::draw(sf::RenderTarget * const this, const sf::Drawable & drawable, const sf::RenderStates & states

is the top of the stack. This function just calls

drawable.draw(*this, states);

I can't step into this call because it crashes immediately if I try  :(

6
Hmm... I just tested and I can read and write any other members I want to. For example, I added an int to my Renderable struct and initialized it to 10 on "hero", then used get_component to change it's value. Maybe it is an SFML issue?  :-\

7
I've since refactored and renamed stuff but the concept is the same. Here is the implementation of Entity just copy-pasted from my editor:

struct Entity {
    Id id;

    std::map<Id, void *> components;
};

template <typename T> void
add_component(Entity& e, T *c) {
    e.components[type_id<T>()] = c;
}

template <typename T> T *
get_component(Entity& e) {
    return static_cast<T *>(e.components[type_id<T>()]);
}

template <typename T> bool
has_component(Entity& e) {
    return (e.components[type_id<T>()] != nullptr);
}
 

A couple of notes regarding this implementation:
1. Id is just typedef'd as an int
2. type_id<> returns a unique Id (int) depending on which type was passed. It will always be consistent when the same type is passed though.

Basically I'm using an Entity-Component System where Entities are just a collection of components identified by a unique ID and components provide data. Systems act on entities with specific sets of components to manipulate them. Like an Entity with a TransformComponent and a RenderableComponent will be picked up by a RenderSystem and draw the entities.

So, to answer your question: get_component returns a pointer to the component of the type you requested so you can access it's data.

8
Okay nevermind lol

I've found that the problem only persists when my Render component is allocated on the heap. If it's on the stack, it works fine but it's pretty impractical to store my components on the stack.

Anyone have any ideas what could be causing this?

From the start I was never saying it's a problem with SFML I was simply asking if anybody knew what was wrong.

9
Okay I've basically done a full refactor and it seems to be working correctly now. I think it was a collection of dumb mistakes. Feel free to delete this topic.

10
Already building with debug symbols.

Here's the call stack:

render_system_draw(Engine *engine, EntityPool &pool)
render(Engine *engine, GameState *state)
main(int argc, char **argv)

OS: Xubuntu 16.04 LTS
GPU: NVIDIA GTX 750 Ti
GPU driver: proprietary NVIDIA version 367.57

I've also just rebuilt SFML from source again and done a clean reinstall to make sure there are no conflicts, no prebuilt packages for SFML are on my system either.

11
Hey,

I need another pair of eyes to look over my code to find out what the hell is going on :P

I get no compiler or link errors but I segfault every time, upon closer inspection with Valgrind, I am given an error message:

Access not within mapped region at address 0x10
==21451==    at 0x52A31B6: sf::RenderTarget::draw(sf::Drawable const&, sf::RenderStates const&) (in /usr/local/lib/libsfml-graphics.so.2.4.1)
 

It crashes during this function:

void
render_system_draw(Engine *engine, EntityPool &pool) {
    std::shared_ptr<TransformComponent> transform;
    std::shared_ptr<RenderComponent> render;

    for (Entity *ent : pool.entities) {
        if (entity_has_component<TransformComponent>(ent) && entity_has_component<RenderComponent>(ent)) {
            transform = entity_get_component<TransformComponent>(ent);
            render = entity_get_component<RenderComponent>(ent);

            render->sprite.setPosition(sf::Vector2f(transform->x, transform->y));

            engine->window.draw(render->sprite); /* CRASHES HERE */

        }
    }
}
 

render->sprite is an sf::Sprite, the texture is maintained since I do all my allocations in a big pool and give out sub-allocations so it only gets freed at the end. I've got into the debugger and poked around, double-triple checking that render->sprite is not null, nor is engine or the entity pool.

If I move the draw code out into game.cpp, and use a separate texture and position, it works fine. But as soon as I call it in render_system_draw, it segfaults. render and texture are not null, nor is any of their members.

Help please :P

If you need to see any more code then just say and I'll post whatever you need.

Pages: [1]