So here's my code, I am trying to understand how I can be able to display the surfaces I created onto the main screen which is SCREEN. I drew the maze onto another surface and then I blitted that surface onto the main screen. Then I blitted the PacMan surface onto the main screen, I am also trying to blit the background image onto the screen as well. My question is how do I blit them properly, like for example do I blit the maze first then the PacMan then the background, or what would be the correct order to blit them?
As for the PacManBite function, I am updating the PacManStartSurface to give it the effect that it is biting the dots, but then I also am updating the entire screen, is there a way to properly use the pygame.update() function because I think that's why the screen tends to flicker?
I also wanted to use SCREEN.fill(BLACK) so that it can get rid of any trails the PacMan leaves but for some reason I don't know where to place it in my main loop. Any help would be appreciated.
import pygame
pygame.init()
pygame.display.set_caption("Pac-Man")
# Sets the size of the screen via (WIDTH, HEIGHT)
SCREEN_WIDTH = 475
SCREEN_HEIGHT = 608
# Speed of Characters
SPEED = 1
# Frames per second, how fast the game runs
FPS = 50
# Colors (RED,GREEN,BLUE)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
HIGH_SCORE = 0
# Sets the WIDTH and HEIGHT of the window
WINDOW = (SCREEN_WIDTH, SCREEN_HEIGHT)
# Displays the screen
SCREEN = pygame.display.set_mode(WINDOW)
CLOCK = pygame.time.Clock()
PacManStartSurface = pygame.transform.scale(pygame.image.load
("PacManStart.png").convert(),
(25, 25))
PacManStartRect = PacManStartSurface.get_rect(topleft =
(((SCREEN_WIDTH - 22) // 2),
(SCREEN_HEIGHT + 225) // 2))
PacManSurface = pygame.transform.scale(pygame.image.load
("PacManRight.png").convert(), (25, 25))
PacManRect = PacManStartSurface.get_rect(topleft =
(((SCREEN_WIDTH - 22) // 2),
(SCREEN_HEIGHT + 225) // 2))
CurrentSurface = PacManStartSurface
CurrentRect = PacManStartRect
BackgroundSurface = pygame.image.load("Background.png").convert()
class PacMan():
def __init__(self):
self.LIVES = 3
class PowerUp(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("PowerUp.png")
.convert(), (23, 23))
self.mask = pygame.mask.from_surface(self.image)
class YellowGhost(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("YellowGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class RedGhost(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("RedGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class BlueGhost(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("BlueGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class PinkGhost(pygame.sprite.Sprite):
def __init__(self):
self.image = pygame.transform.scale(pygame.image.load("PinkGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class Maze():
def __init__(self):
self.DOTS = []
self.WALLS = []
self.BLOCK_WIDTH = 22
self.BLOCK_HEIGHT = 22
self.MARGIN = 3
# 0 - Dots
# 1 - Walls
# 2 - Power Up
# 3 - Empty Space
# 4 - Ghosts
self.MATRIX = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], \
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1], \
[1,2,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,2,1], \
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], \
[1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1], \
[1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1], \
[1,1,1,1,0,1,1,1,3,1,3,1,1,1,0,1,1,1,1], \
[3,3,3,1,0,1,3,3,3,3,3,3,3,1,0,1,3,3,3], \
[1,1,1,1,0,1,3,1,1,1,1,1,3,1,0,1,1,1,1], \
[0,0,0,0,0,3,3,1,4,4,4,1,3,3,0,0,0,0,0], \
[1,1,1,1,0,1,3,1,1,1,1,1,3,1,0,1,1,1,1], \
[3,3,3,1,0,1,3,3,3,3,3,3,3,1,0,1,3,3,3], \
[1,1,1,1,0,1,3,1,1,1,1,1,3,1,0,1,1,1,1], \
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1], \
[1,2,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,2,1], \
[1,0,0,1,0,0,0,0,0,3,0,0,0,0,0,1,0,0,1], \
[1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1], \
[1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1], \
[1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1], \
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], \
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
self.MAZE_HEIGHT = (self.MARGIN + self.BLOCK_HEIGHT) \
* len(self.MATRIX)
self.MAZE_WIDTH = (self.MARGIN + self.BLOCK_WIDTH) \
* len(self.MATRIX[0])
def DrawGrid(self, MazeSurface):
for ROW in range(len(self.MATRIX)):
for COLUMN in range(len(self.MATRIX[0])):
if self.MATRIX[ROW][COLUMN] == 0:
self.DOTS.append(pygame.draw.circle(MazeSurface, YELLOW,
[((self.MARGIN + self.BLOCK_WIDTH)
* COLUMN + self.MARGIN) + 9,
((self.MARGIN + self.BLOCK_HEIGHT)
* ROW + self.MARGIN) + 50], 2))
if self.MATRIX[ROW][COLUMN] == 1:
self.WALLS.append(pygame.draw.rect(MazeSurface, WHITE,
[((self.MARGIN + self.BLOCK_WIDTH)
* COLUMN + self.MARGIN) - 2,
((self.MARGIN + self.BLOCK_HEIGHT)
* ROW + self.MARGIN) + 41,
self.BLOCK_WIDTH, self.BLOCK_HEIGHT]))
class Main(Maze):
def __init__(self):
# Inherits Maze class
Maze.__init__(self)
self.DIRECTION = ""
self.SCORE = 0
def Movement(self):
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] and not key[pygame.K_UP] \
and not key[pygame.K_DOWN]:
self.DIRECTION = "LEFT"
elif key[pygame.K_RIGHT] and not key[pygame.K_UP] \
and not key[pygame.K_DOWN]:
self.DIRECTION = "RIGHT"
elif key[pygame.K_UP] and not key[pygame.K_LEFT] \
and not key[pygame.K_RIGHT]:
self.DIRECTION = "UP"
elif key[pygame.K_DOWN] and not key[pygame.K_LEFT] \
and not key[pygame.K_RIGHT]:
self.DIRECTION = "DOWN"
def ContinueMovement(self):
if self.DIRECTION == "LEFT":
CurrentRect.x -= SPEED
self.WallDetection(-1, 0, CurrentRect)
if self.DIRECTION == "RIGHT":
CurrentRect.x += SPEED
self.WallDetection(1, 0, CurrentRect)
if self.DIRECTION == "UP":
CurrentRect.y -= SPEED
self.WallDetection(0, -1, CurrentRect)
if self.DIRECTION == "DOWN":
CurrentRect.y += SPEED
self.WallDetection(0, 1, CurrentRect)
def ChangeImage(self):
global CurrentSurface
if self.DIRECTION == "LEFT":
CurrentSurface = pygame.transform.rotate(PacManSurface, 180)
if self.DIRECTION == "RIGHT":
CurrentSurface = PacManSurface
if self.DIRECTION == "UP":
CurrentSurface = pygame.transform.rotate(PacManSurface, 90)
if self.DIRECTION == "DOWN":
CurrentSurface = pygame.transform.rotate(PacManSurface, 270)
def Teleport(self):
if CurrentRect.right < 0:
CurrentRect.right = SCREEN_WIDTH + 20
if CurrentRect.left > SCREEN_WIDTH:
CurrentRect.right = 0
def WallDetection(self, x, y, CurrentRect):
CurrentRect.right += x
for wall in self.WALLS:
collide = CurrentRect.colliderect(wall)
if collide:
if x < 0:
CurrentRect.left = wall.right
elif x > 0:
CurrentRect.right = wall.left
break
CurrentRect.top += y
for wall in self.WALLS:
collide = CurrentRect.colliderect(wall)
if collide:
if y < 0:
CurrentRect.top = wall.bottom
if y > 0:
CurrentRect.bottom = wall.top
break
def EatDots(self):
for ROW in range(len(self.MATRIX)):
for COLUMN in range(len(self.MATRIX[0])):
for DOT in self.DOTS:
chomp = CurrentRect.colliderect(DOT)
if chomp:
self.DOTS.remove(DOT)
self.MATRIX[ROW][COLUMN] = 3
self.SCORE += 10
return str(self.SCORE)
def EatGhosts(self):
pass
def EatPowerUp(self):
pass
def ShowText(self):
Font = pygame.font.Font("emulogic.ttf", 15)
OneUpText = Font.render("1UP", True, WHITE)
OneUpTextRect = OneUpText.get_rect(center = (70, 10))
OneUpScoreText = Font.render("00", True, WHITE)
UpdateScore = Main.EatDots(self)
if int(self.SCORE) > 0:
OneUpScoreText = Font.render(UpdateScore, True, WHITE)
OneUpScoreRect = OneUpScoreText.get_rect(center =
((SCREEN_WIDTH - 290)
// 2, 26))
HighScoreText = Font.render("High Score", True, WHITE)
HighScoreTextRect = HighScoreText.get_rect(center =
(SCREEN_WIDTH // 2, 10))
HighScoreNumber = Font.render("00", True, WHITE)
HighScoreNumberRect = HighScoreNumber.get_rect(center =
((SCREEN_WIDTH + 90)
// 2, 26))
SCREEN.blit(OneUpText, OneUpTextRect)
SCREEN.blit(OneUpScoreText, OneUpScoreRect)
SCREEN.blit(HighScoreText, HighScoreTextRect)
SCREEN.blit(HighScoreNumber, HighScoreNumberRect)
def PacManBite(self):
SCREEN.blit(PacManStartSurface, PacManStartRect)
pygame.display.update()
Player = Main()
BackgroundImage = pygame.transform.scale(BackgroundSurface,
(Player.MAZE_WIDTH,
Player.MAZE_HEIGHT))
BackgroundRect = BackgroundImage.get_rect(topleft = (0, 41))
MazeSurface = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT - 10))
MazeRect = MazeSurface.get_rect(topleft = ((SCREEN_WIDTH - 475,
SCREEN_HEIGHT - 608)))
Player.DrawGrid(MazeSurface)
'''
pregame = True
while pregame:
if key button pressed:
pregame = False
run = True
'''
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
Player.Movement()
Player.ChangeImage()
Player.Teleport()
Player.ContinueMovement()
Player.PacManBite()
SCREEN.blit(MazeSurface, MazeRect)
MazeSurface.blit(CurrentSurface, CurrentRect)
#SCREEN.blit(BackgroundImage, BackgroundRect)
Player.ShowText()
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
You have to blit the CurrentSurface on the MazeSurface, before you blit the MazeSurface on the SCREEN:
MazeSurface.blit(CurrentSurface, CurrentRect)
SCREEN.blit(MazeSurface, MazeRect)
Related
I am trying to create a simple bullet function in which am shooting bullets vertically. No bullets seem to be drawing in the program Help would be much appreciated.
class Bullet(pg.sprite.Sprite):
def __init__(self):
super().__init__()
pygame.sprite.Sprite.__init__(self)
self.image = pg.image.load(os.path.join(path, 'img', 'bullet.png'))
self.image = pygame.Surface([4, 10])
self.image.fill(RED)
self.rect = self.image.get_rect()
def update(self):
self.rect.y -= 5 enter code here
elif e.type == pg.KEYDOWN and e.key == pg.K_SPACE:
# Fire a bullet if the user clicks the space button
bullet = Bullet()
# Set the bullet so it is where the player is
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
# Add the bullet to the lists
cars_group.add(bullet)
bullet_list.add(bullet)
# Calculate mechanics for each bullet
for bullet in bullet_list:
# See if it hit a block
block_hit_list = pygame.sprite.spritecollide(bullet, cars_group, True)
# For each block hit, remove the bullet and add to the score
for block in block_hit_list:
bullet_list.remove(bullet)
cars_group.remove(bullet)
disclosure this isnt fully my code
Full code here:
import pygame as pg
import pygame.freetype
import random
import os
import math
os.environ['SDL_VIDEO_CENTERED'] = '1'
path = os.path.dirname(os.path.abspath(__file__))
record_file = os.path.join(path, 'Record', 'record.txt')
try:
with open(record_file, 'x') as f:
f.write(str(0))
except (BaseException, OSError):
pass
SIZE = WIDTH, HEIGHT = 800, 600
GREY = (128, 128, 128)
GREEN = (0, 128, 0)
WHITE = (200, 200, 200)
RED = (230, 0, 0)
rgb = [0, 250, 0]
block = False
pause = [False, True]
count = [0]
car_accident = 0
level = 40
start = 255
blink = 0
hit_old = None
play, out = None, None
def icon():
size, text = 32, '\u0056\u004F'
sur = pg.Surface((size, size), pg.SRCALPHA)
pg.draw.circle(
sur, '#44475a59', (size // 2, size // 2), size // 2)
font_text = pg.freetype.SysFont('Arial', 16, True)
rect = font_text.get_rect(text)
x, y = (size - rect.width) // 2, (size - rect.height) // 2
font_text.render_to(sur, (x, y), text, fgcolor='#ff0000')
pg.display.set_icon(sur)
pg.init()
icon()
pg.display.set_caption('Rally')
screen = pg.display.set_mode(SIZE)
FPS = 120
clock = pg.time.Clock()
font = pygame.freetype.Font(os.path.join(path, 'font', 'seguisym.ttf'), 30)
cars = [pg.image.load(os.path.join(path, 'img', 'car1.png')),
pg.image.load(os.path.join(path, 'img', 'car2.png')),
pg.image.load(os.path.join(path, 'img', 'car3.png'))]
alarm = [pg.image.load(os.path.join(path, 'alarm', '1.png')),
pg.image.load(os.path.join(path, 'alarm', '2.png'))]
sound_car_accident = pg.mixer.Sound(os.path.join(path, 'sound', 'udar.wav'))
sound_canister = pg.mixer.Sound(os.path.join(path, 'sound', 'canister.wav'))
sound_accident = pg.mixer.Sound(os.path.join(path, 'sound', 'accident.wav'))
button_start = pg.image.load(os.path.join(path, 'img', 'btn_play.png'))
button_start_rect = button_start.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100))
button_stop = pg.image.load(os.path.join(path, 'img', 'btn_exit.png'))
button_stop_rect = button_stop.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100))
fuel_image = pg.image.load(os.path.join(path, 'img', 'fuel.png'))
canister_image = pg.image.load(os.path.join(path, 'img', 'canister.png'))
water_image = pg.image.load(os.path.join(path, 'img', 'water.png'))
bullet_image = pg.image.load(os.path.join(path, 'img', 'bullet.png'))
u1_event = pg.USEREVENT + 1
pg.time.set_timer(u1_event, random.randrange(6000, 26001, 4000))
u2_event = pg.USEREVENT + 2
pg.time.set_timer(u2_event, random.randrange(13000, 28001, 5000))
class Player(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.image.load(os.path.join(path, 'img', 'car4.png'))
self.orig_image = self.image
self.angle = 0
self.speed = 2
self.acceleration = 0.02
self.rect = self.image.get_rect(center=(WIDTH - 20, HEIGHT - 70))
self.position = pg.math.Vector2()
self.velocity = pg.math.Vector2()
self.vx = 0 # velocity.x for speedometer
def update(self):
self.image = pg.transform.rotate(self.orig_image, self.angle)
self.position += self.velocity
self.rect = self.image.get_rect(center=self.position)
keys = pg.key.get_pressed()
if keys[pg.K_RIGHT]:
self.velocity.x = self.speed
self.angle -= 1
self.vx -= self.acceleration
if self.angle < -25:
self.angle = -25
elif keys[pg.K_LEFT]:
self.velocity.x = -self.speed
self.angle += 1
self.vx -= self.acceleration
if self.angle > 25:
self.angle = 25
else:
self.vx += self.acceleration if self.vx < 0 else 0
self.velocity.x = 0
if self.angle < 0:
self.angle += 1
elif self.angle > 0:
self.angle -= 1
if keys[pg.K_UP]:
self.velocity.y -= self.acceleration
if self.velocity.y < -self.speed:
self.velocity.y = -self.speed
elif keys[pg.K_DOWN]:
self.velocity.y += self.acceleration
if self.velocity.y > self.speed:
self.velocity.y = self.speed
else:
if self.velocity.y < 0:
self.velocity.y += self.acceleration
if self.velocity.y > 0:
self.velocity.y = 0
elif self.velocity.y > 0:
self.velocity.y -= self.acceleration
if self.velocity.y < 0:
self.velocity.y = 0
def for_speedometer(self):
if self.vx <= -0.4:
self.vx = -0.4 # left-right speedometer max
if self.velocity.y < self.vx or self.velocity.y > 0:
self.vx = self.velocity.y
if self.vx >= 1.04:
self.vx = 1.04 # speedometer min for speed=2
return self.vx
class Alarm(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.images = alarm
self.index = 0
self.range = len(self.images)
self.image = self.images[self.index]
self.rect = self.image.get_rect()
self.speed = 1
def update(self):
self.index += 0.02
self.image = self.images[int(self.index % self.range)]
self.rect.y += self.speed
if self.rect.top > HEIGHT:
self.kill()
class Car(pg.sprite.Sprite):
def __init__(self, x, y, img):
pg.sprite.Sprite.__init__(self)
if img == fuel_image:
self.image = img
self.speed = 0
elif img == canister_image or img == water_image:
self.image = img
self.speed = 1
else:
self.image = pg.transform.flip(img, False, True)
self.speed = random.randint(2, 3)
self.rect = self.image.get_rect(center=(x, y))
def update(self):
self.rect.y += self.speed
if self.rect.top >= HEIGHT:
if self is canister or self is water:
self.kill()
else:
if 40 < player.rect.centerx < WIDTH - 40 \
and player.rect.top < HEIGHT and player.rect.bottom > 0:
count[0] += 1
list_x.remove(self.rect.centerx)
while True:
self.rect.centerx = random.randrange(80, WIDTH, 80)
if self.rect.centerx in list_x:
continue
else:
list_x.append(self.rect.centerx)
self.speed = random.randint(2, 3)
self.rect.bottom = 0
break
class Road(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface(screen.get_size())
self.image.fill(GREY)
pg.draw.line(self.image, GREEN, (20, 0), (20, 600), 40)
pg.draw.line(self.image, GREEN, (780, 0), (780, 600), 40)
for xx in range(10):
for yy in range(10):
pg.draw.line(
self.image, WHITE,
(40 + xx * 80, 0 if xx == 0 or xx == 9 else 10 + yy * 60),
(40 + xx * 80, 600 if xx == 0 or xx == 9 else 50 + yy * 60), 5)
self.rect = self.image.get_rect(topleft=(x, y))
self.speed = 1
def update(self):
self.rect.y += self.speed
if self.rect.top >= HEIGHT:
self.rect.bottom = 0
class Volume(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((20, 140), pg.SRCALPHA)
self.rect = self.image.get_rect(center=(x, y))
self.radius = 10
self.x = self.y = self.radius
self.color_circle = (0, 255, 0, 128)
self.color_rect = (0, 180, 0, 128)
self.color_text = (255, 255, 255)
self.alpha = 255
self.volume = 1
def update(self):
self.image.set_alpha(self.alpha)
pg.draw.rect(
self.image, self.color_rect, [0, 0, *self.rect[2:]],
border_radius=self.radius)
pg.draw.circle(self.image, self.color_circle, (self.x, self.y), self.radius)
text = str(round(self.volume * 100))
text_rect = font.get_rect(text, size=11)
font.render_to(
self.image, (self.x - text_rect[2] / 2., self.y - text_rect[3] / 2.), text,
self.color_text, rotation=0, size=11)
sp = "\U0001F507" if self.volume == 0 else "\U0001F508" if self.volume < 0.2 \
else "\U0001F509" if self.volume < 0.7 else "\U0001F50A"
font.render_to(
screen, (self.rect.x, self.rect.y - font.size), sp, [*WHITE, self.alpha])
def render(self, e_buttons, e_pos):
if self.rect.left < e_pos[0] < self.rect.right and \
self.rect.top < e_pos[1] < self.rect.bottom and \
e_buttons:
self.y = abs(self.rect.top - e_pos[1])
if self.y > self.rect.h - self.radius:
self.y = self.rect.h - self.radius
elif self.y < self.radius:
self.y = self.radius
self.volume = (100 - (self.y - self.radius) / 1.2) / 100.
sound_car_accident.set_volume(self.volume)
sound_canister.set_volume(self.volume)
sound_accident.set_volume(self.volume)
class Speedometer(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
w, h = 150, 150
self.radius = 140
self.image = pg.Surface((w, h), pg.SRCALPHA)
self.rect = self.image.get_rect(bottomright=(WIDTH, HEIGHT))
font.render_to(self.image, (w - 50, h - 50), 'km/h', WHITE, size=20)
for deg in range(5, 84, 6):
length = 18 if deg == 5 or deg == 23 or deg == 41 or deg == 59 or deg == 77 else 10
cos = math.cos(math.radians(deg))
sin = math.sin(math.radians(deg))
pg.draw.line(
self.image, WHITE,
(w - self.radius * cos, h - self.radius * sin),
(w - (self.radius - length) * cos, h - (self.radius - length) * sin), 2)
for value, deg in enumerate(range(9, 78, 17)):
cos = math.cos(math.radians(deg))
sin = math.sin(math.radians(deg))
font.render_to(self.image, (
round(w - (self.radius - 30) * cos), round(h - (self.radius - 30) * sin)),
str(value * 100), WHITE, size=15)
def render(self):
s = 30 - player.for_speedometer() * 25 # from 4 to 80
pg.draw.line(
screen, RED, self.rect.bottomright,
(self.rect.right - (self.radius - 10) * math.cos(math.radians(s)),
self.rect.bottom - (self.radius - 10) * math.sin(math.radians(s))), 4)
pg.draw.circle(screen, WHITE, self.rect.bottomright, 25)
vol.update()
class Bullet(pg.sprite.Sprite):
def __init__(self):
super().__init__()
pygame.sprite.Sprite.__init__(self)
self.image = pg.image.load(os.path.join(path, 'img', 'bullet.png'))
self.image = pygame.Surface([4, 10])
self.image.fill(RED)
self.rect = self.image.get_rect()
def update(self):
self.rect.y -= 5
all_sprite = pg.sprite.LayeredUpdates()
cars_group = pg.sprite.Group()
canister_group = pg.sprite.Group()
bullet_list = pg.sprite.Group()
for r in range(2):
bg = Road(x=0, y=0)
all_sprite.add(Road(0, 0 if r == 0 else -HEIGHT), layer=0)
speedometer = Speedometer()
all_sprite.add(speedometer, layer=0)
player = Player()
list_x = []
n = 0
while n < 6:
car_x = random.randrange(80, WIDTH, 80)
if car_x in list_x:
continue
else:
list_x.append(car_x)
cars_group.add(Car(car_x, random.randint(
-cars[0].get_height() * 3, -cars[0].get_height()),
cars[n] if n < 3 else random.choice(cars)))
n += 1
fuel = Car(WIDTH - 80, 40, fuel_image)
canister = Car(0, 0, canister_image)
water = Car(0, 0, water_image)
vol = Volume(20, HEIGHT - 80)
all_sprite.add(*cars_group, layer=1)
all_sprite.add(player, layer=3)
all_sprite.add(fuel, layer=4)
all_sprite.add(vol, layer=4)
def my_record():
with open(record_file, 'r+') as d:
record = d.read()
if count[0] > int(record):
record = str(count[0])
d.seek(0)
d.truncate()
d.write(record)
return record
def home_screen(b):
screen.blit(all_sprite.get_sprite(0).image, (0, 0))
screen.blit(speedometer.image, speedometer.rect)
button_start.set_alpha(start)
button_stop.set_alpha(start)
screen.blit(button_start, button_start_rect)
screen.blit(button_stop, button_stop_rect)
font.render_to(screen, (48, 10), f'Record: {rec}', [
*RED, 255 if count[0] <= record_old else 255 if int(b) % 2 else 0], size=24)
font.render_to(screen, (48, 40), f'Points: {count[0]}', RED, size=24)
font.render_to(screen, (48, 70), f'Accidents: {car_accident}', RED, size=24)
vol.update()
screen.blit(vol.image, vol.rect)
rec = my_record()
record_old = int(rec)
game = True
while game:
for e in pg.event.get():
if e.type == pg.QUIT or e.type == pg.KEYDOWN and e.key == pg.K_ESCAPE:
game = False
elif e.type == pg.KEYDOWN and e.key == pg.K_p and start == 0:
pause.reverse()
if pause[0]:
pg.mouse.set_visible(True)
vol.alpha = 255
else:
pg.mouse.set_visible(False)
vol.alpha = 0
elif e.type == pg.MOUSEMOTION and (start == 255 or pause[0]):
vol.render(e.buttons[0], e.pos)
elif e.type == pg.KEYDOWN and e.key == pg.K_SPACE:
# Fire a bullet if the user clicks the space button
bullet = Bullet()
# Set the bullet so it is where the player is
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
# Add the bullet to the lists
cars_group.add(bullet)
bullet_list.add(bullet)
elif e.type == pg.MOUSEBUTTONDOWN and start == 255:
if e.button == 1:
if button_start_rect.collidepoint(e.pos):
player.angle = 0
player.velocity.x, player.velocity.y = 0, 0
player.position.x, player.position.y = WIDTH - 400, HEIGHT - 70
player.update()
all_sprite.remove_sprites_of_layer(2)
water.kill()
canister.kill()
for cr in cars_group:
cr.speed = random.randint(2, 3)
cr.rect.bottom = 0
level = 40
car_accident = 0
count[0] = 0
start -= 1
record_old = int(rec)
pg.mouse.set_visible(False)
elif button_stop_rect.collidepoint(e.pos):
game = False
elif e.type == u1_event and not pause[0] and not all_sprite.has(water): # water.alive():
all_sprite.add(water, layer=0)
water.rect.center = \
random.randrange(80, WIDTH, 80), -water.rect.h
timer1 = random.randrange(6000, 26001, 4000)
pg.time.set_timer(u1_event, timer1)
elif e.type == u2_event and not pause[0] and not canister_group.has(canister):
canister_group.add(canister)
all_sprite.add(canister, layer=0)
canister.rect.center = \
random.randrange(80, WIDTH, 80), -canister.rect.h
timer2 = random.randrange(13000, 28001, 5000)
pg.time.set_timer(u2_event, timer2)
# Calculate mechanics for each bullet
for bullet in bullet_list:
# See if it hit a block
block_hit_list = pygame.sprite.spritecollide(bullet, cars_group, True)
# For each block hit, remove the bullet and add to the score
for block in block_hit_list:
bullet_list.remove(bullet)
cars_group.remove(bullet)
hit = pg.sprite.spritecollideany(player, cars_group) # hit -> sprite car
if hit and hit.speed != 1:
player.position.x += 50 * random.randrange(-1, 2, 2)
player.angle = 50 * random.randrange(-1, 2, 2)
hit.speed = 1
car_alarm = Alarm()
all_sprite.add(car_alarm, layer=2)
car_alarm.rect.center = hit.rect.center
car_accident += 1
if car_accident > 10:
car_accident = 10
sound_car_accident.play()
if pg.sprite.spritecollide(player, canister_group, True):
level = 40
sound_canister.play()
if pg.sprite.collide_rect(player, water):
if not block:
player.angle = random.randint(60, 90) * random.randrange(-1, 2, 2)
sound_accident.play()
block = True
else:
block = False
if start > 0:
home_screen(blink)
blink = 0 if blink > 99 else blink + .02
if start != 255:
start -= 1
vol.alpha = start
else:
if not pause[0]:
level -= .01
if level < 0 or car_accident > 9:
rec = my_record()
pg.mouse.set_visible(True)
vol.alpha = start
elif level < 10:
rgb[:2] = 250, 0
elif level < 20:
rgb[0] = 250
else:
rgb[:2] = 0, 250
all_sprite.update()
else:
vol.update()
all_sprite.draw(screen)
pg.draw.rect(
screen, rgb,
(fuel.rect.left + 10, fuel.rect.bottom - level - 8, 21, level))
font.render_to(screen, (48, 10), f'accidents: {car_accident}', GREEN, size=24)
font.render_to(screen, (48, HEIGHT - 30), f'{count[0]}', GREEN, size=24)
speedometer.render() # speedometer
pg.display.update()
clock.tick(FPS)
pg.display.set_caption(f'Rally FPS: {int(clock.get_fps())}')
pygame.quit()
# pg.image.save(screen, 'road.jpg')
aos;dfihj ;aslkdjfh ;salkj
askl;fjas;lkfjd
a sdlfkj as;ldkfj as
asld;kj f;laskjd
asl;kjdf;lasjk f
sdla ;fjkas;ldkf j
asdlf jkasl;dkf j
asld flasdkjf ;
You are drawing all the Sprites in the all_sprites Group:
all_sprite.draw(screen)
However, t he bullets are not in this Group Either add the bullets to the all_sprites Group or draw the Sprites contained in the bullet_list Group.
Either
elif e.type == pg.KEYDOWN and e.key == pg.K_SPACE:
# [...]
bullet_list.add(bullet)
bullet_list.draw(screen)
or
bullet_list.draw(screen)
Remove the bullets form all Groups using kill():
for bullet in bullet_list:
# See if it hit a block
block_hit_list = pygame.sprite.spritecollide(bullet, cars_group, True)
# For each block hit, remove the bullet and add to the score
for block in block_hit_list:
bullet.kill()
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
I am trying to make a simple platformer in pygame, with simulated gravity and collision. I can't make the collision working. On collision with a sprite, the player slowly falls through the sprite and continues falling at normal speed when reached through.
Main.py:
class Game:
def __init__(self):
# initialize pygame library
pg.init()
pg.mixer.init()
# initialize screen
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.font = pg.font.match_font(FONT_NAME)
self.running = True
self.playing = True
def new(self):
# initzialize sprite groups
self.sprites = pg.sprite.Group()
self.objects = pg.sprite.Group()
self.p = Player(self)
self.sprites.add(self.p)
self.g = Ground()
self.sprites.add(self.g)
self.objects.add(self.g)
self.o = Object(100, 350, 100, 20)
self.sprites.add(self.o)
self.objects.add(self.o)
self.collide = False
self.run()
# constant running functions
def run(self):
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
self.running = False
def events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.playing = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
self.p.jump()
def update(self):
self.sprites.update()
hits = pg.sprite.spritecollide(self.p, self.objects, False)
if hits:
self.collide = True
if self.p.vel.y >= 0.0:
self.p.x = hits[0].rect.top
print("Collide bottom")
elif self.p.vel.y < 0: self.p.top = hits[0].rect.bottom
elif self.p.vel.x > 0: self.p.rect.right = hits[0].rect.left
elif self.p.vel.x < 0: self.p.rect.left = hits[0].rect.right
self.p.vel.y = 0
#self.p.acc.y = 0
#print(f"Collision with {hits[0].name}")
else:
self.collide = False
def draw(self):
self.screen.fill(BLACK)
self.sprites.draw(self.screen)
self.drawtext(f"X Pos: = {int(self.p.pos.x)}", 15, WHITE, WIDTH - 5, 20, 3)
self.drawtext(f"Y Pos: = {int(self.p.pos.y)}", 15, WHITE, WIDTH - 5, 40, 3)
self.drawtext(f"Y Velocity = {self.p.vel.y}", 15, WHITE, 5, 50, 0)
self.drawtext(f"Y Accelleration = {self.p.acc.y}", 15, WHITE, 5, 70, 0)
self.drawtext(f"Collision: = {self.collide}", 15, WHITE, 5, 200, 0)
#print(self.p.vel.y)
pg.display.flip()
# other functions
def drawtext(self, text, size, color, x, y, align):
font = pg.font.Font(self.font, size)
text_surface = font.render(text, True, color)
text_rect = text_surface.get_rect()
if align == 0:
text_rect.midleft = (x, y)
elif align == 1:
text_rect.midtop = (x, y)
elif align == 2:
text_rect.midbottom = (x, y)
elif align == 3:
text_rect.midright = (x, y)
else:
text_rect.center = (x, y)
self.screen.blit(text_surface, text_rect)
# def checkCollisionY(self):
# hits = pg.sprite.spritecollide(self.p, self.objects, False)
# if hits:
# self.collide = True
# return True
# else:
# self.collide = False
# return False
g = Game()
while g.running:
g.new()
pg.quit()
Sprites.py:
from settings import *
import pygame as pg
vec = pg.math.Vector2
class Player(pg.sprite.Sprite):
def __init__(self, game):
pg.sprite.Sprite.__init__(self)
self.game = game
self.width = 30
self.height = 30
self.image = pg.Surface((self.width, self.height))
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.rect.center = vec(150, 100)
self.pos = vec(150, 100)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
def update(self):
self.acc = vec(0, PLAYER_GRAV)
#input
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.acc.x = -PLAYER_ACC
if keys[pg.K_RIGHT]:
self.acc.x = PLAYER_ACC
self.acc.x += self.vel.x * PLAYER_FRICTION
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
print(f"{self.vel.y} + 0.5 * {self.acc.y} = {self.vel.y + 0.5 * self.acc.y}")
self.rect.topleft = self.pos
def jump(self):
hits = pg.sprite.spritecollide(self, self.game.objects, False)
if hits:
self.vel.y = -20
class Object(pg.sprite.Sprite):
def __init__(self, x, y, w, h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w, h))
self.image.fill((255, 0, 144))
self.name = "Object"
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Ground(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.name = "Ground"
self.image = pg.image.load("ground.png")
self.rect = self.image.get_rect()
self.rect.x = -100
self.rect.y = 550
Settings.py:
# game settings
TITLE = "My Game"
WIDTH = 480
HEIGHT = 800
FPS = 60
FONT_NAME = 'impact'
#Player properties
PLAYER_ACC = 0.7
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.7
# 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)
CYAN = (0, 255, 255)
PURPLE = (255, 0, 255)
The important code here is the update() in main.py and update() in sprites.py. Help?
EDIT
hits = pg.sprite.spritecollide(self.p, self.objects, False)
for hit in hits:
self.collide = True
if self.p.vel.x > 0.0:
self.p.rect.right = hit.rect.left
self.p.pos.x = self.p.rect.centerx
self.p.vel.x = 0
elif self.p.vel.x < 0.0:
self.p.rect.left = hit.rect.right
self.p.pos.x = self.p.rect.centerx
self.p.vel.x = 0
self.p.pos.x = self.p.rect.x
else:
self.collide = False
hits = pg.sprite.spritecollide(self.p, self.objects, False)
for hit in hits:
self.collide = True
if self.p.vel.y >= 0.0:
self.p.rect.bottom = hit.rect.top
self.p.pos.y = self.p.rect.centery
self.p.vel.y = 0
elif self.p.vel.y < 0.0:
self.p.rect.top = hit.rect.bottom
self.p.pos.y = self.p.rect.centery
self.p.vel.y = 0
self.p.pos.y = self.p.rect.y
else:
self.collide = False
Your Player class doesn't have x and y attributes but a pos attribute which you need to change after a collision. The rect of the object needs to be updated as well and it's better to do that first and then set the pos.y coordinate to the rect.centery coordinate afterwards.
if self.p.vel.y >= 0.0:
self.p.rect.bottom = hits[0].rect.top
self.p.pos.y = self.p.rect.centery
self.p.vel.y = 0
Do the same for the other directions.
Also, the horizontal and vertical movement should be handled separately, otherwise you'll see odd jumps for example from the side to the top of a platform. Take a look at the first part of this platformer example.
And in the jump method you need to move the rect down by 1 pixel so that it's able to collide with the platform sprites.
def jump(self):
self.rect.y += 1
# ...
Here's a complete, runnable example:
import pygame as pg
# game settings
TITLE = "My Game"
WIDTH = 480
HEIGHT = 800
FPS = 60
FONT_NAME = 'impact'
#Player properties
PLAYER_ACC = 0.7
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.7
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
vec = pg.math.Vector2
class Player(pg.sprite.Sprite):
def __init__(self, game):
pg.sprite.Sprite.__init__(self)
self.game = game
self.image = pg.Surface((30, 30))
self.image.fill(YELLOW)
self.rect = self.image.get_rect(center=(150, 100))
self.pos = vec(150, 100)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
self.objects = game.objects
def update(self):
self.acc = vec(0, PLAYER_GRAV)
#input
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.acc.x = -PLAYER_ACC
if keys[pg.K_RIGHT]:
self.acc.x = PLAYER_ACC
self.acc.x += self.vel.x * PLAYER_FRICTION
self.vel += self.acc
# Move along the x-axis first.
self.pos.x += self.vel.x + 0.5 * self.acc.x
# print(f"{self.vel.y} + 0.5 * {self.acc.y} = {self.vel.y + 0.5 * self.acc.y}")
self.rect.centerx = self.pos.x
# Check if the sprite collides with a platform.
hits = pg.sprite.spritecollide(self, self.objects, False)
if hits:
# Reset the x position.
if self.vel.x > 0:
self.rect.right = hits[0].rect.left
self.pos.x = self.rect.centerx
self.vel.x = 0
elif self.vel.x < 0:
self.rect.left = hits[0].rect.right
self.pos.x = self.rect.centerx
self.vel.x = 0
# Move along the y-axis.
self.pos.y += self.vel.y + 0.5 * self.acc.y
self.rect.centery = self.pos.y
# Check if the sprite collides with a platform.
hits = pg.sprite.spritecollide(self, self.objects, False)
if hits:
# Reset the y position.
if self.vel.y >= 0.0:
self.rect.bottom = hits[0].rect.top
self.pos.y = self.rect.centery
self.vel.y = 0
elif self.vel.y < 0:
self.rect.top = hits[0].rect.bottom
self.pos.y = self.rect.centery
self.vel.y = 0
def jump(self):
self.rect.y += 1 # Move it down to check if it collides with a platform.
hits = pg.sprite.spritecollide(self, self.game.objects, False)
if hits:
self.vel.y = -20
self.rect.y -= 1 # Move it up again after the collision check.
class Object(pg.sprite.Sprite):
def __init__(self, x, y, w, h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w, h))
self.image.fill((255, 0, 144))
self.name = "Object"
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Ground(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.name = "Ground"
self.image = pg.Surface((500, 300))
self.image.fill((90, 30, 30))
self.rect = self.image.get_rect()
self.rect.x = -100
self.rect.y = 550
class Game:
def __init__(self):
pg.init()
pg.mixer.init()
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.font = pg.font.match_font(FONT_NAME)
self.running = True
self.playing = True
def new(self):
self.sprites = pg.sprite.Group()
self.objects = pg.sprite.Group()
self.p = Player(self)
self.sprites.add(self.p)
self.g = Ground()
self.sprites.add(self.g)
self.objects.add(self.g)
rects = [(100, 350, 100, 20), (50, 380, 100, 20),
(200, 450, 100, 100)]
for x, y, w, h in rects:
obj = Object(x, y, w, h)
self.sprites.add(obj)
self.objects.add(obj)
self.collide = False
self.run()
def run(self):
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
self.running = False
def events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.playing = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
self.p.jump()
def update(self):
self.sprites.update()
def draw(self):
self.screen.fill(BLACK)
self.sprites.draw(self.screen)
pg.display.flip()
g = Game()
while g.running:
g.new()
pg.quit()
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()
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