pygame sprite.spritecollide() doesn't work with moving sprite Group - python

When my player sprite collides with the coin group the coins disappear as wanted, but when it collides with the enemys group nothing happens. The code is the same. I don't know what I did wrong because I did the same thing twice but it only works once. Does it have anything to do with the enemys moving? Here is the the code:
import pygame as pg
import random
a_white = (245, 245, 245)
a_red = (10, 0, 0)
black = (0, 0, 0)
white = (255, 255, 255)
blue_grey = (51, 93, 127)
dark_red = (85, 0, 0)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
yellow = (255, 255, 0)
bg_color = dark_red
width = 600
height = 500
FPS = 60
p_width = 70
p_height = 70
c_width = 35
c_height = 35
score = 0
level = 0
lives = 3
title = 'This Is My Game!'
pg.init()
pg.mixer.init()
clock = pg.time.Clock()
screen = pg.display.set_mode((width, height))
pg.display.set_caption(title)
font_name = pg.font.match_font("arial")
coin_img = pg.image.load('coin3.png').convert()
player_img = pg.image.load('smiley.png').convert_alpha()
gegner_1 = pg.image.load('gegner_black.png').convert_alpha()
coin_snd = pg.mixer.Sound('coin_snd_2.ogg')
def new_coin():
x = random.randrange(c_width, width - c_width)
y = random.randrange(c_height, height - c_height)
coins = Coin(x, y)
all_sprites.add(player, coins)
coin_group.add(coins)
def draw_text(screen, text, t_color, size, t_x, t_y):
font = pg.font.Font(font_name, size)
text_surface = font.render(text, True, t_color)
text_rect = text_surface.get_rect()
text_rect.midtop = (t_x, t_y)
screen.blit(text_surface, text_rect)
def start_screen():
screen.fill(bg_color)
draw_text(screen, 'Welcome... !', white, 75, width / 2, height / 4 - 100)
draw_text(screen, 'ready to play my game*?', white, 24, width - 150, height / 4 - 20)
draw_text(screen, "Press any key to begin", white, 20, width / 2 + 60, height / 4 + 10)
draw_text(screen, "*The name of the game is \'MY GAME\' but that ",
white, 16, width / 2, height - 150)
draw_text(screen, " has nothing to do with the fact, that the game is", white, 16, width / 2, height - 130)
draw_text(screen, " my game. Yes, the game is actually my game, ", white, 16, width / 2, height - 110)
draw_text(screen, " but that\'s not the reason I named it my game. ", white, 16, width / 2, height - 90)
draw_text(screen, "...or is it?", white, 13, width - 28, height - 20)
pg.display.update()
waiting = True
while waiting:
clock.tick(FPS)
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
if event.type == pg.KEYUP:
waiting = False
class Player(pg.sprite.Sprite):
def __init__(self):
super().__init__()
self.image_orig = pg.transform.scale(player_img, (p_width, p_height))
self.image = self.image_orig.copy()
self.rect = self.image.get_rect()
self.rect.center = (width / 2), (height / 2)
self.radius = 35
def update(self):
keys = pg.key.get_pressed()
if keys[pg.K_RIGHT]:
self.rect.x += 5
if keys[pg.K_LEFT]:
self.rect.x -= 5
if keys[pg.K_UP]:
self.rect.y -= 5
if keys[pg.K_DOWN]:
self.rect.y += 5
if self.rect.right > width:
self.rect.right = width
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > height:
self.rect.bottom = height
class Coin(pg.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pg.transform.scale(coin_img, (c_width, c_height))
self.image.set_colorkey(white)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.radius = 18
class Gegner_1(pg.sprite.Sprite):
def __init__(self, x, y, yon):
super().__init__()
self.image_orig = pg.transform.scale(gegner_1, (p_width, p_height))
self.image_orig.set_colorkey(white)
self.image = self.image_orig.copy()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.radius = 35
self.yon = yon
if yon == 'yes':
self.speedx = 5
self.speed = self.speedx
elif yon == 'no':
self.speedy = 5
self.speed = self.speedy
def update(self):
if self.yon == 'yes':
self.rect.x += self.speed
if self.yon == 'no':
self.rect.y += self.speed
if self.rect.right > width:
self.speed = -5
if self.rect.left == 0:
self.speed = 5
if self.rect.bottom > height:
self.speed = -5
if self.rect.top < 0:
self.speed = 5
all_sprites = pg.sprite.Group()
coin_group = pg.sprite.Group()
enemys_group = pg.sprite.Group()
player = Player()
gegner1 = Gegner_1(0, 60, 'yes')
gegner2 = Gegner_1(width, 350, 'yes')
gegner3 = Gegner_1(50, p_height, 'no')
gegner4 = Gegner_1(width - p_width - 20, p_height, 'no')
enemys_group.add(gegner1, gegner2, gegner3, gegner4)
all_sprites.add(player)
for c in range(3):
new_coin()
start_game = True
game_over = False
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
if start_game:
start_screen()
start_game = False
screen.fill(bg_color)
if score >= 5:
all_sprites.add(gegner1)
if score >= 10:
all_sprites.add(gegner2)
if score >= 15:
all_sprites.add(gegner3)
if score >= 20:
all_sprites.add(gegner4)
all_sprites.draw(screen)
all_sprites.update()
draw_text(screen, 'SCORE: ' + str(score), white, 20, 55, 10)
hits = pg.sprite.spritecollide(player, coin_group, True, pg.sprite.collide_circle)
for hit in hits:
score += 1
coin_snd.play()
new_coin()
hits = pg.sprite.spritecollide(player, enemys_group, True, pg.sprite.collide_circle)
for hit in hits:
lives -= 1
pg.display.update()
clock.tick(FPS)
pg.quit()
I also don't get any errors because of this.

The way you add and remove the gegner instances causes this problem. The enemys_group contains the gegners in the beginning and is used for the collision detection. That means you can already collide with them before they are visible (print the groups and hit in the for hit in hits: loop to check this). If you hit an instance, it is removed from the enemys_group correctly.
Then if you reach a score of 5 or higher you keep adding the instances, that are still bound to the gegner1, etc. variables, to the all_sprites group each frame, so the sprites become visible, but if they're not in the enemys_group they can't collide anymore.
You need to restructure the code. I'd leave the enemys_group empty at the beginning and then add the gegner instances in the coin collision loop:
hits = pg.sprite.spritecollide(player, coin_group, True, pg.sprite.collide_circle)
for hit in hits:
score += 1
new_coin()
if score == 5:
gegner = Gegner_1(0, 60, 'yes')
all_sprites.add(gegner)
enemys_group.add(gegner)
elif score == 10:
gegner = Gegner_1(width, 350, 'yes')
all_sprites.add(gegner)
enemys_group.add(gegner)
elif score == 15:
gegner = Gegner_1(50, p_height, 'no')
all_sprites.add(gegner)
enemys_group.add(gegner)
elif score == 20:
gegner = Gegner_1(width - p_width - 20, p_height, 'no')
all_sprites.add(gegner)
enemys_group.add(gegner)

Related

How Can I make the restart function in pygame?

import pygame
from pygame.locals import *
pygame.init()
screen_width = 600
screen_height = 500
fpsClock = pygame.time.Clock()
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Pong')
#define font
font = pygame.font.SysFont('None', 30)
#define game variables
margin = 50
cpu_score = 0
player_score = 0
fps = 90
live_ball = False
winner = 0
speed_increase = 0
#define colours
bg = (12, 0, 91)
white = (241, 185, 0)
ball_color = (168, 43, 17)
bar_color = (10, 106, 86)
def draw_board():
screen.fill(bg)
pygame.draw.line(screen, white, (0, margin), (screen_width, margin), 2)
def draw_text(text, font, text_col, x, y):
img = font.render(text, True, text_col)
screen.blit(img, (x, y))
class paddle():
def __init__(self, x, y):
self.x = x
self.y = y
self.rect = Rect(x, y, 20, 100)
self.speed = 5
self.ai_speed = 5
def move(self):
key = pygame.key.get_pressed()
if key[pygame.K_UP] and self.rect.top > margin:
self.rect.move_ip(0, -1 * self.speed)
if key[pygame.K_DOWN] and self.rect.bottom < screen_height:
self.rect.move_ip(0, self.speed)
def draw(self):
pygame.draw.rect(screen, bar_color, self.rect)
def ai(self):
#ai to move the paddle automatically
#move down
if self.rect.centery < pong.rect.top and self.rect.bottom < screen_height:
self.rect.move_ip(0, self.ai_speed)
#move up
if self.rect.centery > pong.rect.bottom and self.rect.top > margin:
self.rect.move_ip(0, -1 * self.ai_speed)
class ball():
def __init__(self, x, y):
self.reset(x, y)
def move(self):
#check collision with top margin
if self.rect.top < margin:
self.speed_y *= -1
#check collision with bottom of the screen
if self.rect.bottom > screen_height:
self.speed_y *= -1
if self.rect.colliderect(player_paddle) or self.rect.colliderect(cpu_paddle):
self.speed_x *= -1
#check for out of bounds
if self.rect.left < 0:
self.winner = 1
if self.rect.left > screen_width:
self.winner = -1
#update ball position
self.rect.x += self.speed_x
self.rect.y += self.speed_y
return self.winner
def draw(self):
pygame.draw.circle(screen, ball_color, (self.rect.x + self.ball_rad, self.rect.y + self.ball_rad), self.ball_rad)
def reset(self, x, y):
self.x = x
self.y = y
self.ball_rad = 8
self.rect = Rect(x, y, self.ball_rad * 2, self.ball_rad * 2)
self.speed_x = -4
self.speed_y = 4
self.winner = 0# 1 is the player and -1 is the CPU
#create paddles
player_paddle = paddle(screen_width - 40, screen_height // 2)
cpu_paddle = paddle(20, screen_height // 2)
#create pong ball
pong = ball(screen_width - 60, screen_height // 2 + 50)
#create game loop
run = True
while run:
fpsClock.tick(fps)
draw_board()
draw_text('CPU: ' + str(cpu_score), font, white, 20, 15)
draw_text('Sihu: ' + str(player_score), font, white, screen_width - 100, 15)
draw_text('BALL SPEED: ' + str(abs(pong.speed_x)), font, white, screen_width // 2 - 100 , 15)
#draw paddles
player_paddle.draw()
cpu_paddle.draw()
if live_ball == True:
speed_increase += 1
winner = pong.move()
if winner == 0:
#draw ball
pong.draw()
#move paddles
player_paddle.move()
cpu_paddle.ai()
else:
live_ball = False
if winner == 1:
player_score += 1
elif winner == -1:
cpu_score += 1
#print player instructions
if live_ball == False:
if winner == 0:
draw_text('CLICK ANYWHERE TO START', font, white, 160, screen_height // 2 -0)
if winner == 1:
draw_text('YOU SCORED!', font, white, 220, screen_height // 2 -100)
draw_text('CLICK ANYWHERE TO START', font, white, 160, screen_height // 2 -0)
if winner == -1:
draw_text('CPU SCORED!', font, white, 220, screen_height // 2 -100)
draw_text('CLICK ANYWHERE TO START', font, white, 160, screen_height // 2 -0)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN and live_ball == False:
live_ball = True
pong.reset(screen_width - 60, screen_height // 2 + 50)
if speed_increase > 500:
speed_increase = 0
if pong.speed_x < 0:
pong.speed_x -= 1
if pong.speed_x > 0:
pong.speed_x += 1
if pong.speed_y < 0:
pong.speed_y -= 1
if pong.speed_y > 0:
pong.speed_y += 1
pygame.display.update()
pygame.quit()
I get the code on YOUTUBE
and edit the code a little bits
but I did not add the restart code
How can I make the restart function in pygame?
I just want to over the game when player get a 5 score in the game.
and want to make the game restart.
When the game is overed, the player can restart the game with the button.
To restart you will need to reset any variables that change during the game. Write a function that sets all objects and variables to its initial state:
def reset():
global player_paddle, cpu_paddle, pong
global cpu_score, player_score
global live_ball, winner, speed_increase
player_paddle = paddle(screen_width - 40, screen_height // 2)
cpu_paddle = paddle(20, screen_height // 2)
pong = ball(screen_width - 60, screen_height // 2 + 50)
cpu_score = 0
player_score = 0
live_ball = False
winner = 0
speed_increase = 0
Call the function when you want to restart the game.
Have the loop it's own method, call it from a main() run, when the game is over and ends, have main() ask the user if they want to play again, and if so recall the main loop after setting everything as its default
or
Just have the part that asks again clear and reinitialize all variables as there defaults and let the loop if the user wants to play again

highscore in pygame game

I've made a game in pygame and I want to make it possible to have a high score thaat will be displayed at the the top of the show_go_screen. I just need a simple solution - I don't need to write who has the highest score, just the number itself at the top of the show_go_screen. I know there are already questions about this on Stack Overflow but the solutions don't work for me.
code:
# Pygame template
# Attributions
# (Heart) Icons made by Freepik from www.flaticon.com
# (Play)Background vector created by freepik - www.freepik.com
# (GameOver)Background vector created by pikisuperstar - www.freepik.com
# (Backing)Frozen Jam by tgfcoder <https://twitter.com/tgfcoder> licensed under CC-BY-3 <http://creativecommons.org/licenses/by/3.0/>
# (Graphics)Art by Kenney.nl
# Imports
import pygame as pg
import random
from os import path
# images / sound
img_dir = path.join(path.dirname(__file__), 'img')
snd_dir = path.join(path.dirname(__file__), 'snd')
# Constants
WIDTH = 500
HEIGHT = 700
FPS = 60
POWERUP_TIME = 60000
ENCO_TIME = 40000
# Define Colors
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
MAGENTA = (255, 0, 255)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
CYAN = (0, 255, 255)
GREENISH_BLUE = (0, 255, 180)
# Initialize pygame and create window
pg.init()
pg.mixer.init()
screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption("Galaxy Shooters")
clock = pg.time.Clock()
score = 0
# save score
# import shelve
# d = shelve.open('score.txt') # here you will save the score variable
# d['highscore'] = score # thats all, now it is saved on disk.
# d.close()
font_name = pg.font.match_font('arial')
def draw_text(surf, text, size, x, y):
font = pg.font.Font(font_name, size)
text_surface = font.render(text, True, CYAN)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
def spawnmob():
m = Mob()
all_sprites.add(m)
mobs.add(m)
def draw_shield_status_bar(surf, x, y, pct):
if pct < 0:
pct = 0
BAR_LENGTH = 100
BAR_HEIGHT = 10
fill = (pct / 100) * BAR_LENGTH
outline_rect = pg.Rect(x, y, BAR_LENGTH, BAR_HEIGHT)
fill_rect = pg.Rect(x, y, fill, BAR_HEIGHT)
pg.draw.rect(surf, GREENISH_BLUE, fill_rect)
pg.draw.rect(surf, WHITE, outline_rect, 2)
def draw_lives(surf, x, y, lives, img):
for i in range(lives):
img_rect = img.get_rect()
img_rect.x = x + 30 * i
img_rect.y = y
surf.blit(img, img_rect)
class Player(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.transform.scale(player_img, (50, 38))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = 20
# pg.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT - 10
self.speedx = 0
self.shield = 100
self.shoot_delay = 370
self.last_shot = pg.time.get_ticks()
self.lives = 3
self.hidden = False
self.hide_timer = pg.time.get_ticks()
self.power = 1
self.power_time = pg.time.get_ticks()
def update(self):
# Timeout for powerups
if self.power >= 2 and pg.time.get_ticks() - self.hide_timer > POWERUP_TIME:
self.power -= 1
self.power_time = pg.time.get_ticks
# Unhide if necessary
if self.hidden and pg.time.get_ticks() - self.hide_timer > 1000:
self.hidden = False
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT - 10
self.speedx = 0
keystate = pg.key.get_pressed()
if keystate[pg.K_LEFT]:
self.speedx = -5
if keystate[pg.K_RIGHT]:
self.speedx = 5
if keystate[pg.K_SPACE]:
self.shoot()
self.rect.x += self.speedx
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.left < 0:
self.rect.left = 0
def powerup(self):
self.power += 1
self.power_time = pg.time.get_ticks()
def shoot(self):
now = pg.time.get_ticks()
if now - self.last_shot > self.shoot_delay:
self.last_shot = now
if self.power == 1:
laser = Laser(self.rect.centerx, self.rect.top)
all_sprites.add(laser)
lasers.add(laser)
random.choice(shoot_sounds).play()
if self.power >= 2:
laser1 = Laser(self.rect.left, self.rect.centery)
laser2 = Laser(self.rect.right, self.rect.centery)
all_sprites.add(laser1)
all_sprites.add(laser2)
lasers.add(laser1)
lasers.add(laser2)
random.choice(shoot_sounds).play()
def hide(self):
self.hidden = True
self.hide_timer = pg.time.get_ticks()
self.rect.center = (WIDTH / 2, HEIGHT + 200)
class Mob(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image_orig = random.choice(meteor_images)
self.image_orig.set_colorkey(BLACK)
self.image = self.image_orig.copy()
self.rect = self.image.get_rect()
self.radius = int(self.rect.width * .85 / 2)
# pg.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-150, -40)
self.speedy = random.randrange(1, 8)
self.speedx = random.randrange(-3, 3)
self.rot = 0
self.rot_speed = random.randrange(-8, 8)
self.last_update = pg.time.get_ticks()
def rotate(self):
now = pg.time.get_ticks()
if now - self.last_update > 50:
self.last_update = now
self.rot = (self.rot + self.rot_speed) % 360
new_image = pg.transform.rotate(self.image_orig, self.rot)
old_center = self.rect.center
self.image = new_image
self.rect = self.image.get_rect()
self.rect.center = old_center
def update(self):
self.rotate()
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.right < -25 or self.rect.left > WIDTH + 20:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
class Laser(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = laser_img
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedy = -10
def update(self):
self.rect.y += self.speedy
# Kill it if moves off the top of the screen
if self.rect.bottom < 0:
self.kill()
class Explosion(pg.sprite.Sprite):
def __init__(self, center, size):
pg.sprite.Sprite.__init__(self)
self.size = size
self.image = explosion_anim[self.size][0]
self.rect = self.image.get_rect()
self.rect.center = center
self.frame = 0
self.last_update = pg.time.get_ticks()
self.frame_rate = 75
def update(self):
now = pg.time.get_ticks()
if now - self.last_update > self.frame_rate:
self.last_update = now
self.frame += 1
if self.frame == len(explosion_anim[self.size]):
self.kill()
else:
center = self.rect.center
self.image = explosion_anim[self.size][self.frame]
self.rect = self.image.get_rect()
self.rect.center = center
class Pow(pg.sprite.Sprite):
def __init__(self, center):
pg.sprite.Sprite.__init__(self)
self.type = random.choice(['shield', 'laser', 'star'])
self.image = powerup_images[self.type]
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.center = center
self.speedy = 4
def update(self):
self.rect.y += self.speedy
# Kill it if moves off the bottom of the screen
if self.rect.top > HEIGHT:
self.kill()
class Enco(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = draw_text(screen, (random.choice(encos), 37, WIDTH / 2, HEIGHT/ 4))
self.rect = self.image.get_rect()
self.hidden = True
self.hide_timer = pg.time.get_ticks()
def hide(self):
self.rect.y = HEIGHT - 40
self.rect.x = WIDTH / 2
def show_go_screen():
screen.blit(background2, background_rect2)
draw_text(screen, str(score), 25, WIDTH / 2, 10)
draw_text(screen, " Guardians of the Galaxy ", 37, WIDTH / 2, HEIGHT / 4)
draw_text(screen, "Arrow Keys move, Spacebar to shoot", 29, WIDTH / 2, HEIGHT / 2)
draw_text(screen, "Press any key to BEGIN", 22, WIDTH / 2, HEIGHT * 3/ 4)
pg.display.flip()
print(d)
waiting = True
while waiting:
clock.tick(FPS)
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
if event.type == pg.KEYUP:
waiting = False
# Load all game graphics
background = pg.image.load(path.join(img_dir, "2397814.jpg")).convert()
background_rect = background.get_rect()
background2 = pg.image.load(path.join(img_dir, "2474216.jpg")).convert()
background_rect2 = background2.get_rect()
pg.transform.scale(background, (500, 700))
player_img = pg.image.load(path.join(img_dir, "playerShip3_blue.png")).convert()
heart_img = pg.image.load(path.join(img_dir, "heart.png")).convert()
mini_heart_img = pg.transform.scale(heart_img, (23, 23))
mini_heart_img.set_colorkey(BLACK)
laser_img = pg.image.load(path.join(img_dir, "laserBlue01.png")).convert()
meteor_images = []
meteor_list = ['meteorBrown_big1.png', 'meteorBrown_big2.png', 'meteorBrown_big3.png',
'meteorBrown_med1.png','meteorBrown_small1.png','meteorBrown_small2.png',
'meteorBrown_tiny2.png',]
for img in meteor_list:
meteor_images.append(pg.image.load(path.join(img_dir, img)).convert())
explosion_anim = {}
explosion_anim['lg'] = []
explosion_anim['sm'] = []
explosion_anim['player'] = []
for i in range(9):
filename = 'regularExplosion0{}.png'.format(i)
img = pg.image.load(path.join(img_dir, filename)).convert()
img.set_colorkey(BLACK)
img_lg = pg.transform.scale(img, (75, 75))
explosion_anim['lg'].append(img_lg)
img_sm = pg.transform.scale(img, (32, 32))
explosion_anim['sm'].append(img_sm)
filename = 'sonicExplosion0{}.png'.format(i)
img = pg.image.load(path.join(img_dir, filename)).convert()
img.set_colorkey(BLACK)
explosion_anim['player'].append(img)
powerup_images = {}
powerup_images['shield'] = pg.image.load(path.join(img_dir, 'shield_silver.png')).convert()
powerup_images['laser'] = pg.image.load(path.join(img_dir, 'bolt_gold.png')).convert()
powerup_images['star'] = pg.image.load(path.join(img_dir, 'star_silver.png')).convert()
encos = ("Nice Job!", "You're rocking it man!", " Great!", "What a blast!", "Good one!", "Those asteroids stand no chance against you!"
"You're the master!")
# Load all game sounds
laser_powerup = pg.mixer.Sound(path.join(snd_dir, 'Laser_Powerup.wav'))
shield_powerup = pg.mixer.Sound(path.join(snd_dir, 'Shield_Powerup.wav'))
shoot_sounds = []
for snd in ['Laser_Shoot.wav', 'Laser_Shoot2.wav']:
shoot_sounds.append(pg.mixer.Sound(path.join(snd_dir, snd)))
expl_sounds = []
for snd in ['Expl.wav', 'Expl2.wav']:
expl_sounds.append(pg.mixer.Sound(path.join(snd_dir, snd)))
player_die_sound = pg.mixer.Sound(path.join(snd_dir, 'rumble1.ogg'))
pg.mixer.music.load(path.join(snd_dir, 'tgfcoder-FrozenJam-SeamlessLoop.ogg'))
pg.mixer.music.set_volume(0.7)
pg.mixer.music.play(loops = -1)
# Game loop
game_over = True
running = True
while running:
if game_over:
show_go_screen()
game_over = False
# Sprite groups
all_sprites = pg.sprite.Group()
mobs = pg.sprite.Group()
lasers = pg.sprite.Group()
powerups = pg.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(8):
spawnmob()
score = 0
# Keep loop running at the right speed
clock.tick(FPS)
# Events
for event in pg.event.get():
# Check for closing window
if event.type == pg.QUIT:
running = False
# Update
all_sprites.update()
# Check to see if a laser hit a mob
hits = pg.sprite.groupcollide(mobs, lasers, True, True)
for hit in hits:
score += 50 - hit.radius
random.choice(expl_sounds).play()
expl = Explosion(hit.rect.center, 'lg')
all_sprites.add(expl)
if random.random() > 0.93:
pow = Pow(hit.rect.center)
all_sprites.add(pow)
powerups.add(pow)
spawnmob()
# Check to see if a mob hit the player
hits = pg.sprite.spritecollide(player, mobs, True, pg.sprite.collide_circle)
for hit in hits:
player.shield -= hit.radius * 2
expl = Explosion(hit.rect.center, 'sm')
all_sprites.add(expl)
spawnmob()
if player.shield <= 0:
player_die_sound.play()
death_expl = Explosion(player.rect.center, 'player')
all_sprites.add(death_expl)
player.hide()
player.lives -= 1
player.shield = 100
# Check to see if player hit a powerup
hits = pg.sprite.spritecollide(player, powerups, True)
for hit in hits:
if hit.type == 'shield':
pow.kill()
player.shield += random.randrange(10, 30)
shield_powerup.play()
if player.shield >= 100:
player.shield = 100
if hit.type == 'laser':
player.powerup()
laser_powerup.play()
if hit.type == 'star':
player.lives += 1
if player.lives >= 3:
player.lives = 3
# If the player died and the explosion finished playing
if player.lives == 0 and not death_expl.alive():
game_over = True
# Render
screen.fill(BLACK)
screen.blit(background, background_rect)
all_sprites.draw(screen)
draw_text(screen, str(score), 25, WIDTH / 2, 10)
draw_shield_status_bar(screen, 5, 5, player.shield)
draw_lives(screen, WIDTH - 100, 5, player.lives, mini_heart_img)
if score == 500:
draw_text(screen, "Nice Job!", 37, WIDTH / 2, HEIGHT / 2)
now = pg.time.get_ticks()
last.enco = pg.time.get_ticks()
if now - last.enco == ENCO_TIME:
hide_enco
# *After* drawing everything, flip the display
pg.display.flip()
pg.quit()
thanks!
Create a variable called highscore then then when the player looses, check if the current score is higher than highscore and if it is, then assign the score to highscore. Then you can just easily add a label with the highscore variable as a text
score = 0
highscore = 0
# save score
# import shelve
# d = shelve.open('score.txt') # here you will save the score variable
# d['highscore'] = score # thats all, now it is saved on disk.
# d.close()
# A lot of your code
def show_go_screen():
screen.blit(background2, background_rect2)
draw_text(screen, str(highscore), 50, WIDTH / 2, 10) #change the x value accordingly
# more of your code
while running:
if game_over:
show_go_screen()
game_over = False
# Sprite groups
all_sprites = pg.sprite.Group()
mobs = pg.sprite.Group()
lasers = pg.sprite.Group()
powerups = pg.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(8):
spawnmob()
if score > highscore:
highscore = score
score = 0
# the rest of your code

Black window pygame

I am writing a snake game with pygame but I am just prompted with a black window without any error.
I checked similar problems and they incorrectly used the screen object. However this does not seem to be the case here, since it is only created once?
Any idea what I am doing wrong? Since I am not given any error message I can't figure out why I am only shown a black screen. The key input events work just fine.
import pygame
import random
import sys
# Define colors
GRAY = (240, 240, 245)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (50, 50, 50)
# Field size
width = 400
height = 400
# Calculate the distance between two points
def calculate_distance(x1, x2, y1, y2):
return (x2 - x1)**2 + (y1 - y2)**2 ** 1/2
# Draws a label showing the current score in the top mid of the window
def draw_score_text(surface, text, font_size, x, y):
font_name = pygame.font.match_font('arial')
font = pygame.font.Font(font_name, font_size)
text_surface = pygame.font.render(text, True, WHITE)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
class Snake(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((12,12))
self.image.fill(WHITE)
self.rect=self.image.get_rect()
self.rect.center = (100,100)
self.speedx=0
self.speedy=0
self.score=0
self.tail=[]
def update(self):
if self.score == len(self.tail):
self.tail.append((self.rect.x, self.rect.y))
else:
self.tail.append((self.rect.x, self.rect.y))
self.tail.pop(0)
self.rect.x += self.speedx
self.rect.y += self.speedy
keys = pygame.key.get_pressed()
if(keys[pygame.K_RIGHT] and self.speedx >=0):
self.speedx = 10
self.speedy = 0
if(keys[pygame.K_LEFT] and self.speedx <=0):
self.speedx = -10
self.speedy = 0
if(keys[pygame.K_UP] and self.speedy <=0):
self.speedx = 0
self.speedy = -10
if(keys[pygame.K_DOWN] and self.speedy >=0):
self.speedx = 0
self.speedy = 10
if self.rect.left >= width:
self.rect.left = 1
if self.rect.top >= height:
self.rect.top = 0
if self.rect.bottom <= 0:
self.rect.bottom = height
if self.rect.left <= 0:
self.rect.left = width
def exit(self):
for i in range(1, len(self.tail)):
if dist(self.rect.x, self.rect.y, self.tail[i][0], self.tail[i][1]) < 1:
sys.exit()
class Food(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((12,12))
self.image.fill(RED)
self.rect=self.image.get_rect()
self.rect.center = (x, y)
# Start dah game
pygame.init()
screen = pygame.display.set_mode([width,height])
clock = pygame.time.Clock()
running = True
print("ok?")
all_sprites = pygame.sprite.Group()
player = Snake()
food = Food(random.randrange(20, width - 20), random.randrange(20, height - 20))
all_sprites.add(player)
all_sprites.add(food)
while running:
clock.tick(3)
#pygame.display.update()
keys_pressed = pygame.event.get()
print(keys_pressed)
for i in keys_pressed:
if i.type == pygame.QUIT:
print("quit")
running = False
if pygame.sprite.collide_rect(player, food):
food.kill()
player.score += 1
food = Food(random.randrange(20, width - 20), random.randrange(20, height - 20))
all_sprites.add(food)
all_sprites.update()
screen.fill(BLACK)
player.exit()
for i in range(1, len(player.tail)):
pygame.draw.rect(screen, WHITE, (player.tail[i][0], player.tail[i][2], 12, 12))
#draw_score_text(screen, str(player.score), 18, width/2, 10)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
The update of the display and the drawing of the sprites has to be done in the main loop rather than in the inner for loop:
while running:
# [...]
for i in range(1, len(player.tail)):
pygame.draw.rect(screen, WHITE, (player.tail[i][0], player.tail[i][2], 12, 12))
# <--
all_sprites.draw(screen)
pygame.display.flip()
Note, if the snake consists of a head only, then the inner loop is not executed. If the length of the tail would be > 1, then the display would be updated multiple times per frame, which is not what you want.
I am getting an out of range exception
Traceback (most recent call last): File "snake.py", line 132, in <module> >
pygame.draw.rect(screen, WHITE, (player.tail[i][0], player.tail[i][2], 12, 12))
IndexError: tuple index out of range `
The index of the 2nd (y) coordinate is 1 rather than 2. Ist has to be player.tail[i][1]:
for i in range(1, len(player.tail)):
pygame.draw.rect(screen, WHITE, (player.tail[i][0], player.tail[i][1], 12, 12))

Pygame Game results in Segmentation Fault(pygame parachute)

If you play the game and win, clicking on the screen will cause the game to play again. On the second play, the game segmentation faults after a second or two.
This code is for an intro to coding class and many others have coded this game successfully. I don't understand what is the problem here.
Help!
import sys
import os
import pygame
import random
import math
#Force static position of screen
os.environ ['SDL_VIDEO_CENTERED'] = '1'
#constants
BLACK = (0,0,0)
WHITE = (255, 255, 255)
SHIP_WIDTH = 13
SHIP_HEIGHT = 13
SIZE = WIDTH, HEIGHT = 920, 570
TOP_BUFFER = 50
PILL_HEIGHT = 30
PILL_WIDTH = 10
YELLOW = (157, 185, 45)
RED = (185, 45, 45)
BLUE = (45, 115, 185)
GREEN = (5, 94, 16)
#Runs imported module
pygame.init()
class Text:
def __init__(self, size, text, color, xpos, ypos):
self.font = pygame.font.SysFont("Britannic Bold", size)
self.image = self.font.render(text, 1, color)
self.rect = self.image.get_rect()
self.rect = self.rect.move(xpos, ypos)
class Ship(pygame.sprite.Sprite):
def __init__ (self, x, y, side):
pygame.sprite.Sprite.__init__(self)
self.density = SHIP_HEIGHT * SHIP_WIDTH
self.speed = 10
self.image = pygame.Surface((math.sqrt(self.density), math.sqrt(self.density))).convert()
self.rect = self.image.get_rect()
self.rect = self.rect.move(x, y)
self.type = side
self.score = Text(30, str(self.density - 169), BLACK, WIDTH / 4 , HEIGHT/ 17)
self.score_2 = Text(30, str(self.density - 169), BLACK, WIDTH * .75, HEIGHT / 17)
def update(self, pill_group):
key = pygame.key.get_pressed()
if self.type == "left":
if key[pygame.K_w]:
self.rect.y -= self.speed
if key[pygame.K_s]:
self.rect.y += self.speed
if key[pygame.K_a]:
self.rect.x -= self.speed
if key[pygame.K_d]:
self.rect.x += self.speed
if self.type == "left":
#Boundary Conditions
if self.rect.right > WIDTH/2:
self.rect.right = WIDTH/2
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 50:
self.rect.top = 50
if self.rect.bottom > 570:
self.rect.bottom = 570
elif self.type == "right":
if key[pygame.K_UP]:
self.rect.y -= self.speed
if key[pygame.K_DOWN]:
self.rect.y += self.speed
if key[pygame.K_LEFT]:
self.rect.x -= self.speed
if key[pygame.K_RIGHT]:
self.rect.x += self.speed
# Ship 2 boundary conditions
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.top < TOP_BUFFER:
self.rect.top = TOP_BUFFER
if self.rect.left < WIDTH/2:
self.rect.left = WIDTH/2
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
collisions = pygame.sprite.spritecollide(self, pill_group, True)
for p in collisions:
self.density += p.density * 50
print(self.density)
self.score.image = self.score.font.render(str(self.density - 169), 1, BLACK)
self.score_2.image = self.score.font.render(str(self.density), 1, BLACK)
##if self.density > 500:
##self.play == False
self.rect.width = self.rect.height = math.sqrt(self.density)
self.image = pygame.transform.scale(self.image, (self.rect.width, self.rect.height))
class Pill(pygame.sprite.Sprite):
def __init__(self, xpos, density):
pygame.sprite.Sprite.__init__(self)
self.density = density
self.speed = 3
self.image = pygame.Surface((PILL_WIDTH, PILL_HEIGHT)).convert()
self.image.fill(self.set_color())
self.rect = pygame.Rect(xpos, -PILL_HEIGHT, 10, 30)
self.rect = self.image.get_rect()
self.rect = self.rect.move(xpos, HEIGHT/15)
def set_color(self):
if self.density == 1:
return YELLOW
elif self.density == 2:
return RED
elif self.density == 3:
return BLUE
elif self.density == 4:
return GREEN
def update(self):
self.rect.y += self.speed
if self.rect.y > HEIGHT:
self.kill()
def main():
#Initialize Local Vars
size = width, height = 920, 570
fps = 30
LeftWins = Text(30, "Left Ship Wins!", BLACK, WIDTH / 2.5, HEIGHT / 2)
RightWins = Text(30, "Right Ship Wins!", BLACK, WIDTH / 2.5, HEIGHT / 2)
Winner = Text (30, "Click here to play again", BLACK, WIDTH / 2.6, HEIGHT * .75)
pygame.display.set_caption('Density')
screen = pygame.display.set_mode(SIZE, pygame.SRCALPHA)
clock = pygame.time.Clock()
play = True
loop_counter = 0
vertical = pygame.Surface((1, HEIGHT - TOP_BUFFER)).convert()
horizontal = pygame.Surface((WIDTH, 1)).convert()
#Create Game Objects
ship_left = Ship(WIDTH/4 - SHIP_WIDTH/2, HEIGHT - (4 * SHIP_HEIGHT), "left")
ship_right = Ship((WIDTH * 3) / 4 - SHIP_WIDTH / 2, HEIGHT - (4 * SHIP_HEIGHT), "right")
#Create Groups
ship_group = pygame.sprite.Group()
ship_group.add(ship_left, ship_right)
pill_group = pygame.sprite.Group()
#play = True
outro = True
while True:
#Gameplay
while play:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
if loop_counter % 10 == 0:
pill = Pill(random.randrange(0, (WIDTH/2) - PILL_WIDTH), int(random.choice('1111111111111111111122222334')))
pill2 = Pill(random.randrange((WIDTH/2) + PILL_WIDTH, WIDTH - PILL_WIDTH), int(random.choice('1111111111111111111122222334')))
pill_group.add(pill)
pill_group.add(pill2)
#Update Groups
ship_group.update(pill_group)
pill_group.update()
#Draw/Blit Groups
screen.fill(WHITE)
screen.blit(ship_left.score.image, ship_left.score.rect)
screen.blit(ship_right.score_2.image, ship_right.score_2.rect)
ship_group.draw(screen)
pill_group.draw(screen)
screen.blit(vertical, (WIDTH/2, TOP_BUFFER))
screen.blit(horizontal, (0, TOP_BUFFER))
#60 / second one pill / 10 iterations
loop_counter += 1
#Limits frames per iteration of while loop
clock.tick(60)
# Writes to main surface
pygame.display.flip()
if (ship_left.density >= 500 or ship_right.density >= 500):
play = False
while outro:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN or pygame.key.get_pressed()[pygame.K_RETURN != 0]:
outro = False
play = True
ship_left.density = 0
ship_right.density = 0
for p in pill_group:
p.kill()
ship_left = Ship(WIDTH / 4 - SHIP_WIDTH / 2, HEIGHT - (4 * SHIP_HEIGHT), "left")
ship_right = Ship((WIDTH * 3) / 4 - SHIP_WIDTH / 2, HEIGHT - (4 * SHIP_HEIGHT), "right")
screen.blit(ship_left.image, ship_left.rect)
screen.blit(ship_right.image, ship_right.rect)
#Draw/Blit Groups
screen.fill(WHITE)
if (ship_left.density >= 500):
screen.blit(LeftWins.image, LeftWins.rect)
screen.blit(Winner.image, Winner.rect)
if (ship_right.density >= 500):
screen.blit(RightWins.image, RightWins.rect)
screen.blit(Winner.image, Winner.rect)
#Limits frames per iteration of while loop
clock.tick(60)
# Writes to main surface
pygame.display.flip()
if __name__ == "__main__":
main()
One way to solve this (but arguably not the best one) is to move the setup code inside the while True loop and ditch the reset code in while outro:
def main():
# The setup code from here ...
while True:
# Goes here
#Gameplay
while play:
# The Gameplay code
while outro:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN or pygame.key.get_pressed()[pygame.K_RETURN != 0]:
outro = False
#Draw/Blit Groups
screen.fill(WHITE)
# The reset of outro

Text not bliting to the screen on my pygame script with python

I wanted to add a sorta ammo clip thing in my shooter game, its very simple all I do is blit I * the ammount of ammo, but I wanted there to be three lines to show the clip like so:
IIIIIIIIIIIIIIIIIIIIII
IIIIIIIIIIIIIIIIIIIIII
IIIIIIIIIIIIIIIIIIIIII
Each line has 35 ammo symbols but if the player has more than 95 ammo I wanted it to blit that anount as a number next to the ammo clip, but no matter how much ammo I have it never blits the number and no matter how much ammo I have at the start it never blits more than this at the start until I collect a ammo box:
IIIIIIIIII
I really cant find out why it is doing this, I've tryed changing the amount it blits and many other things but nothing seems to work, so hear is my code:
#wave font
font = pygame.font.SysFont("", 34)
self.text_pause = font.render("WAVE " + str(self.wave) * self.blitwave, -1, RED)
self.text_pause_rect = self.text_pause.get_rect(center=self.screen.get_rect().center) # center text
texthealth = int(self.health / 10)
#health font
self.text_health = font.render("o" * texthealth, -1, RED)
#score font
self.text_score = font.render("SCORE " + str(self.score), -1, BLACK)
#cash font
self.text_cash = font.render(str(self.cash), -1, GREEN)
#ammo font
self.text_ammoS = font.render("I" * 35, -1, RED)
self.text_ammo = font.render("I" * self.ammo_amount, -1, RED)
self.text_ammoW = font.render("I" * (self.ammo_amount - 35), -1, RED)
self.text_ammoE = font.render("I" * (self.ammo_amount - 70), -1, RED)
self.text_ammoN = font.render(str(self.ammo_amount), -1, RED)
# send event to player
self.player.event_handler(event)
if not PAUSED:
self.all_sprites_list.update()
self.bullets_update()
player_rect = pygame.Rect(self.player.rect.x, self.player.rect.y, 20, 20)
block_rect = pygame.Rect(block.rect.x, block.rect.y, 20, 20)
I thought i could make a rect that follows the blocks and if that rect collides witht he player they die, pretty much using the same system as the ammo, coz that works instantly
if pygame.sprite.collide_rect(self.player, block):
self.player.health =- 00.0000000003
print('hit')
if self.ammo and player_rect.colliderect(self.ammo.rect):
self.ammo_amount += 70
self.all_sprites_list.remove(self.ammo)
self.ammo = None
#if self.Bomb and player_rect.colliderect(self.ammo.rect):
#print('nuke')
#self.all_sprites_list.remove(self.ammo)
#self.Bomb = None
self.crosshair.update()
# --- draws ---
self.background.draw(self.screen)
self.all_sprites_list.draw(self.screen)
#must be last
self.screen.blit(self.text_pause, (10, 610))
self.screen.blit(self.text_score, (700, 10))
self.screen.blit(self.text_cash, (740, 500))
#self.screen.blit(self.text_ammo, (450, 610))
if self.ammo_amount > 0 and self.ammo_amount < 36:
self.screen.blit(self.text_ammo, (600, 540))
if self.ammo_amount > 35 and self.ammo_amount < 71:
self.screen.blit(self.text_ammoS, (600, 540))
self.screen.blit(self.text_ammoW, (600, 560))
if self.ammo_amount > 70 and self.ammo_amount < 96:
self.screen.blit(self.text_ammoS, (600, 540))
self.screen.blit(self.text_ammoS, (600, 560))
self.screen.blit(self.text_ammoE, (600, 580))
if self.ammo_amount > 95:
self.screen.blit(self.text_ammoS, (600, 540))
self.screen.blit(self.text_ammoS, (600, 560))
self.screen.blit(self.text_ammoS, (600, 580))
self.screen.blit(self.text_ammoN, (550, 580))
self.screen.blit(self.text_health, (5, 5))
self.crosshair.draw(self.screen)
pygame.display.update() # use flip() OR update()
# --- FPS ---
clock.tick(70)
# --- quit ---
pygame.quit()
#----------------------------------------------------------------------
Game().run()
That is the important part but if you would like to see the whole code here it is:
import pygame
from pygame import *
import sys
import math
import random
import cmath
#----------------------------------------------------------------------
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
GREEN = (154 ,205, 50)
#images
IMAGE_GRASS = "grass_shit.png"
IMAGE_PLAYER = "shithead.png"
IMAGE_ALI = "shit_head2.png"
IMAGE_DEAD_SCREEN = "dead_shit.png"
IMAGE_CROSSHAIR = "crosshair.png"
IMAGE_PLAYBUTTON = "playbutton.png"
IMAGE_AMMO = "ammoshit.png"
#----------------------------------------------------------------------
class Block(pygame.sprite.Sprite):
def __init__(self, color, x, y, player = None):
pygame.sprite.Sprite.__init__(self)
self.player = player
self.image = pygame.Surface([20, 20])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.move_x = self.move_y = 0
def update(self):
if self.player:
player_x, player_y = self.player.rect.center
if self.rect.x < player_x:
self.rect.x += 1
elif self.rect.x > player_x:
self.rect.x -= 1
if self.rect.y < player_y:
self.rect.y += 1
elif self.rect.y > player_y:
self.rect.y -= 1
#----------------------------------------------------------------------
class Player(pygame.sprite.Sprite):
def __init__(self, screen_rect, x=0, y=0):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20,20])
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.min_x = screen_rect.left
self.min_y = screen_rect.top
self.max_x = screen_rect.right
self.max_y = screen_rect.bottom
self.move_x = self.move_y = 0
self.health = 138
def update(self):
pos = pygame.mouse.get_pos()
self.rect.x += self.move_x
self.rect.y += self.move_y
if self.rect.top < self.min_x:
self.rect.top = self.min_x
elif self.rect.bottom > self.max_y:
self.rect.bottom = self.max_y
if self.rect.left < self.min_x:
self.rect.left = self.min_x
elif self.rect.right > self.max_x:
self.rect.right = self.max_x
def event_handler(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
self.move_x = -8
elif event.key == pygame.K_d:
self.move_x = +8
elif event.key == pygame.K_w:
self.move_y = -8
elif event.key == pygame.K_s:
self.move_y = +8
if event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
self.move_x = 0
elif event.key in (pygame.K_w, pygame.K_s):
self.move_y = 0
#----------------------------------------------------------------------
class Bullet(pygame.sprite.Sprite):
def __init__(self, start_pos, mouse_pos):
pygame.sprite.Sprite.__init__(self)
self.start_rect = start_pos.rect.copy()
self.mouse_x, self.mouse_y = mouse_pos # mouse[0], mouse[1]
self.image = pygame.Surface([5, 5])
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.centerx = self.start_rect.centerx
self.rect.centery = self.start_rect.centery
self.speed = 20
self.max_range = 100
self.current_range = 0
distance_x = self.mouse_x - self.start_rect.centerx
distance_y = self.mouse_y - self.start_rect.centery
norm = math.sqrt(distance_x ** 2 + distance_y ** 2)
direction_x = distance_x / norm
direction_y = distance_y / norm
self.bullet_vector_x = direction_x * self.speed
self.bullet_vector_y = direction_y * self.speed
def update(self):
self.current_range += 1
if self.current_range < self.max_range:
#print self.start_rect.centerx + (self.bullet_vector_x*self.current_range),
#print self.rect.centerx + self.bullet_vector_x,
#self.rect.centerx += self.bullet_vector_x
self.rect.centerx = self.start_rect.centerx + (self.bullet_vector_x*self.current_range)
#print self.rect.centerx
#self.rect.centery += self.bullet_vector_y
self.rect.centery = self.start_rect.centery + (self.bullet_vector_y*self.current_range)
else:
self.kill()
#----------------------------------------------------------------------
class Crosshair(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(IMAGE_CROSSHAIR).convert_alpha()
self.rect = self.image.get_rect()
def update(self):
mouse_x, mouse_y = pygame.mouse.get_pos()
self.rect.centerx = mouse_x
self.rect.centery = mouse_y
def draw(self, screen):
screen.blit(self.image,self.rect.topleft)
#----------------------------------------------------------------------
class Background(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(IMAGE_GRASS).convert_alpha()
self.rect = self.image.get_rect()
def draw(self, screen):
screen.fill((128,128,128))
screen.blit(self.image,(0,0))
#----------------------------------------------------------------------
class Ammo(pygame.sprite.Sprite):
def __init__(self, color, x, y, player = None):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 20])
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
pass
class Bomb(pygame.sprite.Sprite):
def __init__(self, color, x, y, player = None):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 20])
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
pass
class Game():
def __init__(self):
pygame.init()
screen_width = 850
screen_height = 640
place_ammo = False
self.screen = pygame.display.set_mode( (screen_width,screen_height) )
pygame.mouse.set_visible(False)
#-----
self.all_sprites_list = pygame.sprite.Group()
self.block_list = pygame.sprite.Group()
self.bullet_list = pygame.sprite.Group()
self.blitwave = 1
# --- create sprites ---
self.background = Background()
self.player = Player(self.screen.get_rect(), 0, 370)
self.all_sprites_list.add(self.player)
self.ammo = Ammo(self.screen.get_rect(),random.randrange(10, 750),random.randint(10,600 - 10))
self.all_sprites_list.add(self.ammo)
self.ammo_amount = 100
self.on_screen = 1
self.score = 0
self.crosshair = Crosshair()
def bullet_create(self, start_pos, mouse_pos):
bullet = Bullet(start_pos, mouse_pos)
self.all_sprites_list.add(bullet)
self.bullet_list.add(bullet)
def bullets_update(self):
for bullet in self.bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, self.block_list, True)
screen_width = 850
screen_height = 640
for block in block_hit_list:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
self.score += 1
self.on_screen -= 1
self.ammo_chance = self.ammo_amount * 5
if self.ammo_chance > 0:
self.drop = random.randint(1, self.ammo_chance)
print(self.drop)
if self.drop > 0 and self.drop < 2:
print('ammo drop')
self.ammo = Ammo(self.screen.get_rect(),random.randrange(10,screen_width),random.randint(10,screen_height - 10))
self.all_sprites_list.add(self.ammo)
if bullet.rect.y < -10:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
# -------- Main Program Loop -----------
def run(self):
screen_width = 850
screen_height = 640
#wave
self.wave = 1
self.wave_no = 2
self.wave_running = True
block = Block(BLUE, random.randrange(100, screen_width), random.randrange(10, screen_height-10), self.player)
self.block_list.add(block)
self.all_sprites_list.add(block)
clock = pygame.time.Clock()
self.cash = 1
self.health = 100
self.ammo_amount = 10
RUNNING = True
PAUSED = False
while RUNNING:
# --- events ---
if self.player.health <= 0:
RUNNING = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = PAUSED
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
PAUSED = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
PAUSED = not PAUSED
elif event.type == pygame.MOUSEBUTTONDOWN and self.ammo_amount > 0:
self.bullet_create(self.player, event.pos)
self.ammo_amount -= 1
self.cash = self.score * 5
if self.on_screen == 0:
for i in range(self.wave_no):
block = Block(BLUE, random.randrange(100, screen_width), random.randrange(10, screen_height-10), self.player)
self.block_list.add(block)
self.all_sprites_list.add(block)
self.on_screen += 1
self.wave_div = int(self.wave_no / 2)
self.wave_no += self.wave_div
self.wave += 1
#wave font
font = pygame.font.SysFont("", 34)
self.text_pause = font.render("WAVE " + str(self.wave) * self.blitwave, -1, RED)
self.text_pause_rect = self.text_pause.get_rect(center=self.screen.get_rect().center) # center text
texthealth = int(self.health / 10)
#health font
self.text_health = font.render("o" * texthealth, -1, RED)
#score font
self.text_score = font.render("SCORE " + str(self.score), -1, BLACK)
#cash font
self.text_cash = font.render(str(self.cash), -1, GREEN)
#ammo font
self.text_ammoS = font.render("I" * 35, -1, RED)
self.text_ammo = font.render("I" * self.ammo_amount, -1, RED)
self.text_ammoW = font.render("I" * (self.ammo_amount - 35), -1, RED)
self.text_ammoE = font.render("I" * (self.ammo_amount - 70), -1, RED)
self.text_ammoN = font.render(str(self.ammo_amount), -1, RED)
# send event to player
self.player.event_handler(event)
if not PAUSED:
self.all_sprites_list.update()
self.bullets_update()
player_rect = pygame.Rect(self.player.rect.x, self.player.rect.y, 20, 20)
block_rect = pygame.Rect(block.rect.x, block.rect.y, 20, 20)
#I thought i could make a rect that follows the blocks and if that rect collides witht he player they die, pretty much using the same system as the ammo, coz that works instantly
if pygame.sprite.collide_rect(self.player, block):
self.player.health =- 00.0000000003
print('hit')
if self.ammo and player_rect.colliderect(self.ammo.rect):
self.ammo_amount += 70
self.all_sprites_list.remove(self.ammo)
self.ammo = None
#if self.Bomb and player_rect.colliderect(self.ammo.rect):
#print('nuke')
#self.all_sprites_list.remove(self.ammo)
#self.Bomb = None
self.crosshair.update()
# --- draws ---
self.background.draw(self.screen)
self.all_sprites_list.draw(self.screen)
#must be last
self.screen.blit(self.text_pause, (10, 610))
self.screen.blit(self.text_score, (700, 10))
self.screen.blit(self.text_cash, (740, 500))
#self.screen.blit(self.text_ammo, (450, 610))
if self.ammo_amount > 0 and self.ammo_amount < 36:
self.screen.blit(self.text_ammo, (600, 540))
if self.ammo_amount > 35 and self.ammo_amount < 71:
self.screen.blit(self.text_ammoS, (600, 540))
self.screen.blit(self.text_ammoW, (600, 560))
if self.ammo_amount > 70 and self.ammo_amount < 96:
self.screen.blit(self.text_ammoS, (600, 540))
self.screen.blit(self.text_ammoS, (600, 560))
self.screen.blit(self.text_ammoE, (600, 580))
if self.ammo_amount > 95:
self.screen.blit(self.text_ammoS, (600, 540))
self.screen.blit(self.text_ammoS, (600, 560))
self.screen.blit(self.text_ammoS, (600, 580))
self.screen.blit(self.text_ammoN, (550, 580))
self.screen.blit(self.text_health, (5, 5))
self.crosshair.draw(self.screen)
pygame.display.update() # use flip() OR update()
# --- FPS ---
clock.tick(70)
# --- quit ---
pygame.quit()
#----------------------------------------------------------------------
Game().run()
Thank you so much for your time and help.
You don't blit ammo number - see # in line:
#self.screen.blit(self.text_ammo, (450, 610))
And it has to be text_ammoN not text_ammo
By the way:
You have to much code in main loop - put some code in functions like update_wave_text() , update_ammo_text(), etc. , blit_wave_text(), blit_ammo_tex(), etc.
Use self.: in __init__ set
self.screen_width = 850
self.screen_height = 640
and than use self.screen_width, self.screen_height and you will not have to repeat
screen_width = 850
screen_height = 640

Categories