3

so i'm fairly new with SDL, and i'm trying to make a little snowboarding game. When the player is moving down the hill, I want to leave a trail of off-coloured snow behind him. Currently, the way i have this working is I have an array (with 1000 elements) that stores the players last position. Then each frame, I have a for loop that loops 1000 times, to draw out the trail texture in all these last 1000 positions of the player...

I feel this is extremely inefficient, and i'm looking for some better alternatives!

The Code:

void Player::draw()
{
    if (posIndex >= 1000)
    {
        posIndex = 0;
    }

    for (int i = 0; i < 1000; i++) // Loop through all the 1000 past positions of the player
    {
        // pastPlayerPos is an array of SDL_Rects that stores the players last 1000 positions
        // This line calculates teh location to draw the trail texture
        SDL_Rect trailRect = {pastPlayerPos[i].x, pastPlayerPos[i].y, 32, 8};
        // This draws the trail texture
        SDL_RenderCopy(Renderer, Images[IMAGE_TRAIL], NULL, &trailRect);
    }

    // This draws the player
    SDL_Rect drawRect = {(int)x, (int)y, 32, 32};
    SDL_RenderCopy(Renderer, Images[0], NULL, &drawRect);

    // This is storing the past position
    SDL_Rect tempRect = {x, y, 0, 0};
    pastPlayerPos[posIndex] = tempRect;

    posIndex++; // This is to cycle through the array to store the new position

The result

This is the result, which is exactly what i'm trying to accomplish, but i'm just looking for a more efficient way. If there isn't one, i will stick with this.

picklechips
  • 746
  • 2
  • 8
  • 28

1 Answers1

1

There are multiple solutions. I'll give you two.

1.

Create screen-size surface. Fill it with alpha. On each player move, draw it's current position into this surface - so each movement will add you extra data to this would-be mask. Then blit this surface on screen (beware of blit order). In your case it could be improved by disabling alpha and initially filling surface with white, and blitting it first, before anything else. With that approach you can skip screen clearing after flip, by the way.

I recommend starting with this one.

2.

Not easy one, but may be more efficient (it depends). Save array points where player actually changed movement direction. After it, you need to draw chainline between these points. There is however no builtin functions in SDL to draw lines; maybe there are in SDL_gfx, i never tried it. This approach may be better if you'll use OpenGL backend later on; with SDL (or any other ordinary 2D drawing library), it's not too useful.

keltar
  • 17,711
  • 2
  • 37
  • 42
  • The first option sounds like it might work for me. But I'm a little lost. What do you mean "draw it's current position into this surface"? Also you said I can skip the screen clearing by "Disabling alpha, and initially filling the surface with white, and blitting it first". How would this work? Do you mean i draw it's current position onto the surface, and than do that to this surface? I would like to accomplish this, but I'm a little confused. Would you be able to elaborate? – picklechips Nov 26 '13 at 20:41
  • Ough, just realised you're using SDL2. It actually does have lines drawing, if you'll need one. But back to the first one: if it is SDL2, you have texture set up as render target (with `SDL_SetRenderTarget`), so your drawing functions will actually draw into this texture. Fill it with white color, since your background is white. On each frame draw rectangle with current player position, just like you do now. Then reset render target back to screen, copy your resulting texture on screen and draw trees and other things needed. No need to clear screen anymore, since it is already white. – keltar Nov 27 '13 at 03:19
  • If it still doesn't gives you an idea, you could upload your source/images somewhere so i could take a look and modify it when i'll have a time. If it isn't too messy or windows-specific. – keltar Nov 27 '13 at 03:22
  • Ahhh, ok that makes more sense! I think i should be able to accomplish it that way. I'll try it out tomorrow (I have a chemistry test to study for right now :/ ) and then let you know how it goes! – picklechips Nov 28 '13 at 01:02
  • Ughhhh i'm having a tough time... So i created a new texture, set it to the render target, rendered the trails to the screen and it works perfectly, but the background is pitch black. I tried using fillRect but no matter whether or not i draw it before or after the trails, it covers them up! What's the deal? – picklechips Nov 29 '13 at 03:23
  • Could only guess that you haven't filled your render target texture with white color initially, before drawing any tracks. – keltar Nov 29 '13 at 06:20