Variable in Python going up by more than 1 at a time

55 views Asked by At

I am currently making a project for my school for fun, and I came across a problem. The project is a paddle and ball game, and every time the ball hits the paddle the score SHOULD go up by one, but instead it increments by 3, and sometimes 2. I have thought of manually incrementing with another variable and a constant check, but I think there is another better solution. Here is the code:

#----- IMPORTS --------
import time
import math

app.score = Label('0', 200, 50, size=25)

ball = Group(
Circle(200, 200, 17, fill=rgb(130, 130, 130), border='black', borderWidth=7)  
)

paddle = Group(
Circle(170, 375, 18, fill=rgb(130, 130, 130), border='black', borderWidth=10),
Circle(240, 375, 18, fill=rgb(130, 130, 130), border='black', borderWidth=10),
Line(170, 362, 240, 362, lineWidth=10),
Line(170, 388, 240, 388, lineWidth=10),
Rect(170, 366.5, 70, 17, fill=rgb(130, 130, 130))
)

app.press = False
app.sec = time.time()
app.xvel = 0
app.yvel = 0
app.paddle_xvel = 0
app.mousex = 0
app.mousey = 0
app.scoreVar = 0

app.ballx = 0
app.bally = 0
app.padx = 0
app.pady = 0

def onMouseMove(mouseX, mouseY):
app.mousex = mouseX
app.mousey = mouseY

def onMousePress(mouseX, mouseY):
app.press = True

def onMouseRelease(mouseX, mouseY):
app.press = False

def _init_():
ball.visible = False
paddle.visible = False
app.background = 'skyblue'
app.score.visible = False

_init_()

playBtn = Group(
Circle(140, 210, 30, fill=rgb(150, 225, 170), border='black', borderWidth=10),
Circle(260, 210, 30, fill=rgb(150, 225, 170), border='black', borderWidth=10),
Rect(140, 190, 120, 40, fill=rgb(150, 225, 170)),
Line(140, 185, 260, 185, lineWidth=10),
Line(140, 235, 260, 235, lineWidth=10),
Label('P l a y', 200, 210, size=30, bold=False, font='montserrat')
)

def onStep():
app.sec = time.time()
#----- Ball physics ------
ball.centerY += app.yvel
ball.centerX += app.xvel
app.yvel += 1
app.ballx = ball.centerX
app.bally = ball.centerY
app.padx = paddle.centerX
app.pady = paddle.centerY - 20

    paddle.rotateAngle = (app.paddle_xvel / 2)
    if app.mousex > paddle.centerX:
        app.paddle_xvel += 3
    if app.mousex < paddle.centerX:
        app.paddle_xvel += -3
    app.paddle_xvel = app.paddle_xvel / 1.2
    paddle.centerX += app.paddle_xvel
    
    if app.yvel < -20:
        app.yvel = -20
    if ball.centerX > 390:
        app.xvel = -5
    if ball.centerX < 10:
        app.xvel = 5
    if ball.centerY >= 400:
        ball.centerY = 200
        app.yvel = 0
        app.xvel = 0
        ball.centerX = 200
    
    #---- HIT CHECK -------
    
    for shape in paddle:
        if ball.hitsShape(shape) == True:
            app.yvel = -20
            app.xvel = app.paddle_xvel
            app.scoreVar += 1
            app.score.value = app.scoreVar
        
    
    #----- Ball physics explanation ------
    
    # First, we set the ball's y velocity (the speed that it goes down by exponentially). 
    # Then, we make it so that the Y and X values are CHANGED by, not set to, the velocities.
    # Next we do a few checks, like if the ball is touching the wall, if it is touching 
    # the ground, and we reset it. If it touches the wall we just bounce it the opposite way.
    # The ball's terminal velocity is -20, which is the max speed the ball can get to.'''
    
    #---- Play btn physics
    playBtn.rotateAngle = math.sin((((app.sec*2)+100) * 2) + 100)
    playBtn.centerX = math.sin(app.sec*2.5) * 3 + 200
    
    if playBtn.contains(app.mousex, app.mousey):
        if app.press == True:
            paddle.visible = True
            ball.visible = True
            app.background = 'white'
            playBtn.visible = False
            app.score.visible = True

lastTime = app.sec
app.sec -= lastTime

Note that this code is in CMU CS academy, so forever loops like while true loops are impossible, you can't nest loops, and you can't define the same function twice. The docs are VERY useful: https://academy.cs.cmu.edu/docs. You might have to click on the docs/colors tab to get it open. My problem is with the "app.scoreVar += 1, app.score.value = app.scoreVar" These lines of code make it so that the Label of the score changes by "1" but instead it changes by 2 or 3 based on the speed of your paddle. I can't use time.sleep() because it freezes the whole game instead of only the respective scope.

1

There are 1 answers

0
Kraigolas On BEST ANSWER

The culprit is here:

for shape in paddle:
    if ball.hitsShape(shape) == True:
        app.yvel = -20
        app.xvel = app.paddle_xvel
        app.scoreVar += 1
        app.score.value = app.scoreVar

Probably, if the inner if statement is True, you should just break out of the for loop.

for shape in paddle:
    if ball.hitsShape(shape) == True:
        app.yvel = -20
        app.xvel = app.paddle_xvel
        app.scoreVar += 1
        app.score.value = app.scoreVar
        break

Otherwise, if the ball hits multiple shapes, the score will go up by more than 1.