Search code examples
cgraphicsspritesfml

CSFML unintended repeating texture behaviour


I'm working on a CSFML 2d runner game project and want to implement some parallax to give the player an impression of speed. To do this I'd like to have some assets repeated through sfTexture_setRepeated but alas. It doesn't repeat them, it extends it borders pixels to the size of the sprite rectangle I've set for some reason unknown to me.

Here are snippets concerning what I'm trying to do :

runner_objects.h

included in runner_objects.c

typedef enum {
    PLAYER      ,
    OBSTACLE    ,
    BACKGOUND1  ,
    BACKGOUND2  ,

    OBJ_COUNT
} objtype_t;

static const char *texture[OBJ_COUNT] = {
        "res/undefined.png"     ,
        "res/undefined.png"     ,
        "res/bg_clouds.png"     ,
        "res/bg_mountain.tga"   ,
};

static const sfIntRect rect[OBJ_COUNT] = {
        {0,         0,          0,          0}          ,
        {0,         0,          0,          0}          ,
        {0,         0,          1920*3,     1080}       ,
        {0,         0,          1920*2,     1080}       ,
};

typedef struct object {
    // Properties
    objtype_t       type;
    sfTexture       *texture;
    sfSprite        *sprite;
    sfIntRect       rect;
    sfVector2f      pos;

    // Linked listing
    struct object   *next;
} obj_t;

runner_objects.c

// Macros like TE_CREATE etc are simply CSFML functions made
// shorter to respect a strict 80 columns limit.
// TE_ = sfTexture, S_ = sfSprite

...
obj_t *object_create (objtype_t type, sfVector2f pos)
{
    obj_t *new_obj = malloc(sizeof(obj_t));

    if (!new_obj)
        return NULL;
    new_obj->texture        = TE_CREATE_WHOLE(texture[type]);
    new_obj->sprite         = S_CREATE;
    if (!new_obj->texture || !new_obj->sprite)
        return object_destroy(&new_obj); // Destroys existing parts and returns NULL
    new_obj->type           = type;
    new_obj->rect           = rect[type];
    new_obj->pos            = pos;
    S_SETTEXTURE(new_obj->sprite, new_obj->texture);
    if (type == BACKGOUND2 || type == BACKGOUND1)
        TE_SETREPREATED(new_obj->texture, true);
    S_SETINTRECT(new_obj->sprite, new_obj->rect);
    S_SETPOS(new_obj->sprite, new_obj->pos);
    new_obj->next           = NULL;
    return new_obj;
}
...

runner_env.c

Where I setup the game environment

...
// This function is called by int env_create(env_t **env) which is called
// from my main with the address of my env struct pointer.
int env_create_background(env_t **env)
{
    (*env)->objects = object_create(BACKGOUND2, (sfVector2f) {0 , 0});
    if (!(*env)->objects)
        return mr_puterr(ERR_CREABG); // Puts an error string on STDERR and returns corresponding error code
    (*env)->objects->speed = (sfVector2f) { 0, 0 };
    (*env)->objects->next = object_create(BACKGOUND1, (sfVector2f) {0 , 0});
    if (!(*env)->objects->next)
        return mr_puterr(ERR_CREABG);
    (*env)->objects->next->speed = (sfVector2f) { 0, 0 };
    return NO_ERR;
}
// I know it's very ugly and I'll make an actual linked
// list constructor later this is just for testing for now.
...

and my env_t structure contains these, if you're curious.

typedef struct environment {
    sfRenderWindow      *window;
    sfClock             *clock;
    sfEvent             *evt;
    obj_t               *objects;
} env_t;

Now for a visual explanation of the issue.

Here's a screenshot of what I get. Not the kind of clouds I expected.

So what am I doing wrong ? What did I miss ? Is there a way or order to set this up that I could have messed up ?


Solution

  • Okay I'm just an idiot I made my TE_SETREPEATED macro use sfTexture_setSmooth. I feel dumb.