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
Related
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
This question already has answers here:
Could not open resource file, pygame error: "FileNotFoundError: No such file or directory."
(1 answer)
Is there any other way to load a resource like an image, sound, or font into Pygame? [closed]
(1 answer)
Closed 2 years ago.
I'm making a game and I tried to add some images instead of surfaces but I don't really know how it works I was wondering if some could explain to how its work cause I'm getting pygame.error: Unsupported image format and I don't know what that means or what I've done wrong.
Below is an image of the code in question as well as my directory files (on the left)
also im using a program called Pycharm idk if that might affect at all or not
# import images for sprites
img_dir = path.join(path.dirname(__file__), 'Img')
# load images
player_img = py.image.load(path.join(img_dir, "Playerimg.png")).convert()
class Player(py.sprite.Sprite):
def __init__(self):
py.sprite.Sprite.__init__(self)
self.image = player_img
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT / 2
self.Yspeed = 0
self.rotatableimage = self.image
The rest of the code is below if you need it also I know it might be hard to troubleshoot image-based stuff soo here the code but without the images (two parts btw)
import random
import math
import pygame as py
from PlayerSprite import *
WIDTH = 800
HEIGHT = 600
FPS = 60
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
# initialize pygame and create window
py.init()
py.mixer.init()
screen = py.display.set_mode((WIDTH, HEIGHT))
py.display.set_caption("Dimensional Drifter")
clock = py.time.Clock()
all_sprites = py.sprite.Group()
NPCs = py.sprite.Group()
bullets = py.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(14):
n = NPC(player)
all_sprites.add(n)
NPCs.add(n)
# Game loop
running = True
while running:
# keep loop running at the right speed
clock.tick(FPS)
for event in py.event.get():
# check for closing window
if event.type == py.QUIT:
running = False
elif event.type == py.MOUSEBUTTONDOWN:
if event.button == 1:
New_bullet = player.Shoot()
all_sprites.add(New_bullet)
bullets.add(New_bullet)
# Update
all_sprites.update()
# # check if there a collision between the bullet and NPC
hits = py.sprite.groupcollide(NPCs, bullets, True, True)
# check if there a collision between the player and NPC
hits = py.sprite.spritecollide(player, NPCs, True)
if hits:
running = False
# updates the position of of mouse and rotates it towards the mouse position
mouse_x, mouse_y = py.mouse.get_pos()
player.rotate(mouse_x, mouse_y)
# render
screen.fill(BLACK)
all_sprites.draw(screen)
# flip the display
py.display.flip()
py.quit()
import pygame as py
import math
import random
WIDTH = 800
HEIGHT = 600
FPS = 60
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
class Player(py.sprite.Sprite):
def __init__(self):
py.sprite.Sprite.__init__(self)
self.image = py.Surface((40, 40), py.SRCALPHA)
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT / 2
self.Yspeed = 0
self.rotatableimage = self.image
def update(self):
self.Xspeed = 0
self.Yspeed = 0
# line below allow for key press to equate to move of sprite
keypreesed = py.key.get_pressed()
if keypreesed[py.K_a]:
self.Xspeed = - 11
if keypreesed[py.K_d]:
self.Xspeed = 11
if keypreesed[py.K_w]:
self.Yspeed = - 11
if keypreesed[py.K_s]:
self.Yspeed = 11
self.rect.x += self.Xspeed
self.rect.y += self.Yspeed
# line below allow the sprite to wrap around the screen
if self.rect.left > WIDTH:
self.rect.right = 0
if self.rect.right < 0:
self.rect.left = WIDTH
if self.rect.top > HEIGHT:
self.rect.top = 0
if self.rect.bottom < 0:
self.rect.bottom = HEIGHT
def rotate(self, mouse_x, mouse_y):
rel_x = mouse_x - self.rect.x
rel_y = mouse_y - self.rect.y
angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
self.image = py.transform.rotate(self.rotatableimage, int(angle))
self.rect = self.image.get_rect(center=(self.rect.centerx, self.rect.centery))
return
def Shoot(self):
pos = self.rect.centerx, self.rect.centery
mpos = py.mouse.get_pos()
direction = py.math.Vector2(mpos[0] - pos[0], mpos[1] - pos[1])
direction.scale_to_length(10)
return Bullet(pos[0], pos[1], round(direction[0]), round(direction[1]))
class NPC(py.sprite.Sprite):
def __init__(self, player):
py.sprite.Sprite.__init__(self)
self.player = player
self.image = py.Surface((30, 30)).convert_alpha()
self.image.fill(RED)
self.originalimage = self.image
self.rect = self.image.get_rect()
self.spawn()
# allows of spawning from all four side of the screen and set the x, y speed and spawn position
def spawn(self):
self.direction = random.randrange(4)
if self.direction == 0:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.Xspeed = random.randrange(-2, 2)
self.Yspeed = random.randrange(4, 8)
elif self.direction == 1:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(HEIGHT, HEIGHT + 60)
self.Xspeed = random.randrange(-2, 2)
self.Yspeed = -random.randrange(4, 8)
elif self.direction == 2:
self.rect.x = random.randrange(-100, -40)
self.rect.y = random.randrange(HEIGHT - self.rect.height)
self.Xspeed = random.randrange(4, 8)
self.Yspeed = random.randrange(-2, 2)
elif self.direction == 3:
self.rect.x = random.randrange(WIDTH, WIDTH + 60)
self.rect.y = random.randrange(HEIGHT - self.rect.height)
self.Xspeed = -random.randrange(4, 8)
self.Yspeed = random.randrange(-2, 2)
def update(self):
self.rect.x += self.Xspeed
self.rect.y += self.Yspeed
# makes it so that NPC point to wards the player as it passes from side to side
dir_x, dir_y = self.player.rect.x - self.rect.x, self.player.rect.y - self.rect.y
self.rot = (180 / math.pi) * math.atan2(-dir_x, -dir_y)
self.image = py.transform.rotate(self.originalimage, self.rot)
# Respawns the NPC when they hit an side
if self.direction == 0:
if self.rect.top > HEIGHT + 10:
self.spawn()
elif self.direction == 1:
if self.rect.bottom < -10:
self.spawn()
elif self.direction == 2:
if self.rect.left > WIDTH + 10:
self.spawn()
elif self.direction == 3:
if self.rect.right < -10:
self.spawn()
class Bullet(py.sprite.Sprite):
def __init__(self, x, y, Xspeed, Yspeed):
py.sprite.Sprite.__init__(self)
self.image = py.Surface((5, 5))
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.Xspeed = Xspeed
self.Yspeed = Yspeed
def update(self):
self.rect.x += self.Xspeed
self.rect.y += self.Yspeed
# kill if moved of screen
if self.rect.bottom > HEIGHT or self.rect.top < 0:
self.kill()
if self.rect.right > WIDTH or self.rect.left < 0:
self.kill()
it might be hard to help me on this one so because of images and what not but if could just explain it to me then i could implement on my own that could work too :)
edit 3:
Edit 2:
Edit: image of error
I'm trying to make my tanks shoot, and I did all the code I think I should have done but I don't know why the tanks aren't shooting anything.
import pygame, assetloader
from pygame.locals import *
import random, time, math
import pygame
GRAD = math.pi/180
blue = (0, 0, 255)
wallRects = []
bullets = []
maze = [[] for i in range(25)]
assetloader.set_asset_path("assets/")
I defined the Bullet Class here:
def calculate_dir_with_angle(angle):
direction = [0, 0]
if (angle > 0 and angle < 180) or (angle > -360 and angle < -180):
direction[0] = -1
elif (angle > -180 and angle < 0) or (angle > 180 and angle < 360):
direction[0] = 1
elif (angle > -90 and angle < 90) or (angle > 270 and anlge < 360):
direction[1] = -1
elif (angle > 90 and angle < 270) or (angle > -270 and angle < -90):
direction[1] = 1
return direction
class Bullet:
def __init__(self, pos, r, angle):
self.x = pos[0]
self.y = pos[1]
self.r = r
self.counter = 50
direction = calculate_dir_with_angle(angle)
self.vel = [direction[0] * 2, direction[1] * 2]
def draw(self, screen):
self.x = int(self.x)
self.y = int(self.y)
pygame.draw.circle(screen, (25, 25, 25), (self.x, self.y), (self.r))
def move(self):
self.x += self.vel[0]
self.y += self.vel[1]
self.rect = pygame.Rect(self.x-self.r, self.y - self.r, 2 * self.r, 2 * self.r)
for wr in wallRects:
if self.rect.centery >= wr.top and self.rect.centery <= wr.bottom:
if self.rect.left <= wr.right and self.rect.left > wr.left:
self.vel[0] = -self.vel[0]
self.x = wr.right + self.r + 1
self.rect.x = wr.right + 1
elif self.rect.right >= wr.left and self.rect.right < wr.right:
self.vel[0] = -self.vel[0]
self.x = wr.left + self.r - 1
self.rect.x = wr.left - 2 * self.r - 1
if self.rect.centerx >= wr.left and self.rect.centerx <= wr.right:
if self.rect.top <= wr.bottom and self.rect.top > wr.top:
self.vel[1] = -self.vel[1]
self.y = wr.bottom + self.r + 1
self.rect.y = wr.bottom + 1
elif self.rect.bottom >= wr.top and self.rect.bottom < wr.bottom:
self.vel[1] = -self.vel[1]
self.y = wr.top - self.r - 1
self.rect.y = wr.top - 2 * self.r - 1
if self.counter > 0:
self.counter -= 1
def generateRandomPosition():
row = random.randint(1, 23)
col = random.randint(1, 23)
while maze[row][col-1] != 0 or maze[row][col] != 0 or maze[row][col+1] != 0:
row = random.randint(1, 23)
col = random.randint(1, 23)
return row, col
Player 1:
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, pos):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = assetloader.load_image("Tank.png", -1)
self.rect.x = x
self.rect.y = y
self.rect.clamp_ip(screen.get_rect())
self.rows = pos[0]
self.cols = pos[1]
self.x = self.cols * gsize
self.y = self.rows * gsize
self.orig_image, self.orig_rect = assetloader.load_image("Tank.png", -1)
self.orig_rect.x = self.x
self.orig_rect.y = self.y
self.orig_gun_pos = self.orig_rect.midtop
self.ammo = 5
def checkCollisions(self):
for b in bullets:
if b.counter <= 0:
if b.rect.colliderect(self.orig_rect):
self.dead = True
def calculate_gun_pos(self):
self.orig_gun_pos = self.orig_rect.midtop
new_y = self.orig_gun_pos[1] - self.orig_rect.centery
new_x = self.orig_gun_pos[0] - self.orig_rect.centerx
rads = self.dir * GRAD
gun_x = (new_y * math.sin(rads)) + (new_x * math.cos(rads)) + (self.orig_rect.centerx)
gun_y = (new_y * math.cos(rads)) - (new_x * math.sin(rads)) + (self.orig_rect.centery)
self.gun_pos = (gun_x, gun_y)
def shoot(self):
if self.ammo > 0:
self.calculate_gun_pos()
b = Bullet(self.gun_pos, 3, self.dir)
bullets.append(b)
self.ammo -= 1
def draw(self, screen):
image = pygame.transform.rotate(self.image, self.dir)
screen.blit(image, self.rect)
def update(self):
oldCenter = self.rect.center
self.rect = self.image.get_rect()
self.rect.center = oldCenter
screen_rect = screen.get_rect()
keys = pygame.key.get_pressed()
if keys[K_m]:
p.shoot()
if not screen_rect.contains(self.rect):
self.rect.clamp_ip(screen_rect)
Calling the functions:
size = width, height = 500, 400
gsize = 25
start_x, start_y = 0, 0
bgColor = 255, 255, 255
pygame.init()
screen = pygame.display.set_mode(size)#, pygame.FULLSCREEN)
pygame.display.set_caption("Sample Sprite")
clock = pygame.time.Clock()
p = Player(width/2, height/4, (3,4))
coll_font = pygame.font.Font(None, 30)
going = True
while going:
clock.tick(60)
for event in pygame.event.get():
if event.type == QUIT:
going = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
going = False
elif event.type == KEYDOWN:
if event.key == K_m:
p.shoot()
for b in bullets:
b.move()
p.update()
screen.fill(bgColor)
p.draw(screen)
pygame.display.flip()
pygame.quit()
How would I call the bullet to actually appear and fire because I have the Bullet class which gets called within the Player class in def shoot(self) so does anyone have an idea why the bullets aren't appearing?
I usually add bullets in this way: I pass the group that contains all sprites and the bullet group to the player instance and add new bullets to these group in the player's handle_event method.
import pygame as pg
from pygame.math import Vector2
pg.init()
screen = pg.display.set_mode((640, 480))
screen_rect = screen.get_rect()
FONT = pg.font.Font(None, 24)
BG_COLOR = pg.Color('gray12')
BULLET_IMAGE = pg.Surface((20, 11), pg.SRCALPHA)
pg.draw.polygon(
BULLET_IMAGE, pg.Color('aquamarine1'), [(0, 0), (20, 5), (0, 11)])
PLAYER_IMAGE = pg.Surface((50, 30), pg.SRCALPHA)
pg.draw.polygon(
PLAYER_IMAGE, pg.Color('dodgerblue1'), [(0, 0), (50, 15), (0, 30)])
class Player(pg.sprite.Sprite):
def __init__(self, pos, all_sprites, bullet_group):
super().__init__()
self.image = PLAYER_IMAGE
self.orig_image = self.image # Needed to preserve image quality.
self.rect = self.image.get_rect(center=(pos))
self.pos = Vector2(pos)
self.vel = Vector2(1, 0)
self.angle = 0
self.angle_speed = 0
self.all_sprites = all_sprites
self.bullet_group = bullet_group
def handle_event(self, event):
if event.type == pg.MOUSEBUTTONDOWN:
# Left button fires a bullet from cannon center with
# current angle. Add the bullet to the bullet_group.
if event.button == 1:
bullet = Bullet(self.pos, self.angle)
self.bullet_group.add(bullet)
self.all_sprites.add(bullet)
elif event.type == pg.KEYDOWN:
# Rotate self by setting the .angle_speed.
if event.key in (pg.K_a, pg.K_LEFT):
self.angle_speed = -3
elif event.key in (pg.K_d, pg.K_RIGHT):
self.angle_speed = 3
elif event.type == pg.KEYUP:
if event.key in (pg.K_a, pg.K_LEFT):
self.angle_speed = 0
elif event.key in (pg.K_d, pg.K_RIGHT):
self.angle_speed = 0
def update(self):
self.pos += self.vel
self.rect.center = self.pos
if self.angle_speed != 0:
self.rotate()
def rotate(self):
# Update the angle and the velocity vector.
self.angle += self.angle_speed
self.vel.rotate_ip(self.angle_speed)
# Rotate the image and get a new rect with the previous center.
self.image = pg.transform.rotozoom(self.orig_image, -self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)
class Bullet(pg.sprite.Sprite):
def __init__(self, pos, angle):
super().__init__()
self.image = pg.transform.rotate(BULLET_IMAGE, -angle)
self.rect = self.image.get_rect(center=pos)
# To apply an offset (40 pixels) to the start position,
# create another vector and rotate it as well.
offset = Vector2(40, 0).rotate(angle)
# Add the offset vector to the position vector (the center).
self.pos = Vector2(pos) + offset
# Rotate the start velocity vector (9, 0) by the angle.
self.vel = Vector2(9, 0).rotate(angle)
def update(self):
# Add the velocity to the pos to move the sprite.
self.pos += self.vel
self.rect.center = self.pos # Update the rect as well.
# Remove bullets outside of the screen area.
if not screen_rect.contains(self.rect):
self.kill()
def main():
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
# Bullets will be added to this group.
bullet_group = pg.sprite.Group()
# Pass the bullet group to the player.
player = Player((300, 200), all_sprites, bullet_group)
all_sprites.add(player)
playing = True
while playing:
for event in pg.event.get():
if event.type == pg.QUIT:
playing = False
# Pass events to the player instance.
player.handle_event(event)
all_sprites.update()
screen.fill(BG_COLOR)
all_sprites.draw(screen)
pg.display.update()
clock.tick(30)
if __name__ == '__main__':
main()
pg.quit()
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)
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