[pygame] TypeError pygame.Surface, not pygame.Rect ?

[pygame] TypeError pygame.Surface, not pygame.Rect ?

Postby spamynator_1 » Thu Aug 01, 2013 4:42 am

i am trying to invent some sort of button or rectangle that functions as a button.

Code: Select all
import sys
import os
import pygame as pg
import pickle
import pygame.mixer
from pygame.locals import *

SCREEN_SIZE = SCREEN_WIDTH,SCREEN_HEIGHT = (640,480)

RED = (255,0,0)
ORANGE = (255,127,0)
YELLOW = (255,255,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
INDIGO = (75,0,130)
VIOLET = (143,0,255)

class Control(object):
    def __init__(self):
        self.screen = pg.display.get_surface()
        self.done = False
        self.state = "START"
        self.clock = pg.time.Clock()
        self.fps = 60
        self.enter_coords = [0,400]
        self.keys = pg.key.get_pressed()
       
    def event_loop(self):
        for event in pg.event.get():
            self.keys = pg.key.get_pressed()
            if event.type == pg.QUIT or self.keys[pg.K_ESCAPE]:
                self.done = True

            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_RETURN and self.state == "START":
                    self.state = "MENU"

            elif self.state == "MENU":
                if event.type == MOUSEBUTTONDOWN:
                    if event.button == 1:
                        if BUTTON_NEW_rect.collidepoint(mx,my):
                            self.state == "START"
                   
            elif self.state == "map1":
                crud = "1-0,0    0"
                sys(exit)
                with open("bruce", "wb") as f:
                    pickle.dump(crud, f)

    def main_loop(self):
        while not self.done:
            self.event_loop()
            self.update()
            pg.display.update()
            self.clock.tick(self.fps)

    def update(self):
        if self.state == "START":
            self.screen.blit(START_PAGE,(0,0))
            self.screen.blit(PRESS_ENTER,self.enter_coords)
            self.enter_coords[0] = (self.enter_coords[0]+2)
        elif self.state == "MENU":
            self.screen.blit(START_PAGE,(0,0))
            self.screen.blit(BUTTON_NEW,(100,200))
            self.screen.blit(BUTTON_NEW_rect,(100,200))
            self.screen.blit(BUTTON_CONTINUE,(420,200))
            self.screen.blit(BUTTON_CONTIUNE_rect,(420,200))
        elif self.state == "NEW":
            self.screen.blit(START_PAGE, (0,0))
           
if __name__ == "__main__":
    os.environ["SDL_VIDEO_CENTERED"] = '1'
    pg.init()
    pg.display.set_mode(SCREEN_SIZE)

    START_PAGE = pg.image.load(os.path.join('images', 'startpage.png'))
   
    #start of button shit
    BUTTON_NEW = pg.image.load(os.path.join('images', 'buttonnew.png'))
    BUTTON_NEW_rect = BUTTON_NEW.get_rect()
    BUTTON_CONTINUE = pg.image.load(os.path.join('images', 'buttoncontinue.png'))
    BUTTON_CONTINUE_rect = BUTTON_CONTINUE.get_rect()
    #end of button shit
    mx,my = pg.mouse.get_pos()
    PRESS_ENTER = pg.image.load(os.path.join('images', 'pressenter.png'))
    MENU_SOUND = pg.mixer.Sound(os.path.join('sounds', 'startsound.wav'))
    BUTTON_NOISE = pg.mixer.Sound(os.path.join('sounds', 'buttonnoise.wav'))
    MENU_SOUND.play

    run_it = Control()
    run_it.main_loop()
    pg.quit()
    sys.exit()



that is my code the error i am getting is

Code: Select all
in update
    self.screen.blit(BUTTON_NEW_rect,(100,200))
TypeError: argument 1 must be pygame.Surface, not pygame.Rect


how do i fix this?
Last edited by Yoriz on Thu Aug 01, 2013 11:51 pm, edited 1 time in total.
Reason: changed title
spamynator_1
 
Posts: 63
Joined: Sun Mar 03, 2013 12:45 am

Re: What does this error even mean?

Postby Mekire » Thu Aug 01, 2013 5:03 am

pygame.Surface objects and pygame.Rect objects are different things. Images are always Surfaces. You generally keep track of an image's location with a Rect.

So if you have a really basic sprite class:
Code: Select all
class BasicSprite(object):
    def __init__(self,image,location):
        self.image = image
        self.rect = self.image.get_rect(topleft=location)

    def draw(self,surface):
        surface.blit(self.image,self.rect)


Basically what you probably meant was:
Code: Select all
self.screen.blit(BUTTON_NEW,BUTTON_NEW_rect)
The rectangle contains the location information (or at least it should).

-Mek
User avatar
Mekire
 
Posts: 983
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: What does this error even mean?

Postby spamynator_1 » Thu Aug 01, 2013 5:10 am

Code: Select all
BUTTON_NEW_rect = BUTTON_NEW.get_rect()

i thought this was a rect... are you saying the .get_rect() has nothing to do with rectangles? :D
spamynator_1
 
Posts: 63
Joined: Sun Mar 03, 2013 12:45 am

Re: What does this error even mean?

Postby Mekire » Thu Aug 01, 2013 5:29 am

get_rect() is a Surface (an image) method. It returns a Rect the dimensions of the image.

This line:
Code: Select all
BUTTON_NEW_rect = BUTTON_NEW.get_rect()
creates a rectangle the dimensions of BUTTON_NEW, and assigns it to the name BUTTON_NEW_rect.

The blit function takes two arguments (well three if you count the destination surface):
Code: Select all
self.screen.blit(image,location)
The location variable can either be a (x,y) coordinate, or a Rect. Usually passing a Rect is easiest.

-Mek
User avatar
Mekire
 
Posts: 983
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: What does this error even mean?

Postby spamynator_1 » Thu Aug 01, 2013 5:33 am

im sorry i really cannot wrap my head around this rect function, what is passing a rect?
spamynator_1
 
Posts: 63
Joined: Sun Mar 03, 2013 12:45 am

Re: What does this error even mean?

Postby Mekire » Thu Aug 01, 2013 5:52 am

Ok.

An instance of pygame.Rect is just an object with an x, y, width, and height.

An instance of pygame.Surface is an image that we can draw on our display (or another Surface).

get_rect() is a method of Surface. It returns a Rect corresponding to the size of the image calling it.

If I want to draw an image on the display with the center of the image at (250,250) I would do this:

Code: Select all
image = pg.image.load("whatever.png").convert() #this is our image
rect = image.get_rect(center=(250,250)) #creates a rect the size of image with center at (250,250)
screen.blit(image,rect)

-Mek
User avatar
Mekire
 
Posts: 983
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: What does this error even mean?

Postby spamynator_1 » Thu Aug 01, 2013 5:40 pm

ok so if i then wanted to then use rect.colliderpoint to make it so when the rectangle is clicked in can function?
spamynator_1
 
Posts: 63
Joined: Sun Mar 03, 2013 12:45 am

Re: What does this error even mean?

Postby Mekire » Thu Aug 01, 2013 11:38 pm

Yes. If you have a rect representing your image's location you can tell if the mouse is over it using rect.collidepoint(mouse_position).

Your event loop would be something like this:
Code: Select all
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        pygame.quit(); sys.exit()
    elif event.type == pygame.MOUSEBUTTONDOWN:
        if event.button == 1:
            if rect.collidepoint(event.pos):
                button_clicked = True

Look here for an example of mouse interaction (although not a button as such):
https://github.com/Mekire/meks-pygame-samples/blob/master/drag_text.py

-Mek

Edit:
Wrote if event instead of if event.type
Last edited by Mekire on Fri Aug 02, 2013 12:19 am, edited 1 time in total.
User avatar
Mekire
 
Posts: 983
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: [pygame] TypeError pygame.Surface, not pygame.Rect ?

Postby spamynator_1 » Fri Aug 02, 2013 12:03 am

is "rect" in rect.collidepoint just a variable?
spamynator_1
 
Posts: 63
Joined: Sun Mar 03, 2013 12:45 am

Re: [pygame] TypeError pygame.Surface, not pygame.Rect ?

Postby Mekire » Fri Aug 02, 2013 12:11 am

The rect in that case was a variable referring to an instance of pygame.Rect.

ie:
Code: Select all
rect = pygame.Rect(0,0,50,50) #create a rect at (0,0) with width and height of 50.
if rect.collidepoint(pygame.mouse.get_pos()):
    #do stuff

-Mek
User avatar
Mekire
 
Posts: 983
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: [pygame] TypeError pygame.Surface, not pygame.Rect ?

Postby spamynator_1 » Fri Aug 02, 2013 12:12 am

Code: Select all
import sys
import os
import pygame as pg
import pickle
import pygame.mixer
from pygame.locals import *

SCREEN_SIZE = SCREEN_WIDTH,SCREEN_HEIGHT = (640,480)

RED = (255,0,0)
ORANGE = (255,127,0)
YELLOW = (255,255,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
INDIGO = (75,0,130)
VIOLET = (143,0,255)

class Control(object):
    def __init__(self):
        self.screen = pg.display.get_surface()
        self.done = False
        self.state = "START"
        self.clock = pg.time.Clock()
        self.fps = 60
        self.enter_coords = [0,400]
        self.keys = pg.key.get_pressed()
       
    def event_loop(self):
        for event in pg.event.get():
            self.keys = pg.key.get_pressed()
            if event.type == pg.QUIT or self.keys[pg.K_ESCAPE]:
                self.done = True

            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_RETURN and self.state == "START":
                    self.state = "MENU"

            elif self.state == "MENU":
                if event == pygame.MOUSEBUTTONDOWN:
                    if event.button == 1:
                        if BUTTON_NEW_rect.collidepoint(event.pos):
                            self.done = True
                   
            elif self.state == "NEW":
                crud = "1-0,0    0"
                sys(exit)
                with open("bruce", "wb") as f:
                    pickle.dump(crud, f)

    def main_loop(self):
        while not self.done:
            self.event_loop()
            self.update()
            pg.display.update()
            self.clock.tick(self.fps)

    def update(self):
        if self.state == "START":
            self.screen.blit(START_PAGE,(0,0))
            self.screen.blit(PRESS_ENTER,self.enter_coords)
            self.enter_coords[0] = (self.enter_coords[0]+2)
        elif self.state == "MENU":
            self.screen.blit(START_PAGE,(0,0))
            self.screen.blit(BUTTON_NEW, BUTTON_NEW_rect)
            self.screen.blit(BUTTON_CONTINUE, BUTTON_CONTINUE_rect)
        elif self.state == "NEW":
            self.screen.blit(START_PAGE, (0,0))
           
if __name__ == "__main__":
    os.environ["SDL_VIDEO_CENTERED"] = '1'
    pg.init()
    pg.display.set_mode(SCREEN_SIZE)

    START_PAGE = pg.image.load(os.path.join('images', 'startpage.png'))
   
    #start of button shit
    BUTTON_NEW = pg.image.load(os.path.join('images', 'buttonnew.png'))
    BUTTON_NEW_rect = BUTTON_NEW.get_rect(center=(160,200))
    BUTTON_CONTINUE = pg.image.load(os.path.join('images', 'buttoncontinue.png'))
    BUTTON_CONTINUE_rect = BUTTON_CONTINUE.get_rect(center=(480,200))
    #end of button shit
    mx,my = pg.mouse.get_pos()
    PRESS_ENTER = pg.image.load(os.path.join('images', 'pressenter.png'))
    MENU_SOUND = pg.mixer.Sound(os.path.join('sounds', 'startsound.wav'))
    BUTTON_NOISE = pg.mixer.Sound(os.path.join('sounds', 'buttonnoise.wav'))
    MENU_SOUND.play

    run_it = Control()
    run_it.main_loop()
    pg.quit()
    sys.exit()




this doesnt seem to work any obvious problems?
spamynator_1
 
Posts: 63
Joined: Sun Mar 03, 2013 12:45 am

Re: [pygame] TypeError pygame.Surface, not pygame.Rect ?

Postby Mekire » Fri Aug 02, 2013 12:18 am

Lol... that was actually my fault. Typo in my previous snippet on the event loop.

It has to say:
Code: Select all
if event.type == pygame.MOUSEBUTTONDOWN:

Instead of:
Code: Select all
if event == pygame.MOUSEBUTTONDOWN:

Change that and it works,
-Mek

Edit: rather it works if what you are expecting it to do is quit when you hit the button. You never change to state "NEW" so that stuff never runs (and it has an error in it).
User avatar
Mekire
 
Posts: 983
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: [pygame] TypeError pygame.Surface, not pygame.Rect ?

Postby spamynator_1 » Fri Aug 02, 2013 1:22 am

thank you very very much, i have been looking for days for a way to make a button work and this is the first. i appreciate your help.
spamynator_1
 
Posts: 63
Joined: Sun Mar 03, 2013 12:45 am


Return to Game Development

Who is online

Users browsing this forum: No registered users and 2 guests