Krystian O
Krystian O

Reputation: 35

TypeError: Rect argument is invalid, but syntax looks fine

I had a function to draw a health bar, using a global variable to set the width of a green rectangle to cover a preset red one. When I changed my code to be able to have monsters actually damage the wall, the rect argument stopped working.

I have tried as many different ways to make it work but none of them worked.

Here is my code:

import pygame
import random

pygame.init()

displayWidth = 500
displayHeight = 600
currentWeapon = 'Bow'
projectileLength = 64
projectileHeight = 10
wallHealth = 100
coinCount = 0
currentWave = 0

black = (0, 0, 0)
white = (255, 255, 255)
darkGrey = (100, 100, 100)
orange = (200, 100, 0)
brightOrange = (250, 125, 0)
green = (0, 200, 0)
brightGreen = (0, 255, 0)
red = (200, 0, 0)

gameDisplay = pygame.display.set_mode((displayWidth, displayHeight))
pygame.display.set_caption('Project')

clock = pygame.time.Clock()

wallImg = pygame.image.load('buildings/wall.png')
blacksmithImg = pygame.image.load('buildings/blacksmith.png')
bookshelfImg = pygame.image.load('buildings/bookshelf_and_cauldron.png')

bowImg = pygame.image.load('weapons/bow.png')
arrowImg = pygame.image.load('weapons/arrow.png')
bowSelectedImg = pygame.image.load('weapons/weapon_select_bow.png')
magicSelectedImg = pygame.image.load('weapons/weapon_select_magic.png')
magicBoltImg = pygame.image.load('weapons/magic_bolt.png')

elementalFireImg = pygame.image.load('monsters/misc/elementalFire.png')
elementalWaterImg = pygame.image.load('monsters/misc/elementalWater.png')
lizardImg = pygame.image.load('monsters/misc/lizard.png')
medusaImg = pygame.image.load('monsters/misc/medusa.png')
slimeImg = pygame.image.load('monsters/misc/slime.png')
spiderImg = pygame.image.load('monsters/misc/spider.png')

coinImg = pygame.image.load('coin.png')

def background():
    gameDisplay.fill(green)
    gameDisplay.blit(wallImg, (0, 0))
    pygame.draw.rect(gameDisplay, black, (0, (displayHeight/2)-1, displayWidth, 2))
    button('(Price)', 225, 550, 50, 30, orange, brightOrange, None)
    button('(Price)', 80, 550, 50, 30, orange, brightOrange, None)
    button('(Price)', 380, 550, 50, 30, orange, brightOrange, None)

def blacksmith():
    gameDisplay.blit(blacksmithImg, (125,330))
    button('(Price)', 150, 430, 50, 30, orange, brightOrange, None)

def magicBuilding():
    gameDisplay.blit(bookshelfImg, (275, 330))
    button('(Price)', 300, 430, 50, 30, orange, brightOrange, None)

def coins():
    global coinCount
    gameDisplay.blit(coinImg, (displayWidth-100, 25))

def wallHealth(health):
    global wallHealth
    pygame.draw.rect(gameDisplay, red, (displayWidth - 110, 5, 100, 15))
    pygame.draw.rect(gameDisplay, brightGreen, (displayWidth - 110, 5, wallHealth, 15))

def text_objects(text, font, colour):
    textSurface = font.render(text, True, colour)
    return textSurface, textSurface.get_rect()

def button(msg, x, y, w, h, ic, ac, action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(gameDisplay, ac, (x, y, w, h))
        if click[0] == 1 and action != None:
            action()

    else:
        pygame.draw.rect(gameDisplay, ic, (x, y, w, h))

    smallText = pygame.font.Font('freesansbold.ttf', 10)
    textSurf, textRect = text_objects(msg, smallText, black)
    textRect.center = ((x+(w/2)), (y+(h/2)))
    gameDisplay.blit(textSurf, textRect)

def weapon():
    global currentWeapon
    mouse = pygame.mouse.get_pos()

    if currentWeapon == 'Bow':
        if mouse[1] < (displayHeight/2)-20:
            gameDisplay.blit(bowImg, (0, mouse[1]-20))
        elif mouse[1] > (displayHeight/2)-20:
            gameDisplay.blit(bowImg, (0, (displayHeight/2)-40))
        gameDisplay.blit(bowSelectedImg, (50, 0))
    if currentWeapon == 'Magic':
        if mouse[1] < (displayHeight/2)-20:
            gameDisplay.blit(magicBoltImg, (0, mouse[1]-20))
        elif mouse[1] > (displayHeight/2)-20:
            gameDisplay.blit(magicBoltImg, (0, (displayHeight/2)-40))
        gameDisplay.blit(magicSelectedImg, (50, 0))

def projectile1(x, y):
    gameDisplay.blit(arrowImg, (x, y))

def monster(x, y):
    gameDisplay.blit(lizardImg, (x, y))

def game_loop():
    global currentWeapon
    global projectileLength
    global projectileHeight
    global wallHealth

    projectile1X = 0
    projectile1Xchange = 10
    projectile1Fired = False

    monsterX = displayWidth
    monsterXchange = 2
    monsterSpawned = False
    monsterDamage = 10

    wallDamaged = False

    gameExit = False

    while not gameExit:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    currentWeapon == 'Bow'
                if event.key == pygame.K_2:
                    currentWeapon == 'Magic'

        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed()

        background()
        weapon()
        blacksmith()
        magicBuilding()

        if click[0] == 1 and projectile1Fired == False and mouse[1] < displayHeight/2:
            projectile1Fired = True
            projectile1X = 0
            projectile1Y = mouse[1]-5

        if monsterSpawned == False:
            monsterSpawned = True
            monsterX = displayWidth
            monsterY = random.randrange(0, displayWidth/2-50)

        if monsterSpawned == True:
            monster(monsterX, monsterY)

        if monsterX == 50:
            monsterSpawned = False
            wallDamaged = True

        if projectile1Fired == True:
            projectile1(projectile1X, projectile1Y)

        projectile1X += projectile1Xchange
        monsterX -= monsterXchange

        if projectile1X > displayWidth:
            projectile1Fired = False

        if projectile1Fired == True:
            if projectile1X + projectileLength > monsterX:
                if projectile1Y > monsterY and projectile1Y + projectileHeight < monsterY + 50:
                    monsterSpawned = False
                    projectile1Fired = False

        if wallDamaged == True:
            wallHealth -= monsterDamage
            wallDamaged = False

        coins()
        wallHealth(wallHealth)

        pygame.display.update()
        clock.tick(60)
game_loop()

pygame.quit()
quit()

The parts of my code which I think might be part of the problem are here:

wallHealth = 100
brightGreen = (0, 255, 0)
red = (200, 0, 0)

def wallHealth(health):
    global wallHealth
    pygame.draw.rect(gameDisplay, red, (displayWidth - 110, 5, 100, 15))
    pygame.draw.rect(gameDisplay, brightGreen, (displayWidth - 110, 5, wallHealth, 15))

def game_loop():
    global wallHealth

    monsterDamage = 10
    wallDamaged = False

    if wallDamaged == True:
        wallHealth -= monsterDamage
        wallDamaged = False

I have no idea why it doesn't work and I am hoping for some useful advice.

Upvotes: 1

Views: 519

Answers (1)

sloth
sloth

Reputation: 101042

Look at this code inside the wallHealth function:

pygame.draw.rect(gameDisplay, brightGreen, (displayWidth - 110, 5, wallHealth, 15))

Here you pass a tuple to pygame.draw.rect, but that tuple consists of an integer, a second integer, the wallHealth function and a third integer. It should be four integers instead.

Now you see your problem.

To make a long story short: either rename the variable you store the amount of wall health in or rename the function.

You can't use the same name for different things at once.

Upvotes: 1

Related Questions