Hey I have a problem with my game code. Is there a way to check if, for example, the right side of my player sprite (hero) is colliding with the group obstacle_sprite?
I can only figure out how to check for collision in general but I want only a true output if the right side of the player is colliding wit the obstacle.
In my code I am using a invisible sprite as hitbox and draw the player inside this invisible sprite to check collisions but make it look like the obstacle denies moving of the player.
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
PINK = (230, 77, 149)
FPS = 60
window_width = 900
window_height = 600
window_color = WHITE
window = pygame.display.set_mode((window_width, window_height))
window.fill(window_color)
pygame.display.set_caption("Bub - the game")
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, velocity, color):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((width + 2*velocity, height + 2*velocity))
self.rect = self.image.get_rect()
self.rect.topleft = (x - velocity, y - velocity)
self.velocity = velocity
self.is_jump = False
self.jump_count = 15
self.fall_count = 1
self.ground = self.rect.bottom
self.body = pygame.Rect(x, y, width, height)
pygame.draw.rect(window, color, self.body)
def move(self):
key = pygame.key.get_pressed()
if key[pygame.K_a] and self.rect.left >= 0:
self.rect.x -= self.velocity
if key[pygame.K_d] and self.rect.right <= window_width:
self.rect.x += self.velocity
if not self.is_jump:
if key[pygame.K_SPACE] and self.rect.bottom == self.ground:
self.is_jump = True
else:
if self.jump_count >= 0:
self.rect.y -= round((self.jump_count ** 2) * 0.1)
self.jump_count -= 1
else:
self.jump_count = 15
self.is_jump = False
def gravity(self):
if not self.is_jump and self.rect.bottom != self.ground:
self.rect.y += round((self.fall_count ** 2) * 0.1)
if self.fall_count <= 15:
self.fall_count += 1
else:
self.fall_count = 1
def update(self):
self.move()
self.gravity()
pygame.draw.rect(window, BLACK, self.body)
self.body.topleft = (self.rect.x + self.velocity, self.rect.y + self.velocity)
class Obstacle(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, color):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.center = (x, y)
player_sprite = pygame.sprite.Group()
obstacle_sprite = pygame.sprite.Group()
hero = Player(0, 570, 30, 30, 5, BLACK)
player_sprite.add(hero)
obstacle_1 = Obstacle(100, 585, 120, 30, PINK)
obstacle_sprite.add(obstacle_1)
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(window_color)
player_sprite.update()
player_sprite.draw(window)
obstacle_sprite.update()
obstacle_sprite.draw(window)
pygame.display.update()
pygame.quit()
It's easier if you keep track of your player's velocity; this will make handling jumping also less complex.
A common technique AFAIK is to do two collision detection runs: one for the x-axis and one for the y-axis.
Here's how I changed your code. As you can see, checking for the side of a collision is as easy as checking xvel < 0 or xvel > 0:
import pygame
pygame.init()
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
PINK = (230, 77, 149)
FPS = 60
window_width = 900
window_height = 600
window_color = WHITE
window = pygame.display.set_mode((window_width, window_height))
window.fill(window_color)
pygame.display.set_caption("Bub - the game")
clock = pygame.time.Clock()
class Toast(pygame.sprite.Sprite):
def __init__(self, *grps):
super().__init__(*grps)
self.image = pygame.Surface((900, 200))
self.image.fill(WHITE)
self.rect = self.image.get_rect(topleft=(10, 10))
self.font = pygame.font.SysFont(None, 32)
def shout(self, message):
self.text = self.font.render(message, True, BLACK)
self.image.fill(WHITE)
self.image.blit(self.text, (0, 0))
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, velocity, color, *grps):
super().__init__(*grps)
self.image = pygame.Surface((width + 2*velocity, height + 2*velocity))
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.topleft = (x - velocity, y - velocity)
self.velocity = velocity
self.on_ground = True
self.xvel = 0
self.yvel = 0
def collide(self, xvel, yvel, obstacle_sprites):
global toast
for p in pygame.sprite.spritecollide(self, obstacle_sprites, False):
if xvel > 0:
self.rect.right = p.rect.left
toast.shout('collide RIGHT')
if xvel < 0:
self.rect.left = p.rect.right
toast.shout('collide LEFT')
if yvel > 0:
self.rect.bottom = p.rect.top
self.on_ground = True
self.yvel = 0
toast.shout('collide BOTTOM')
if yvel < 0:
self.rect.top = p.rect.bottom
self.yvel = 0
toast.shout('collide TOP')
def update(self, obstacle_sprites):
global toast
key = pygame.key.get_pressed()
self.xvel = 0
if key[pygame.K_a]:
self.xvel =- self.velocity
if key[pygame.K_d]:
self.xvel = self.velocity
if self.on_ground:
if key[pygame.K_SPACE]:
toast.shout('JUMPING')
self.on_ground = False
self.yvel = -20
else:
self.yvel += 1
self.rect.left += self.xvel
self.collide(self.xvel, 0, obstacle_sprites)
self.rect.top += self.yvel
self.on_ground = False
self.collide(0, self.yvel, obstacle_sprites)
self.rect.clamp_ip(pygame.display.get_surface().get_rect())
if self.rect.bottom == pygame.display.get_surface().get_rect().bottom:
self.on_ground = True
class Obstacle(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, color, *grps):
super().__init__(*grps)
self.image = pygame.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect(center=(x, y))
all_sprites = pygame.sprite.Group()
player_sprite = pygame.sprite.Group()
obstacle_sprites = pygame.sprite.Group()
toast = Toast(all_sprites)
hero = Player(0, 570, 30, 30, 5, GREEN, all_sprites, player_sprite)
for x in [
(100, 585, 120, 30),
(300, 535, 120, 30),
(500, 485, 120, 30)
]:
Obstacle(*x, PINK, all_sprites, obstacle_sprites)
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(window_color)
all_sprites.update(obstacle_sprites)
all_sprites.draw(window)
pygame.display.update()
pygame.quit()
Related
sprites.py:
import pygame as pg
from settings import *
vec = pg.math.Vector2
# for movement
class Player(pg.sprite.Sprite):
def __init__(self, game):
pg.sprite.Sprite.__init__(self)
self.game = game
self.image = pg.Surface((30, 40))
self.image.fill((255, 255, 153))
self.rect = self.image.get_rect()
self.rect.center = WIDTH / 2, HEIGHT / 2
self.pos = vec(WIDTH / 2, HEIGHT / 2)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
def jump(self):
self.rect.x += 1
hits = pg.sprite.spritecollide(self, self.game.platforms, False)
self.rect.x -= 1
if hits:
self.vel.y = -20
def update(self):
self.acc = vec(0, PLAYER_GRAV)
# pouze zryhlení
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
# apply friction
self.acc.x += self.vel.x * PLAYER_FRICTION
# pohyb tělesa
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
self.rect.midbottom = self.pos
if self.pos.x > WIDTH:
self.pos.x = 0
if self.pos.x < 0:
self.pos.x = WIDTH
class Platform(pg.sprite.Sprite):
def __init__(self, x, y, w, h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w, h))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
main.py:
import random
import pygame as pg
from settings import *
from sprites import *
class Game:
def __init__(self):
# initialize the game window
self.running = True
pg.init()
pg.mixer.init()
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption('My game')
self.clock = pg.time.Clock()
def new(self):
# to start a new game, reset the pieces
self.all_sprites = pg.sprite.Group()
self.platforms = pg.sprite.Group()
self.player = Player(self)
self.all_sprites.add(self.player)
p1 = Platform(0, HEIGHT - 40, WIDTH, 40)
p2 = Platform(WIDTH / 2 - 50, HEIGHT * 3 / 4, 100, 20)
self.platforms.add(p2)
self.platforms.add(p1)
self.all_sprites.add(p1)
self.all_sprites.add(p2)
self.run()
def run(self):
self.playing = True
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
def update(self):
self.all_sprites.update()
hits = pg.sprite.spritecollide(self.player, self.platforms, False)
if hits:
self.player.pos.y = hits[0].rect.top
self.player.rect.midbottom = self.player.pos
self.player.vel.y = 0
def events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
if self.playing:
self.playing = False
self.running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_SPACE:
self.player.jump()
def draw(self):
self.screen.fill(BLACK)
self.all_sprites.draw(self.screen)
pg.display.flip()
def show_start_screen(self):
pass
def show_go_screen(self):
pass
game = Game()
game.show_start_screen()
while game.running:
game.new()
game.show_go_screen()
pg.quit()
settings.py:
# game settings
WIDTH = 480
HEIGHT = 600
FPS = 60
# player settings
PLAYER_ACC = 0.5
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.8
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = ((255, 255, 153))
I have a few questions:
Question n. 1:
Why doesn't the jump method work? And why is it using velocity -20 to jump?
Question n. 2:
I'm not quite sure if I understand the vector coordinates, can someone please try to explain it to me?
I think that this is exactly why I have problems understanding the code.
In pygame, the screen coordinates start at the top left (0,0). Positive Y goes down. Jump is -20 because the player is going up (toward zero). It looks like the player bounces up when it hits an object.
Concerning the jump issue, the game does not start for (Platform not defined) so I can't help there.
I am writing a snake game with pygame but I am just prompted with a black window without any error.
I checked similar problems and they incorrectly used the screen object. However this does not seem to be the case here, since it is only created once?
Any idea what I am doing wrong? Since I am not given any error message I can't figure out why I am only shown a black screen. The key input events work just fine.
import pygame
import random
import sys
# Define colors
GRAY = (240, 240, 245)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (50, 50, 50)
# Field size
width = 400
height = 400
# Calculate the distance between two points
def calculate_distance(x1, x2, y1, y2):
return (x2 - x1)**2 + (y1 - y2)**2 ** 1/2
# Draws a label showing the current score in the top mid of the window
def draw_score_text(surface, text, font_size, x, y):
font_name = pygame.font.match_font('arial')
font = pygame.font.Font(font_name, font_size)
text_surface = pygame.font.render(text, True, WHITE)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
class Snake(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((12,12))
self.image.fill(WHITE)
self.rect=self.image.get_rect()
self.rect.center = (100,100)
self.speedx=0
self.speedy=0
self.score=0
self.tail=[]
def update(self):
if self.score == len(self.tail):
self.tail.append((self.rect.x, self.rect.y))
else:
self.tail.append((self.rect.x, self.rect.y))
self.tail.pop(0)
self.rect.x += self.speedx
self.rect.y += self.speedy
keys = pygame.key.get_pressed()
if(keys[pygame.K_RIGHT] and self.speedx >=0):
self.speedx = 10
self.speedy = 0
if(keys[pygame.K_LEFT] and self.speedx <=0):
self.speedx = -10
self.speedy = 0
if(keys[pygame.K_UP] and self.speedy <=0):
self.speedx = 0
self.speedy = -10
if(keys[pygame.K_DOWN] and self.speedy >=0):
self.speedx = 0
self.speedy = 10
if self.rect.left >= width:
self.rect.left = 1
if self.rect.top >= height:
self.rect.top = 0
if self.rect.bottom <= 0:
self.rect.bottom = height
if self.rect.left <= 0:
self.rect.left = width
def exit(self):
for i in range(1, len(self.tail)):
if dist(self.rect.x, self.rect.y, self.tail[i][0], self.tail[i][1]) < 1:
sys.exit()
class Food(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((12,12))
self.image.fill(RED)
self.rect=self.image.get_rect()
self.rect.center = (x, y)
# Start dah game
pygame.init()
screen = pygame.display.set_mode([width,height])
clock = pygame.time.Clock()
running = True
print("ok?")
all_sprites = pygame.sprite.Group()
player = Snake()
food = Food(random.randrange(20, width - 20), random.randrange(20, height - 20))
all_sprites.add(player)
all_sprites.add(food)
while running:
clock.tick(3)
#pygame.display.update()
keys_pressed = pygame.event.get()
print(keys_pressed)
for i in keys_pressed:
if i.type == pygame.QUIT:
print("quit")
running = False
if pygame.sprite.collide_rect(player, food):
food.kill()
player.score += 1
food = Food(random.randrange(20, width - 20), random.randrange(20, height - 20))
all_sprites.add(food)
all_sprites.update()
screen.fill(BLACK)
player.exit()
for i in range(1, len(player.tail)):
pygame.draw.rect(screen, WHITE, (player.tail[i][0], player.tail[i][2], 12, 12))
#draw_score_text(screen, str(player.score), 18, width/2, 10)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
The update of the display and the drawing of the sprites has to be done in the main loop rather than in the inner for loop:
while running:
# [...]
for i in range(1, len(player.tail)):
pygame.draw.rect(screen, WHITE, (player.tail[i][0], player.tail[i][2], 12, 12))
# <--
all_sprites.draw(screen)
pygame.display.flip()
Note, if the snake consists of a head only, then the inner loop is not executed. If the length of the tail would be > 1, then the display would be updated multiple times per frame, which is not what you want.
I am getting an out of range exception
Traceback (most recent call last): File "snake.py", line 132, in <module> >
pygame.draw.rect(screen, WHITE, (player.tail[i][0], player.tail[i][2], 12, 12))
IndexError: tuple index out of range `
The index of the 2nd (y) coordinate is 1 rather than 2. Ist has to be player.tail[i][1]:
for i in range(1, len(player.tail)):
pygame.draw.rect(screen, WHITE, (player.tail[i][0], player.tail[i][1], 12, 12))
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 making a game with Asteroids like controls, UP arrow for acceleration,
RIGHT arrow to rotate clockwise and LEFT arrow counterclockwise so for example if I want to slow down I need to rotate ship 180° and accelerate.
I'm able to rotate and also for this purpose I drew two vectors (velocity and heading).
I'm trying to achieve this type of movement with vectors but maybe I shouldn't ?
So here's what I came up with.
import pygame
import sys
from pygame.locals import * # pygame.locals.QUIT --> QUIT
# Vector2
vec = pygame.math.Vector2
# initialize pygame
pygame.init()
FPS = 60 # frames per second
fps_clock = pygame.time.Clock()
# set up the window
WIDTH = 800
HEIGHT = 800
DISPLAY = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('VECTOR_2')
FONT = pygame.font.Font(None, 24)
# RGB colors
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
MAX_SPEED = 9
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
# set ship image
self.image = pygame.Surface((70, 50), pygame.SRCALPHA)
pygame.draw.polygon(self.image, (50, 120, 180), ((35, 0), (0, 35), (70, 35)))
self.original_image = self.image
self.rect = self.image.get_rect()
self.rect.center = (WIDTH / 2, HEIGHT / 2)
self.position = vec(WIDTH / 2, HEIGHT / 2)
self.vel = vec(0, 0)
self.acceleration = vec(0, 0)
# heading vector
self.heading = vec(0, -1) # upwards
self.rect.center = self.position
self.angle_speed = 0
self.angle = 0
def update(self):
self.acceleration = vec(0, 0)
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
self.acceleration.x = -0.2
if keys[K_RIGHT]:
self.acceleration.x = 0.2
if keys[K_UP]:
self.acceleration.y = -0.2
if keys[K_DOWN]:
self.acceleration.y = 0.2
if keys[K_a]:
self.angle_speed = -1
player.rotate()
if keys[K_d]:
self.angle_speed = 1
player.rotate()
# max speed
if self.vel.length() > MAX_SPEED:
self.vel.scale_to_length(MAX_SPEED)
self.vel += self.acceleration
self.position += self.vel
self.rect.center = self.position
def rotate(self):
# rotate the heading vector
self.heading.rotate_ip(self.angle_speed)
self.angle += self.angle_speed
if self.angle > 360:
self.angle -= 360
elif self.angle < 0:
self.angle += 360
self.image = pygame.transform.rotate(self.original_image, -self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
def draw_vectors(self, screen):
scale = 20
# vel
pygame.draw.line(screen, GREEN, self.position, (self.position + self.vel * scale), 5)
# desired
pygame.draw.line(screen, RED, self.position, (self.position + self.heading * scale), 5)
def wrap_around_screen(self):
"""Wrap around screen."""
if self.position.x > WIDTH:
self.position.x = 0
if self.position.x < 0:
self.position.x = WIDTH
if self.position.y <= 0:
self.position.y = HEIGHT
if self.position.y > HEIGHT:
self.position.y = 0
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
while True: # game loop
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
DISPLAY.fill(BLACK)
player.wrap_around_screen()
all_sprites.update()
all_sprites.draw(DISPLAY)
player.draw_vectors(DISPLAY)
txt = FONT.render('angle {:.1f}'.format(player.angle), True, (150, 150, 170))
DISPLAY.blit(txt, (10, 10))
pygame.display.update()
fps_clock.tick(FPS)
Any help would be appreciated
You can give the self.acceleration vector a initial length (0.2 in this case), rotate it if the player presses ← or →, and only accelerate (add it to the self.vel vector) if ↑ or ↓ are pressed.
import sys
import pygame
from pygame.locals import *
vec = pygame.math.Vector2
pygame.init()
FPS = 60
fps_clock = pygame.time.Clock()
WIDTH = 800
HEIGHT = 800
DISPLAY = pygame.display.set_mode((WIDTH, HEIGHT))
BLACK = (0, 0, 0)
MAX_SPEED = 9
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((70, 50), pygame.SRCALPHA)
pygame.draw.polygon(self.image, (50, 120, 180), ((35, 0), (0, 35), (70, 35)))
self.original_image = self.image
self.position = vec(WIDTH / 2, HEIGHT / 2)
self.rect = self.image.get_rect(center=self.position)
self.vel = vec(0, 0)
self.acceleration = vec(0, -0.2) # The acceleration vec points upwards.
self.angle_speed = 0
self.angle = 0
def update(self):
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
self.angle_speed = -1
player.rotate()
if keys[K_RIGHT]:
self.angle_speed = 1
player.rotate()
# If up or down is pressed, accelerate the ship by
# adding the acceleration to the velocity vector.
if keys[K_UP]:
self.vel += self.acceleration
if keys[K_DOWN]:
self.vel -= self.acceleration
# max speed
if self.vel.length() > MAX_SPEED:
self.vel.scale_to_length(MAX_SPEED)
self.position += self.vel
self.rect.center = self.position
def rotate(self):
# Rotate the acceleration vector.
self.acceleration.rotate_ip(self.angle_speed)
self.angle += self.angle_speed
if self.angle > 360:
self.angle -= 360
elif self.angle < 0:
self.angle += 360
self.image = pygame.transform.rotate(self.original_image, -self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
def wrap_around_screen(self):
"""Wrap around screen."""
if self.position.x > WIDTH:
self.position.x = 0
if self.position.x < 0:
self.position.x = WIDTH
if self.position.y <= 0:
self.position.y = HEIGHT
if self.position.y > HEIGHT:
self.position.y = 0
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
player.wrap_around_screen()
all_sprites.update()
DISPLAY.fill(BLACK)
all_sprites.draw(DISPLAY)
pygame.display.set_caption('angle {:.1f} accel {} accel angle {:.1f}'.format(
player.angle, player.acceleration, player.acceleration.as_polar()[1]))
pygame.display.update()
fps_clock.tick(FPS)
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