Cannot see bullets when game is running - python

Hello, so I can only see the bullet when i'm closing my game's window, but I do not see the mistake.
import pygame, math, random, os
pygame.init()
clock = pygame.time.Clock()
width = 800
height = 608
screen = pygame.display.set_mode((width, height))
running = True
gameover = False
levelferdig = False
levelnr = 0
ferdig = False
jump = False
levels =[[[1,1,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,8,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0],
[1,0,0,0,1,1,1,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0],
[1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0],
[1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0],
[1,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,7,0,0,0],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0],
[1,0,0,2,0,0,0,0,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,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]],
[[1,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[9,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,0,0,0,0,1],
[0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1],
[0,0,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1],
[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1],
[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0],
[0,0,0,0,1,1,1,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0],
[0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0],
[0,1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0],
[0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,1,1]]]
ghostgruppe = pygame.sprite.Group()
tilegruppe = pygame.sprite.Group()
utganggruppe = pygame.sprite.Group()
backgroundgruppe_1 = pygame.sprite.Group()
backgroundgruppe_2 = pygame.sprite.Group()
moving_sprites = pygame.sprite.Group()
spillergruppe = pygame.sprite.Group()
bullet_img = pygame.transform.scale(pygame.image.load(os.path.join('Bullets', 'bullet.png.png')), (10,10))
background_image_2 = pygame.image.load('skog.png').convert()
background_image_1 = pygame.image.load("beach.png").convert()
pygame.display.set_caption('pygame') #setter navnet på spillet når du åpner spillet
icon = pygame.image.load('menneske.png')
pygame.display.set_icon(icon)
font = pygame.font.Font('freesansbold.ttf', 72 ) #font som skal brukes
gameovertekst = font.render('Game over', True, (255,0,0)) #farge og tekst gameover
gameoverrect = gameovertekst.get_rect()
gameoverrect.center = (width/2, height/2)
font = pygame.font.Font('freesansbold.ttf', 72 ) #font som skal brukes
levelferdigtekst = font.render('Ferdig', True, (0,255,0)) #farge og tekst gameover
levelferdigrect = levelferdigtekst.get_rect()
levelferdigrect.center = (width/2, height/2)
ferdigtekst = font.render('Victory', True, (0,0,255))
ferdigrect = levelferdigtekst.get_rect()
ferdigrect.center = (width/2, height/2)
class Spiller(pygame.sprite.Sprite):
def __init__(self,x,y):
super().__init__()
self.spiller_animation = False
self.sprites = []
self.sprites.append(pygame.image.load('spiller.rett(1).png'))
self.sprites.append(pygame.image.load('spiller.høyre(1).png'))
self.sprites.append(pygame.image.load('spiller.venstre(1).png'))
self.sprites.append(pygame.image.load('spiller.hopp(1).png'))
self.current_sprite = 0
self.image = self.sprites[self.current_sprite]
self.rect = self.image.get_rect()
self.rect.topleft =[x,y]
self.bullets = [] #list
self.x = x
self.y = y
self.stepIndex = 0
self.face_right = True
self.face_left = False
self.fy = 10
self.fx = 10
self.jump = False
def direction(self):
if self.face_right:
return 1
if self.face_left:
return -1
def animation(self):
self.spiller_animation = True
def skytt(self):
if trykketliste[pygame.K_RIGHT] and not gameover:
bullet = Bullet(self.x, self.y, self.direction())
self.bullets.append(bullet)
for bullet in self.bullets:
bullet.move()
def reset(self):
self.fartx = 0
self.farty = 0
def update(self,speed):
if self.spiller_animation == True:
self.current_sprite += speed
if int(self.current_sprite) >= len(self.sprites):
self.current_sprite = 0
self.is_animating = False
self.image = self.sprites[int(self.current_sprite)]
self.rect.x += self.fartx
tiletreffliste = pygame.sprite.spritecollide(self,tilegruppe, False)
if tiletreffliste:
if self.fartx > 0:
self.rect.right = tiletreffliste[0].rect.left
else:
self.rect.left = tiletreffliste[0].rect.right
self.rect.y += self.farty
tiletreffliste = pygame.sprite.spritecollide(self, tilegruppe, False)
if tiletreffliste:
if self.farty > 0:
self.rect.bottom = tiletreffliste[0].rect.top
else:
self.rect.top = tiletreffliste[0].rect.bottom
utgangtreffliste = pygame.sprite.spritecollide(self, utganggruppe, False)
if utgangtreffliste:
global levelferdig
levelferdig = True
global levelnr
levelnr += 1
restart()
class Bullet:
def __init__(self,x,y, direction):
super().__init__()
self.x = x + 15
self.y = y + 25
self.direction = direction
def draw_bullet(self):
screen.blit(bullet_img, (self.x, self.y))
def move(self):
if self.direction == 1:
self.x += 15
if self.direction == -1:
self.x -= 15
class Ghost(pygame.sprite.Sprite):
def __init__(self, x, y, fx,fy):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('ghost.png').convert_alpha()
self.rect = self.image.get_rect() #self rect rektangler, fin rektangel bilde som passer
self.rect.x = x
self.rect.y = y
self.fartx = fx
self.farty = fy
def flytt(self):
self.rect.x = self.rect.x + self.fartx
self.rect.y = self.rect.y + self.farty
def update(self):
# Flytter høyre/venstre og sjekker kollisjon
self.rect.x += self.fartx
tiletreffliste = pygame.sprite.spritecollide(self,tilegruppe, False)
if tiletreffliste:
if self.fartx > 0:
self.rect.right = tiletreffliste[0].rect.left
else:
self.rect.left = tiletreffliste[0].rect.right
self.fartx *= -1
self.rect.y += self.farty
tiletreffliste = pygame.sprite.spritecollide(self, spillergruppe, False)
if tiletreffliste:
if self.farty > 0:
self.rect.bottom = tiletreffliste[0].rect.top
else:
self.rect.top = tiletreffliste[0].rect.bottom
self.farty *= -1
def treffTile(self):
if self.rect.x > width or self.rect.x < 0:
self.fartx = self.fartx * -1
if self.rect.y > height or self.rect.y < 0:
self.farty = self.farty * -1
class Tile(pygame.sprite.Sprite):
def __init__(self,x,y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('sand.png').convert_alpha()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Utgang(pygame.sprite.Sprite):
def __init__(self,x,y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('dør.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def restart():
global gameover
global levelferdig
gameover = False
levelferdig = False
for tile in tilegruppe:
tile.kill()
for utgang in utganggruppe:
utgang.kill()
for ghost in ghostgruppe:
ghost.kill()
spiller.reset()
for i in range(5): #hvor mange ghosts skal vi ha
ghost = Ghost(random.randint(0,width),random.randint(0, height), random.randint(1,8),random.randint(1,8))
ghostgruppe.add(ghost)
if levelnr < len(levels):
for y,rad in enumerate(levels[levelnr]):
for x,verdi in enumerate(rad):
if verdi == 1:
tile = Tile(x*32,y*32)
tilegruppe.add(tile)
if verdi == 9:
utgang = Utgang(x*32, y*32)
utganggruppe.add(utgang)
if verdi == 8:
spiller.rect.x = x*32
spiller.rect.y = y*32
else:
global ferdig
ferdig = True
#skytt
spiller = Spiller(100, 100)
moving_sprites.add(spiller)
restart()
while running:
pygame.display.bullet()
spiller.farty = 0
spiller.fartx = 0
trykketliste = pygame.key.get_pressed()
spiller.skytt()
background_image_1 = pygame.image.load("beach.png").convert()
screen.blit(background_image_1, [0,0])
if trykketliste[pygame.K_RIGHT] and not gameover:
spiller.farty = -1
spiller.sprites.append(pygame.image.load('spiller.venstre(1).png'))
spiller.animation()
spiller.skytt()
if trykketliste[pygame.K_LEFT] and not gameover:
spiller.farty = 1
spiller.sprites.append(pygame.image.load('spiller.høyre(1).png'))
spiller.animation()
if trykketliste[pygame.K_UP] and not gameover:
spiller.fartx = -1
spiller.animation()
spiller.sprites.append(pygame.image.load('spiller.hopp(1).png'))
if trykketliste[pygame.K_DOWN]and not gameover:
spiller.fartx = 1
spiller.animation()
spiller.sprites.append(pygame.image.load('spiller.rett(1).png'))
if jump is False and trykketliste[pygame.K_SPACE] and not gameover:
jump = True
spiller.animation()
spiller.sprites.append(pygame.image.load('spiller.hopp(1).png'))
if jump is True:
spiller.rect.y -= spiller.farty *4
spiller.farty -= 1
if spiller.farty < -10:
jump = False
spiller.farty = 10
if levelnr == 1:
background_image_1 = pygame.image.load("skog.png").convert()
screen.blit(background_image_2, [0,0])
spillertruffet = pygame.sprite.groupcollide(spillergruppe, ghostgruppe, False, False, pygame.sprite.collide_mask)
if spillertruffet:
gameover = True
ghosttruffet = pygame.sprite.groupcollide(ghostgruppe, spillergruppe, True, True, pygame.sprite.collide_mask)
if ghosttruffet:
spiller.kill()
#Gruppene oppdateres
ghostgruppe.update()
tilegruppe.update()
utganggruppe.update()
spillergruppe.update()
moving_sprites.draw(screen)
moving_sprites.update(0.25)
#gruppene vises på skjermen.
ghostgruppe.draw(screen)
tilegruppe.draw(screen)
utganggruppe.draw(screen)
spillergruppe.draw(screen)
if gameover:
screen.blit(gameovertekst,gameoverrect)
if levelferdig:
screen.blit(levelferdigtekst, levelferdigrect)
spillergruppe.draw(screen)
clock.tick(60)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.K_n:
levelnr = O
restart()
for bullet in spiller.bullets:
bullet.draw_bullet()
pygame.time.delay(30)
pygame.display.flip()
pygame.quit()

You have to draw the bullets after drawing the background. Use a loop to iterate through the list of bullets and call the draw_bullet method for each bullet:
while running:
# pygame.display.bullet() <--- DELETE
spiller.farty = 0
spiller.fartx = 0
trykketliste = pygame.key.get_pressed()
spiller.skytt()
background_image_1 = pygame.image.load("beach.png").convert()
screen.blit(background_image_1, [0,0])
# INSERT
for bullet in spiller.bullets:
bullet.draw_bullet()
# [...]
pygame.display.update()
# [...]
screen.blit(background_image_1, [0,0]) draws the background and hides anything previously drawn. pygame.display.update() updates the display and makes everything that is drawn visible. Therefor you need to draw all the objects of the scene after screen.blit(background_image_1, [0,0]) and before pygame.display.update().

Related

I am having trouble with my stat function in my player class

When I shoot at my cement block sprites I have it set so that self.score is self.score += 1 in my player collision function, but when I shoot my cement blocks and destroy them, either 1 or 2 points is added at random to my score. Why? How can I fix this? A clear example is, I shoot at and destroy 2 cement blocks in a row and 1 point is added for each one destroyed which means my score is 2, which is what I want cause I want to add 1 point to my score whenever I destroy a cement block, but then when I shoot and destroy the third cement block, 2 points are added instead of 1 bringing my score to 4 instead of being a score of 3 points.
Github: https://github.com/Enoc-Mena99/AutoPilot
My code:
import random
import pygame
import pygame.freetype
pygame.init()
#screen settings
WIDTH = 1000
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("AutoPilot")
screen.fill((255, 255, 255))
#fps
FPS = 120
clock = pygame.time.Clock()
#load images
bg = pygame.image.load('background/street.png').convert_alpha() # background
bullets = pygame.image.load('car/bullet.png').convert_alpha()
debris_img = pygame.image.load('debris/cement.png')
#define game variables
shoot = False
#player class
class Player(pygame.sprite.Sprite):
def __init__(self, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.bullet = pygame.image.load('car/bullet.png').convert_alpha()
self.bullet_list = []
self.speed = speed
#self.x = x
#self.y = y
self.moving = True
self.frame = 0
self.flip = False
self.direction = 0
self.score = 0
#load car
self.images = []
img = pygame.image.load('car/car.png').convert_alpha()
img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
self.update_time = pygame.time.get_ticks()
self.movingLeft = False
self.movingRight = False
self.rect.x = 465
self.rect.y = 325
#draw car to screen
def draw(self):
screen.blit(self.image, (self.rect.centerx, self.rect.centery))
#move car
def move(self):
#reset the movement variables
dx = 0
dy = 0
#moving variables
if self.movingLeft and self.rect.x > 33:
dx -= self.speed
self.flip = True
self.direction = -1
if self.movingRight and self.rect.x < 900:
dx += self.speed
self.flip = False
self.direction = 1
#update rectangle position
self.rect.x += dx
self.rect.y += dy
#shoot
def shoot(self):
bullet = Bullet(self.rect.centerx + 18, self.rect.y + 30, self.direction)
bullet_group.add(bullet)
#check collision
def collision(self, debris_group):
for debris in debris_group:
if pygame.sprite.spritecollide(debris, bullet_group, True):
debris.health -= 1
if debris.health <= 0:
self.score += 1
#player stats
def stats(self):
myfont = pygame.font.SysFont('comicsans', 30)
scoretext = myfont.render("Score: " + str(self.score), 1, (0,0,0))
screen.blit(scoretext, (100,10))
#bullet class
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, direction):
pygame.sprite.Sprite.__init__(self)
self.speed = 5
self.image = bullets
self.rect = self.image.get_rect()
self.rect.center = (x,y)
self.direction = direction
def update(self):
self.rect.centery -= self.speed
#check if bullet has gone off screen
if self.rect.centery < 1:
self.kill()
#debris class
class Debris(pygame.sprite.Sprite):
def __init__(self,scale,speed):
pygame.sprite.Sprite.__init__(self)
self.scale = scale
self.x = random.randrange(100,800)
self.speed_y = 10
self.y = 15
self.speed = speed
self.vy = 0
self.on_ground = True
self.move = True
self.health = 4
self.max_health = self.health
self.alive = True
self.velocity = random.randrange(1,2)
self.speed_x = random.randrange(-3,3)
self.moving_down = True
self.is_destroyed = False
#load debris
self.image = debris_img
self.rect = self.image.get_rect()
self.rect.x = random.randrange(100, 800)
self.rect.y = random.randrange(-150, -100)
self.rect.center = (self.x,self.y)
#load explosion
self.img_explosion_00 = pygame.image.load('explosion/0.png').convert_alpha()
self.img_explosion_00 = pygame.transform.scale(self.img_explosion_00, (self.img_explosion_00.get_width() * 2,
self.img_explosion_00.get_height() * 2))
self.img_explosion_01 = pygame.image.load('explosion/1.png').convert_alpha()
self.img_explosion_01 = pygame.transform.scale(self.img_explosion_01, (self.img_explosion_01.get_width() * 2,
self.img_explosion_01.get_height() * 2))
self.img_explosion_02 = pygame.image.load('explosion/2.png').convert_alpha()
self.img_explosion_02 = pygame.transform.scale(self.img_explosion_02, (self.img_explosion_02.get_width() * 2,
self.img_explosion_02.get_height() * 2))
self.img_explosion_03 = pygame.image.load('explosion/3.png').convert_alpha()
self.img_explosion_03 = pygame.transform.scale(self.img_explosion_03, (self.img_explosion_03.get_width() * 2,
self.img_explosion_03.get_height() * 2))
#explosion list
self.anim_explosion = [self.img_explosion_00,
self.img_explosion_01,
self.img_explosion_02,
self.img_explosion_03]
self.anim_index = 0
self.frame_len = 10
#spawn new debris
def spawn_new_debris(self):
self.rect.x = random.randrange(100, 800)
self.rect.y = random.randrange(-150, -100)
self.velocity = random.randrange(1, 2)
self.speed_x = random.randrange(-3, 3)
#respawn debris when they go of the screen
def boundaries(self):
if self.rect.left > WIDTH + 10 or self.rect.right < -10 or self.rect.top > HEIGHT + 10:
self.spawn_new_debris()
#update image
def update(self):
self.rect.y += self.velocity
self.rect.x += self.speed_x
self.boundaries()
if self.health <= 0:
max_index = len(self.anim_explosion) - 1
if self.anim_index > max_index:
self.kill()
else:
if self.frame_len == 0:
self.image = self.anim_explosion[self.anim_index]
self.anim_index += 1
self.frame_len = 10
else:
self.frame_len -= 1
#make debris fall down
def falldown(self):
self.rect.centery += self.velocity
if self.moving_down and self.rect.y > 350:
self.kill()
######################CAR/DEBRIS##########################
player = Player(1,5)
##########################################################
#groups
bullet_group = pygame.sprite.Group()
debris_group = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
for x in range(50):
d = Debris(1, 5)
debris_group.add(d)
all_sprites.add(d)
#game runs here
run = True
while run:
#draw street
screen.blit(bg, [0, 0])
#update groups
bullet_group.update()
bullet_group.draw(screen)
debris_group.update()
debris_group.draw(screen)
#draw car
player.draw()
player.move()
player.collision(debris_group)
player.stats()
#update all sprites
all_sprites.update()
all_sprites.draw(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#check if key is down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if event.key == pygame.K_a:
player.movingLeft = True
if event.key == pygame.K_d:
player.movingRight = True
if event.key == pygame.K_SPACE:
player.shoot()
shoot = True
#check if key is up
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movingLeft = False
if event.key == pygame.K_d:
player.movingRight = False
#update the display
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
Do not count debris objects with healt <= 0:
class Player(pygame.sprite.Sprite):
# [...]
def collision(self, debris_group):
for debris in debris_group:
# if health > 0 and collision:
if debris.health > 0 and pygame.sprite.spritecollide(debris, bullet_group, True):
debris.health -= 1
if debris.health <= 0:
self.score += 1

Enemy collision with pygame.sprite.spritecollide()

In my game, there is a sprite player which I can control. It can move right or left, it can jump, shoot fireballs(bullets) and a breathe fire. I have added an enemy which can move on itself from right to left on a limited distance that I set. What I would like to do now is make my player loose health if it collides with the enemy sprite using pygame.sprite.spritecollide(). However it isn't working out well I don't know how to fix my issue which is the following: if I run my code below it says NameError: name 'enemy_list' is not defined. The errored line is in Sprite1.py in the Player class under the update function. How do I fix my code? I created my Enemy class and Level class with the following website: https://opensource.com/article/18/5/pygame-enemy. I'm open to all suggestions. Thanks beforehand! I separated my code into three files: main.py, settings.py and Sprite1.py. Here's main.py:
import pygame
import os
import sys
import time
from pygame import mixer
from Sprite1 import *
from settings import *
'''
Setup
'''
pygame.init()
clock = pygame.time.Clock()
pygame.mixer.music.load('.\\sounds\\Fairy.mp3')
pygame.mixer.music.play(-1, 0.0)
all_sprites = pygame.sprite.Group()
player = Player(all_sprites)
player.rect.x = 500
player.rect.y = 500
eloc = []
eloc = [400,500]
enemy_list = Level.bad( 1, eloc )
showStartScreen(surface)
x = 0
'''
Main loop
'''
main = True
while main == True:
background = pygame.image.load(os.path.join('images', 'Bg.png')).convert()
surface.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
main = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.control(-steps,0)
if event.key == pygame.K_RIGHT:
player.control(steps,0)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.control(steps,0)
if event.key == pygame.K_RIGHT:
player.control(-steps,0)
keys = pygame.key.get_pressed()
if not(isJump):
if keys[pygame.K_UP]:
isJump = True
else:
if jumpCount >= -10:
player.rect.y -= (jumpCount * abs(jumpCount)) * 1
jumpCount -= 2
else:
jumpCount = 10
isJump = False
# dt = time since last tick in milliseconds.
dt = clock.tick(60) / 1000
all_sprites.update(dt)
player.update(dt)
all_sprites.draw(surface) #refresh player position
enemy_list.draw(surface)
for e in enemy_list:
e.move()
pygame.display.flip()
Here's my settings.py:
import pygame
isJump = False
jumpCount = 10
width = 960
height = 720
fps = 40 # frame rate
pygame.display.set_caption('B.S.G.')
surface = pygame.display.set_mode((width, height))
PLAYER_ACC = 0.5
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.8
PLAYER_JUMP = 20
PLAYER_LAYER = 2
PLATFORM_LAYER = 1
RED = (255, 0, 0)
steps = 10 # how fast to move
And here's my Sprite1.py:
import pygame
import sys
import os
import time
from pygame import mixer
from pygame.locals import *
from settings import *
vec = pygame.math.Vector2
def showStartScreen(surface):
show = True
while (show == True):
background = pygame.image.load(os.path.join('images', 'Starting_scr.png'))
# rect = surface.get_rect()
surface.blit(background, (0,0))
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
show = False
class Player(pygame.sprite.Sprite):
def __init__(self, all_sprites):
pygame.sprite.Sprite.__init__(self)
self.movex = 0
self.movey = 0
self.frame = 0
self.health = 10
self.jumping = False
self.images = []
self.imagesleft = []
self.imagesright = []
self.direction = "right"
self.alpha = (0,0,0)
self.ani = 4 # animation cycles
self.all_sprites = all_sprites
self.add(self.all_sprites)
self.fire_timer = .1
self.bullet_timer = .1
self.pos = vec(40, height - 100)
self.vel = vec(0, 0)
for i in range(1,5):
img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
img.convert_alpha()
img.set_colorkey(self.alpha)
self.imagesright.append(img)
self.image = self.imagesright[0]
self.rect = self.image.get_rect()
for i in range(1,5):
img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
img = pygame.transform.flip(img, True, False)
img.convert_alpha()
img.set_colorkey(self.alpha)
self.imagesleft.append(img)
self.image = self.imagesleft[0]
self.rect = self.image.get_rect()
def control(self,x,y):
'''
control player movement
'''
self.movex += x
self.movey -= y
def update(self, dt):
'''
Update sprite position
'''
self.rect.x = self.rect.x + self.movex
self.rect.y = self.rect.y + self.movey
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
for enemy in ennemy_hit_list:
self.health -= 1
print(self.health)
# moving left
if self.movex < 0:
self.frame += 1
if self.frame > 3*self.ani:
self.frame = 0
self.image = self.imagesleft[self.frame//self.ani]
self.direction = "left"
# moving right
if self.movex > 0:
self.frame += 1
if self.frame > 3*self.ani:
self.frame = 0
self.image = self.imagesright[self.frame//self.ani]
self.direction = "right"
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
self.bullet_timer -= dt # Subtract the time since the last tick.
if keys[pygame.K_x]:
self.fire_timer -= dt
if self.bullet_timer <= 0:
self.bullet_timer = 100 # Bullet ready.
if keys: # Left mouse button.
# Create a new bullet instance and add it to the groups.
if self.direction == "right":
Bullet([self.rect.x + self.image.get_width(), self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
else:
Bullet([self.rect.x, self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
self.bullet_timer = .5 # Reset the timer.
if self.fire_timer <= 0:
self.fire_timer = 100
if keys:
if self.direction == "right":
Fire([self.rect.x + 170, self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
else:
Fire([self.rect.x - 90, self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
self.fire_timer = .1
if self.health == 0:
self.kill()
class Enemy(pygame.sprite.Sprite):
'''
Spawn an enemy
'''
def __init__(self,x,y,img):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join('images',img))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.counter = 0 # counter variable
def move(self):
'''
enemy movement
'''
distance = 20
speed = 15
if self.counter >= 0 and self.counter <= distance:
self.rect.x += speed
elif self.counter >= distance and self.counter <= distance*2:
self.rect.x -= speed
else:
self.counter = 0
self.counter += 1
class Bullet(pygame.sprite.Sprite):
IMAGE = None
FLIPPED_IMAGE = None
def __init__(self, pos, direction, *sprite_groups):
super().__init__(*sprite_groups)
# cache images
if not Bullet.IMAGE:
Bullet.IMAGE = pygame.image.load(os.path.join('images','fireball.png'))
Bullet.FLIPPED_IMAGE = pygame.transform.flip(Bullet.IMAGE, True, False)
if direction == "right":
self.vel = pygame.math.Vector2(750, 0)
self.image = Bullet.IMAGE
else:
self.vel = pygame.math.Vector2(-750, 0)
self.image = Bullet.FLIPPED_IMAGE
self.pos = pygame.math.Vector2(pos)
self.rect = self.image.get_rect(center=pos)
def update(self, dt):
# Add the velocity to the position vector to move the sprite
self.pos += self.vel * dt
self.rect.center = self.pos # Update the rect pos.
if not pygame.display.get_surface().get_rect().colliderect(self.rect):
self.kill()
class Fire(pygame.sprite.Sprite):
IMAGE = None
FLIPPED_IMAGE = None
def __init__(self, pos, direction, *sprite_groups):
super().__init__(*sprite_groups)
# cache images
if not Fire.IMAGE:
Fire.IMAGE = pygame.image.load(os.path.join('images','fire_drag.png'))
Fire.FLIPPED_IMAGE = pygame.transform.flip(Fire.IMAGE, True, False)
if direction == "right":
self.image = Fire.IMAGE
self.vel = pygame.math.Vector2(0, 0)
else:
self.image = Fire.FLIPPED_IMAGE
self.vel = pygame.math.Vector2(0, 0)
self.pos = pygame.math.Vector2(pos)
self.rect = self.image.get_rect(center=pos)
def update(self, dt):
self.too = True
self.pos += self.vel * dt
self.rect.center = self.pos # Update the rect pos.
if self.too == True:
self.kill()
class Level():
def bad(lvl,eloc):
if lvl == 1:
enemy = Enemy(eloc[0],eloc[1],'cookie1.png') # spawn enemy
enemy_list = pygame.sprite.Group() # create enemy group
enemy_list.add(enemy) # add enemy to group
if lvl == 2:
print("Level " + str(lvl) )
return enemy_list
def loot(lvl,lloc):
print(lvl)
enemy_list is defined in global namespace, in main.py, thus it is not accessible in the module Sprite.py.
Add an additional argument to the update method of the class Player:
class Player(pygame.sprite.Sprite):
# [...]
def update(self, dt, enemy_list):
# [...]
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
# [...]
Since player is a member of all_sprites, you have to add the argument to the update methods of the other sprites (Enemy, Bullet), too.
Pass enemy_list to the update method all_sprites in the main application loop. Note the update method of Player is invoked by all_sprites.update, thus player.update(dt, enemy_list) is superflous:
while main == True:
# [...]
all_sprites.update(dt, enemy_list)
# [...]

Check for collision and stop velocity in pygame

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()

Collision detection not working in pygame

I am making a game at the moment and I am experiencing problems with collision detection. I am making an end of level block but it can not detect if the player is standing on it to change to level 2. The collision detection for the block is found in player.updater(). As well as this the block is a class and in a group called endPlatform to allow the collision detection to work. The game runs perfectly fine however it can not detect when the Player hits Endplatform. I get no errors which show up.
EndPlatform:
class EndPlatform(pygame.sprite.Sprite):
def __init__(self, display):
super().__init__()
self.image = pygame.image.load("endPlatform.png")
self.rect = self.image.get_rect()
display.blit(self.image, self.rect)
Player:
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# Is it touching the floor?
self.standing = True
# Rendering image and creating some variables
self.image = pygame.image.load("Slime.png")
self.sprite_x_change = 0
self.sprite_y_change = 0
self.rect = self.image.get_rect()
self.rect.y = 460
self.rect.x = 120
# Mobility: Left, right, up and stop
def move_right(self):
self.sprite_x_change = 8
def move_left(self):
self.sprite_x_change = -8
def move_up(self, platform):
if self.standing == True:
self.sprite_y_change = -25
self.standing = False
def stop(self):
self.sprite_x_change = 0
def sprint(self):
self.sprite_x_change += 10
def updater(self, platforms, powerups, score, endPlatform):
self.gravity()
self.rect.x += self.sprite_x_change
self.standing = False
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
if self.sprite_x_change > 0:
self.rect.right = blocks.rect.left
elif self.sprite_x_change < 0:
self.rect.left = blocks.rect.right
self.rect.y += self.sprite_y_change
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
# Going down
if self.sprite_y_change > 0:
self.rect.bottom = blocks.rect.top - 1
self.standing = True
# Going up
elif self.sprite_y_change < 0:
self.rect.top = blocks.rect.bottom
self.standing = False
self.sprite_y_change = 0
coins_hit = pygame.sprite.spritecollide(self, powerups, True)
if len(coins_hit) > 0:
score.add()
endLevel = pygame.sprite.spritecollide(self, endPlatform, True)
if len(endLevel) > 0:
score.add()
All the code:
import pygame
import random
pygame.font.init()
# Colours + Global constants
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
RANDOM = (12, 211, 123)
WIDTH = 800
HEIGHT = 600
SIZE = (WIDTH, HEIGHT)
AGENT = pygame.font.SysFont("Agent Orange", 30)
# CLASSES
# Block is the common platform
class EndPlatform(pygame.sprite.Sprite):
def __init__(self, display):
super().__init__()
self.image = pygame.image.load("endPlatform.png")
self.rect = self.image.get_rect()
display.blit(self.image, self.rect)
class Coins(pygame.sprite.Sprite):
def __init__(self, display):
super().__init__()
self.image = pygame.image.load("hud_coins.png")
self.rect = self.image.get_rect()
display.blit(self.image, self.rect)
class Score:
def __init__(self):
self.score = 0
def msgs(self, msg, colour, display):
screen_text = AGENT.render(msg, True, colour)
display.blit(screen_text, [0, 0])
def add(self):
self.score += 1
class Monster(pygame.sprite.Sprite):
def __init__(self, length, height, colour):
super().__init__()
self.image = pygame.Surface([length, height])
self.image.fill(colour)
self.rect = self.image.get_rect()
# Setting Y coordinates
self.rect.y = HEIGHT - 80
def jump(self):
self.rect.y = -10
class Block(pygame.sprite.Sprite):
def __init__(self, length, height, colour):
super().__init__()
# Making image
self.image = pygame.Surface([length, height])
self.image.fill(colour)
self.rect = self.image.get_rect()
# Setting Y coordinates
self.rect.y = 468
class Platform(pygame.sprite.Sprite):
def __init__(self, display, x_screen, y_screen, x_sheet, y_sheet, height, length):
super().__init__()
self.tiles = pygame.image.load("tiles_spritesheet.png")
self.image = self.tiles.subsurface(pygame.Rect(x_sheet, y_sheet, height, length))
self.rect = self.image.get_rect(x=x_screen, y=y_screen)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# Is it touching the floor?
self.standing = True
# Rendering image and creating some variables
self.image = pygame.image.load("Slime.png")
self.sprite_x_change = 0
self.sprite_y_change = 0
self.rect = self.image.get_rect()
self.rect.y = 460
self.rect.x = 120
# Mobility: Left, right, up and stop
def move_right(self):
self.sprite_x_change = 8
def move_left(self):
self.sprite_x_change = -8
def move_up(self, platform):
if self.standing == True:
self.sprite_y_change = -25
self.standing = False
def stop(self):
self.sprite_x_change = 0
def sprint(self):
self.sprite_x_change += 10
def updater(self, platforms, powerups, score, endPlatform):
self.gravity()
self.rect.x += self.sprite_x_change
self.standing = False
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
if self.sprite_x_change > 0:
self.rect.right = blocks.rect.left
elif self.sprite_x_change < 0:
self.rect.left = blocks.rect.right
self.rect.y += self.sprite_y_change
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
# Going down
if self.sprite_y_change > 0:
self.rect.bottom = blocks.rect.top - 1
self.standing = True
# Going up
elif self.sprite_y_change < 0:
self.rect.top = blocks.rect.bottom
self.standing = False
self.sprite_y_change = 0
coins_hit = pygame.sprite.spritecollide(self, powerups, True)
if len(coins_hit) > 0:
score.add()
endLevel = pygame.sprite.spritecollide(self, endPlatform, True)
if len(endLevel) > 0:
score.add()
def gravity(self):
self.sprite_y_change += 3
class Level:
def __init__(self):
# Creating groups
self.endPlatform = pygame.sprite.Group()
self.powerups = pygame.sprite.Group()
self.sprites = pygame.sprite.Group()
self.all_things = pygame.sprite.Group()
self.platforms = pygame.sprite.Group()
self.entities = pygame.sprite.Group()
self.shift_x = 0
self.shift_y = 0
def updater(self, display, score):
self.all_things.draw(display)
score.msgs("Score: " + str(score.score), RED, display)
def scroll_x(self, shift_x_change):
self.shift_x += shift_x_change
for platform in self.entities:
platform.rect.x += shift_x_change
def scroll_y(self, shift_y_change):
self.shift_y += shift_y_change
for platform in self.entities:
platform.rect.y += shift_y_change
class Level01(Level):
def __init__(self, player1, monster, display):
# Initialise level1
super().__init__()
# Level01 things
block = Block(245, 3, BLACK)
Level.all_things = self.all_things
self.sprites.add(player1, monster)
self.platforms.add(block)
self.all_things.add(player1, block, monster)
self.entities.add(block)
theLevel = []
level = [[600, 400, 648, 0, 70, 70],
[740, 320, 648, 0, 70, 70],
[380, 400, 648, 0, 70, 70],
[900, 280, 648, 0, 70, 70],
[1200, 530, 648, 0, 70, 70],
[1350, 450, 648, 0, 70, 70],
[1500, 550, 648, 0, 70, 70],
[1680, 500, 648, 0, 70, 70],
]
for platform in theLevel:
block = Block(platform[0], platform[1], RED)
block.rect.x = platform[2]
block.rect.y = platform[3]
self.platforms.add(block)
self.all_things.add(block)
self.entities.add(block)
for goodPlatform in level:
platform = Platform(display, goodPlatform[0], goodPlatform[1], goodPlatform[2], goodPlatform[3], goodPlatform[4], goodPlatform[5])
self.platforms.add(platform)
self.all_things.add(platform)
self.entities.add(platform)
for n in range(1):
coin = Coins(display)
coin.rect.x = random.randint(0, WIDTH*3)
coin.rect.y = 400
self.all_things.add(coin)
self.entities.add(coin)
self.powerups.add(coin)
platforms_hit = pygame.sprite.spritecollide(coin, self.entities, False)
for hit in platforms_hit:
coin.rect.x = random.randrange(0, WIDTH*3)
finalPlatform = EndPlatform(display)
finalPlatform.rect.x = 1900
finalPlatform.rect.y = 420
self.all_things.add(finalPlatform)
self.entities.add(finalPlatform)
self.platforms.add(finalPlatform)
self.endPlatform.add(finalPlatform)
class Level02(Level):
def __init__(self, player1, monster):
super().__init__()
# Level01 things
block = Block(245, 3, BLACK)
Level.all_things = self.all_things
self.sprites.add(player1, monster)
self.platforms.add(block)
self.all_things.add(player1, block, monster)
def main():
# Init pygame
pygame.init()
# Set screen
backgrounds = ["background2.jpg", "background.jpg"]
background = pygame.image.load(backgrounds[0])
backgroundRect = background.get_rect()
display = pygame.display.set_mode(background.get_size())
# Creating FPS thingy
clock = pygame.time.Clock()
# Making levels + Player
score = Score()
monster = Monster(30, 30, RANDOM)
player = Player()
level_1 = Level01(player, monster, display)
level_2 = Level02(player, monster)
# Choosing level
levelList = []
levelList.append(level_1)
levelList.append(level_2)
currentLevelNumber = 0
# Game loop
loop = True
while loop == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.move_right()
if event.key == pygame.K_LEFT:
player.move_left()
if event.key == pygame.K_UP:
player.move_up(currentLevel.platforms)
if event.key == pygame.KMOD_LSHIFT and event.key == pygame.K_RIGHT:
player.sprint()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and player.sprite_x_change < 0:
player.stop()
if event.key == pygame.K_RIGHT and player.sprite_x_change > 0:
player.stop()
if event.key == pygame.KMOD_LSHIFT:
player.sprite_x_change -= 10
# Update things
#monster.jump()
if player.rect.x > 400:
player.rect.x = 400
currentLevel.scroll_x(-10)
if player.rect.x >= WIDTH:
player.rect.x = WIDTH
currentLevel.scroll(0)
if player.rect.y >= HEIGHT:
main()
if player.sprite_x_change < 0 and player.rect.x >= 120:
currentLevel.scroll_x(0)
if player.rect.left <= 120 and player.sprite_x_change < 0:
player.rect.x = 120
player.rect.left = 120
currentLevel.scroll_x(10)
'''
if player.rect.y <= 300:
if player.standing == False and player.sprite_y_change < 0:
currentLevel.scroll_y(10)
if currentLevel.shift_y > 0:
y_speed = -4
if player.standing == True and player.rect.y < 300:
y_speed = 4
print(currentLevel.shift_y)
currentLevel.scroll_y(y_speed)
'''
currentLevel = levelList[currentLevelNumber]
if currentLevel.shift_x > 0:
currentLevel.scroll_x(currentLevel.shift_x * -1)
display.blit(background, backgroundRect)
player.updater(currentLevel.platforms, currentLevel.powerups, score, currentLevel.endPlatform)
currentLevel.updater(display, score)
# Refresh screen
clock.tick(30)
pygame.display.update()
pygame.quit()
loop = False
if __name__ == "__main__":
main()
It seems I found the problem, for some daft reason you can't use collision detection twice on the same object. I used it once so that the player could stand on the block and another time so that you could go on to the next level!
The reason why it doesn't switch to the next level is that you change the position of the rect when it collides with a platform, so the player.rect gets moved out of the blocks.rect and therefore can't collide again when you call spritecollide with the endPlatform group.
A quick and dirty fix would be to check in the for blocks in platforms_hit: loops if the block is in the endPlatform group and then return True:
for blocks in platforms_hit:
if blocks in endPlatform:
score.add()
return True
And then increase the currentLevelNumber in the main function if True is returned:
change_level = player.updater(currentLevel.platforms, currentLevel.powerups, score, currentLevel.endPlatform)
if change_level:
currentLevelNumber += 1

__init__() takes exactly 3 arguments (1 given)?

It is asking for 3 arguments and i have given it one. How do i give it 2 more and could you explain how to do that as well? Thanks
import pygame, random, collisionObjects
pygame.init()
screen = pygame.display.set_mode((640,480))
class Pirate(pygame.sprite.Sprite):
EAST = 0
def __init__(self, screen, dx):
self.screen = screen
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("king_pirate/running e0000.bmp")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-50, -30)
self.rect.center = (0, random.randrange(30,450))
self.img = []
self.loadPics()
self.frame = 0
self.delay = 4
self.pause = self.delay
self.dx = dx
def update(self):
#set delay
self.pause -= 1
if self.pause <= 0:
self.pause = self.delay
self.frame += 1
if self.frame > 7:
self.frame = 0
self.image = self.img[self.frame]
self.rect.centerx += self.dx
if self.rect.centerx > self.screen.get_width():
self.rect.centerx = 0
self.rect.centery = random.randrange(30,450)
#load pictures
def loadPics(self):
for i in range(8):
imgName = "king_pirate/running e000%d.bmp" % i
tmpImg = pygame.image.load(imgName)
tmpImg.convert()
tranColor = tmpImg.get_at((0, 0))
tmpImg.set_colorkey(tranColor)
self.img.append(tmpImg)
class Pirate2(pygame.sprite.Sprite):
WEST = 0
def __init__(self, screen, dx):
self.screen = screen
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("pirate/running w0000.bmp")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-50, -30)
self.rect.center = (640, random.randrange(20,460))
self.img = []
self.loadPics()
self.frame = 0
self.delay = 4
self.pause = self.delay
self.dx = dx
def update(self):
#set delay
self.pause -= 1
if self.pause <= 0:
self.pause = self.delay
self.frame += 1
if self.frame > 7:
self.frame = 0
self.image = self.img[self.frame]
self.rect.centerx -= self.dx
if self.rect.centerx < 0:
self.rect.centerx = self.screen.get_width()
self.rect.centery = random.randrange(20,460)
#load pictures
def loadPics(self):
for i in range(8):
imgName = "pirate/running w000%d.bmp" % i
tmpImg = pygame.image.load(imgName)
tmpImg.convert()
tranColor = tmpImg.get_at((0, 0))
tmpImg.set_colorkey(tranColor)
self.img.append(tmpImg)
#set up class for gold object,
class Gold(pygame.sprite.Sprite):
def __init__(self, screen, imageFile):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imageFile)
self.image = self.image.convert()
self.rect = self.image.get_rect()
self.rect.centerx = random.randrange(0, screen.get_width())
self.rect.centery = random.randrange(0, screen.get_height())
#main character class
class Thief(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("thief2.gif")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-15, -10)
self.rect.center = (30, (screen.get_height()-40))
self.dx = 30
self.dy = 30
if not pygame.mixer:
print("problem with sound")
else:
pygame.mixer.init()
self.collectcoin = pygame.mixer.Sound("collectcoin.wav")
self.hit = pygame.mixer.Sound("hit.ogg")
def update(self):
if self.rect.bottom > screen.get_height():
self.rect.centery = (screen.get_height()-40)
elif self.rect.top < 0:
self.rect.centery = 40
elif self.rect.right > screen.get_width():
self.rect.centerx = (screen.get_width()-30)
elif self.rect.left < 0:
self.rect.centerx = 30
#define movements
def moveUp(self):
self.rect.centery -= self.dy
def moveDown(self):
self.rect.centery += self.dy
def moveLeft(self):
self.rect.centerx -= self.dx
def moveRight(self):
self.rect.centerx += self.dx
def reset(self):
self.rect.center = (30, (screen.get_height()-40))
#set up a scoreboard
class Scoreboard(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.lives = 0
self.score = 0
self.font = pygame.font.SysFont("None", 40)
self.number = 0
#with a self updating label
def update(self):
self.text = "Damage: %d %% Gold Taken: %d" % (self.lives, self.score)
self.image = self.font.render(self.text, 1, (199,237,241))
self.rect = self.image.get_rect()
#define the game function
def game():
#set up background
background = pygame.Surface(screen.get_size())
background = pygame.image.load("sand.jpg")
background = pygame.transform.scale(background, screen.get_size())
screen.blit(background, (0, 0))
#initialize pirates & scoreboard sprites
pirate = Pirate()
scoreboard = Scoreboard()
#create two arrays for multiple gold object occurances
#two arrays are used for better distribution on screen
gold1 = []
numberofGold = 16
for i in range(numberofgolds):
oneGold = golds(screen,"gold1.png")
golds1.append(onegold)
for gold in golds1:
gold.rect.centerx = random.randrange(20,620)
gold.rect.centery = random.randrange(20,240)
gold.rect.inflate_ip(-5, -5)
gold2 = []
for i in range(numberofgolds):
onegold = golds(screen,"gold1.png")
golds2.append(onegold)
for gold in golds2:
gold.rect.centerx = random.randrange(20,620)
gold.rect.centery = random.randrange(250,460)
gold.rect.inflate_ip(-5, -5)
totalgolds = ((len(golds1)-1)+(len(golds2)-1))
#initialize gold sprites
goldSprites = pygame.sprite.Group(golds1,
#initialize pirate sprites & instances
pirate1 = pirate1(screen,13)
pirate2 = pirate2(screen,13)
pirate3 = pirate1(screen,11)
pirate4 = pirate2(screen,11)
pirate5 = pirate1(screen,13)
pirateSprites = pygame.sprite.Group(pirate1, pirate2, pirate3, pirate4, pirate5)
#use ordered updates to keep clean appearance
allSprites = pygame.sprite.OrderedUpdates(goldSprites, thief, pirateSprites, scoreboard)
#set up clock & loop
clock = pygame.time.Clock()
keepGoing = True
while keepGoing:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
thief.moveUp()
elif event.key == pygame.K_DOWN:
thief.moveDown()
elif event.key == pygame.K_LEFT:
thief.moveLeft()
elif event.key == pygame.K_RIGHT:
thief.moveRight()
elif event.key == pygame.K_ESCAPE:
keepGoing = False
#check collisions here
hitpirates = pygame.sprite.spritecollide(thief, pirateSprites, False)
hitgold = pygame.sprite.spritecollide(thief, goldSprites, True)
if hitpirates:
thief.hit.play()
scoreboard.lives += 1
if scoreboard.lives >= 100:
keepGoing = False
number = 0
if hitgolds:
thief.collectcoin.play()
scoreboard.score += 1
totalgolds -= 1
if totalgolds <= 0:
keepGoing = False
number = 1
#draw sprites
allSprites.clear(screen, background)
allSprites.update()
allSprites.draw(screen)
pygame.display.flip()
return scoreboard.score
return scoreboard.number
def instructions(score, number):
pygame.display.set_caption("Hunt for Gold!")
background = pygame.Surface(screen.get_size())
background = pygame.image.load("sand.jpg")
background = pygame.transform.scale(background, screen.get_size())
screen.blit(background, (0, 0))
if number == 0:
message = "Sorry try again..."
elif number == 1:
message = "The theif escapes!"
else:
message = "Onto the hunt for gold!"
insFont = pygame.font.SysFont("Calibri", 25)
insLabels = []
instructions = (
"Last score: %d" % score ,
"%s" % message,
"",
"GOLD!",
"Get all the gold before you are "
"obliterated!",
"Use arrow keys to move the thief.",
"Space to start, Esc to quit."
)
for line in instructions:
tempLabel = insFont.render(line, 1 , (0,0,0))
insLabels.append(tempLabel)
#set up homescreen loop
keepGoing = True
clock = pygame.time.Clock()
while keepGoing:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
donePlaying = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
keepGoing = False
donePlaying = False
if event.key == pygame.K_ESCAPE:
keepGoing = False
donePlaying = True
for i in range(len(insLabels)):
screen.blit(insLabels[i], (50, 30*i))
pygame.display.flip()
return donePlaying
#define main function
def main():
donePlaying = False
score = 0
message = ""
while not donePlaying:
donePlaying = instructions(score, message)
if not donePlaying:
score = game()
else:
pygame.quit()
if __name__ == "__main__":
main()
Glancing at your code, this line:
pirate = Pirate()
Your Pirate class expects self, screen, dx. You only implicitly provide self.
I can only guess at what you want, especially since I don't know off the bat what dx is supposed to mean in respect to your game, but this will probably at least avoid the error:
pirate = Pirate(pygame.display.get_surface(), 60)

Categories