• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM The score system in my flight game works... but not as intended.

B

BenSunhoof

Guest
Hello. It's been a while.

I'm trying to make something simple - an auto-scrolling flying game where you click to gradually ascend. I've implemented almost everything I wanted, except for the score system.
Runner_2020-03-08_17-45-36.png
1 point is assigned each 6 frames, making up 10 points per second. Here's what I'm trying to do - bonus points should be assigned whenever the player comes close to the edge of the obstacle. Here's the code I tried (a separate piece of code in the Step event of obj_score that affects obj_wall):
GML:
//Bonus score
if obj_player.x = x
{
    if (bbox_top > obj_player.bbox_bottom > bbox_top-obj_player.bbox_top) | (bbox_bottom < obj_player.bbox_top < bbox_bottom+obj_player.bbox_bottom)
        score += 25;
}
Instead of doing what I want it to do, the game adds 50 points whenever the player passes by a wall, I suppose its 25 points for both the bottom and the top sections of the wall, and it adds these points regardless of whether I'm near the obstacle or not.
What can I do here? Please help.
 

Slyddar

Member
(bbox_top > obj_player.bbox_bottom > bbox_top-obj_player.bbox_top)
I don't believe this is doing what you think it's doing. If you compare A to B to C, you are comparing True/False to C.

Also obj_player.x = x is an extremely unlikely comparison, as, depending on your speed values, the objects x values may be decimals. You probably want to look for when the players x is greater then the objects x, and ensure you have a way to only run that check once, using a flag variable.
 
Last edited:

Alice

Darts addict
Forum Staff
Moderator
The most obvious mistake is chaining the greater than/lower than signs. You should never write "a > b > c" in most programming languages, but rather write "a > b && b > c" instead. I'm pretty sure @FrostyCat made a tutorial pointing it out as one of common mistakes, but don't remember where exactly.

Also, you used a bitwise OR (single |) instead of logical OR (double ||).

By the way, I'd recommend using "==" for equality check instead of "=" (which is used for value assignment). Wrapping "if" conditions in brackets is also a good habit, as some programming languages require these.
"if some_variable = value" may be functional GML, but it's generally safer and more compatible with other languages to use "if (some_variable == value)".

So, this code with mistakes cleared up would be like:
GML:
//Bonus score
if (obj_player.x == x)
{
    if ((bbox_top > obj_player.bbox_bottom && obj_player.bbox_bottom > bbox_top-obj_player.bbox_top) ||
        (bbox_bottom < obj_player.bbox_top && obj_player.bbox_top < bbox_bottom+obj_player.bbox_bottom))
    {
        score += 25;
    }
}
I can't guarantee that it works as intended, but at least it should have the basic mistakes cleared up. I think you might sometimes be using bbox_* as coordinates of collision box boundaries (which is correct) and sometimes as bounding box heights? I'm afraid as it is now, it still wouldn't work as intended...
 
B

BenSunhoof

Guest
I can't guarantee that it works as intended, but at least it should have the basic mistakes cleared up. I think you might sometimes be using bbox_* as coordinates of collision box boundaries (which is correct) and sometimes as bounding box heights? I'm afraid as it is now, it still wouldn't work as intended...
Would using obj_player.sprite_height for heights be more reasonable?
I don't think it would, I tried it and it's still the same. What can I use to determine the height of a bbox?
 
B

BenSunhoof

Guest
I don't believe this is doing what you think it's doing. If you compare A to B to C, you are comparing True/False to C.
I don't think I quite get it yet. If so, what should I use to compare A, B and C?
 

Alice

Darts addict
Forum Staff
Moderator
I don't think I quite get it yet. If so, what should I use to compare A, B and C?
That's the problem I mentioned in my post.
What TheSly said probably meant that when you do comparison like this: "A > B > C", you actually do "(A > B) > C", and with "A > B" being either True or False it effectively becomes "True > C" or "False > C".

Would using obj_player.sprite_height for heights be more reasonable?
I don't think it would, I tried it and it's still the same. What can I use to determine the height of a bbox?
It would be something similar to obj_player.bbox_bottom - obj_player.bbox_top, maybe with 1 pixel added?

By the way, you mentioned having a separate obj_score. Is it that whole red rectangle with the same width as a wall, but extra height added to the top and bottom? If it's so, I can suggest simplifying the whole bonus checking a lot.
 
B

BenSunhoof

Guest
By the way, you mentioned having a separate obj_score. Is it that whole red rectangle with the same width as a wall, but extra height added to the top and bottom? If it's so, I can suggest simplifying the whole bonus checking a lot.
Nono, that's just a part of my debug GUI so that I can see where the player must travel through in order to get bonus points. As for the simplification part, I'm not sure how much else I can simplify it.

That's the problem I mentioned in my post.
What TheSly said probably meant that when you do comparison like this: "A > B > C", you actually do "(A > B) > C", and with "A > B" being either True or False it effectively becomes "True > C" or "False > C".
That's a lot to wrap my head around :p Well, I tried it again using your code as aid, but nothing's changed. I honestly don't know how else I could approach this.
 

Alice

Darts addict
Forum Staff
Moderator
Basically, have a separate obj_bonus created for each wall, corresponding more or less to the area drawn by the debug GUI.
Something like instance_create_layer(x,y,layer,obj_bonus) in obj_wall Create event should work, especially if both obj_wall and obj_bonus sprites have their origin centered.

Then, handle the collisions between the player and wall, and if there's no collision, the collisions between the player and bonuses.

In obj_player Step event, it would be roughly like that:
GML:
// First, check collisions with walls
with (instance_place(x, y, obj_wall)) {
    // destroy the player or something
    exit; // end the Step event here, so that no bonuses are collected
}
// If player didn't run into any wall, check collision with a bonus
with (instance_place(x, y, obj_bonus)) {
    score += 25; // claim the bonus
    instance_destroy(); // ensure the bonus is collected only once per wall
}
This should work properly under assumptions that:
- the player is destroyed right after a contact with a wall, so that in the next step it won't be there to potentially collect the bonus (if not, you can additionally make the wall delete its corresponding obj_bonus)
- the walls are always spread so far apart that the player can't collide with two bonuses at once
- there's no extra obj_player Step logic following the collisions check; otherwise, the "exit;" will prevent the execution of extra logic (you can mitigate that by wrapping collision checks in a script; then it's only the script logic being exit;-ed from)

This is slightly different from the logic you attempted to implement (especially the hard "obj_player.x == x" requirement), but I think it should work more or less as intended.
 
B

BenSunhoof

Guest
Basically, have a separate obj_bonus created for each wall, corresponding more or less to the area drawn by the debug GUI.
Something like instance_create_layer(x,y,layer,obj_bonus) in obj_wall Create event should work, especially if both obj_wall and obj_bonus sprites have their origin centered.

Then, handle the collisions between the player and wall, and if there's no collision, the collisions between the player and bonuses.

In obj_player Step event, it would be roughly like that:
GML:
// First, check collisions with walls
with (instance_place(x, y, obj_wall)) {
    // destroy the player or something
    exit; // end the Step event here, so that no bonuses are collected
}
// If player didn't run into any wall, check collision with a bonus
with (instance_place(x, y, obj_bonus)) {
    score += 25; // claim the bonus
    instance_destroy(); // ensure the bonus is collected only once per wall
}
This should work properly under assumptions that:
- the player is destroyed right after a contact with a wall, so that in the next step it won't be there to potentially collect the bonus (if not, you can additionally make the wall delete its corresponding obj_bonus)
- the walls are always spread so far apart that the player can't collide with two bonuses at once
- there's no extra obj_player Step logic following the collisions check; otherwise, the "exit;" will prevent the execution of extra logic (you can mitigate that by wrapping collision checks in a script; then it's only the script logic being exit;-ed from)

This is slightly different from the logic you attempted to implement (especially the hard "obj_player.x == x" requirement), but I think it should work more or less as intended.
Wow... this is a lot to unwrap. I think I might scrap the whole score idea until I actually understand this stuff. Thank you for your help either way.
 
Top