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\$
  • \$\begingroup\$ How do you store the stars in your game code? \$\endgroup\$ – Tyyppi_77 Aug 20 '16 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 '16 at 14:47
  • \$\begingroup\$ And how do you check for the collisions? How do you store the positions of the stars? \$\endgroup\$ – Tyyppi_77 Aug 20 '16 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 '16 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 '16 at 14:50
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\$
  • \$\begingroup\$ Yes, that's pretty much what I'm aiming for. I'll post my code in my question. \$\endgroup\$ – AkThao Aug 20 '16 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\$ – Tyyppi_77 Aug 20 '16 at 14:59
  • 1
    \$\begingroup\$ Ok I'll keep that in mind, thank you for your help. \$\endgroup\$ – AkThao Aug 20 '16 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 '16 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 '16 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.