I created a snake-like game in which the user moves the sprite, and the sprite leaves a trail. If the user runs into the trail he's created, I'd like the game to end, and the player to lose.
One idea I had was to somehow track past positions of the sprite (maybe in a list), and then create an 'if' statement that would lead to a game loss (However, I'm was a little unclear on how to do that).
I received an answer to this question that coded for this list:
"I think you could declare a two dimensional list like this:
pastPositions = [[400, 300]]
Then every time the player's position moves, check the list:
for row in pastPositions:
If (player.rect.x == pastPositions[row][0] and player.rect.y == >pastPositions[row][1]):
done = true # game over
If the player hasn't been there yet, then add that position to the list.
pastPositions.append([player.rect.x, player.rect.y])"
This looks like it should work, but when I try to run the code (in Python Interactive), I get an error message that reads: "line 86, in if player.rect.x == astPositions[row][0] and player.rect.y == pastPositions[row][1]: IndexError: list index out of range" – Gal 2 days ago
What would you suggest I change the range to so that this doesn't happen? I tried setting it to the width and height of the pygame window.
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface([15, 15])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
pygame.init()
screen = pygame.display.set_mode([800, 600])
pygame.display.set_caption('The Etch-a-Sketch Game')
myfont = pygame.font.SysFont('Times', 20)
textsurface = myfont.render('This is the Etch-a-Sketch Game', False, (255, 255, 255))
screen.blit(textsurface,(0,0))
myfont = pygame.font.SysFont('Times', 15)
textsurface = myfont.render('Feel free to draw, but if you cross your own path, you will die.', False, (255, 255, 255))
screen.blit(textsurface,(0,20))
player = Player(400, 300)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
clock = pygame.time.Clock()
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
player.update()
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(75)
pygame.quit ()
I think you could declare a two dimensional list like this:
pastPositions = [[400, 300]]
Then every time the player's position moves, check the list:
for row in pastPositions:
if (player.rect.x == row[0] and player.rect.y == row[1]):
done = true # game over
If the player hasn't been there yet, then add that position to the list.
pastPositions.append([player.rect.x, player.rect.y])
Are you looking for something like that?
Related
I created a snake-like game in which the user moves the sprite, and the sprite leaves a trail. If the user runs into the trail he's created, I'd like the game to end, and the player to lose.
As the sprite moves, it makes a white trail on a black background. If I can detect that the user-controlled sprite will hit one of the white areas (its 'tail'), I can create an if statement that leads to a game loss.
I use the [Surface.get_at()][1] function to grab the color of the space the sprite will move into, and checking if this color is black or white. If it's white, that means it's the sprite's tail, and the game ends in a loss.
Here's the code:
In the player.update():
if (screen.get_at((player_next_x, player_next_y)) != BACKGROUND_COLOUR):
# player hit tail
However, this isn't working, and I know why:
1) I don't know how to define (player_next_x) or (player_next_y) while taking into account the user's input on the direction keys.
2) I tried this just using (player.rect.x) and (player.rect.y), which I had already defined, and of course the system closed immediately because it detected a "collision" with its current position (which is white).
Here is the full code, if it helps:
import pygame
import os
import time
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
class Player(pygame.sprite.Sprite):
# -- Methods
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface([15, 15])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
pygame.init()
screen = pygame.display.set_mode([800, 600])
pygame.display.set_caption('The Etch-a-Sketch Game')
myfont = pygame.font.SysFont('Times', 20)
textsurface = myfont.render('This is the Etch-a-Sketch Game', False, (255, 255, 255))
screen.blit(textsurface,(0,0))
myfont = pygame.font.SysFont('Times', 15)
textsurface = myfont.render('Feel free to draw, but if you cross your own path, you will die.', False, (255, 255, 255))
screen.blit(textsurface,(0,20))
player = Player(400, 300)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
clock = pygame.time.Clock()
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
player.update()
if (screen.get_at((player.rect.x, player.rect.y)) != WHITE):
myfont = pygame.font.SysFont('Times', 20)
textsurface = myfont.render('You have lost the Etch-a-Sketch Game.', False, (255, 255, 255))
screen.blit(textsurface,(0,0))
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(250)
pygame.quit ()
The straightforward way is to compute the step and check whether you just stomped on a white space. If this doesn't fit with the design of your timing engine, then peek at the next location, just as you would take the step:
def peek_next(self):
return (self.rect.x + self.change_x,
self.rect.y + self.change_y)
...
player_next_x, player_next_y = player.peek_next()
if (screen.get_at((player_next_x, player_next_y)) != BACKGROUND_COLOUR):
# player hit tail
Or feed the new position directly to get_at:
if screen.get_at(player.peek_next()) != BACKGROUND_COLOUR:
# player bit own tail; dies of poisoning
I created a snake-like game in which the user moves the sprite, and the sprite leaves a trail. If the user runs into the trail he's created, I'd like the game to end, and the player to lose.
As the sprite moves, it makes a white trail on a black background. If I can detect that the user-controlled sprite will hit one of the white areas (its 'tail'), I can create an if statement that leads to a game loss.
I use the [Surface.get_at()][1] function to grab the color of the space the sprite will move into, and checking if this color is the same as the background color. If it's not the same as the background color, that means it's the sprite's tail, and the game ends in a loss.
Here's the code:
if screen.get_at(player.peek_next()) != BACKGROUND:
done=True
However, as soon as I run the game, I can travel in a straight line for about two seconds before that 'if statement' kicks in, and the game ends. I don't know why it thinks that the 'next' position is !=BACKROUND. I tried to slow down the clock so it would register less frames per second, but that doesn't keep it from closing, it only delays it.
Here's the code:
import pygame
import os
import time
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BACKGROUND = (100, 30, 100)
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface([20, 20])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.change_x = 0
self.change_y = 0
def peek_next(self):
return (self.rect.x+self.change_x, self.rect.y+self.change_y)
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
pygame.init()
screen = pygame.display.set_mode([800, 600])
pygame.display.set_caption('The Etch-a-Sketch Game')
screen.fill(BACKGROUND)
myfont = pygame.font.SysFont('Times', 20)
textsurface = myfont.render('This is the Etch-a-Sketch Game', False, (255, 255, 255))
screen.blit(textsurface,(0,0))
myfont = pygame.font.SysFont('Times', 15)
textsurface = myfont.render('Feel free to draw, but if you cross your own path, you will die.', False, (255, 255, 255))
screen.blit(textsurface,(0,20))
player = Player(400, 300)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
clock = pygame.time.Clock()
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
if screen.get_at(player.peek_next()) != BACKGROUND:
done=True
player.update()
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(250)
pygame.quit ()
There are 2 issues.
First you have to respect the size of the player (white rectangle) when you calculate the position for the collision test. Test the "next", beside the rectangle:
def peek_next(self):
if self.change_x > 0:
return (self.rect.right+1, self.rect.centery)
elif self.change_x < 0:
return (self.rect.left-1, self.rect.centery)
elif self.change_y > 0:
return (self.rect.centerx, self.rect.bottom+1)
elif self.change_y < 0:
return (self.rect.centerx, self.rect.top-1)
return (self.rect.x, self.rect.y)
It makes no sense to test, if there is no change of the position, because then the test position is the current position and this will always lead to a "collision". The collision test is only allowed to be done, if player.change_x != 0 or player.change_y != 0 is fulfilled.
Further the test has to be done outside the event loop, note if key is hold, the "player" still moves and you have to check for a collision too:
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
# <----
if (player.change_x != 0 or player.change_y != 0) and screen.get_at(player.peek_next()) != BACKGROUND:
done=True
I created a snake-like game in which the user moves the sprite, and the sprite leaves a trail. If the user runs into the trail he's created, I'd like the game to end, and the player to lose.
One idea I had was to somehow track past positions of the sprite (maybe in a list), and then create an if statement that would lead to a game loss (However, I'm was a little unclear on how to do that).
I received an answer to this question that coded for this list:
"I think you could declare a two dimensional list like this:
pastPositions = [[400, 300]]
Then every time the player's position moves, check the list:
for row in pastPositions:
If (player.rect.x == pastPositions[row][0] and player.rect.y == pastPositions[row][1]): done = true # game over
If the player hasn't been there yet, then add that position to the list.
pastPositions.append([player.rect.x, player.rect.y])
This looks like it should work, but when I try to run the code (in Python Interactive), I get an error message that reads: "line 86, in <module> if player.rect.x == astPositions[row][0] and player.rect.y == pastPositions[row][1]: IndexError: list index out of range"
What would you suggest I change the range to so that this doesn't happen? I tried setting it to the width and height of the pygame window.
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface([15, 15])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
pygame.init()
screen = pygame.display.set_mode([800, 600])
pygame.display.set_caption('The Etch-a-Sketch Game')
myfont = pygame.font.SysFont('Times', 20)
textsurface = myfont.render('This is the Etch-a-Sketch Game', False, (255, 255, 255))
screen.blit(textsurface,(0,0))
myfont = pygame.font.SysFont('Times', 15)
textsurface = myfont.render('Feel free to draw, but if you cross your own path, you will die.', False, (255, 255, 255))
screen.blit(textsurface,(0,20))
player = Player(400, 300)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
clock = pygame.time.Clock()
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
player.update()
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(75)
pygame.quit ()
Recording the points of a very long path seems like a slow way of checking for hitting one's own tail.
If the background is a known colour, perhaps checking for non-background pixel colours in the area the player is about to move into.
It's possible to grab a single pixel colour with the Surface.get_at() function. This returns a RGBA colour, this colour can be compared against a single background colour (or the known background colour from a bitmap at that point), allowing collision to be decided.
In the player.update():
if (screen.get_at((player_next_x, player_next_y)) != BACKGROUND_COLOUR):
# player hit tail
Of course it may be necessary to check both corners of the player's sprite (in the direction of travel).
Previously in my projectiles module, I had a class that handled each direction of fire seperately (a class for firing up, down, left and right) and this did it's job. However, now that I'm trying to incorporate shot speed and other things into the class, having 4 seperate classes is just too messy and so I tried to trim it down so that I only have one class for all projectiles fired.
However, now that I have done this, when I fire a projectile, it will only move so long as I am holding the fire button ('a' key if firing left) down. Also, if I fire left, then fire right, the projectile that was previously travelling left will begin to travel right instead.
My question is; How do I handle the projectiles so that when I fire one, it no longer accepts updates and travels in a straight line?
This is my working code;
Main game module
import pygame
from constants import *
from player import Player
from Projectile import Projectiles
pygame.init()
screen = pygame.display.set_mode([500, 500])
pygame.display.set_caption('Labyrinth')
# Spawn player
player = Player(50, 50)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
projectile_list = pygame.sprite.Group()
clock = pygame.time.Clock()
done = False
# ----- Event Loop
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == ord('a'):
player.changespeed(-3, 0)
elif event.key == ord('d'):
player.changespeed(3, 0)
elif event.key == ord('w'):
player.changespeed(0, -3)
elif event.key == ord('s'):
player.changespeed(0, 3)
elif event.key == pygame.K_LEFT:
projectile = Projectiles(0, 0)
projectile.rect.x = player.rect.x
projectile.rect.y = player.rect.y
elif event.key == pygame.K_RIGHT:
projectile = Projectiles(0, 0)
projectile.rect.x = player.rect.x
projectile.rect.y = player.rect.y
elif event.key == pygame.K_UP:
projectile = Projectiles(0, 0)
projectile.rect.x = player.rect.x
projectile.rect.y = player.rect.y
elif event.key == pygame.K_DOWN:
projectile = Projectiles(0, 0)
projectile.rect.x = player.rect.x
projectile.rect.y = player.rect.y
try:
if projectile:
projectile_list.add(projectile)
except:
pass
elif event.type == pygame.KEYUP:
if event.key == ord('a'):
player.changespeed(3, 0)
elif event.key == ord('d'):
player.changespeed(-3, 0)
elif event.key == ord('w'):
player.changespeed(0, 3)
elif event.key == ord('s'):
player.changespeed(0, -3)
# ----- Game Logic
all_sprites_list.update()
projectile_list.update()
screen.fill(GREEN)
all_sprites_list.draw(screen)
projectile_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Player module
from constants import *
import pygame
import time
from datetime import datetime, timedelta
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface([15, 15])
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
Projectile module
import pygame
from constants import *
class Projectiles(object):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface([4, 4])
self.image.fill(RED)
self.rect = self.image.get_rect()
def update(self):
key = pygame.key.get_pressed()
if key[pygame.K_UP]:
self.rect.y -= 5
if key[pygame.K_DOWN]:
self.rect.y += 5
if key[pygame.K_LEFT]:
self.rect.x -= 5
if key[pygame.K_RIGHT]:
self.rect.x += 5
As always any help would be much appreciated!
The first problem is that you only create ONE projectile. Your class is called Projectiles which is misleading because it's only one object not multiple. This causes the projectile to be controlled even after firing.
Also, the reason why the projectile only moves while you press a key is that in the update() method, you only add to the projectiles x or y coordinate when e.g. key[pygame.K_UP]: is true.
So, to fix this issues you will have to change the way your game handles projectiles.
If I understand your question right, you want to have multiple projectiles at once.
The way to implement this is to use a collection of projectiles.
Game
//nothing changed till here
elif event.key == pygame.K_LEFT:
p = Projectile(player.rect.x, player.rect.y, -5, 0)
projectile_list.add(p)
elif event.key == pygame.K_RIGHT:
p = Projectile(player.rect.x, player.rect.y, 5, 0)
projectile_list.add(p)
elif event.key == pygame.K_UP:
p = Projectile(player.rect.x, player.rect.y, 0, -5)
projectile_list.add(p))
elif event.key == pygame.K_DOWN:
p = Projectile(player.rect.x, player.rect.y, 0, 5)
projectile_list.add(p)
// moved the part where you append the projectile to in the if statement
# ----- Game Logic
all_sprites_list.update()
projectile_list.update()
screen.fill(GREEN)
all_sprites_list.draw(screen)
projectile_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Projectile:
import pygame
from constants import *
// projectile needs to extend Sprite
class Projectile(pygame.sprite.Sprite):
def __init__(self, x, y, x_speed, y_speed):
super().__init__()
self.image = pygame.Surface([4, 4])
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.x_speed = x_speed
self.y_speed = y_speed
def update(self):
self.rect.x += self.x_speed
self.rect.y += self.y_speed
Im not so familiar with Pygame but I hope this will help you at least somehow.
I have never used PyGame but one can see that your update() method in the Projectiles class depends on key press while it should depend on elapsed time instead.
Your projectile moves 5 units per key press, not 5 units per game tick once launched.
I want to move a rectangle with the arrow keys, so far I only can draw the rectangle but I don't get the keyhandler to work.
I'm a newbie in python and pygame.
This is my main.py:
import pygame
import time
import random
from Player import *
# Initialize Pygame
pygame.init()
game_over = False
# Color
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (192, 192, 192)
# Setting up the window
surfaceWidth = 800
surfaceHeight = 500
surface = pygame.display.set_mode((surfaceWidth, surfaceHeight))
pygame.display.set_caption("Rectangle Runner")
clock = pygame.time.Clock()
#Player(surface, surface_height, surface_width, size, jump_height, color)
player = Player(surface, surfaceHeight, surfaceWidth, 50, 200, BLACK)
# Game Loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if game_over == True:
pygame.quit()
quit()
surface.fill(GRAY)
#Player.draw()
player.keyHandling()
player.checkBoundaries()
player.draw()
#Obstacle.draw()
pygame.display.update()
clock.tick(60)
# This code shall be unreachable
pygame.quit()
quit()
This is the Player.py:
import pygame
class Player:
def __init__(self, surface, surface_height, surface_width, size, jump_height, color):
self.surface = surface
self.surface_height = surface_height
self.surface_width = surface_width
self.size = size
self.jump_height = jump_height
self.color = color
self.x = (0 + (self.surface_width/10))
self.y = self.surface_height - self.size
self.x_move = 0
self.y_move = 0
self.rect = pygame.draw.rect(self.surface, self.color, [self.x, self.y, self.size, self.size])
def keyHandling(self):
# Draw the player
#pygame.draw.rect(self.surface, self.color,
#[self.x, self.y, self.size, self.size])
# KeyListener
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
self.y_move = -10
#self.y += self.y_move
#self.rect.move_ip(0, -10)
if event.key == pygame.K_LEFT:
self.x_move = -5
#self.x += self.x_move
#self.rect.move_ip(-5, 0)
if event.key == pygame.K_RIGHT:
self.x_move = 5
#self.x += self.x_move
#self.rect.move_ip(5, 0)
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
self.y_move = 0
#self.y += self.y_move
#self.rect.move_ip(0, 10)
if event.key == pygame.K_LEFT:
self.x_move = 0
if event.key == pygame.K_RIGHT:
self.x_move = 0
self.x += self.x_move
self.y += self.y_move
def checkBoundaries(self):
# Checking for Boundaries
#if self.y <= self.jump_height:
# self.y_move = -10
if self.y > self.surface_height - self.size:
self.y_move = 0
if self.y <= self.jump_height + self.size:
self.y_move = -10
def draw(self):
pygame.draw.rect(self.surface, self.color, [self.x, self.y, self.size, self.size])
#pygame.draw.rect(self.surface, self.color,[self.x, self.y, self.size, self.size])
I need help. I'm thinking thru this the whole day.
Thanks in advance :D
The problem in your code is that pygame.event.get() is a generator. Each item that is obtained from it can ONLY be obtained once. Hence, each time the clock ticks, you are grabbing everything within the events generator and they are all destroyed. Next, when the Player object iterates over pygame.event.get, it does nothing, as the generator was already made empty. See this about generators.
What you need to do is catch the KEYDOWN event in the main.py module and then pass key information onto the Player object.
Replace the main loop in main.py with the following:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
player.keyDown(event.key)
if game_over == True:
pygame.quit()
quit()
surface.fill(GRAY)
player.checkBoundaries()
player.draw()
pygame.display.update()
clock.tick(60)
Remove the keyHandling method from Player.py and replace with the following method:
def keyDown(self, key):
if key == pygame.K_w:
self.y -= 10
elif key == pygame.K_a:
self.x -= 10
elif key == pygame.K_d:
self.x += 10
This now removes the issue with the generator.
Full code