I'm making a game with pygame, Space Invaders, and now I'm doing the collisions between the shoot of the eneimies and the player (those are images), but it doesn't work all time and I'd like to know why, and what's the solution.
Thanks for attention!
Here's the code:
# -*- coding: cp1252 -*-
import sys
import random
import pygame
import time
print pygame.init()
x_player, y_player = 650, 440
screen = pygame.display.set_mode((700, 500))
pygame.display.set_caption("Space Invaders v1.0.0")
invaders = pygame.image.load(
"C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders- my_own\\space-invaders.jpeg").convert_alpha()
player = pygame.image.load(
"C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\28006.png").convert_alpha()
mother_ship = pygame.image.load(
"C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\mother_ship.png").convert_alpha()
lifes = pygame.image.load(
"C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\28007.png").convert_alpha()
shoot_enemie = pygame.image.load(
"C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\shots_and_bombs2.png").convert_alpha()
shoot = pygame.image.load(
"C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\shots_and_bombs2.png").convert_alpha()
pygame.font.init()
clock = pygame.time.Clock()
move_x = 0
x_invaders, y_invaders = 60, 60
lifes_list = [lifes, lifes, lifes]
x_mother = 0
invaders_matrix = [[invaders] * 11] * 5
existe_nave = False
start = True
tru = False
tru3= True
x_shoot = x_player
y_shoot = 0
tru2 = True
shoot_enemie1, shoot_enemie2, shoot_enemie3 = shoot_enemie, shoot_enemie, shoot_enemie
shoot_list = [shoot_enemie1, shoot_enemie2, shoot_enemie]
tiros = {
"se1" : [0, 0],
"se2" : [0, 0],
"se3" : [0, 0]
}
cont = 0
while True:
invaders_matrix = [[invaders] * 11] * 5
if len(lifes_list) > 0:
clock.tick(40)
screen.fill((0, 0, 0))
screen.blit(player, ((x_player / 2), y_player))
if not tru:
invaders = pygame.image.load(
"C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\space- invader-motif.png"
).convert_alpha()
tru = True
else:
invaders = pygame.image.load(
"C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\space-invaders.jpeg"
).convert_alpha()
tru = False
x_invaders, y_invaders = 105, 125
for invader in range(len(invaders_matrix)):
for invad in range(len(invaders_matrix[invader])):
screen.blit(invaders_matrix[invader][invad], (x_invaders, y_invaders))
x_invaders += 45
x_invaders = 105
y_invaders += 30
if tru2:
for i in tiros.keys():
tiros[i][0] += tiros[i][0] + random.randint(0, 10) * 45 + 105
tiros[i][1] += tiros[i][1] + random.randint(0, 4) * 45 + 125
tru2 = False
elif tiros["se1"][1] >= 600 and tiros["se2"][1] >= 600 and tiros["se3"][1] >= 600:
tiros["se1"][1], tiros["se2"][1], tiros["se3"][1], \
tiros["se1"][0], tiros["se2"][0], tiros["se3"][0] = 0, 0, 0, 0, 0, 0
for i in tiros.keys():
tiros[i][0] += tiros[i][0] + random.randint(0, 10) * 45 + 105
tiros[i][1] += tiros[i][1] + random.randint(0, 4) * 45 + 125
for i in shoot_list:
for j in tiros.keys():
screen.blit(i, (tiros[j][0], tiros[j][1]))
for i in tiros.keys():
tiros[i][1] += 4
if existe_nave and (x_mother < 700):
screen.blit(mother_ship, [x_mother, 35])
x_mother += 4.5
screen.blit(mother_ship, [x_mother, 35])
elif random.randint(0, 800) == 0:
existe_nave = True
x_mother = 0
width_for_lifes = 680
for icon_lifes in lifes_list:
width_for_lifes -= 50
screen.blit(icon_lifes, (width_for_lifes, 15))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
move_x -= 10
if event.key == pygame.K_RIGHT:
move_x += 10
if tru3:
if event.key == pygame.K_SPACE:
y_shoot = y_player - player.get_height()
x_shoot = x_player / 2 + 20
tru3 = False
elif not tru3:
if y_shoot <= 0 and event.key == pygame.K_SPACE:
y_shoot = y_player - player.get_height()
x_shoot = x_player / 2 + 20
if event.type == pygame.KEYUP and (event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT):
move_x = 0
if y_shoot > -50:
screen.blit(shoot, (x_shoot, y_shoot))
y_shoot -= 10
if x_player >= 1280:
x_player = 1280
if x_player <= 25:
x_player = 25
x_player += move_x
font = pygame.font.Font(None, 36)
text = font.render("Lifes", 1, (0, 255, 85))
screen.blit(text, (450, 15))
font = pygame.font.Font(None, 36)
text = font.render("Score", 1, (0, 255, 85))
screen.blit(text, (20, 15))
#Here is the problem
player_rect = pygame.Rect(x_player, y_player, player.get_height(), player.get_width())
shoot_enemie1_rect = pygame.Rect(tiros["se1"][0], tiros["se1"][1], shoot_enemie1.get_height(),
shoot_enemie1.get_width())
shoot_enemie2_rect = pygame.Rect(tiros["se2"][0], tiros["se2"][1], shoot_enemie2.get_height(),
shoot_enemie2.get_width())
shoot_enemie3_rect = pygame.Rect(tiros["se3"][0], tiros["se3"][1], shoot_enemie3.get_height(),
shoot_enemie3.get_width())
if player_rect.colliderect(shoot_enemie1_rect) or player_rect.colliderect(shoot_enemie2_rect) or \
player_rect.colliderect(shoot_enemie3_rect):
print True
print player_rect
pygame.display.update()
Here is a collision detection code that will sense if one rectangle collides with another rectangle, if the enemy's shot hits the player:
if player x < shot x + player width and player x + shot width > shot x and player y < shot y + player height and shot height + player_y > shot y:
It works by sensing if any of the edges of the bullet are touching any edges of the character. I hope this helps.
Related
I want to make it so when my character touches the "v" block the game quits. What I tried was to find all blocks that are "v" and put them in the list. If player colliderect with any in list of "v" game will quit.
I think this should work although it does not seem to be working. Whenever I run it when I touch the "v" block nothing happens.
Here is my code
import pygame
from pygame.locals import *
pygame.init()
clock = pygame.time.Clock()
WINDOW_SIZE = (600, 400)
pygame.display.set_caption("Game")
screen = pygame.display.set_mode(WINDOW_SIZE, 0, 32)
display = pygame.Surface((300, 200))
player_image = pygame.image.load("Jacques clone-1.png (1).png").convert()
player_image.set_colorkey((255,255,255))
location = [50, 50]
#boolean for movement
moving_right = False
moving_left = False
scroll = [0, 0]
Stay_right = True
game_map1 = """
-----------------------------------------------------
-----------------------------------------------------
-----------------------------------------------------
-----------------------------------------------------
-----------------------------------------------------
xx----------x----------------------------------------
----------vvvv---------------------xxx----------------
---------xooo----------------------------------------
xxxxxxxxxooooxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ooooooooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooooooooo
""".splitlines()
game_map = [list(lst) for lst in game_map1]
tl = {}
tl["v"] = spike_img = pygame.image.load('dirt.png')
tl["o"] = dirt_img = pygame.image.load('grass.png')
tl["x"] = grass_img = pygame.image.load('grass.png')
player_rect = pygame.Rect(50, 50, 25, 25)
momentum = 0
air_timer = 0
#adding tiles list that are hit for movement
def collision_test(rect, tiles):
hit_list = []
for tile in tiles:
if rect.colliderect(tile):
hit_list.append(tile)
#print(hit_list)
return hit_list
def move(rect, movement, tiles):
collision_types = {'top': False, 'bottom': False, 'right': False, 'left': False}
rect.x += movement[0]
hit_list = collision_test(rect, tiles)
for tile in hit_list:
if movement[0] > 0:
rect.right = tile.left
collision_types['right'] = True
elif movement[0] < 0:
rect.left = tile.right
collision_types['left'] = True
rect.y += movement[1]
hit_list = collision_test(rect, tiles)
for tile in hit_list:
if movement[1] > 0:
rect.bottom = tile.top
collision_types['bottom'] = True
elif movement[1] < 0:
rect.top = tile.bottom
collision_types['top'] = True
return rect, collision_types
run = True
while run:
display.fill((146, 244, 255))
scroll[0] += (player_rect.x - scroll[0] - 130)
tile_rects = []
y = 0
for line_of_symbols in game_map:
x = 0
for symbol in line_of_symbols:
if symbol in tl:
display.blit(tl[symbol], (x * 16 - scroll[0], y * 16 - scroll[1]))
if symbol != "-":
tile_rects.append(pygame.Rect(x * 16, y * 16, 16, 16))
x += 1
y += 1
list_ofspike = []
y2 = 0
for lineofsymbols in game_map:
x2 = 0
for symbols in lineofsymbols:
if symbols == "v":
list_ofspike.append(pygame.Rect(x2 * 16, y2 * 16, 16, 16))
x2 += 1
y2 += 1
for spike in list_ofspike:
if player_rect.colliderect(spike):
pygame.quit()
player_movement = [0, 0]
if moving_right:
player_movement[0] += 2
if moving_left:
player_movement[0] -= 2
player_movement[1] += momentum
momentum += 0.3
if momentum > 3:
momentum = 3
player_rect, collisions = move(player_rect, player_movement, tile_rects)
if collisions['bottom']:
air_timer = 0
momentum = 0
else:
air_timer += 1
if Stay_right:
display.blit(player_image, (player_rect.x - scroll[0], player_rect.y - scroll[1]))
else:
display.blit(pygame.transform.flip(player_image, 1, 0 ),(player_rect.x - scroll[0], player_rect.y - scroll[1]))
for event in pygame.event.get():
if event.type == QUIT:
run = False
if event.type == KEYDOWN:
if event.key == K_RIGHT:
moving_right = True
Stay_right = True
if event.key == K_LEFT:
moving_left = True
Stay_right = False
if event.key == K_SPACE:
if air_timer < 6:
momentum = -5
if event.type == KEYUP:
if event.key == K_RIGHT:
moving_right = False
if event.key == K_LEFT:
moving_left = False
screen.blit(pygame.transform.scale(display, (WINDOW_SIZE)), (0, 0))
pygame.display.update()
clock.tick(60)
pygame.quit()
You do not detect a collision with the spikes, because your collision detection works too perfectly.
When you move the player then you ensure, that the player does not intersect any object, thus the player does not intersect a spike, too.
You have to test if the player touches a spike. Increase the player rectangle by 1 in direction and use the increased rectangle to do the collision test with the spikes:
while run:
# [...]
test_rect = pygame.Rect(player_rect.left-1, player_rect.top-1,
player_rect.width+2, player_rect.height+2)
for spike in list_ofspike:
if test_rect.colliderect(spike):
pygame.quit()
# [...]
So I have this code that's my main game:
def game():
running = True
import pygame, sys
import random
import math as m
mainClock = pygame.time.Clock()
pygame.init()
pygame.font.init
pygame.display.set_caption('Ping Pong')
SCREEN = width, height = 900,600
white = (255, 255, 255)
green = (0, 255, 0)
blue = (0, 0, 128)
black = (0,0,0)
speed = [4,4]
font = pygame.font.Font('freesansbold.ttf', 32)
score = 0
score = str(score)
font.size(score)
font.set_bold(True)
text = font.render(score, True, white)
textRect = text.get_rect()
textRect.center = ((width/2 - width / 20), (height/60 + height/20))
screen = pygame.display.set_mode(SCREEN, 0,32)
height1 = height/4
score = int(score)
ball = pygame.Rect(width/2, height/2, 50,50)
player = pygame.Rect(0,(height/2),25,height1)
player_1 = pygame.Rect(width - 25,(height/2),25,height1)
font1 = pygame.font.Font('freesansbold.ttf', 32)
score1 = 0
score1 = str(score)
font1.size(score1)
font1.set_bold(True)
text1 = font1.render(score1, True, white)
score1 = int(score1)
textRect1 = text1.get_rect()
textRect1.center = ((width/2 + width / 15), (height/60 + height/20))
up = False
down = False
up_1 = False
down_1 = False
RED = (255,0,0)
particles = []
while running:
color = (192,192,192)
# clear display #
screen.fill((0,0,0))
screen.blit(text, textRect)
screen.blit(text1, textRect1)
bx = ball.centerx
by = ball.centery
particles.append([[bx, by],[random.randint(0,20) / 10 - 1, -1], random.randint(4,6)])
for particle in particles:
particle[0][0] += particle[1][0]
particle[0][1] += particle[1][1]
particle[2] -= 0.1
particle[1][1] += 0.1
pygame.draw.circle(screen, color, [int(particle[0][0]), int(particle[0][1])], int(particle[2]))
if particle[2] <= 0:
particles.remove(particle)
if up == True:
player.y -= 5
if down == True:
player.y += 5
if up_1 == True:
player_1.y -= 5
if down_1 == True:
player_1.y += 5
if player.top < 0 :
player.y = 0
if player.bottom > height:
player.bottom = height
if player_1.top < 0 :
player_1.y = 0
if player_1.bottom > height :
player_1.bottom = height
for i in range(-90,(height + 130), 120):
rectangle = pygame.Rect((width/2), i, 13, 60)
pygame.draw.rect(screen, (255,255,255), rectangle)
pygame.draw.rect(screen,(191, 224, 255),player)
pygame.draw.rect(screen,(191, 224, 255),player_1)
color = (192,192,192)
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
pygame.draw.rect(screen,color,ball, 3)
import time
ball.x += speed[0]
ball.y += speed[1]
if ball.top < 0 or ball.bottom > height:
speed[1] = -speed[1]
r = random.randint(0,255)
g = random.randint(0,255)
b = random.randint(0,255)
pygame.draw.rect(screen,(r,b,g),ball, 3)
pygame.draw.circle(screen, (r,b,g), [int(particle[0][0]), int(particle[0][1])], int(particle[2]))
dab = random.randint(0,1)
if ball.left < 0 :
font = pygame.font.Font('freesansbold.ttf', 32)
score1 = int(score1)
score1 += 1
score1 = str(score1)
font.set_bold(True)
text1 = font.render(score1, True, white)
textRect1 = text.get_rect()
textRect1.center = ((width/2 + width / 15), (height/60 + height/20))
screen.blit(text1, textRect1)
ball.x = width/2
ball.y = height/2
if dab == 1:
ball.x += -speed[0]
ball.y += -speed[1]
elif dab == 0:
ball.x += speed[0]
ball.y += speed[1]
if ball.right > width:
font = pygame.font.Font('freesansbold.ttf', 32)
score = int(score)
score += 1
score = str(score)
font.set_bold(True)
text = font.render(score, True, white)
textRect = text.get_rect()
textRect.center = ((width/2 - width / 20), (height/60 + height/20))
screen.blit(text, textRect)
ball.x = width/2
ball.y = height/2
if dab == 1:
ball.x += -speed[0]
ball.y += -speed[1]
elif dab == 0:
ball.x += speed[0]
ball.y += speed[1]
# event handling #
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_s:
down = True
if event.key == K_w:
up = True
if event.key == K_UP:
up_1 =True
if event.key == K_ESCAPE:
running = False
if event.key == K_DOWN:
down_1 = True
if event.type == KEYUP:
if event.key == K_s:
down = False
if event.key == K_w:
up = False
if event.key == K_UP:
up_1 = False
if event.key == K_DOWN:
down_1 = False
if ball.colliderect(player_1):
dab = random.randint(0,1)
if dab == 1:
speed[1] = -speed[1]
speed[0] = -speed[0]
r = random.randint(0,255)
g = random.randint(0,255)
b = random.randint(0,255)
pygame.draw.rect(screen,(r,b,g),ball, 3)
if ball.colliderect(player):
speed[0] = -speed[0]
speed[0] = random.randint(4,6)
r = random.randint(0,255)
g = random.randint(0,255)
b = random.randint(0,255)
pygame.draw.rect(screen,(r,b,g),ball, 3)
# update display #
pygame.display.update()
mainClock.tick(60)
and I have a menu screen that displays some options. Only button_1 works.:
def main_menu():
while True:
white = (255,255,255)
font = pygame.font.Font('freesansbold.ttf', 32)
font.set_bold(True)
screen.fill((0,0,0))
button_1 = pygame.Rect(width/2, (height/2), width/2, 50)
button_1.centerx = width/2
button_2 = pygame.Rect(width/2, height/1.5, width/2, 50)
button_2.centerx = width/2
pygame.draw.rect(screen, (255, 0, 0), button_1)
pygame.draw.rect(screen, (255, 0, 0), button_2)
#draw_text('Start!', font, (255, 255, 255), screen, button_1.centerx, button_1.centery)
font = pygame.font.Font('freesansbold.ttf', 32)
font.set_bold(True)
text1 = font.render('Start!', True, white)
textRect1 = text1.get_rect()
textRect1.center = (button_1.centerx, button_1.centery)
screen.blit(text1, textRect1)
mx, my = pygame.mouse.get_pos()
if button_1.collidepoint((mx, my)):
if click:
game()
if button_2.collidepoint((mx, my)):
if click:
options()
click = False
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
if event.button == 1:
click = True
pygame.display.update()
clock.tick(60)
How do I make it so that after button_1 is pressed, there's a 3,2,1 countdown on the screen, and then the game starts?
In order to do the countdown, you import the time module:
import time
...then you need a for loop, with a step -1, counting down from 3 to 1. Inside the for loop, print the numbers and sleep one second, using the time module:
for a in range(3,0,-1):
print(a)
time.sleep(1)
After this for loop, you put the rest of your code.
This question already has an answer here:
How do I get the snake to grow and chain the movement of the snake's body?
(1 answer)
Closed 2 years ago.
I am remaking snake game. And have a moving function and don't know where to call it. The snake is the green rect
the function is just before the while loop.
it is to make other segments of the snake move into the pos of the last segment.
here is the code so far:
import pygame, sys, random
from pygame.locals import *
pygame.init()
movement_x = movement_y = 0
RED = (240, 0, 0)
GREEN = (0, 255, 0)
ran = [0,25,50,75,100,125,150,175,200,225,250,275,300,325,350,375,400,425,450,475]
ax = 0
ay = 0
x = 0
y = 0
sa = 0
sizex = 500
sizey = 500
tilesize = 25
screen = pygame.display.set_mode((sizex,sizey))
pygame.display.set_caption('Snake')
pygame.display.set_icon(pygame.image.load('images/tile.png'))
tile = pygame.image.load('images/tile.png')
tile = pygame.transform.scale(tile, (tilesize, tilesize))
x2 = 0
pag = 0
clock = pygame.time.Clock()
sx = 0
sy = 0
vel_x = 0
vel_y = 0
ap = True
snake_parts = [] # /N/ Pygame rects
def slither( new_head_coord ):
# Move each body part to the location of the previous part
# So we iterate over the tail-parts in reverse
for i in range( len( snake_parts )-1, 0, -1 ):
x, y = snake_parts[i-1].centerx, snake_parts[i-1].centery
snake_parts[i].center = ( x, y )
# Move the head
snake_parts[0].centre = new_head_coord
while True:
sx = x
sy = y
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
for row in range(sizex):
for column in range(sizey):
screen.blit(tile,(column*tilesize, row*tilesize,tilesize,tilesize))
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_UP:
vel_y = -25
vel_x = 0
elif event.key == K_DOWN:
vel_y = 25
vel_x = 0
elif event.key == K_LEFT:
vel_x = - 25
vel_y = 0
elif event.key == K_RIGHT:
vel_x= 25
vel_y = 0
elif event.key == K_y:
pag = 1
elif event.key == K_n:
pag = 2
inBounds = pygame.Rect(0, 0, sizex, sizey).collidepoint(x+vel_x, y+vel_y)
if inBounds:
y += vel_y
x += vel_x
else:
basicFont = pygame.font.SysFont(None, 48)
text = basicFont.render('Game Over! Play again? y/n', True, GREEN, RED)
textRect = text.get_rect()
textRect.centerx = screen.get_rect().centerx
textRect.centery = screen.get_rect().centery
pygame.draw.rect(screen, RED, (textRect.left - 20, textRect.top - 20, textRect.width + 40, textRect.height + 40))
screen.blit(text, textRect)
ay = -25
ax = -25
x = -25
y = -25
if pag == 1:
pag = 0
inBounds = True
x = 0
y = 0
vel_x = 0
vel_y = 0
ax = random.choice(ran)
ay = random.choice(ran)
pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
if pag == 2:
pygame.quit()
sys.exit()
if ap:
pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
if x == ax and y == ay:
pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
ax = random.choice(ran)
ay = random.choice(ran)
sa += 1
pygame.draw.rect(screen, GREEN, pygame.Rect(x,y,tilesize,tilesize))
pygame.display.update()
clock.tick(100)
I am not quite sure on how to use functions yet as I have only been learning python for a few weeks.
Add a new function which draws the snake:
def drawSnake():
for p in snake_parts:
screen.blit(shake, p.topleft)
Of course you can draw an image, instead of the recatangl. snake is an image of type pygame.Surface:
def drawSnake():
for p in snake_parts:
pygame.draw.rect(screen, RED, p)
Add the head to the list snake_parts before the main loop (before while True:):
snake_parts.append(pygame.Rect(x,y,tilesize,tilesize))
ax, ay = random.choice(ran), random.choice(ran)
Use drawSnake to draw the snake and update the positions of the parts right before:
slither( (x, y) )
if ap:
pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
if x == ax and y == ay:
pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
ax, ay = random.choice(ran), random.choice(ran)
sa += 1
snake_parts.append(pygame.Rect(x, y, tilesize, tilesize))
drawSnake()
pygame.display.update()
There is a typo in slither. It has to be snake_parts[0].center rather than snake_parts[0].centre.
But anyway, in your case the origin of the pars of the snake is topleft, rather than center. Change the function slither:
def slither( new_head_coord ):
for i in range( len(snake_parts)-1, 0, -1 ):
snake_parts[i] = snake_parts[i-1].copy()
snake_parts[0].topleft = new_head_coord
Do only 1 event loop in the main loop:
e.g.
run = True
while run:
sx, sy = x, y
for row in range(sizex):
for column in range(sizey):
screen.blit(tile,(column*tilesize, row*tilesize,tilesize,tilesize))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
run = False
if event.type == KEYDOWN:
if event.key == K_UP:
vel_y = -25
vel_x = 0
# [...]
Demo
import pygame, sys, random
from pygame.locals import *
pygame.init()
movement_x = movement_y = 0
RED = (240, 0, 0)
GREEN = (0, 255, 0)
ran = [0,25,50,75,100,125,150,175,200,225,250,275,300,325,350,375,400,425,450,475]
sizex, sizey = 500, 500
tilesize = 25
screen = pygame.display.set_mode((sizex,sizey))
pygame.display.set_caption('Snake')
tile = pygame.Surface((tilesize, tilesize))
tile.fill((0, 0, 64))
tile = pygame.transform.scale(tile, (tilesize, tilesize))
x2 = 0
pag = 0
clock = pygame.time.Clock()
sx, sy = 0, 0
vel_x, vel_y = 0, 0
x, y = 0, 0
sa = 0
ap = True
snake_parts = [] # /N/ Pygame rects
def slither( new_head_coord ):
for i in range( len(snake_parts)-1, 0, -1 ):
snake_parts[i] = snake_parts[i-1].copy()
snake_parts[0].topleft = new_head_coord
def drawSnake():
for p in snake_parts:
pygame.draw.rect(screen, GREEN, p)
snake_parts.append(pygame.Rect(x,y,tilesize,tilesize))
ax, ay = random.choice(ran), random.choice(ran)
run = True
while run:
sx, sy = x, y
for row in range(sizex):
for column in range(sizey):
screen.blit(tile,(column*tilesize, row*tilesize,tilesize,tilesize))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
run = False
if event.type == KEYDOWN:
if event.key == K_UP:
vel_x, vel_y = 0, -25
elif event.key == K_DOWN:
vel_x, vel_y = 0, 25
elif event.key == K_LEFT:
vel_x, vel_y = -25, 0
elif event.key == K_RIGHT:
vel_x, vel_y = 25, 0
elif event.key == K_y:
pag = 1
elif event.key == K_n:
pag = 2
inBounds = pygame.Rect(0, 0, sizex, sizey).collidepoint(x+vel_x, y+vel_y)
if inBounds:
y += vel_y
x += vel_x
else:
basicFont = pygame.font.SysFont(None, 48)
text = basicFont.render('Game Over! Play again? y/n', True, GREEN, RED)
textRect = text.get_rect()
textRect.centerx = screen.get_rect().centerx
textRect.centery = screen.get_rect().centery
pygame.draw.rect(screen, RED, (textRect.left - 20, textRect.top - 20, textRect.width + 40, textRect.height + 40))
screen.blit(text, textRect)
ax, ay = -25, -25
x, y = -25, -25
if pag == 1:
pag = 0
inBounds = True
x, y = 0, 0
vel_x, vel_y = 0, 0
ax, ay = random.choice(ran), random.choice(ran)
pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
if pag == 2:
pygame.quit()
sys.exit()
slither( (x, y) )
if ap:
pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
if x == ax and y == ay:
pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
ax, ay = random.choice(ran), random.choice(ran)
sa += 1
snake_parts.append(pygame.Rect(x, y, tilesize, tilesize))
drawSnake()
pygame.display.update()
clock.tick(100)
I've written a game where the main character can shoot daggers on mouseclick, and move around with the up, down, left, and right keys. THe character also follows the mouse around. I have added the villains into the screen, however I am unsure of how to make a rect for my daggers. My intention is to use colliderect when the dagger and the villain collide; and recode the villain to disappear, and code it off of the screen and have him reappear. However; before I can do this I need to make a rect for my daggers; which I, for whatever reason cannot find out.
This is the portion of the code in which I define my rects variables and rect:
xPlayer = 200
yPlayer = 275
dxPlayer = 0
dyPlayer = 0
playerPosition = (200,275)
daggers = []
angle = 0
villainStartx = 800
villainStarty = random.randrange(0, 550)
villainSpeed = -10
villainWidth = 100
villainHeight = 100
villainTWOStartx = 800
villainTWOStarty = random.randrange(0, 550)
villainTWOSpeed = -20
villainTWOWidth = 100
villainTWOHeight = 100
villainRect = pygame.Rect(villainStartx, villainStarty, villainWidth, villainHeight)
villainTWORect = pygame.Rect(villainTWOStartx, villainTWOStarty, villainTWOWidth, villainTWOHeight)
player = pygame.Rect(xPlayer, yPlayer, 160, 146)
This is the portion of my code where I draw the daggers to the screen on mouseclick:
filtered_daggers = []
for shot in daggers:
if not outOfBounds(shot[0]):
filtered_daggers.append(shot)
daggers = filtered_daggers
for shot in daggers:
shot[0][0] += shot[1][0]
shot[0][1] += shot[1][1]
screen.blit(cloudSky, (0,0))
screen.blit(playerRotate, playerPositionNew)
for shot in daggers:
x, y = shot[0]
screen.blit(shot[2], shot[0])
And if necessary, below is my entire code:
#Import the necessary modules
import pygame
import sys
import os
import math
import random
#Initialize pygame
pygame.init()
# Set the size for the surface (screen)
screenSize = (900,600)
screen = pygame.display.set_mode((screenSize),0)
# Set the caption for the screen
pygame.display.set_caption("Neverland")
#Define Colours
WHITE = (255,255,255)
BLUE = (0,0,255)
BLACK = (0,0,0)
GRAY = (128, 128, 128)
MAROON = (128, 0, 0)
NAVYBLUE = (0, 0, 128)
OLIVE = (128, 128, 0)
PURPLE = (128, 0, 128)
TEAL = (0,128,128)
PINK = (226,132,164)
MUTEDBLUE = (155,182,203)
PLUM = (221,160,221)
#Clock Setup
clock = pygame.time.Clock()
#Load Images
peterPlayer = pygame.image.load('pixelPirateOne.png')
nightBackground = pygame.image.load ('skyTwo_1.png')
daggerPlayer = pygame.image.load('daggerPlayer.png')
captHook = pygame.image.load('/pixelCaptainHook.png')
cloudSky = pygame.image.load('cloudSky.png')
pirateTwo = pygame.image.load('pixelPirateTwo.png')
#Define All Variables
xPlayer = 200
yPlayer = 275
dxPlayer = 0
dyPlayer = 0
playerPosition = (200,275)
accuracyShot = [0,0]
daggers = []
angle = 0
healthValue=194
villainStartx = 800
villainStarty = random.randrange(0, 550)
villainSpeed = -10
villainWidth = 100
villainHeight = 100
villainTWOStartx = 800
villainTWOStarty = random.randrange(0, 550)
villainTWOSpeed = -20
villainTWOWidth = 100
villainTWOHeight = 100
villainRect = pygame.Rect(villainStartx, villainStarty, villainWidth, villainHeight)
villainTWORect = pygame.Rect(villainTWOStartx, villainTWOStarty, villainTWOWidth, villainTWOHeight)
player = pygame.Rect(xPlayer, yPlayer, 160, 146)
#dagger = pygame.Rect(
def quitGame():
pygame.quit()
sys.exit()
def outOfBounds(shot):
return shot[0] < -40 or shot[0] > 900 or shot[1] < -40 or shot[1] > 600
def villains(x,y):
screen.blit(captHook, (x,y))
def villainsTwo(x,y):
screen.blit(pirateTwo, (x,y))
go = True
while go:
#Quit Game
for event in pygame.event.get():
if event.type == pygame.QUIT:
quitGame()
#Move Player
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
dxPlayer -= 25
elif event.key == pygame.K_RIGHT:
dxPlayer += 25
elif event.key == pygame.K_UP:
dyPlayer -= 25
elif event.key == pygame.K_DOWN:
dyPlayer += 25
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
dxPlayer = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
dyPlayer = 0
elif event.type == pygame.MOUSEBUTTONDOWN:
mousePosition = pygame.mouse.get_pos()
velx = math.cos(angle)*20
vely = math.sin(angle)*20
daggerImage = pygame.transform.rotate(daggerPlayer, -math.degrees(angle))
width, height = daggerImage.get_size()
daggers.append([[xPlayer,yPlayer],
[velx, vely], daggerImage])
#Update move player
xPlayer = xPlayer + dxPlayer
yPlayer = yPlayer + dyPlayer
pygame.display.update()
#Learned about atan2 from --> https://docs.python.org/2/library/math.html
#Allows To Rotate Player With Mouse
mousePosition = pygame.mouse.get_pos()
rise = mousePosition[1] - player.centery
run = mousePosition[0] - player.centerx
angle = math.atan2(rise, run)
playerRotate = pygame.transform.rotate(peterPlayer, -math.degrees(angle))
playerPositionNew = (xPlayer-playerRotate.get_rect().width/2, yPlayer-playerRotate.get_rect().height/2)
player = playerRotate.get_rect(center=player.center)
#Learned about cos and sin in python from --> https://docs.python.org/2/library/math.html
#Draw daggers to screen
filtered_daggers = []
for shot in daggers:
if not outOfBounds(shot[0]):
filtered_daggers.append(shot)
daggers = filtered_daggers
for shot in daggers:
shot[0][0] += shot[1][0]
shot[0][1] += shot[1][1]
screen.blit(cloudSky, (0,0))
screen.blit(playerRotate, playerPositionNew)
for shot in daggers:
x, y = shot[0]
screen.blit(shot[2], shot[0])
if villainRect.colliderect(dagger):
print(dagger)
pygame.display.update()
clock.tick(30)
#Drawing the villains at random
villains(villainStartx, villainStarty)
villainStartx +=villainSpeed
if villainStartx < -50:
villainStartx = random.randrange(800,900)
villainStarty = random.randrange(0,550)
villainsTwo(villainTWOStartx, villainTWOStarty)
villainTWOStartx +=villainTWOSpeed
if villainTWOStartx < -50:
villainTWOStartx = random.randrange(800,1000)
villainTWOStarty = random.randrange(0,550)
#Redrawing villain after collision- To be finished after defining dagger rect
pygame.display.update()
You can use an image for your dagger, and then get the rect properties from it:
dagger = pygame.image.load("dagger.png")
#you can then blit it on the screen:
screen.blit(dagger, (corrd1, corrd2))
dagger_rect = dagger.get_rect() #get the location of the dagger
if villianRect.colliderect(dagger_rect):
#do something
Well In a game I am working on I have recently allowed mouse click to shoot wherever the mouse is. But the bullets will only shoot at either a 0 degree angle or 45 degree angle. I am wanting to try and make this to be 360 degrees. Here is the code for my main game file:
import pygame, sys
import random
import pygame.mixer
import Funk, math
from time import sleep
from player import *
from zombie import *
from level import *
from bullet import *
from constants import *
from Drops import *
from menus import *
from meteors import *
import menu as dm
class Game():
def __init__(self):
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load('data/sounds/menugame.ogg')
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
# A few variables
self.gravity = .50
self.red = (255, 0, 0)
self.darkred = (200, 0, 0)
self.darkblue = (0, 0, 200)
self.darkgreen = (0, 200, 0)
self.gameover = pygame.image.load('data/images/gameover.png')
self.victory = pygame.image.load('data/images/victory.png')
# Bullets and Drops
self.bullets = []
self.gameDrops = []
# Screen
icon = pygame.image.load('data/icons/moonsurvival.bmp')
size = SCREEN_WIDTH, SCREEN_HEIGHT
self.screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')
pygame.display.set_icon(icon)
self.screen_rect = self.screen.get_rect()
# Moon / Background
self.moon = Background()
self.text1 = pygame.image.load('data/images/TextSlides/Text1.jpg')
self.text2 = pygame.image.load('data/images/TextSlides/Text2.jpg')
# Zombies and boss
self.zombies = []
self.bosses = []
#for i in range(15):
# self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,0)) )
self.zombieskilled = 0
# Spawn time
self.last_spawn_time = 0
# Meteors
self.meteors = []
# Menus
self.menuStartGame = MenuStartGame(self.screen, self)
self.menuAbout = MenuAbout(self.screen, self)
#self.menuSettings = MenuSettings(self.screen, self)
self.menuScene = MenuScene(self.screen, self)
self.menuGameOver = MenuGameOver(self.screen, self)
#self.menuGameFinish = MenuGameFinish(self.screen, self)
# Player
self.player = Player(25, 320, self.gravity)
# Font for text
self.font = pygame.font.SysFont(None, 72)
self.point = self.player.rect.x, self.player.rect.y
self.max_radius = math.hypot(self.screen_rect.w, self.screen_rect.h)
self.mouse_angle = (0, 0)
# game over
self.gameover_text = self.font.render("The Aliens Are Too Good", -1, (255, 0, 0))
self.gameover_rect = self.gameover_text.get_rect(center=self.screen.get_rect().center)
# game state
self.game_state = STATE_MENU
def run(self):
clock = pygame.time.Clock()
# "state machine"
RUNNING = True
PAUSED = False
GAME_OVER = False
# Game loop
while RUNNING:
# (all) Events
if self.game_state == STATE_INGAME:
print(self.mouse_angle)
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
if self.player.power == POWER_TRIBULLETS:
self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 35, self.mouse_angle))
self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 25, self.mouse_angle))
else:
self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
if event.key == pygame.K_ESCAPE:
RUNNING = False
elif event.key == pygame.K_p:
# set state to paused
self.game_state = STATE_PAUSED
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if self.player.power == POWER_TRIBULLETS:
self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 35, self.mouse_angle))
self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 25, self.mouse_angle))
else:
self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
# Player/Zombies events
self.player.handle_events(event)
# (all) Movements / Updates
self.player_move()
self.player.update()
for z in self.zombies:
self.zombie_move(z)
z.update(self.screen.get_rect())
for boss in self.bosses:
self.boss_move(boss)
boss.update(self.screen.get_rect())
for b in self.bullets:
b.update()
for tile in self.moon.get_surrounding_blocks(b):
if tile is not None:
if pygame.sprite.collide_rect(b, tile):
# Destroy block
x = tile.rect.x / tile.rect.width
y = tile.rect.y / tile.rect.height
self.moon.levelStructure[x][y] = None
try:
self.bullets.remove(b)
except:
continue
for m in self.meteors:
m.update()
for tile in self.moon.get_surrounding_blocks(m):
if tile is not None:
if pygame.sprite.collide_rect(m, tile):
# Destroy block
x = tile.rect.x / tile.rect.width
y = tile.rect.y / tile.rect.height
self.moon.levelStructure[x][y] = None
self.moon.levelStructure[x + 1][y + 1] = None
self.moon.levelStructure[x - 1][y - 1] = None
self.moon.levelStructure[x + 2][y + 2] = None
self.moon.levelStructure[x - 2][y - 2] = None
try:
self.meteors.remove(m)
except:
continue
self.check_game_state()
# (all) Display updating
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
for boss in self.bosses:
boss.render(self.screen)
for b in self.bullets:
b.render(self.screen)
for m in self.meteors:
m.render(self.screen)
for drop in self.gameDrops:
drop.render(self.screen)
self.player.render(self.screen)
self.updateMousePosition(self.screen, pygame.mouse.get_pos())
Funk.text_to_screen(self.screen, 'Level 1', 5, 675)
Funk.text_to_screen(self.screen, 'Health: {0}'.format(self.player.health), 5, 0)
Funk.text_to_screen(self.screen, 'Score: {0}'.format(self.player.score), 400, 0)
Funk.text_to_screen(self.screen, 'Time: {0}'.format(self.player.alivetime), 750, 0)
Funk.text_to_screen(self.screen, 'Kills: {0}'.format(self.zombieskilled), 5, 50)
Funk.text_to_screen(self.screen, 'Lives: {0}'.format(self.player.lives), 300, 50)
elif self.game_state == STATE_GAMEOVER:
self.menuGameOver.draw()
self.menuGameOver.update()
elif self.game_state == STATE_SETTINGS:
self.menuSettings.draw()
self.menuSettings.update()
elif self.game_state == STATE_ABOUT:
self.menuAbout.draw()
self.menuAbout.update()
elif self.game_state == STATE_SCENE:
self.menuScene.draw()
self.menuScene.update()
elif self.game_state == STATE_MENU:
self.menuStartGame.draw()
self.menuStartGame.update()
elif self.game_state == STATE_PAUSED:
# (all) Display updating
if self.game_state == STATE_INGAME:
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
choose = dm.dumbmenu(self.screen, [
'Resume Game',
'Menu',
'Quit Game'], 200, 200,'orecrusherexpanded',100,0.75,self.darkred,self.red)
if choose == 0:
print "You choose 'Start Game'."
# set state to ingame
self.game_state = STATE_INGAME
elif choose == 1:
print "You choose 'Controls'."
if choose == 2:
print "You choose 'Quit Game'."
pygame.quit()
sys.exit()
#for event in pygame.event.get():
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
for boss in self.bosses:
boss.render(self.screen)
for b in self.bullets:
b.render(self.screen)
for m in self.meteors:
m.render(self.screen)
self.player.render(self.screen)
pygame.display.update()
# FTP
clock.tick(100)
# --- the end ---
pygame.quit()
def updateMousePosition(self, surface, mouse):
x_comp, y_comp = mouse[0] - self.point[0], mouse[1] - self.point[1]
self.mouse_angle = math.atan2(y_comp, x_comp)
x = self.max_radius * math.cos(self.mouse_angle) + self.point[0]
y = self.max_radius * math.sin(self.mouse_angle) + self.point[1]
pygame.draw.line(surface, pygame.Color("white"), self.point, (x, y))
def check_game_state(self):
elapsed_time = pygame.time.get_ticks()
if elapsed_time > self.last_spawn_time + 10:
# Spawn aliens
if len(self.zombies) <= 10:
self.zombies.append(Zombie(random.randint(0,1280), random.randint(0,0)))
# Spawned! Change last spawn time!
self.last_spawn_time = elapsed_time
meteor_time = pygame.time.get_ticks()
if meteor_time > self.last_spawn_time + random.randint(1000, 3000):
# Spawn meteors
if len(self.meteors) <= 1:
self.meteors.append(Meteor(random.randint(0,1280), random.randint(-100,0)))
# Spawned! Change last spawn time!
self.last_spawn_time = meteor_time
def player_move(self):
# Line start
self.point = self.player.rect.x + 30, self.player.rect.y + 30
# add gravity
self.player.do_jump()
# simulate gravity
self.player.on_ground = False
if not self.player.on_ground and not self.player.jumping:
self.player.velY = 4
# Drops
for drop in self.gameDrops:
if pygame.sprite.collide_rect(self.player, drop):
if type(drop) == HealthDrop:
self.player.health += 50
self.gameDrops.remove(drop)
elif type(drop) == SuperHealthDrop:
self.player.health += 1000
self.gameDrops.remove(drop)
elif type(drop) == TriBullets:
self.player.power = POWER_TRIBULLETS
self.gameDrops.remove(drop)
elif type(drop) == ShieldDrop:
self.player.power = POWER_SHIELD
self.gameDrops.remove(drop)
# Health
for zombie in self.zombies:
if pygame.sprite.collide_rect(self.player, zombie):
if self.player.power == POWER_SHIELD:
self.player.health -= 1
else:
self.player.health -= 5
# check if we die
if self.player.health <= 0:
self.player.power = POWER_NONE
self.player.lives -= 1
self.player.rect.x = 320
self.player.rect.y = 320
self.player.health += 200
if self.player.lives <= 0:
self.game_state = STATE_GAMEOVER
# move player and check for collision at the same time
self.player.rect.x += self.player.velX
self.check_collision(self.player, self.player.velX, 0)
self.player.rect.y += self.player.velY
self.check_collision(self.player, 0, self.player.velY)
def zombie_move(self, zombie_sprite):
# add gravity
zombie_sprite.do_jump()
percentage = random.randint(0, 100)
# simualte gravity
zombie_sprite.on_ground = False
if not zombie_sprite.on_ground and not zombie_sprite.jumping:
zombie_sprite.velY = 4
# Zombie damage
for zombie in self.zombies:
for b in self.bullets:
if pygame.sprite.collide_rect(b, zombie):
#The same bullet cannot be used to kill
#multiple zombies and as the bullet was
#no longer in Bullet.List error was raised
zombie.health -= 10
self.bullets.remove(b)
if zombie.health <= 0:
if (percentage >= 0) and (percentage < 40):
self.gameDrops.append(HealthDrop(zombie.rect.x + 10, zombie.rect.y + 30))
elif (percentage >= 0) and (percentage < 1):
self.gameDrops.append(SuperHealthDrop(zombie.rect.x + 20, zombie.rect.y + 30))
elif (percentage >= 1) and (percentage < 20):
self.gameDrops.append(TriBullets(zombie.rect.x + 30, zombie.rect.y + 30, self.player.direction))
elif (percentage >= 1) and (percentage < 50):
self.gameDrops.append(ShieldDrop(zombie.rect.x + 40, zombie.rect.y + 30))
self.zombieskilled += 1
self.player.score += 20
self.zombies.remove(zombie)
break
# move zombie and check for collision
zombie_sprite.rect.x += zombie_sprite.velX
self.check_collision(zombie_sprite, zombie_sprite.velX, 0)
zombie_sprite.rect.y += zombie_sprite.velY
self.check_collision(zombie_sprite, 0, zombie_sprite.velY)
def check_collision(self, sprite, x_vel, y_vel):
# for every tile in Background.levelStructure, check for collision
for block in self.moon.get_surrounding_blocks(sprite):
if block is not None:
if pygame.sprite.collide_rect(sprite, block):
# we've collided! now we must move the collided sprite a step back
if x_vel < 0:
sprite.rect.x = block.rect.x + block.rect.w
if type(sprite) is Zombie:
# the sprite is a zombie, let's make it jump
if not sprite.jumping:
sprite.jumping = True
sprite.on_ground = False
if x_vel > 0:
sprite.rect.x = block.rect.x - sprite.rect.w
if type(sprite) is Zombie:
# the sprite is a zombie, let's make it jump
if not sprite.jumping:
sprite.jumping = True
sprite.on_ground = False
if y_vel < 0:
sprite.rect.y = block.rect.y + block.rect.h
if y_vel > 0 and not sprite.on_ground:
sprite.on_ground = True
sprite.rect.y = block.rect.y - sprite.rect.h
#---------------------------------------------------------------------
Game().run()
Here is the code for the bullets:
import pygame, math
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, angle):
self.image = pygame.image.load('data/images/Sprites/laser.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.velX = math.cos(angle * math.pi / 180) * 8
self.velY = math.sin(angle * math.pi / 180) * 8
# self.velX = 8
# self.velX = -8
# Bullet updates
def update(self):
# Velocity
self.rect.x += self.velX
self.rect.y += self.velY
def render(self, surface):
surface.blit(self.image, self.rect)
self.mouse_angle is already in radians. If you multiply it again by math.pi / 180, as you do in Bullet.__init__(), it will always give a value very close to zero.