3

I'm making a paddle ball game on Scratch (just for fun), and I'm running into a problem with my scoring. If you want to look at the code I already wrote, the link to the game is https://scratch.mit.edu/projects/66541388/ . For some reason, when the game is played the score variable does not actually always change by one. It changes by a different number every time I test it. Any ideas on what the problem is or how to fix it?

Here's the core of the code:

when green flag clicked
set [Score v] to [0]
set x to (0)
set y to (0)
point in direction (pick random (-90) to (90))
forever
    if <(y position) < [-146]> then
        broadcast [gameOver v]
        stop [all v]
    end
    if <touching [Paddle v]?> then
        change [color v] effect by (pick random (1) to (1000))
        change [Score v] by (1)
        point in direction (pick random (-90) to (90))
    end
    move (10) steps
    if on edge, bounce
end
Scimonster
  • 32,893
  • 9
  • 77
  • 89
  • 1
    Keep an "already scored" flag, that changes when the ball has passed certain thresh-hold, and score only when it is not set. I assume your ball can't come twice towards the same penguin before having gone to the other one first, So you could restart the flag when the ball goes through an area in the middle of the screen and such. That way you won't have to be trying to calculate proper timing, that can vary for different conditions or need to fine tweak the steps you move, which assume could change if you change the figure (instead of a penguin an octopus, etc.) – Dzyann Jul 03 '15 at 13:10

6 Answers6

3

Though both answers are correct, you can simply put the scoring in a different block of code, with a wait until <not<touching [Paddle v]>>, like this:

when green flag clicked
forever
    if <touching [Paddle v]> {
        change [color v] effect by (pick random (1) to (1000))
        change [Score v] by (1)
        wait until <not<touching [Paddle v]>>
UnsignedByte
  • 849
  • 10
  • 29
0

Your problem is that you are dealing with a race condition. When you test for collision between your paddle and penguin the penguin does not leave the paddle as quick as the detection is getting called again causing it to add more than one to the score. You can add some timing code so that it can only increment score by 1 if a timer is greater than lets say one second. Then reset the timer after every "legal" hit.

There are other ways to deal with these conditions, but you have to be creative.

urnotsam
  • 770
  • 7
  • 24
0

urnotsam's answer is technically correct, but i'd like to give some reasoning behind it and an alternate solution.

The problem lies in the fact that a penguin is not a square. When you hit the paddle, it turns to a random direction, and moves 10 steps. Now, if it started out facing sideways, and the random direction is also pretty much sideways, it can escape with those 10 steps. Same if both are straight up. But if it starts sideways and ends straight up, it's now further below the line than it had been, and even after moving 10 steps, part of it is still touching the paddle. It seems to me that giving it a head start of another ten or twenty steps should let it escape, and not mess up your scoring.

if <touching [Paddle v]?> then
    change [color v] effect by (pick random (1) to (1000))
    change [Score v] by (1)
    point in direction (pick random (-90) to (90))
    move (20) steps
end
Community
  • 1
  • 1
Scimonster
  • 32,893
  • 9
  • 77
  • 89
0

The easiest way to avoid scoring multiple touches at the paddle is to count only touches of a ball that is going downwards, not upwards. Once a ball touches the paddle going downwards, its direction is changed to go upwards, so it would not be recounted.

To achieve this in your code, extend the line

if <touching [Paddle v]?> then

by

if <<touching [Paddle v] ?> and <([abs v] of (direction)) > [90]>> then

This works without additional variables or wait functions.

Peter B.
  • 371
  • 2
  • 16
0

The first thing you can do is to add a short delay for the scoring, so that the delay would let the penguin move away from the paddle. Then it will not be counted as a score.

However, another idea is to respawn the penguin whenever they score. You will still need a short delay, though. In this way, the penguin would not be in the way of the paddle.

Account_2
  • 53
  • 6
  • A delay is a workaround, not a proper fix. What if the sprites are still touching after the delay? Then you have an "only sometimes but", which is much harder to track down. – Roland Illig Oct 17 '19 at 03:45
  • Alright, you got me. Maybe during the delay, the penguin moves up until it no longer touches the paddle. – Account_2 Oct 18 '19 at 12:09
-1

When you change your score by 1 it may count it a few times because it is touching the paddle so you have to add a wait block right after the point in random direction block. It would look like this:

    if <touching [Paddle v]?> then
    change [color v] effect by (pick random (1) to (1000))
    change [Score v] by (1)
    point in direction (pick random (-90) to (90))
    wait [0.1] sec
end
TheLittleCoder
  • 21
  • 2
  • 11