I'm implementing and "IA" to my ghost in my copy of Pac-Man, the ghost when hit a block check for every way it can go, but one of that ways is the opposite direction he was taking and that makes that for example if hits a block while moving left, then move right, and then hit a block and move left again, how can I avoid that? I tried doing a "oppositeDirection" variable that changes depending where it the block but the ghost keep doig the same
import pygame, sys, random
from pygame.locals import *
pygame.init()
#Variables del juego
windowWidth = 504
windowHeight = 648
windowSurface = pygame.display.set_mode((windowWidth, windowHeight), 0, 32)
mainClock = pygame.time.Clock()
FPS = 30
pygame.display.set_caption('Pac-Man')
#Colores
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
yellow = (255, 255, 0)
cyan = (0, 255, 255)
navyBlue = (0, 0, 53)
pink = (255, 192, 203)
#Tamaño del bloque
blockSize = 24
dotSize = 4
pillSize = 10
#Datos del jugador
playerSize = 24
player = pygame.Rect(240, 480, playerSize, playerSize)
speed = 5
#Datos del fantasma
ghostSize = 24
player = pygame.Rect(240, 480, playerSize, playerSize)
ghostSpeed = 4
#Variables de movimiento del jugador
moveLeft = moveRight = moveDown = moveUp = False
#Variables del fantasma
ghost = pygame.Rect(240, 480, ghostSize, ghostSize)
ghostMoveLeft = 1
ghostMoveRight = 2
ghostMoveUp = 3
ghostMoveDown = 4
ghostCurrentDirection = None
ghostPossibleMove = []
ghostOpossiteDirection = None
#Laberinto
maze = [
"xxxxxxxxxxxxxxxxxxxxx",
"x.........x.........x",
"x.xxx.xxx.x.xxx.xxx.x",
"x-xxx.xxx.x.xxx.xxx-x",
"x.xxx.xxx.x.xxx.xxx.x",
"x...................x",
"x.xxx.x.xxxxx.x.xxx.x",
"x.xxx.x.xxxxx.x.xxx.x",
"x.....x...x...x.....x",
"xxxxx.xxxoxoxxx.xxxxx",
"oooox.xooooooox.xoooo",
"oooox.xoxxoxxox.xoooo",
"xxxxx.xoxoooxox.xxxxx",
"ooooo.ooxoooxoo.ooooo",
"xxxxx.xoxxxxxox.xxxxx",
"oooox.xooooooox.xoooo",
"oooox.xoxxxxxox.xoooo",
"xxxxx.xoxxxxxox.xxxxx",
"x.........x.........x",
"x.xxx.xxx.x.xxx.xxx.x",
"x-..x.....o.....x..-x",
"xxx.x.x.xxxxx.x.x.xxx",
"xxx.x.x.xxxxx.x.x.xxx",
"x.....x...x...x.....x",
"x.xxxxxxx.x.xxxxxxx.x",
"x...................x",
"xxxxxxxxxxxxxxxxxxxxx"
]
def createMaze():
pointX = 0
pointY = 0
y = 0
for i in maze:
x = 0
for j in i:
if j == "x":
block = pygame.Rect(pointX, pointY, blockSize, blockSize)
pygame.draw.rect(windowSurface, navyBlue, block)
global ghostCurrentDirection
if block.colliderect(player):
if player.bottom - block.top < 10:
player.y = block.top - playerSize
if block.bottom - player.top < 10:
player.y = block.bottom
if block.right - player.left < 10:
player.x = block.right
if player.right - block.left < 10:
player.x = block.left - playerSize
global ghostPossibleMove
global ghostOpossiteDirection
if ghost.right is not block.left:
ghostPossibleMove.append(ghostMoveRight)
if ghost.left is not block.right:
ghostPossibleMove.append(ghostMoveLeft)
if ghost.top is not block.bottom:
ghostPossibleMove.append(ghostMoveDown)
if ghost.bottom is not block.top:
ghostPossibleMove.append(ghostMoveUp)
if ghostCurrentDirection == None:
ghostCurrentDirection = random.choice(ghostPossibleMove)
ghostPossibleMove = []
if ghostCurrentDirection == ghostOpossiteDirection:
ghostCurrentDirection = None
else:
pass
if block.colliderect(ghost):
if ghost.bottom - block.top < 10:
ghost.y = block.top - playerSize
ghostCurrentDirection = None
ghostOpossiteDirection = ghostMoveUp
if block.bottom - ghost.top < 10:
ghost.y = block.bottom
ghostCurrentDirection = None
ghostOpossiteDirection = ghostMoveDown
if block.right - ghost.left < 10:
ghost.x = block.right
ghostCurrentDirection = None
ghostOpossiteDirection = ghostMoveRight
if ghost.right - block.left < 10:
ghost.x = block.left - playerSize
ghostCurrentDirection = None
ghostOpossiteDirection = ghostMoveLeft
if j == ".":
dot = pygame.Rect(pointX + (blockSize / 2) - (dotSize / 2), pointY + (blockSize / 2) - (dotSize / 2), dotSize, dotSize)
pygame.draw.rect(windowSurface, white, dot)
if dot.colliderect(player):
maze[y] = maze[y][:x] + "o" + maze[y][x + 1:]
if j == "-":
pill = pygame.Rect(pointX + (blockSize / 2) - (pillSize / 2), pointY + (blockSize / 2) - (pillSize / 2), pillSize, pillSize)
pygame.draw.rect(windowSurface, white, pill)
if pill.colliderect(player):
maze[y] = maze[y][:x] + "o" + maze[y][x + 1:]
if j == "o":
pass
pointX += blockSize
x += 1
pointX = 0
pointY += blockSize
y += 1
#Función para cerrar juego
def close():
pygame.quit()
sys.exit()
#Ciclo principal del juego
while True:
#Buscar evento QUIT
for event in pygame.event.get():
if event.type == QUIT:
close()
if event.type == KEYDOWN:
if event.key == K_w:
moveUp = True
moveDown = False
moveLeft = False
moveRight = False
if event.key == K_s:
moveUp = False
moveDown = True
moveLeft = False
moveRight = False
if event.key == K_a:
moveUp = False
moveDown = False
moveLeft = True
moveRight = False
if event.key == K_d:
moveUp = False
moveDown = False
moveLeft = False
moveRight = True
if event.key == K_c:
ghostCurrentDirection = random.choice(ghostPossibleMove)
#Mover jugador
if moveLeft:
player.move_ip(-1 * speed, 0)
if moveRight:
player.move_ip(speed, 0)
if moveUp:
player.move_ip(0, -1 * speed)
if moveDown:
player.move_ip(0, speed)
#Mover al fantasma
# if ghost.x % 24 == 0:
# ghostCurrentDirection = random.choice(ghostPossibleMove)
if ghostCurrentDirection == ghostMoveLeft:
ghost.move_ip(-1 * ghostSpeed, 0)
if ghostCurrentDirection == ghostMoveRight:
ghost.move_ip(ghostSpeed, 0)
if ghostCurrentDirection == ghostMoveUp:
ghost.move_ip(0, -1 * ghostSpeed)
if ghostCurrentDirection == ghostMoveDown:
ghost.move_ip(0, ghostSpeed)
#Portal
if player.left > windowWidth:
player.x = 0 - playerSize
if player.right < 0:
player.x = windowWidth
windowSurface.fill(black)
createMaze()
pygame.draw.rect(windowSurface, yellow, player)
pygame.draw.rect(windowSurface, cyan, ghost)
pygame.display.update()
mainClock.tick(FPS)
Keep track of the direction he was heading. Make the opposite of that direction be the last possible choice. If you want to do a little more work, keep track of each block visited (a simple Boolean map), and when there is a choice to make, then sort the directions of any visited blocks to the end of the choice list.
Related
I'm making a copy of Pac-Man with Python and Pygame, but I'm having a problem when trying to delete the dots a pills, I'm not sure of how to do it I tried to use "del" and didn't work, I also tried adding the dots to a list and then make a for loop that iterates in every dot and remove it if the player collide with one of them, but it makes the game to laggy, how can I remove the pills from the screen?
from pygame.locals import *
pygame.init()
#Variables del juego
windowWidth = 504
windowHeight = 648
windowSurface = pygame.display.set_mode((windowWidth, windowHeight), 0, 32)
mainClock = pygame.time.Clock()
FPS = 30
pygame.display.set_caption('Pac-Man')
#Colores
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
yellow = (255, 255, 0)
cyan = (0, 255, 255)
navyBlue = (0, 0, 53)
pink = (255, 192, 203)
#Tamaño del bloque
blockSize = 24
dotSize = 4
pillSize = 8
#Datos del jugador
playerSize = 24
player = pygame.Rect(240, 480, playerSize, playerSize)
speed = 5
#Variables de movimiento
moveLeft = moveRight = moveDown = moveUp = False
#Laberinto
maze = [
"xxxxxxxxxxxxxxxxxxxxx",
"x.........x.........x",
"x.xxx.xxx.x.xxx.xxx.x",
"x-xxx.xxx.x.xxx.xxx-x",
"x.xxx.xxx.x.xxx.xxx.x",
"x...................x",
"x.xxx.x.xxxxx.x.xxx.x",
"x.xxx.x.xxxxx.x.xxx.x",
"x.....x...x...x.....x",
"xxxxx.xxxoxoxxx.xxxxx",
"oooox.xooooooox.xoooo",
"oooox.xoxxoxxox.xoooo",
"xxxxx.xoxoooxox.xxxxx",
"ooooo.ooxoooxoo.ooooo",
"xxxxx.xoxxxxxox.xxxxx",
"oooox.xooooooox.xoooo",
"oooox.xoxxxxxox.xoooo",
"xxxxx.xoxxxxxox.xxxxx",
"x.........x.........x",
"x.xxx.xxx.x.xxx.xxx.x",
"x-..x.....o.....x..-x",
"xxx.x.x.xxxxx.x.x.xxx",
"xxx.x.x.xxxxx.x.x.xxx",
"x.....x...x...x.....x",
"x.xxxxxxx.x.xxxxxxx.x",
"x...................x",
"xxxxxxxxxxxxxxxxxxxxx"
]
def createMaze():
pointX = 0
pointY = 0
for i in maze:
for j in i:
if j == "x":
block = pygame.Rect(pointX, pointY, blockSize, blockSize)
pygame.draw.rect(windowSurface, navyBlue, block)
if block.colliderect(player):
if player.bottom - block.top < 10:
player.y = block.top - playerSize
if block.bottom - player.top < 10:
player.y = block.bottom
if block.right - player.left < 10:
player.x = block.right
if player.right - block.left < 10:
player.x = block.left - playerSize
if j == ".":
dot = pygame.Rect(pointX + (blockSize / 2) - (dotSize / 2), pointY + (blockSize / 2) - (dotSize / 2), dotSize, dotSize)
pygame.draw.rect(windowSurface, white, dot)
if j == "-":
pygame.draw.circle(windowSurface, white, (pointX + pillSize + (pillSize / 2), pointY + pillSize + (pillSize / 2)), pillSize)
if j == "o":
pass
pointX += blockSize
pointX = 0
pointY += blockSize
#Función para cerrar juego
def close():
pygame.quit()
sys.exit()
#Ciclo principal del juego
while True:
#Buscar evento QUIT
for event in pygame.event.get():
if event.type == QUIT:
close()
if event.type == KEYDOWN:
if event.key == K_w:
moveUp = True
moveDown = False
moveLeft = False
moveRight = False
if event.key == K_s:
moveUp = False
moveDown = True
moveLeft = False
moveRight = False
if event.key == K_a:
moveUp = False
moveDown = False
moveLeft = True
moveRight = False
if event.key == K_d:
moveUp = False
moveDown = False
moveLeft = False
moveRight = True
#Mover jugador
if moveLeft:
player.move_ip(-1 * speed, 0)
if moveRight:
player.move_ip(speed, 0)
if moveUp:
player.move_ip(0, -1 * speed)
if moveDown:
player.move_ip(0, speed)
#Portal
if player.left > windowWidth:
player.x = 0 - playerSize
if player.right < 0:
player.x = windowWidth
windowSurface.fill(black)
createMaze()
pygame.draw.rect(windowSurface, yellow, player)
pygame.display.update()
mainClock.tick(FPS)```
I changed the "." with and "o" (that represents a emty space) by creating a new string
if dot.colliderect(player):
maze[y] = maze[y][:x] + "o" + maze[y][x + 1:]
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.
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.
I am trying to make my game have special abilities for the player, but am having some issues. For some reason user_health_active and user_health_display_active do not update after reaching round 10. I can't figure out why this is and have been attempting to for about two hours. By the seems of it, not only does the surface not update, but the actual background function doesn't either. If anyone can provide me some insight on why this isn't working, please let me know. Here is my code.
"""
Game Developer: Austin H.
Game Owner: Austin H.
Licensed Through: theoiestinapps
Build: 2
Version: 1.0.1
"""
import os
import pygame as pygame
import random
import sys
import time
pygame.init()
left = False
right = False
playerDead = False
devMode = False
game_completed = False
game_level_score = (0)
game_display_score = (0)
enemy_speed = (5)
user_teleport_active = False
user_health_active = False
user_teleport_display_active = ("False")
user_health_display_active = ("False")
display_width = 800
display_height = 600
customBlue = (17, 126, 194)
black = (0, 0, 0)
blue = (0, 0, 255)
green = (0, 255, 0)
red = (255, 0, 0)
white = (255, 255, 255)
gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption("Space Dodge")
clock = pygame.time.Clock()
backgroundMusic = pygame.mixer.music.load('C:/Program Files/Space Dodge/game_background_music.mp3')
enemyImg = pygame.image.load('C:/Program Files/Space Dodge/enemy_image.png')
backgroundImg = pygame.image.load('C:/Program Files/Space Dodge/background_image.png')
rocketImg = pygame.image.load('C:/Program Files/Space Dodge/player_image.png')
injuredSound = pygame.mixer.Sound('C:/Program Files/Space Dodge/player_hurt_sound.wav')
def teleport_powerup(user_teleport_display_active):
font = pygame.font.SysFont(None, 25)
text = font.render("Teleport Powerup: " + str(user_teleport_display_active), True, red)
gameDisplay.blit(text, (display_width - 205, 5))
def ehealth_powerup(user_health_display_active):
font = pygame.font.SysFont(None, 25)
text = font.render("Ehealth Powerup: " + str(user_health_display_active), True, red)
gameDisplay.blit(text, (display_width - 205, 25))
def enemies_dodged(enemy_objects_dodged):
font = pygame.font.SysFont(None, 25)
text = font.render("Dodge Asteroids: " + str(enemy_objects_dodged), True, green)
gameDisplay.blit(text, (5, 5))
def game_level(game_display_score):
font = pygame.font.SysFont(None, 25)
game_display_score = game_level_score + 1
text = font.render("Game Level: " + str(game_display_score), True, green)
gameDisplay.blit(text, (5, 25))
def enemies(enemyx, enemyy, enemyw, enemyh, color):
pygame.draw.rect(gameDisplay, color, [enemyx, enemyy, enemyw, enemyh])
def rocket(x, y):
gameDisplay.blit(rocketImg, (x, y))
def background(cen1, cen2):
gameDisplay.blit(backgroundImg, (cen1, cen2))
def text_objects(text, font):
textSurface = font.render(text, True, blue)
return textSurface, textSurface.get_rect()
def message_display(text):
global game_completed
largeText = pygame.font.Font('freesansbold.ttf', 70)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width / 2), (display_height / 2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
if game_completed == True:
time.sleep(300)
else:
time.sleep(5)
if game_level_score > 0:
pass
else:
pygame.mixer.music.play()
game_loop()
def crash():
injuredSound.play()
message_display("You Died. Game Over!")
def game_loop():
global left
global right
global playerDead
global game_level_score
global enemy_speed
global game_completed
global user_teleport_active
global user_teleport_display_active
global user_health_active
global user_health_display_active
x = (display_width * 0.43)
y = (display_height * 0.74)
cen1 = (0)
cen2 = (0)
x_change = 0
rocket_width = (86)
game_score = (0)
enemy_objects_dodged = (0)
enemy_startx = random.randrange(0, display_width)
enemy_starty = -600
enemy_width = 100
enemy_height = 100
while not playerDead:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.mixer.music.stop()
playerDead = True
if devMode == True:
print(event)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
left = True
if event.key == pygame.K_d:
right = True
if event.key == pygame.K_LEFT:
left = True
if event.key == pygame.K_RIGHT:
right = True
if event.key == pygame.K_KP4:
left = True
if event.key == pygame.K_KP6:
right = True
if event.key == pygame.K_ESCAPE:
playerDead = True
if event.key == pygame.K_SPACE:
game_level_score += 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or pygame.K_d:
left = False
if event.key == pygame.K_d:
right = False
if event.key == pygame.K_LEFT:
left = False
if event.key == pygame.K_RIGHT:
right = False
if event.key == pygame.K_KP4:
left = False
if event.key == pygame.K_KP6:
right = False
if event.key == pygame.K_SPACE:
pass
if left and right:
x_change *= 1
elif left and x > -86:
x_change = -5
elif right and x < (display_width - 89):
x_change = 5
else:
x_change = 0
if game_score == 10:
enemy_speed += 0.5
game_level_score += 1
if game_level_score == 49:
game_completed = True
message_display('Game Complete!')
else:
message_display('Levels Completed: %s' % game_level_score)
if game_level_score > 4:
user_teleport_active = True
user_teleport_display_active = ("True")
elif game_level_score > 9:
user_health_active = True
user_health_display_active = ("True")
if user_teleport_active == True:
if x < -0:
x = 850
if enemy_starty > display_height:
enemy_starty = 0 - enemy_height
enemy_startx = random.randrange(0, display_width)
game_score += 1
enemy_objects_dodged += 1
if y < enemy_starty + enemy_height:
if x > enemy_startx and x < enemy_startx + enemy_width or x + rocket_width > enemy_startx and x + rocket_width < enemy_startx + enemy_width:
pygame.mixer.music.stop()
game_level_score = (0)
user_teleport_active = False
user_teleport_display_active = ("False")
crash()
x += x_change
background(cen1, cen2)
enemies(enemy_startx, enemy_starty, enemy_width, enemy_height, customBlue)
enemy_starty += enemy_speed
rocket(x, y)
enemies_dodged(enemy_objects_dodged)
game_level(game_display_score)
teleport_powerup(user_teleport_display_active)
ehealth_powerup(user_health_display_active)
pygame.display.update()
clock.tick(90)
pygame.mixer.music.set_volume(0.20)
pygame.mixer.music.play(-1)
game_loop()
pygame.quit()
quit()
The code that modifies the variables you mention will never be run. Here's the relevant bit:
if game_level_score > 4:
user_teleport_active = True
user_teleport_display_active = ("True")
elif game_level_score > 9:
user_health_active = True
user_health_display_active = ("True")
Because you're using an if and an elif, the condition for the second block is only ever tested if the first block's condition was false. Since any value greater than 9 is also going to be greater than 4, the second block will never run.
If you want the two conditions to be tested independently, you need to just use plain if statements for both conditions. If you only want one block to run , you either need to extend the first condition to 4 < game_level_score <= 9 or you need to change the order so that the > 9 test comes before the > 4 test.