bhamhawker
bhamhawker

Reputation: 95

How can I blit my selection to the screen in pygame?

I'm still working my way through, slowly, creating my own simple card game. I have the following code (which works fine):

player_hand_images = []
opponent_hand_images = []
player_image_rects = []
for item in player_hand:
    player_hand_images.append(pygame.image.load(os.path.join('Images', item.name+'.png')))
for item in opponent_hand:
    opponent_hand_images.append(pygame.image.load(os.path.join('Images', item.name+'.png')))
for n, item in enumerate(player_hand_images):
    player_image_rects.append(screen.blit(item, ((n * (SCREEEN_WIDTH/5))+50, SCREEN_HEIGHT*.6)))
for n, item in enumerate(opponent_hand_images):
    screen.blit(item, ((n * (SCREEEN_WIDTH/5))+50, SCREEN_HEIGHT*.15))
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT

# ALL EVENT PROCESSING SHOULD GO BELOW THIS COMMENT
for event in pygame.event.get(): # User did something
    if event.type == pygame.QUIT: # If user clicked close
        done = True # Flag that we are done so we exit this loop
    if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
        # Set the x, y postions of the mouse click
        x, y = event.pos
        #print x, y
        for n, item in enumerate(player_image_rects):
            if item.collidepoint(x, y):
                card_picked = player_hand[n]
                print card_picked.name

The code successfully lets me click on one of my "card" images on the screen and prints out a corresponding "name" in the console.

I've been working for an hour this morning in an attempt to have my selection cleared out (or blitted over) and "moved" (or re-blitted) upwards toward the middle of the screen (think similar to choosing a card in Hearts on Windows - I want the selection of the card to have a visible response on my screen).

No matter what I seemed to try, I could never get the selection to blit to another area and I could not get the surface to not display the original selection.

Can someone help me understand the blitting process so that I can clear off one card and have it reappear in another area of the screen?


EDIT1

Here is the 'Card' class that I already have implemented:

class Card(object):
    def __init__(self, name="", attack=0, defense=0, magic=0, shield=0, description=""):
        self.name = name
        self.attack = int(attack)
        self.defense = int(defense)
        self.magic = int(magic)
        self.shield = int(shield)
        self.description = description

I use this method to populate a 'Deck' class with the above 'Card' objects:

class Deck(object):

    def __init__(self, deck):
        self.deck = self.getDeck(deck)


    def getDeck(self, deck):
        with open(deck, "rU") as csvfile:
            deckReader = csv.DictReader(csvfile, delimiter=',')
            newDeck = []
            for row in deckReader:
                for x in range(int(row['NumberOfCards'])):
                    if row['NameOfCard'] in cards:
                         newDeck.append(cards[row['NameOfCard']])

        return newDeck

EDIT2

I am now getting the following error when I implement the suggested changes:

Traceback (most recent call last):
  File "/.../Card Game 1/pygame_new_attempt.py", line 176, in <module>
    if item.hitpoint(x, y):
 AttributeError: 'pygame.Surface' object has no attribute 'hitpoint'

EDIT3

When I run the code:

for event in pygame.event.get(): # User did something
    if event.type == pygame.QUIT: # If user clicked close
        done = True # Flag that we are done so we exit this loop
    if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
        # Set the x, y postions of the mouse click
        x, y = event.pos
        #print x, y
        for card in player_cards:
            print card.hittest(x, y)

I get 'False' printed out no matter where I click on my screen.

Upvotes: 0

Views: 404

Answers (1)

Samy Arous
Samy Arous

Reputation: 6814

Blitting is basically the process of drawing one image(or surface) A into a second image B one pixel at a time.

The easiest way to achieve that would be to clear out the screen, draw all the elements (called sprites) in their respective position.

Looking at your code, I see that you don't use the item (x,y) coordinates to draw your cards, instead you are using their index n. Which basically, will always draw your card on the same location without any regards to their coordinates.

First, instead of storing the items on one list and the images on a second list and the rects on a third list, I would use a single class: from rect import Rect

class Card:

    def __init__(self, name, x, y, width, height, image):
        self.name = name
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.image = image

    def hittest(x, y):
        return Rect((self.x, self.y, self.width, self.height)).collidepoint((x, y))

Now I create the hands

player_cards = []
for n, item in enumerate(player_hand):
    image = pygame.image.load(os.path.join('Images', item.name+'.png'))
    x = (n * (SCREEEN_WIDTH/5))+50
    y = SCREEN_HEIGHT*.6
    width = 20
    height = 60
    name = item.name
    players_cards.append(Card(name, x,y,width,height, image))

Blitting is just straight forward:

for card in player_cards:
    screen.blit(card.image, card.x, card.y)

Last but not the least, we handle the selection process and move the card to the middle of the screen:

if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
        # Set the x, y postions of the mouse click
        x, y = event.pos
        #print x, y
        for card in player_cards:
            if item.hitpoint(x, y):
                card_picked = card
                print card_picked.name
                card_picked.x = (SCREEEN_WIDTH - card_picked.width) / 2
                card_picked.y = (SCREEEN_HEIGHT - card_picked.width) / 2

And this should do it.

Upvotes: 2

Related Questions