Reputation: 211
I am trying to write a code for a pvp battleship game and I'm kinda stuck.
I will show you the codes first then explain how they work.
Here is the first code. This function is used to locate each ships on a grid:
def ship_builder(name):
# client ship value = 6, server ship value = 7
v_or_h = randrange(2)
if v_or_h == 0:
vertical = True
else:
vertical = False
if name == 'destroyer':
print('Click a cell to build a destroyer.')
if vertical == True:
print('Vertical')
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
col = (pos[0] // (cell_side + margin)) + 1
row = (pos[1] // (cell_side + margin)) + 1
grid[row][col] = 7
for i in range(3):
row += 1
grid[row][col] = 7
elif vertical == False:
print('Horizontal')
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
col = (pos[0] // (cell_side + margin)) + 1
row = (pos[1] // (cell_side + margin)) + 1
grid[row][col] = 7
for i in range(3):
col += 1
grid[row][col] = 7
elif name == 'frigate':
print('Click a cell to build a frigate')
if vertical == True:
print('Vertical')
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
col = (pos[0] // (cell_side + margin)) + 1
row = (pos[1] // (cell_side + margin)) + 1
grid[row][col] = 7
for i in range(2):
row += 1
grid[row][col] = 7
elif vertical == False:
print('Horizontal')
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
col = (pos[0] // (cell_side + margin)) + 1
row = (pos[1] // (cell_side + margin)) + 1
grid[row][col] = 7
for i in range(2):
col += 1
grid[row][col] = 7
Second is a for loop for the function above:
for ship in ['destroyer','frigate']:
ship_builder(ship)
color_change()
#color_change() is a function that colors the responding cells for the ships.
This is how they are supposed to work. First, ship_builder
is called with a name of a ship (say, 'battleship'). The first thing the code does is to check whether the ship should be placed vertically or horizontally. According to its value, the user can click on a cell to determine the location. This is where I am having an issue; the code just jumps over that part and proceeds without doing anything.
My question is: Why is it jumping over the mouse click part? Is pygame.event.get() not supposed to make Python 'wait' for an action?
I am not sure if I explained it substantially. Leave me a comment if I need to provide further information. I really need some help!
Thank you!
Upvotes: 4
Views: 4033
Reputation: 508
The short answer:
No, pygame.event.get() -> EventList
is not supposed to 'wait' for an action. Use pygame.event.wait() -> EventType
instead.
The longer answer:
Pygame is using an event queue in which it stores events that have happened. Let us have a look at the pygame.event.get()
documentation.
pygame.event.get() get events from the queue get() -> Eventlist get(type) -> Eventlist get(typelist) -> Eventlist
This will get all the messages and remove them from the queue. If a type or sequence of types is given only those messages will be removed from the queue. If you are only taking specific events from the queue, be aware that the queue could eventually fill up with the events you are not interested.
So basically, pygame.event.get()
returns every event that has happened since the last time we called it. If our event did not happen yet, it will not be in the returned EventList
.
But there is another function called pygame.event.wait()
that is behaving in the way asked for (although it only returns a single event).
pygame.event.wait() wait for a single event from the queue wait() -> EventType instance
Returns a single event from the queue. If the queue is empty this function will wait until one is created. The event is removed from the queue once it has been returned.
So it is possible to wait for a mousedown event with something like
event_happened = False
while not event_happened:
event = pygame.event.wait()
if event.type == pygame.MOUSEBUTTONDOWN:
do_something()
event_happened = True
However, we need to be carefull here, because as stated in the documentation the events are removed from the queue, meaning that all the events that are not of the type pygame.MOUSEBUTTONDOWN
will be lost. We would have to handle them or pass them on/safe them manually, if we needed them.
That was the longer answer, but I have one addition/warning. Getting the events at different points in the code like this can lead to confusion very quickly (e.g. because of lost events as described above etc.). The decision in this case could have to do with the lack of a main game loop in the program (I cannot tell for sure because I don't know the surrounding code, but the current implementation seems to suggest something like that).
Usually, events are accessed in a continous main game loop which could look like this
while True:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
build_ship_on_event(event)
elif event.type == pygame.QUIT:
pygame.quit()
sys.exit()
And the build_ship_on_event(event)
function could try to do something like
def build_ship_on_event(event):
if event_is_mouse_click(event):
ship_builder(selected_ship_type, event.pos)
and build the ship for a previously selected type at the given position (of course checking if the ship has been build before and so forth).
Upvotes: 4