4

I am trying to blit an image on the screen when clicking a button in line

screen.blit(buttonPlusImage,
           [random.randrange(560, 680),
            random.randrange(330, 450)])

but the image disappears not long after because of the screen refreshes I got (I am using these 3 lines for updating the display: pygame.display.flip(), FPS.tick(144) and screen.fill(white)). How can i do it in a way that the image stays on the screen and not go away with the screen.fill(white)? (I think that is what's causing it).

I pasted the code in https://dpaste.org/qGdi

import pygame
import random
pygame.init()
​
# variables
mainLoop = True
font = pygame.font.SysFont('comicsansms', 25)
white = [255, 255, 255]
green = [0, 150, 0]
gray = [140, 140, 140]
black = [0, 0, 0]
clickNum = 0
clickAmount = 1
FPS = pygame.time.Clock()
screen = pygame.display.set_mode((1300, 700))
​
# functions
def switchButton01():
    global button02
    button02 = pygame.transform.scale(button02, (100, 100))
    screen.blit(button02, [580, 350])
    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONDOWN:
            global clickNum
            clickNum += 1
            screen.blit(buttonPlusImage, [random.randrange(560, 680), random.randrange(330, 450)])
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            pygame.quit()
            quit()
​
# load images
button01 = pygame.image.load('button_100.png')
button02 = pygame.image.load('button_100hovered.png')
icon = pygame.image.load('icon_128.png')
buttonPlusImage = pygame.image.load('buttonPlus_32.png')
​
# window itself and icon
pygame.display.set_caption("incremental adventures")
pygame.display.set_icon(icon)
​
while mainLoop:
    pygame.display.flip()
    FPS.tick(144)
    screen.fill(white)
​
    # actual content in the game
​
    button01 = pygame.transform.scale(button01, (100, 100))
    screen.blit(button01, [580, 350])
    click_counter_text = font.render("Click counter: ", True, black, white)
    screen.blit(click_counter_text, [525, 50])
    button01rect = button01.get_rect(center=(630, 400))
    button01collidepoint = button01rect.collidepoint(pygame.mouse.get_pos())
    click_counter = font.render((str(clickNum)), True, black, white)
    screen.blit(click_counter, [700, 50])
    if button01collidepoint:
        switchButton01()
​
​
    # quits
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            pygame.quit()
            quit()
Z4-tier
  • 7,287
  • 3
  • 26
  • 42
  • Save it and redraw it after clearing the screen – DJSchaffner Feb 21 '20 at 01:24
  • 1
    you blit it when you get `MOUSEBUTTONDOWN` but `event` is single message created when mouse button change position from `not pressed` to `pressed` - but it is not create when you keep it pressed. So you draw it only once and later it doesn't draw it again when you keep button pressed. You may need `pygame.mouse.get_pressed()` to test if you keep button pressed - check it in every loop. OR better learn how to use class to keep information about object like button. – furas Feb 21 '20 at 01:57

2 Answers2

2

I did not change everything.

Avoid multiple event loops in the application loop. Note, pygame.event.get() removes all event from the queue. So either the first or the 2nd event loop would get the events. But not both loops. You can get rid about that, by getting the events once in the loops and using the list of events multiple times:

while mainLoop:

    events = pygame.event.get()

    # [...]

    if button01collidepoint:
        switchButton01(events)

    # [...]

    for event in events:
        # [...]

If you want that the image stays on the screen then you have to draw it in every frame. Add a which stores the position of the button buttonPlusPos and draw the position in the main application loop. The function switchButton01 has toi return the position:

buttonPlusPos = None
while mainLoop:

    # [...]
  
    if button01collidepoint:
        buttonPlusPos = switchButton01(events, buttonPlusPos)
    if buttonPlusPos:
        screen.blit(buttonPlusImage, buttonPlusPos)  

The function switchButton01 doesn't blit the button, it just returns the position. Furthermore list of events is passed to the function and the function process the events in the list rather than retrieving its "own" list. In any cas the position of the image is returned. Either the new position or the current position (which is allowed to be None):

def switchButton01(events, buttonPlusPos):
    global button02
    button02 = pygame.transform.scale(button02, (100, 100))
    screen.blit(button02, [580, 350])
    for event in events:
        if event.type == pygame.MOUSEBUTTONDOWN:
            global clickNum
            clickNum += 1
            return (random.randrange(560, 680), random.randrange(330, 450))
    return buttonPlusPos

Full code:

import pygame
import random
pygame.init()

# variables
mainLoop = True
font = pygame.font.SysFont('comicsansms', 25)
white = [255, 255, 255]
green = [0, 150, 0]
gray = [140, 140, 140]
black = [0, 0, 0]
clickNum = 0
clickAmount = 1
FPS = pygame.time.Clock()
screen = pygame.display.set_mode((1300, 700))

# functions
def switchButton01(events, buttonPlusPos):
    global button02
    button02 = pygame.transform.scale(button02, (100, 100))
    screen.blit(button02, [580, 350])
    for event in events:
        if event.type == pygame.MOUSEBUTTONDOWN:
            global clickNum
            clickNum += 1
            return (random.randrange(560, 680), random.randrange(330, 450))
    return buttonPlusPos

# load images
button01 = pygame.image.load('button_100.png')
button02 = pygame.image.load('button_100hovered.png')
icon = pygame.image.load('icon_128.png')
buttonPlusImage = pygame.image.load('buttonPlus_32.png')

# window itself and icon
pygame.display.set_caption("incremental adventures")
pygame.display.set_icon(icon)

buttonPlusPos = None
while mainLoop:
    pygame.display.flip()
    FPS.tick(144)
    screen.fill(white)

    events = pygame.event.get()
    
    # actual content in the game
 
    button01 = pygame.transform.scale(button01, (100, 100))
    screen.blit(button01, [580, 350])
    click_counter_text = font.render("Click counter: ", True, black, white)
    screen.blit(click_counter_text, [525, 50])
    button01rect = button01.get_rect(center=(630, 400))
    button01collidepoint = button01rect.collidepoint(pygame.mouse.get_pos())
    click_counter = font.render((str(clickNum)), True, black, white)
    
    screen.blit(click_counter, [700, 50])
    if button01collidepoint:
        buttonPlusPos = switchButton01(events, buttonPlusPos)
    if buttonPlusPos:
        screen.blit(buttonPlusImage, buttonPlusPos)    

    # quits
    for event in events:
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            pygame.quit()
            quit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
1

I changed everything.

I keep all button's information in dictionary. There is also state which keep information if button is normal, hovered or clicked. I change it using pygame.mouse.get_pressed() instead of even MOUSEBUTTONDOWN. I could use state to select image to display but I set image when I check pygame.mouse.get_pressed()

import pygame
import random

# --- constants --- (UPPER_CASE_NAMES)

WHITE = (255, 255, 255)
GREEN = (0, 150, 0)
RED   = (255, 0, 0)
GRAY  = (140, 140, 140)
BLACK = (0, 0, 0)

FPS = 25 # 144

# --- functions ---

# empty

# --- main ---

pygame.init()
screen = pygame.display.set_mode((1300, 700))

# - objects -

button01 = dict()
button01['image_normal'] = pygame.surface.Surface((100,100))#
button01['image_normal'].fill(GRAY)
#button01['image_normal'] = pygame.image.load('button_100.png')
#button01['image_normal'] = pygame.transform.scale(button01['image_normal'], (100, 100))
button01['image_hovered'] = pygame.surface.Surface((100,100))
button01['image_hovered'].fill(GREEN)
#button01['image_hovered'] = pygame.image.load('button_100hovered.png')
#button01['image_hovered'] = pygame.transform.scale(button02['image_hovered'], (100, 100))
button01['image_clicked'] = pygame.surface.Surface((100,100))
button01['image_clicked'].fill(RED)
#button01['image_clicked'] = pygame.image.load('button_100clicked.png')
#button01['image_clicked'] = pygame.transform.scale(button02['image_clicked'], (100, 100))
button01['state'] = 'normal'
button01['image'] = button01['image_normal']
button01['rect'] = button01['image'].get_rect(center=(630, 400))

plus_image = dict()
plus_image['image'] = pygame.surface.Surface((30, 30))
plus_image['image'].fill(BLACK)
plus_image['rect'] = plus_image['image'].get_rect()
plus_image['state'] = 'hidden'
#screen.blit(buttonPlusImage, [random.randrange(560, 680), random.randrange(330, 450)])

# - other -

click_number = 0

# - mainloop -

mainloop = True
clock = pygame.time.Clock()

while mainloop:

    pygame.display.flip()
    clock.tick(FPS)
    screen.fill(WHITE)

    # draw elements

    screen.blit(button01['image'], button01['rect'])
    if plus_image['state'] == 'displayed':
        screen.blit(plus_image['image'], plus_image['rect'])

    # check collisions and clicks

    if not button01['rect'].collidepoint(pygame.mouse.get_pos()):
        button01['state'] = 'normal'
        button01['image'] = button01['image_normal']
    elif pygame.mouse.get_pressed()[0]:
        button01['state'] = 'clicked'
        button01['image'] = button01['image_clicked']
    else:
        button01['state'] = 'hovered'
        button01['image'] = button01['image_hovered']

    #if button01['state'] == 'clicked':
    #    plus_image['rect'].center = [random.randrange(560, 680), random.randrange(330, 450)]
    #    plus_image['state'] = 'displayed'
    #else:
    #    plus_image['state'] = 'hidden'

    # other events

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            mainloop = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                mainloop = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            #if button01['state'] == 'hovered':
            if button01['rect'].collidepoint(event.pos):
                click_number += 1
                print('click_number:', click_number)
                plus_image['rect'].center = [random.randrange(560, 680), random.randrange(330, 450)]
                plus_image['state'] = 'displayed'
                button01['rect'].center = [random.randrange(560, 680), random.randrange(330, 450)]
        if event.type == pygame.MOUSEBUTTONUP:
            plus_image['state'] = 'hidden'

# - end -            

pygame.quit()
quit()
furas
  • 134,197
  • 12
  • 106
  • 148