Archimedes - Charles
Archimedes - Charles

Reputation: 15

If statement works on one, but not the other

I am using Pygame and a Buttons Module to replicate the code for a simple elevator program. I am running into the issue not displaying a certain button(created by the Buttons Module) based off of what the currentFloor is.

if currentFloor != maxFloor:#Checks if the currentFloor is not equal to the maxFloor
            self.Button3.create_button(self.setDisplay, colcyan, 550, 100, 200, 100,0,"Up",colblack)#Button to add one to currentLevel

This code provided is working for the button to go up. Although, when I attempt to recreate it using a similar line of code for the down button, It yeilds a error.

elif currentFloor != startFloor:#Checks if the currentFloor is not equal to the startFloor
            self.Button1.create_button(self.setDisplay, colred, 550, 400, 200, 100,0,"Down",colblack)#Button to subtract one to currentLevel

Error yielded:

Traceback (most recent call last):
  File "G:\Python APCSP\Elevator\Example.py", line 72, in <module>
    obj = Elevator()
  File "G:\Python APCSP\Elevator\Example.py", line 24, in __init__
    self.runGame()
  File "G:\Python APCSP\Elevator\Example.py", line 66, in runGame
    if self.Button1.pressed(pygame.mouse.get_pos()):
  File "G:\Python APCSP\Elevator\Buttons.py", line 29, in pressed
    if mouse[0] > self.rect.topleft[0]:
AttributeError: Button instance has no attribute 'rect'

I am unsure why a if statement very similar to the first one would provide such error.

The full source code will be provided below.

Elevator Program Source Code:

import pygame, Buttons, sys
from pygame.locals import *

#Color Options
colwhite = (255,255,255)
colblack = (0,0,0)
colgray = (33,33,33)
colblue = (0,61,103)
colred = (103,0,9)
colyellow = (255,229,9)
colgreen = (0,103,42)
colcyan = (0,118,118)
colpurple = (103,0,103)

#Initialize pygame
pygame.init()

currentFloor = 0
maxFloor = 5
startFloor = 0

class Elevator:
    def __init__(self):
        self.runGame()

    #Create a display
    def display(self):
        width = 800
        height = 600
        self.setDisplay = pygame.display.set_mode((width,height),0,32)
        pygame.display.set_caption("Elevator Program")

    #Update the display and show the button
    def update_display(self):
        global currentFloor
        self.setDisplay.fill(colblue)
        #Parameters:                     surface,   color,   x,   y,   length, height, width,    text,      text_color
        self.Button2.create_button(self.setDisplay, colblue, 525, 225, 250, 150,0,"Current Floor: "+str(currentFloor),colwhite)#Not a used button, just to display currentFloor
        if currentFloor != maxFloor:#Checks if the currentFloor is not equal to the maxFloor
            self.Button3.create_button(self.setDisplay, colcyan, 550, 100, 200, 100,0,"Up",colblack)#Button to add one to currentLevel
        elif currentFloor != startFloor:#Checks if the currentFloor is not equal to the startFloor
            self.Button1.create_button(self.setDisplay, colred, 550, 400, 200, 100,0,"Down",colblack)#Button to subtract one to currentLevel
        pygame.display.flip()


    #Run the loop
    def runGame(self):
        global currentFloor
        self.Button2 = Buttons.Button()
        self.Button1 = Buttons.Button()
        self.Button3 = Buttons.Button()
        self.display()
        while True:
            self.update_display()
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == MOUSEBUTTONDOWN:
                    if currentFloor != maxFloor:
                        if self.Button3.pressed(pygame.mouse.get_pos()):
                            print "Going Up"
                            currentFloor += 1
                            print currentFloor
                    if currentFloor != startFloor:
                        if self.Button1.pressed(pygame.mouse.get_pos()):
                            print "Going Down"
                            currentFloor -= 1
                            print currentFloor

if __name__ == '__main__':
    obj = Elevator()

Buttons Module Source Code:

import pygame
from pygame.locals import *
pygame.init()
class Button:
    def create_button(self, surface, color, x, y, length, height, width, text, text_color):
        surface = self.draw_button(surface, color, length, height, x, y, width)
        surface = self.write_text(surface, text, text_color, length, height, x, y)
        self.rect = pygame.Rect(x,y, length, height)
        return surface

    def write_text(self, surface, text, text_color, length, height, x, y):
        font_size = int(length//len(text))
        myFont = pygame.font.SysFont("Calibri", font_size)
        myText = myFont.render(text, 1, text_color)
        surface.blit(myText, ((x+length/2) - myText.get_width()/2, (y+height/2) - myText.get_height()/2))
        return surface

    def draw_button(self, surface, color, length, height, x, y, width):           
        for i in range(1,10):
            s = pygame.Surface((length,height))
            s.fill(color)
            pygame.draw.rect(s, color, (x-i,y-i,length+i,height+i), width)
            surface.blit(s, (x,y))

        pygame.draw.rect(surface, (190,190,190), (x,y,length,height), 1)  
        return surface

    def pressed(self, mouse):
        if mouse[0] > self.rect.topleft[0]:
            if mouse[1] > self.rect.topleft[1]:
                if mouse[0] < self.rect.bottomright[0]:
                    if mouse[1] < self.rect.bottomright[1]:
                        return True
                    else: return False
                else: return False
            else: return False
        else: return False

Upvotes: 0

Views: 89

Answers (2)

xor
xor

Reputation: 2698

Call the update_display() function after every update to currentFloor .

As once up button is pressed value of currentFloor is no longer 0.

As a result the second if condition (if currentFloor != startFloor in runGame's while loop) will also be checked but as the update_diplay() is not called in between so no button for down is initialised.

Also in update_display() function make both the condition as if as you need to check for both buttons no matter what.
Here is how your while loop should look like:

self.update_display()
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:
            if currentFloor != maxFloor:
                if self.Button3.pressed(pygame.mouse.get_pos()):
                    print "Going Up"
                    currentFloor += 1
                    print currentFloor
                    self.update_display()
            if currentFloor != startFloor:
                if self.Button1.pressed(pygame.mouse.get_pos()):
                    print "Going Down"
                    currentFloor -= 1
                    print currentFloor
                    self.update_display()

Upvotes: 0

DNA
DNA

Reputation: 42597

The rect attribute is only initialised when you call Button.create_button().

However, you run code in runGame() that expects this attribute to be present: you call Button.pressed() before calling Button.create_button() on button 1 or 3.

You need to ensure that the buttons are properly initialised before trying to use or query them. Or your pressed() method needs to check whether the button has been initialised, and return False if not.

Upvotes: 4

Related Questions