Hi, myself and two of my friends are creating a game that imitates that of Whack-a-mole. I am trying to implement code so that when I click on the mole with the mouse, the image changes to a different image, eg. the image when just moving the mouse is a mallet, and Im trying to change that when the mousebutton is clicked, the image will change to a different one, eg. mallet facing downwards as if it is hitting the mole and then revert back to the first image.

Here is mallet class and the code that's done so far:

class MalletUp(pygame.sprite.Sprite):
    def __init__ (self, (posX, posY)):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("../src/images/malletup.jpg")
        self.rect = self.image.get_rect()
        transColor = self.image.get_at((1,1))
        self.image.set_colorkey(transColor)
        self.x = posX
        self.y = posY
        self.rect.center = (self.x, self.y)
        
        ' States for mouse click down or up '
        self.noClick = 0
        self.mouseRelease = 1
        self.mouseClick = 2
        self.mouseCounter = 3

    def update(self):
        self.x, self.y = pygame.mouse.get_pos()
        self.rect.center = (self.x, self.y)
        ''' keys = pygame.key.get_pressed()
        if keys[pygame.MOUSEBUTTONUP]:
        self.noClick = self.mouseRelease '''
        
        gameRunning = True
        while gameRunning == True:
        #while stay_in_loop == True:
            for event in pygame.event.get():     
                if event.type == pygame.MOUSEBUTTONDOWN:
                    self.noClick = self.mouseClick
                    self.image = pygame.image.load("../src/images/malletdown.png")
                    print "mouse pos:", pygame.mouse.get_pos()

Here is the mallet class being updated in the main code:

backgroundSprite.update(screen)        
        malletSprites.clear(screen, background)        
            
        ' Update mallet to the screen '
        malletSprites.update()
        backgroundSprite.draw(screen)
    
        ' Draw the mallet to the screen '
        malletSprites.draw(screen)
        pygame.display.flip()

We cant really do much more until we get this part working so would appreciate any help given.

Thanks

-Edit- If anyone wants to see my main code class I can post all of the code.

Dani AI

Generated

you are close. The main issue is doing your own while-loop and calling pygame.event.get() inside the sprite. That drains the event queue and blocks the main loop, which is why saw a black window. Keep a single event loop in game(), pass those events to the sprite, and switch images without reloading files every frame.

Here is a minimal pattern you can drop in. It preloads both images, switches on click, briefly shows the hit frame, then reverts:

import pygame

class Mallet(pygame.sprite.Sprite):
    def __init__(self, pos):
        super(Mallet, self).__init__()
        self.up = pygame.image.load("mallet_up.png").convert_alpha()
        self.down = pygame.image.load("mallet_down.png").convert_alpha()
        self.image = self.up
        self.rect = self.image.get_rect(center=pos)
        self._down_until = 0  # time in ms to keep the down image

    def update(self, events):
        self.rect.center = pygame.mouse.get_pos()

        now = pygame.time.get_ticks()
        if self._down_until and now >= self._down_until:
            self.image = self.up
            self._down_until = 0

        for e in events:
            if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
                self.image = self.down
                self._down_until = now + 100  # show down frame ~0.1s
            elif e.type == pygame.MOUSEBUTTONUP and e.button == 1:
                self.image = self.up
                self._down_until = 0

# in your game loop:
events = pygame.event.get()
for e in events:
    if e.type == pygame.QUIT:
        keepGoing = False
mallet_group.update(events)

Notes:

  • Load images once in init (reloading on every click will stutter).
  • Prefer PNG with transparency and use convert_alpha(); JPG has no alpha.
  • Keep both images the same size to avoid rect jumps when swapping.
  • If you want the simpler behavior (down while the button is held), inside update use: self.image = self.down if pygame.mouse.get_pressed()[0] else self.up.

Recommended Answers

All 5 Replies

You can simplify out parts which are not essential to demonstrate and you should post code which is runnable to see what problem you have, especially when you are not giving any error messages and exact problems.

At least I do not see how the indentation of the second piece of code would work.

The second part of code is just a small section of my main code. Here is the whole lot of my main class:

'''
Created on 18 Feb 2011

@author: A00161415
'''

import pygame, random, malletUp

screen = pygame.display.set_mode((1000, 700))

class Background(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("../src/images/background.png")
        self.rect = self.image.get_rect()
                
def game():
    pygame.display.set_caption("Example of mallet up and down")
   
    background = pygame.Surface(screen.get_size())
    background.fill((0, 0, 0))
    screen.blit(background, (0, 0))
    
    ' Mallet Up and Down '
    mallet_up = malletUp.MalletUp((320, 100))
    
    background1 = Background()
    
    backgroundSprite = pygame.sprite.Group(background1)
    
    ' Sprite Groups '
    malletSprites = pygame.sprite.Group(mallet_up)
       
    clock = pygame.time.Clock()
    keepGoing = True
    while keepGoing:
        clock.tick(100)
        pygame.mouse.set_visible(False)
        for event in pygame.event.get():
            
            if event.type == pygame.QUIT:
                keepGoing = False
                
        backgroundSprite.update(screen)        
        malletSprites.clear(screen, background)        
            
        ' Update mallet to the screen '
        malletSprites.update()
        backgroundSprite.draw(screen)
    
        ' Draw the mallet to the screen '
        malletSprites.draw(screen)
        pygame.display.flip()
        
    pygame.mouse.set_visible(True)

if __name__ == "__main__":
    game()

And here is the mallet class, Im nearly 100% sure that its something got to do with the update function because its printing out the mouse position but not changing the image:

'''
Created on 18 Feb 2011

@author: A00161415
'''

import pygame, random
pygame.init()

class MalletUp(pygame.sprite.Sprite):
    def __init__ (self, (posX, posY)):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("../src/images/malletup.jpg")
        self.rect = self.image.get_rect()
        transColor = self.image.get_at((1,1))
        self.image.set_colorkey(transColor)
        self.x = posX
        self.y = posY

    def update(self):                                
                                
        self.x, self.y = pygame.mouse.get_pos()
        self.rect.center = (self.x, self.y)   
   
            gameRunning = True
            while gameRunning == True:
                for event in pygame.event.get():     
                    if event.type == pygame.MOUSEBUTTONDOWN:
                        self.image = pygame.image.load("../src/images/malletdown.png")
                        print "mouse pos:", pygame.mouse.get_pos()

Anyone?

I get only black window, even after putting few jpg:s to the directory of program and mouse cordinates printed in console.

Ok. Do you have any idea how I could implement it so that when I click an image will change? Maybe using a counter or something..

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.