Search code examples
pythonfunctionpygamekey-events

Pygame keypress should call function just once


Hi the title says it basicly all... To describe it a little more: it a 2D random tilemap on wich you can move a player and he can mine coal. The problem is that if he's standing on the coal and pressed space more than one time the coal gets added more then one time to his inventory, AND thats the problem.He can mine more coal even no more is there. I have searched google but the only thing that i found out was that i have to use flag , some boolean values ...but HOW ?

I know the code is written were dirty,ugly etc...can be optimized...

import random
import pygame
import Images_raw
from colors import *
from timeit import default_timer as timer


pygame.init()
#----------------------------------------------------------------------------------------------------------------------
#pygame Display settings
display_width=704;  display_height=512
gameDisplay=pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('2D Coal miner')

# Misc
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 25)
mouseX=int;    mouseY=int

class Map:
    def __init__(self):
        global mapp,mapSize,mappSurfaces,QD_array,inventory,ammount,minedCoal
        mapSize=100
        ammount=0
        mapp=[[random.randint(0,1) for i in range(mapSize)] for i in range(mapSize)]
        mappSurfaces=mapp
        QD_array=[[random.randint(0,1) for i in range(mapSize)] for i in range(mapSize)]
        inventory=[[{'item':ammount} for i in range(5)] for i in range(5)]
        minedCoal=[]

    def createMap(self):
        global tileImage,recti,coalRect_list,chacheList
        tileImage=pygame.Surface
        coalRect=pygame.Surface
        coalRect_list=[]
        chacheList=[]

        for i in range(mapSize):
            for j in range(mapSize):
                randNum=random.randint(0,11)
                randNum2=random.randint(0,1)

                if randNum == 0 and randNum2==1:
                    tileImage= Images_raw.coal_img
                    QD_array[i][j]=0

                elif randNum== 2 and randNum2<= 9:
                    tileImage= Images_raw.water_img
                    QD_array[i][j]=1

                elif randNum>= 3 or randNum2>= 12:
                    tileImage= Images_raw.grass_img
                    QD_array[i][j]=2

                elif randNum== 5 or randNum2== 5:
                    tileImage= Images_raw.stone_img
                    QD_array[i][j]=3
                else:
                    tileImage= Images_raw.dirt_img
                    QD_array[i][j]=4

                mappSurfaces[i][j]=tileImage

        for k in range(mapSize):
            for l in range(mapSize):
                if QD_array[k][l]==0:
                    coalRect=pygame.Rect(k*32,l*32,32,32)
                    coalRect_list.append(coalRect)
                else:
                    pass

    def mineCoalAt(self,noCoal):

        for i in range(mapSize):
            for j in range(mapSize):
                if QD_array[i][j]==0:
                    chacheList.append((i,j))

        x=chacheList[noCoal][0]
        y=chacheList[noCoal][1]

        QD_array[x][y]=10

        inventory[0][0]['item']+=1

    def update(self,x_dif,y_dif):
        for i in range(mapSize):
            for j in range(mapSize):
                if QD_array[i][j] == 0:
                    tileImage= Images_raw.coal_img

                elif QD_array[i][j]== 1:
                    tileImage= Images_raw.water_img

                elif QD_array[i][j]== 2:
                    tileImage= Images_raw.grass_img

                elif QD_array[i][j]== 3:
                    tileImage= Images_raw.stone_img

                elif QD_array[i][j]== 10:
                    tileImage= Images_raw.coalUsed_img
                else:
                    tileImage= Images_raw.dirt_img

                mappSurfaces[i][j]=tileImage
                gameDisplay.blit(mappSurfaces[i][j],(x_dif+(i*32),y_dif+(j*32)),None,0)


#----------------------------------------------------------------------------------------------------------------------

# Main game function
#----------------------------------------------------------------------------------------------------------------------
def gameLoop():
    gameExit=False; outRight=False
    player_X=11;   player_Y=8
    allowMovement=False
    moveRight,moveLeft,moveUp,moveDown=False,False,False,False
    Space,sSpace=False,False
    x_difference,y_difference=0,0
    mapO=Map()
    mapO.createMap()
    counter=0
    allowMovement=True


    while not gameExit:
#-----------event loop---------------------------------------------------------
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                gameExit = True

            elif event.type == pygame.KEYDOWN:
                if (event.key == pygame.K_DOWN):
                    moveDown=True
                elif(event.key == pygame.K_UP):
                    moveUp=True
                elif(event.key == pygame.K_LEFT):
                    moveLeft=True
                elif(event.key == pygame.K_RIGHT):
                    moveRight=True
                elif(event.key == pygame.K_p):
                    print(player_X*32,player_Y*32)
                elif(event.key == pygame.K_SPACE):
                    Space=True
                elif(event.key == pygame.K_i):
                    print(inventory)

            elif event.type == pygame.KEYUP:
                if (event.key == pygame.K_DOWN):
                    moveDown=False
                elif(event.key == pygame.K_UP):
                    moveUp=False
                elif(event.key == pygame.K_LEFT):
                    moveLeft=False
                elif(event.key == pygame.K_RIGHT):
                    moveRight=False
                elif(event.key == pygame.K_SPACE):
                    Space=False


#-----------event loop END-----------------------------------------------------
        a=len(coalRect_list)

        #Logical/Main part

        if allowMovement==True:
            if moveRight==True:
                player_X+=1
                x_difference-=32
                for i in range(a):
                    coalRect_list[i].x-=32

            elif moveLeft==True:
                player_X-=1
                x_difference+=32
                for i in range(a):
                    coalRect_list[i].x+=32

            elif moveDown==True:
                 player_Y+=1
                 y_difference-=32
                 for i in range(a):
                    coalRect_list[i].y-=32

            elif moveUp==True:
                player_Y-=1
                y_difference+=32
                for i in range(a):
                    coalRect_list[i].y+=32

            else:
                player_X+=0;player_Y+=0
                y_difference+=0;x_difference+=0

            if Space==True:
                sSpace=True
            else:
                sSpace=False
        else:
            pass

        #Drawing objects to screen part
        gameDisplay.fill(white)  #Backgroundcolor

        mapO.update(x_difference,y_difference)
        playerRect=gameDisplay.blit(Images_raw.man_img,(player_X*0+352,player_Y*0+256),None,0)

        aba=playerRect.collidelist(coalRect_list)



        '''
        if aba!=-1 and sSpace==True:
            counter+=1


            if counter==1:
                minedCoal.append(aba)
                mapO.mineCoalAt(aba)
                inventory[0][0]['item']+=1
            elif counter==2:
                counter=0

            else:
                pass
        '''

        if aba!=1:
            if sSpace==True:
                minedCoal.append(aba)
                mapO.mineCoalAt(aba)

            else:
                pass

        #Update everything and set FPS-timer
        pygame.display.update()
        clock.tick(20)

    #Needed so that the program gets closed properly
    pygame.quit()
    quit()
#----------------------------------------------------------------------------------------------------------------------
#End of the Main game function
#---Normal coding goes on

#call the gameLoop
gameLoop()

Solution

  • There are a lot of problems with your code, but let's focus on your question:

    aba=playerRect.collidelist(coalRect_list)
    

    aba now contains the index of the first Rect in coalRect_list which collides with playerRect, or -1.

    if aba!=1:
        if sSpace==True:
             minedCoal.append(aba)
             mapO.mineCoalAt(aba)
         else:
             pass
    

    I guess you wanted to check for aba != -1 here, since -1 indicates that no collision happend:

    if aba != -1 and sSpace:
        ...
    

    What now happens is up to you, but I guess you want to remove the coal from the map, so you could simply remove the Rect from coalRect_list

    if aba != -1 and sSpace:
        minedCoal.append(aba)
        mapO.mineCoalAt(aba)
        del coalRect_list[aba]
    

    Since you only use coalRect_list to check whether the coal can be mined, this should be enough.