Pygame event inside class not recognized - python

I have completed a game using pygame without any problems. Now I am trying to organise the code and add classes. However, I am having a problem with the event command.
I tried using pygame.event.poll() and pygame.event.get(), but neither helped.
class MainRun():
run = True
def Main(self):
#some code
while MainRun.run:
pygame.time.delay(35)
for event in pygame.event.get():
if event.type == pygame.QUIT:
MainRun.run = False
a.activate_skills()
class Player():
#code
def activate_skills(self):
if event.type == pygame.MOUSEBUTTONDOWN:
#some code
a = Player
main = MainRun().Main()
if event.type == pygame.MOUSEBUTTONDOWN: NameError: name 'event' is not defined
So how can I define the event? Please see what I have already tried.

You should only call pygame.event.get() once, as it will fetch all the events that have happened. For example:
a = pygame.event.get() # Contains the events that has happen.
for event in a:
if event.type == pygame.QUIT:
quit()
b = pygame.event.get() # Will probably contain nothing, as the code above took the events from the event queue.
for event in b:
if event.type == pygame.MOUSEBUTTONDOWN:
do_something()
do_some_calculation()
c = pygame.event.get() # Might contain something, if the user did something during the time it took to do the calculation.
for event in c:
if event.type == pygame.MOUSEBUTTONDOWN:
do_other_thing()
In the above example, it's likely do_something() will never be called, as the event queue has been cleared just before. do_other_thing() might be called, but that's only if the user pressed the button during the time it took to execute do_some_calculations(). If the user pressed before or after, the click event will have been cleared and lost.
So in your situation, you could do something like this:
class MainRun():
run = True
def Main(self):
#some code
while MainRun.run:
pygame.time.delay(35)
for event in pygame.event.get(): # ONLY CALLED HERE IN THE ENTIRE PROGRAM.
if event.type == pygame.QUIT:
MainRun.run = False
a.activate_skills(event) # MOVED THIS INTO THE FOR LOOP!
class Player():
#code
def activate_skills(self, event): # TAKING THE EVENT AS PARAMETER.
if event.type == pygame.MOUSEBUTTONDOWN:
#some code
a = Player
main = MainRun().Main()

Try this, hope it works for you :D
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
# your code

Related

Pygame project, screen doesn't update in one function, but it works within two other functions

My pygame project consists of several parts, including global map and towns. I use one Game class to contain necessary objects. All game is shown on one screen and works properly with global map and town (in_city function), it changes the screen and shows necessary information, but when I call another function (buy), it doesn't update screen.
def buy(self):
while self.running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
if event.type == pygame.KEYDOWN:
return
self.screen.fill('BLACK')
pygame.display.update()
pygame.display.flip()
def in_city(self):
while self.running:
stop = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
if event.type == pygame.MOUSEMOTION:
all_sprites.update(pygame.mouse.get_pos())
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
button_right.click(mouse_pos)
button_left.click(mouse_pos)
button_next.click(mouse_pos)
button_prev.click(mouse_pos)
if button_close.on_button(mouse_pos):
stop = True
if event.type == pygame.KEYDOWN:
self.buy()
if stop:
self.player.route = [(0, 0)]
self.player.next_move(self.maps)
self.camera.update(self.player)
return
screen.fill('WHITE')
city.render(screen)
current_text = city.enemies[city.current_enemy]
window.show(screen, current_text.get_text())
print(current_text.goods)
all_sprites.draw(screen)
pygame.display.update()
pygame.display.flip()`
Never run game loops recursively. Use the one application loop to draw the scene depending on states. You should never jump to another application loop in an event. The event should only change a state that is used to draw the scene. e.g.:
game_state = 'A'
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
game_state = 'B'
screen.fill('WHITE')
if game_state == 'A':
# draw scene A
elif game_state == 'B':
# draw scene B
pygame.display.flip()

My game won't work when I use the controls, how do I fix it?

I can not get the controls to work, I try to press escape to open a menu I made but it will not open and I do not know if I am checking for events correctly, is there a way I am SUPPOSED to do it?
I tried using the functions for checking for different keys and I went to the spread-sheet that displays all the event names so you can map them at pygame.org but it will not open when I use the escape or also known as:
elif event.type == pygame.K_ESCAPE:
Frame.blit('Textures/GUI/loom.png', (0,0))
Heres the full code:
import pygame
#Textures/Blocks/loom_side.png
pygame.init()
Screen = "None"
DB = 0
Width = 800
Height = 600
Frame = pygame.display.set_mode((Width,Height))
pygame.display.set_caption("HypoPixel")
FPS = pygame.time.Clock()
def Raycast(TTR, RayXPos, RayYPos, RaySizeX, RaySizeY):
RaycastThis = pygame.image.load(TTR)
RaycastThis = pygame.transform.scale(RaycastThis,(RaySizeX,RaySizeY))
Frame.blit(RaycastThis, (RayXPos, RayYPos))
Loop = True
Raycast('Textures/Screens/Skybox/Earth.png',0,0,800,600)
while Loop == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
elif event.type == pygame.K_ESCAPE:
Frame.blit('Textures/GUI/loom.png', (0,0))
pygame.display.update()
FPS.tick(60)
I expected to get the loom GUI that I made. Once I tried to press escape, nothing happened.
pygame.K_ESCAPE is not event type (see pygame.event), but it is a pygame.key.
First check if a key was pressed by comparing the event type to pygame.KEYDOWN:
event.type == pygame.KEYDOWN
Then check if the event.key, which cause the event, is the pygame.K_ESCAPE key:
event.key == pygame.K_ESCAPE
Furthermore, the parameter to Surface.blit() has to be a Surface object rather than a filename.
first load the image to a Surface, by pygame.image.load(), then blit the Surface:
sprite = pygame.image.load('Textures/GUI/loom.png')
Frame.blit(sprite, (0,0))
Of course the your Raycast function can be called to do so:
Raycast('Textures/GUI/loom.png',0,0,800,600)
Your code should look somehow like this:
while Loop == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
Raycast('Textures/GUI/loom.png',0,0,800,600)

How can I make multi thread program in Python

I'm using Python 3.5, and I want to make multi-keystroke function.
I mean, I want to make a function that notices Ctrl+S and Q.
But my program doesn't notice it.
Here's my code:
import threading, pygame, sys
from pygame.locals import *
from time import sleep
pygame.init()
screen = pygame.display.set_mode((1160, 640), 0, 0)
screen.fill((255, 255, 255))
pygame.display.flip()
def background():
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if pygame.key.get_mods() & pygame.KMOD_CTRL and event.key == pygame.K_s:
print('GOOD')
def foreground():
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
print('HELLO_WORLD')
if event.type == QUIT:
pygame.quit()
sys.exit()
b = threading.Thread(name='background', target=background)
b.start()
foreground()
By calling b.start(), you let the program go into the infinite loop of listening Ctrl+S event. The event of key combination, once obtained in the background thread, will not be released back into the event queue. and the foreground function won't be able to capture and process it.
If you want your program to be able to process different key combination. You should let one function to listen to key press event, and dispatch the event to different processing functions.

Change a value using mouse click with pygame

I am trying to create a nice and simple game just for practice with pygame, and I was trying to change a value using mouse click and I can't find out what to do
global item
ev = pygame.event.get()
item = 0
while True:
for event in ev:
if event.type == QUIT:
pygame.quit()
sys.exit()
for event in ev:
if event.type == pygame.MOUSEBUTTONDOWN:
item + 1
print (item)
After this is run, and I click the mouse, the game just freezes and nothing appears in the shell.
Please help
Thanks
Welcome to stackoverflow.
A simple script where clicking in the window increments item by 1 and prints it:
import pygame
pygame.init()
screen = pygame.display.set_mode((400,400))
clock = pygame.time.Clock()
item = 0
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
item += 1
print item
clock.tick(30)
pygame.quit()
This example shows the basic layout and flow of a pygame program.
Notice the for event in pygame.event.get() loop contains both of the loops in your example.
Hope this helps

Pygame nested while loop: [Errno 10054] An existing connection was forcibly closed by the remote host

I am using pygame with pyscripter and pyopengl, and am trying to put a while loop inside the main while loop, but as soon as the game enters the inner loop, it repeats the loop forever and I can't get out
running = True
while running:
keys=pygame.key.get_pressed()
## do game stuff
if keys[K_l]:
a=True
while a:
keys2=pygame.key.get_pressed()
## do something
print a
if keys2[K_p]:
a = False
break
for event in pygame.event.get():
if event.type == pygame.QUIT or keys[K_ESCAPE]:
running = False
pygame.quit()
sys.exit()
After pressing l, this continuously prints True even if I press p
How can I exit the inside loop?
You need to call pygame.event.pump() inside your inner while loop to ensures that your program can internally interact with the rest of the operating system.
# ....
while a:
pygame.event.pump()
keys2 = pygame.key.get_pressed()
# do something ...
An alternative would be to listen for pygame.KEYDOWN events on the event queue in your game loop:
running = True
l_KeyPressed = False
while running:
# get events from the queue
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN :
if event.key == pygame.K_SPACE:
running = False
if event.key == pygame.K_l:
# do something
l_KeyPressed = True
if event.key == pygame.K_p and lPressed:
l_KeyPressed = False
Hope this helps :)

Categories