0
\$\begingroup\$

I am fairly new to SDL in C, but I have written a simple game whereby a character has to reach the end of a level and avoid bad stars on the way. If he hits a star, he dies. There are also good stars he can collect and get points.

I have set up my point system so now when he hits a good star, he should get a point. However, when he hits a star, he actually gets lots of points, as long as he is touching the star, which I don't want. I think that what's happening is because the stars are moving and he rubs up against the stars; each pixel he moves counts as a new collision so he gets a point per collision. Ideally, he should only get one point per star.

So I have two problems: 1) I need to figure out how to make it so that he can only get one point when he hits a star. 2) Since he is supposed to be 'collecting' the stars, I want to make the star disappear when he collects it.

So it's similar to most of these types of games, whereby, the player collects something, it disappears and they get a point.

EDIT:

This is struct I've made:

typedef struct {
    int x, y, w, h, baseX, baseY, mode;
    float phase;
} Goodstar;

I've then referenced it in another struct like so:

Goodstar goodStars[GOOD_STARS];
SDL_Texture *goodStar;

[GOOD_STARS] is equal to 100.

And then here's my collision detection code:

// Check for collision with good stars
for (int i = 0; i < GOOD_STARS; i++) {
    if (collide2d(game->man.x, game->man.y, game->goodStars[i].x, game->goodStars[i].y, 48, 48, 32, 32)) {
        if (!game->man.isDead) {
            game->man.points++;
        }
        break;
    }
}

So right now it only checks for a collision and then adds a point.

EDIT 2:

This is the code you suggested and it works:

for (int i = 0; i < GOOD_STARS; i++) {
    if (!game->goodStars[i].awarded) {
        if (collide2d(game->man.x, game->man.y, game->goodStars[i].x, game->goodStars[i].y, 48, 48, 32, 32)) {
            if (!game->man.isDead) {
                game->man.points++;
                game->goodStars[i].awarded = 1;
            }
            break;
        }
    }
}

And this is my initialisation code:

  // Initialise stars
  for (int i = 0; i < GOOD_STARS; i++) {
    game->goodStars[i].baseX = 320 + random() % 38400;
    game->goodStars[i].baseY = random() % 480;
    game->goodStars[i].mode = random() % 2;
    game->goodStars[i].phase = 2 * 3.14 * (random() % 360) / 360.0f;
        game->goodStars[i].awarded = 0;
  }
\$\endgroup\$
5
  • \$\begingroup\$ How do you store the stars in your game code? \$\endgroup\$
    – user35344
    Aug 20, 2016 at 14:46
  • \$\begingroup\$ I've made an array of surfaces and textures of the stars. I load the image of the star and create a surface from it, which I then use to make a texture. \$\endgroup\$
    – AkThao
    Aug 20, 2016 at 14:47
  • \$\begingroup\$ And how do you check for the collisions? How do you store the positions of the stars? \$\endgroup\$
    – user35344
    Aug 20, 2016 at 14:47
  • \$\begingroup\$ I use a function which checks if the x co-ordinates of any side of the man are equal to the x co-ordinates of a star. And I do the same for y co-ordinates. \$\endgroup\$
    – AkThao
    Aug 20, 2016 at 14:48
  • \$\begingroup\$ I use co-ordinates of the game window and I initialise the stars this way. Then I use SDL_RenderCopy and SDL_RenderPresent to draw the stars. \$\endgroup\$
    – AkThao
    Aug 20, 2016 at 14:50

1 Answer 1

0
\$\begingroup\$

So the general approach is the following: you check if the player collides with a star, and if it does, you award the player a point, and then destroy the star.

All right, so seeing your code, I would simply add a boolean called awarded or something similar to the Goodstar. Initialize that to false when you create your stars.

Now, when the player collides with a star, mark awarded as true, and in the future, don't award points to players if awarded is true. So something like

for (int i = 0; i < GOOD_STARS; i++) {
    if (!game->goodStars[i]->awarded)
    {
        if (collide2d(game->man.x, game->man.y, game->goodStars[i].x, game->goodStars[i].y, 48, 48, 32, 32)) {
            if (!game->man.isDead) {
                game->man.points++;
                game->goodStars[i]->awarded = true;
            }
            break;
        }
    }
}

You would also then not render stars that have awarded set to true.

\$\endgroup\$
15
  • \$\begingroup\$ Yes, that's pretty much what I'm aiming for. I'll post my code in my question. \$\endgroup\$
    – AkThao
    Aug 20, 2016 at 14:58
  • \$\begingroup\$ So? This is what you already have? What's the issue then? You want me to debug your current code? \$\endgroup\$
    – user35344
    Aug 20, 2016 at 14:59
  • 1
    \$\begingroup\$ Ok I'll keep that in mind, thank you for your help. \$\endgroup\$
    – AkThao
    Aug 20, 2016 at 15:04
  • 1
    \$\begingroup\$ I just did that now before I read your comment :) I didn't get it first, but then I realised what you meant. I created an if statement, saying if awarded is false, then draw the stars. So now it fully works and when he collects a star, it disappears and he gets a point. Thank you so much, that really helped. \$\endgroup\$
    – AkThao
    Aug 20, 2016 at 15:27
  • 1
    \$\begingroup\$ Thank you, my project is pretty much finished now, this was just the final thing I needed to sort out. \$\endgroup\$
    – AkThao
    Aug 20, 2016 at 15:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .