Reputation: 79
I'm trying to code my first game with Python and Pygame. I'm fairly new to Python and coding in general, so I'm sorry if my code is hard to read.
There are 4 circles, moving from the middle of the screen to the 4 edges. I'm dropping cubes (enemies) from the 4 edges to the middle. The goal is to stop those cubes from reaching the middle of the screen, by pressing keyboard arrows. I
Now I'm working on the logic of lifes. The player has 5 lifes. If an enemy reaches the middle of the screen, the player loses a life. I got this part.
The player also loses a life when he misscliks. I'm struggling with this part. I can see a few scenario. Let's say that the player clicks LEFT:
Any idea ?
Here's my code.
# ---------- Packages and Inits ----------
import pygame, random, math
pygame.init()
# ---------- Settings ----------
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600
FPS = 60
SPEED = 1
SPEED_ENEMIES = 0.5
CIRCLE_RADIUS = 50
ENEMY_SIZE = 40
red = (255,000,000)
blue = (000,000,255)
yellow = (255,255,000)
green = (000,128,000)
pink = (255,192,203)
black = (000,000,000)
# ---------- Classes ----------
class Enemies:
def __init__(self, x, y, size=ENEMY_SIZE, thick=5, color=blue, speed=SPEED_ENEMIES, position="top"):
self.rect = pygame.Rect(0, 0, size, size)
if ( x == 0 and y == 0 ):
self.randomise()
self.rect.centerx = x
self.rect.centery = y
self.size = size
self.thick = thick
self.color = color
self.speed = speed
self.calcDirection()
self.position = position
def calcDirection( self ):
self.x_float = 1.0 * self.rect.centerx
self.y_float = 1.0 * self.rect.centery
# Determine direction vector from (x,y) to the centre of the screen
self.position_vector = pygame.math.Vector2( self.x_float, self.y_float )
self.velocity_vector = pygame.math.Vector2( SCREEN_WIDTH/2 - self.x_float, SCREEN_HEIGHT/2 - self.y_float )
self.velocity_vector = self.velocity_vector.normalize()
def update( self ):
x_delta = self.speed * self.velocity_vector[0]
y_delta = self.speed * self.velocity_vector[1]
self.x_float += x_delta
self.y_float += y_delta
self.rect.centerx = int( self.x_float )
self.rect.centery = int( self.y_float )
def draw(self, screen):
pygame.draw.rect(screen, self.color, self.rect )
def reachedPoint( self, x, y ):
return self.rect.collidepoint( x, y )
def randomise( self ):
self.rect.centerx = SCREEN_WIDTH//2
self.rect.centery = SCREEN_HEIGHT//2
side = random.randint( 0, 4 )
if ( side == 0 ):
self.rect.centery = SCREEN_HEIGHT
self.color = green
self.position= "bot"
elif ( side == 1 ):
self.rect.centery = 0
self.color = yellow
self.position= "top"
elif ( side == 2 ):
self.rect.centerx = 0
self.color = blue
self.position= "left"
else:
self.rect.centerx = SCREEN_WIDTH
self.color = red
self.position= "right"
self.calcDirection()
class Circle:
def __init__(self, x, y, radius=CIRCLE_RADIUS, thick=5, color=blue, speed=SPEED, position="top"):
self.rect = pygame.Rect(0, 0, 2*radius, 2*radius)
self.rect.centerx = x
self.rect.centery = y
self.radius = radius
self.thick = thick
self.color = color
self.speed = speed
self.position = position
if speed >= 0:
self.directionX = 'right'
self.direction = 'up'
else:
self.directionX = 'left'
self.direction = 'down'
def draw(self, screen):
pygame.draw.circle(screen, self.color, self.rect.center, self.radius, self.thick)
def swing(self):
if self.position == "top":
self.rect.y -= self.speed
if self.rect.top <= 0 and self.direction == 'up':
self.direction = 'down'
self.speed = -self.speed
elif self.rect.bottom > int(SCREEN_HEIGHT/2) - self.radius and self.direction == 'down':
self.direction = 'up'
self.speed = -self.speed
if self.position == "bot":
self.rect.y -= self.speed
if self.rect.top < int(SCREEN_HEIGHT/2) + self.radius and self.direction == 'up':
self.direction = 'down'
self.speed = -self.speed
elif self.rect.bottom >= SCREEN_HEIGHT and self.direction == 'down':
self.direction = 'up'
self.speed = -self.speed
if self.position == "left":
self.rect.x -= self.speed
if self.rect.right > int(SCREEN_WIDTH/2) - self.radius and self.directionX == 'left':
self.directionX = 'right'
self.speed = -self.speed
elif self.rect.left <= 0 and self.directionX == 'right':
self.directionX = 'left'
self.speed = -self.speed
if self.position == "right":
self.rect.x -= self.speed
if self.rect.left < int(SCREEN_WIDTH/2) + self.radius and self.directionX == 'right':
self.directionX = 'left'
self.speed = -self.speed
elif self.rect.right >= SCREEN_WIDTH and self.directionX == 'left':
self.directionX = 'right'
self.speed = -self.speed
def isCollision(self, enemyX, enemyY, circleX, circleY):
distance = math.sqrt((math.pow(enemyX-circleX,2))+(math.pow(enemyY-circleY,2)))
if distance < 65:
return True
else:
return False
# ---------- Main ----------
def main():
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
game_over = False
lifes = 5
score = 0
myFont = pygame.font.SysFont("monospace", 25)
# Start with 4 enemies
all_enemies = [
Enemies(int(SCREEN_WIDTH/2) , 0 , color = yellow, position = "top"),
Enemies(int(SCREEN_WIDTH/2) , SCREEN_HEIGHT-ENEMY_SIZE, color = green , position = "bot"),
Enemies(0 ,int(SCREEN_HEIGHT/2) , color = blue , position = "left"),
Enemies(SCREEN_WIDTH-ENEMY_SIZE, int(SCREEN_HEIGHT/2) , color = red , position = "right")
]
# Start with 4 circles
all_circles = [
Circle(screen_rect.centerx, screen_rect.centery - 2*CIRCLE_RADIUS, position="top"),
Circle(screen_rect.centerx, screen_rect.centery + 2*CIRCLE_RADIUS, position="bot"),
Circle(screen_rect.centerx + 2*CIRCLE_RADIUS, screen_rect.centery, position="right"),
Circle(screen_rect.centerx - 2*CIRCLE_RADIUS, screen_rect.centery, position="left")
]
while not game_over:
screen.fill(black)
# Reference enemy lists
left_enemies = [x for x in all_enemies if x.position == "left"]
right_enemies = [x for x in all_enemies if x.position == "right"]
top_enemies = [x for x in all_enemies if x.position == "top"]
bot_enemies = [x for x in all_enemies if x.position == "bot"]
# Place and swing 4 circles (the player)
for c in all_circles:
c.draw(screen)
c.swing()
# The enemy reaches the middle
for e in all_enemies:
e.update()
if ( e.reachedPoint( SCREEN_WIDTH//2, SCREEN_HEIGHT//2 ) ):
lifes -=1
e.randomise()
e.draw( screen )
# Score points with keyboard arrow
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
for c in all_circles:
if event.type == pygame.KEYDOWN:
# LEFT
if event.key == pygame.K_LEFT and c.position == "left":
if not left_enemies :
lifes -=1
for e in left_enemies:
collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
if e.position == "left" and collision == True :
score +=1
e.randomise()
else:
lifes -=1
# RIGHT
if event.key == pygame.K_RIGHT and c.position == "right":
if not right_enemies :
lifes -=1
for e in right_enemies:
collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
if e.position == "right" and collision == True :
score +=1
e.randomise()
else:
lifes -=1
# TOP
if event.key == pygame.K_UP and c.position == "top":
if not top_enemies :
lifes -=1
for e in top_enemies:
collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
if e.position == "top" and collision == True :
score +=1
e.randomise()
else:
lifes -=1
# BOT
if event.key == pygame.K_DOWN and c.position == "bot":
if not bot_enemies :
lifes -=1
for e in bot_enemies:
collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
if e.position == "bot" and collision == True :
score +=1
e.randomise()
else:
lifes -=1
print_lifes = myFont.render("Lifes:" + str(lifes), 1, red)
screen.blit(print_lifes, (10, SCREEN_HEIGHT-50))
print_score = myFont.render("Score:" + str(score), 1, red)
screen.blit(print_score, (10, 10))
pygame.display.update()
clock.tick(FPS)
main()
pygame.quit()
Upvotes: 2
Views: 187
Reputation: 101162
Your rules can be broken down to one simply rule:
If the player presses a key, look if there's an enemy under the circle.
So on KEYDOWN
, filter the enemy list for all enemies that collide with the circle and just check if the number is > 0.
Replace your checks/loops:
if not left_enemies:
lifes -=1
for e in left_enemies:
collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
if e.position == "left" and collision == True :
score +=1
e.randomise()
else:
lifes -=1
with something like this:
hits = [e for e in left_enemies if c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery) and position == "left"]
if not hits:
lifes -=1
for e in hits:
score +=1
e.randomise()
Upvotes: 3