I am having trouble with my stat function in my player class - python
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
Related
i have a problem: my enemies are stacked vertically, on top of my player which is weird, and they don't move to their predefined positions [duplicate]
This question already exists: in my shooting game, my players are positioned on top of my head (player) which is very abnormal and also once the game starts, they start shooting [closed] Closed 6 months ago. i have earlier tried to format my question properly but i hope this one is better. am creating a shooter game from https://github.com/russs123/Shooter. however my problem is that my enemies are stacked vertically upwards in a straight line when i run my game and the enemies don't start off at their predefined location. below is the full code i wrote. perhaps if you can run it, it will be better understood. import pygame, sys from player import Player import os import random import csv pygame.init() screen_width = 600 scroll_thresh = 200 screen_scroll = 0 bg_scroll = 0 screen_height = int(screen_width * 0.8) screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("Shooter Game") clock = pygame.time.Clock() fps = 60 # define game variables GRAVITY = 0.75 level = 1 ROWS = 16 COLS = 150 TILE_SIZE = screen_height // ROWS TILE_TYPES = 21 img_list = [] for x in range(TILE_TYPES): img = pygame.image.load(f"img/tile/{x}.png") img = pygame.transform.scale(img, (TILE_SIZE, TILE_SIZE)) img_list.append(img) # color variables bg = (144, 201, 120) RED = (255, 0, 0) WHITE = (255, 255, 255) GREEN = (0, 255, 0) BLACK = (0, 0, 0) # define player action variables moving_left = False moving_right = False shoot = False grenade = False grenade_thrown = False # load up images pine1_img = pygame.image.load("img/Background/pine1.png").convert_alpha() pine2_img = pygame.image.load("img/Background/pine2.png").convert_alpha() mountain_img = pygame.image.load("img/Background/mountain.png").convert_alpha() sky_cloud_img = pygame.image.load("img/Background/sky_cloud.png").convert_alpha() bullet_img = pygame.image.load("img/icons/bullet.png").convert_alpha() grenade_img = pygame.image.load("img/icons/grenade.png").convert_alpha() # pick up boxes health_box_img = pygame.image.load("img/icons/health_box.png").convert_alpha() ammo_box_img = pygame.image.load("img/icons/ammo_box.png").convert_alpha() grenade_box_img = pygame.image.load("img/icons/grenade_box.png").convert_alpha() # name_dt = type(name) item_boxes = { "Health": health_box_img, "Ammo": ammo_box_img, "Grenade": grenade_img, } # define fonts font = pygame.font.SysFont("Futura", 30) def draw_text(text, font, text_col, x, y): img = font.render(text, True, text_col) screen.blit(img, (x, y)) def draw_bg(): screen.fill(bg) screen.blit(sky_cloud_img, (0, 0)) screen.blit(mountain_img, (0, screen_height - mountain_img.get_height() - 300)) screen.blit(pine1_img, (0, screen_height - pine1_img.get_height() - 150)) screen.blit(pine2_img, (0, screen_height - pine2_img.get_height())) class Soldier(pygame.sprite.Sprite): def __init__(self, char_type, x, y, scale, speed, ammo, grenades): pygame.sprite.Sprite.__init__(self) self.alive = True self.char_type = char_type self.speed = speed self.ammo = ammo self.start_ammo = ammo self.shoot_cooldown = 0 self.grenades = grenades self.health = 100 self.max_health = self.health self.direction = 1 self.vel_y = 0 self.jump = False self.in_air = True self.flip = False self.animation_list = [] self.frame_index = 0 self.action = 0 # ai specific variables self.move_counter = 0 self.vision = pygame.Rect(0, 0, 150, 20) self.idling = 0 self.idling_counter = 0 self.update_time = pygame.time.get_ticks() # load all images for the players animation_types = ["idle", "run", "jump", "death"] for animation in animation_types: temp_list = [] # reset temporary list of images # count number of files in the folder num_of_frames = len(os.listdir(f"img/{self.char_type}/{animation}")) for i in range(num_of_frames): img = pygame.image.load(f"img/{self.char_type}/{animation}/{i}.png").convert_alpha() img = pygame.transform.scale(img, (int(img.get_width() * scale), int(img.get_height() * scale))) temp_list.append(img) self.animation_list.append(temp_list) self.image = self.animation_list[self.action][self.frame_index] self.rect = self.image.get_rect() self.rect.center = (x, y) self.width = self.image.get_width() self.height = self.image.get_height() def update(self): self.update_animation() self.check_alive() # update cooldown if self.shoot_cooldown > 0: self.shoot_cooldown -= 1 def move(self, moving_left, moving_right): screen_scroll = 0 dx = 0 dy = 0 if moving_left: dx = -self.speed self.flip = True self.direction = -1 if moving_right: dx = self.speed self.flip = False self.direction = 1 if self.jump == True and self.in_air == False: self.vel_y = -11 self.jump = False self.in_air = True # apply gravity self.vel_y += GRAVITY if self.vel_y > 10: self.vel_y dy += self.vel_y # check for collision for tile in world.obstacle_list: # check collision in the x direction if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): dx = 0 # check for collision in the y direction if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): # check if below the ground, i.e jumping if self.vel_y < 0: self.vel_y = 0 dy = tile[1].bottom - self.rect.top # check if above the ground, ie falling elif self.vel_y >= 0: self.vel_y = 0 self.in_air = False dy = tile[1].top - self.rect.bottom self.rect.x += dx self.rect.y += dy # update scroll based on player position if self.char_type == "player": if self.rect.right > screen_width - scroll_thresh or self.rect.left < scroll_thresh: self.rect.x = -dx screen_scroll = -dx return screen_scroll def shoot(self): if self.shoot_cooldown == 0 and self.ammo > 0: self.shoot_cooldown = 20 bullet = Bullet(self.rect.centerx + (0.75 * self.rect.size[0] * self.direction), self.rect.centery, self.direction) bullet_group.add(bullet) # reduce ammo after each shot self.ammo -= 1 def ai(self): if self.alive and player.alive: if self.idling == False and random.randint(1, 200) == 1: self.update_action(0) self.idling = True self.idling_counter = 50 # check if ai is near the player if self.vision.colliderect(player.rect): # stop running and face the player self.update_action(0) self.shoot() else: if self.idling == False: if self.direction == 1: ai_moving_right = True else: ai_moving_right = False ai_moving_left = not ai_moving_right self.move(ai_moving_left, ai_moving_right) self.update_action(1) self.move_counter += 1 # update ai vision as the enemy moves self.vision.center = (self.rect.centerx + 75 * self.direction, self.rect.centery) if self.move_counter > TILE_SIZE: self.direction *= -1 self.move_counter *= -1 else: self.idling_counter -= 1 if self.idling_counter <= 0: self.idling = False # scroll self.rect.x = screen_scroll def update_animation(self): ANIMATION_COOLDOWN = 100 # update image depending on current index self.image = self.animation_list[self.action][self.frame_index] # check if enough time has passed since the last update if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN: self.update_time = pygame.time.get_ticks() self.frame_index += 1 # if animation has run out then restart to the first if self.frame_index >= len(self.animation_list[self.action]): if self.action == 3: self.frame_index = len(self.animation_list[self.action]) - 1 else: self.frame_index = 0 def check_alive(self): if self.health <= 0: self.health = 0 self.speed = 0 self.alive = False self.update_action(3) def update_action(self, new_action): # check if new action is different from the previous one if new_action != self.action: self.action = new_action # update animation settings self.frame_index = 0 self.update_time = pygame.time.get_ticks() def draw(self): screen.blit(pygame.transform.flip(self.image, self.flip, False), self.rect) class HealthBar(): def __init__(self, health, x, y, max_health): self.x = x self.y = y self.health = health self.max_health = max_health def draw(self, health): self.health = health pygame.draw.rect(screen, BLACK, (self.x - 2, self.y - 2, 154, 24)) pygame.draw.rect(screen, RED, (self.x, self.y, 150, 20)) ratio = self.health / self.max_health pygame.draw.rect(screen, GREEN, (self.x, self.y, 150 * ratio, 20)) class World(): def __init__(self): self.obstacle_list = [] def process_data(self, data): for y, row in enumerate(data): for x, tile in enumerate(row): if tile >= 0: img = img_list[tile] img_rect = img.get_rect() img_rect.x = x * TILE_SIZE img_rect.y = y * TILE_SIZE tile_data = (img, img_rect) if 0 <= tile <= 8: self.obstacle_list.append(tile_data) elif 9 <= tile <= 10: # water water = Water(img, x * TILE_SIZE, y * TILE_SIZE, ) water_group.add(water) pass elif 11 <= tile <= 14: # decoration decoration = Decoration(img, x * TILE_SIZE, y * TILE_SIZE) decoration_group.add(decoration) elif tile == 15: # create a player player = Soldier("player", x * TILE_SIZE, y * TILE_SIZE, 1.65, 5, 20, 5) health_bar = HealthBar(10, 10, player.health, player.health) elif tile == 16: # create enemy enemy = Soldier("enemy", x * TILE_SIZE, y * TILE_SIZE, 1.65, 2, 20, 0) enemy_group.add(enemy) elif tile == 17: # create ammo box item_box = ItemBox("Ammo", x * TILE_SIZE, y * TILE_SIZE) item_box_group.add(item_box) elif tile == 18: # create grenade box item_box = ItemBox("Grenade", x * TILE_SIZE, y * TILE_SIZE) item_box_group.add(item_box) elif tile == 19: # create health box item_box = ItemBox("Health", x * TILE_SIZE, y * TILE_SIZE) item_box_group.add(item_box) elif tile == 20: # create exit point exit = Exit(img, x * TILE_SIZE, y * TILE_SIZE, ) exit_group.add(exit) return player, health_bar def draw(self): for tile in self.obstacle_list: tile[1][0] += screen_scroll screen.blit(tile[0], tile[1]) class Decoration(pygame.sprite.Sprite): def __init__(self, img, x, y): pygame.sprite.Sprite.__init__(self) self.image = img self.rect = self.image.get_rect() self.rect.midtop = (x + TILE_SIZE // 2, y + (TILE_SIZE - self.image.get_height())) def update(self): self.rect.x += screen_scroll class Water(pygame.sprite.Sprite): def __init__(self, img, x, y): pygame.sprite.Sprite.__init__(self) self.image = img self.rect = self.image.get_rect() self.rect.midtop = (x + TILE_SIZE // 2, y + (TILE_SIZE - self.image.get_height())) def update(self): self.rect.x += screen_scroll class Exit(pygame.sprite.Sprite): def __init__(self, img, x, y): pygame.sprite.Sprite.__init__(self) self.image = img self.rect = self.image.get_rect() self.rect.midtop = (x + TILE_SIZE // 2, y + (TILE_SIZE - self.image.get_height())) class ItemBox(pygame.sprite.Sprite): def __init__(self, item_type, x, y): pygame.sprite.Sprite.__init__(self) self.item_type = item_type self.image = item_boxes[self.item_type] self.rect = self.image.get_rect() self.rect.midtop = (x + TILE_SIZE // 2, y + (TILE_SIZE - self.image.get_height())) def update(self): # scroll self.rect.x += screen_scroll # check if player has picked up the box if pygame.sprite.collide_rect(self, player): # check what kind of box it was if self.item_type == "Health": player.health += 25 if player.health > player.max_health: player.health = player.max_health elif self.item_type == "Ammo": player.ammo += 15 elif self.item_type == "Grenade": player.grenades += 3 # delete the item box self.kill() class Bullet(pygame.sprite.Sprite): def __init__(self, x, y, direction): pygame.sprite.Sprite.__init__(self) self.speed = 10 self.image = bullet_img self.rect = self.image.get_rect() self.rect.center = (x, y) self.direction = direction def update(self): self.rect.x += self.direction * self.speed # check if bullet has left the screen if self.rect.right < 0 and self.rect.left > screen_width: self.kill() # check for collision with level for tile in world.obstacle_list: if tile[1].colliderect(self.rect): self.kill() # check collision with characters if pygame.sprite.spritecollide(player, bullet_group, False): if player.alive: player.health -= 5 self.kill() for enemy in enemy_group: if pygame.sprite.spritecollide(enemy, bullet_group, False): if enemy.alive: enemy.health -= 25 self.kill() class Grenade(pygame.sprite.Sprite): def __init__(self, x, y, direction): pygame.sprite.Sprite.__init__(self) self.timer = 100 self.vel_y = -11 self.speed = 7 self.image = grenade_img self.rect = self.image.get_rect() self.rect.center = (x, y) self.direction = direction self.width = self.image.get_width() self.height = self.image.get_height() def update(self): self.vel_y += GRAVITY dx = self.direction * self.speed dy = self.vel_y # check for collision with level for tile in world.obstacle_list: # check if grenade has hit a wall if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): self.direction *= -1 dx = self.direction * self.speed if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): self.speed = 0 # check if below the ground, i.e thrown if self.vel_y < 0: self.y = 0 dy = tile[1].bottom - self.rect.top # check if above the ground, ie falling elif self.vel_y >= 0: self.vel_y = 0 dy = tile[1].top - self.rect.bottom # update grenade position self.rect.x += dx self.rect.y += dy # explosion countdown self.timer -= 1 if self.timer <= 0: self.kill() explosion = Explosion(self.rect.x, self.rect.y, 0.5) explosion_group.add(explosion) # do damage to anyone nearby if abs(self.rect.centerx - player.rect.centerx) < TILE_SIZE * 2 and \ abs(self.rect.centery - player.rect.centery) < TILE_SIZE * 2: player.health -= 50 for enemy in enemy_group: if abs(self.rect.centerx - enemy.rect.centerx) < TILE_SIZE * 2 and \ abs(self.rect.centery - enemy.rect.centery) < TILE_SIZE * 2: enemy.health -= 50 class Explosion(pygame.sprite.Sprite): def __init__(self, x, y, scale): pygame.sprite.Sprite.__init__(self) self.images = [] for num in range(1, 6): img = pygame.image.load(f"img/explosion/exp{num}.png").convert_alpha() img = pygame.transform.scale(img, (int(img.get_width() * scale), (int(img.get_height() * scale)))) self.images.append(img) self.frame_index = 0 self.image = self.images[self.frame_index] self.rect = self.image.get_rect() self.rect.center = (x, y) self.counter = 0 def update(self): EXPLOSION_SPEED = 4 # update explosion animation self.counter += 1 if self.counter >= EXPLOSION_SPEED: self.counter = 0 self.frame_index += 1 # if animation is complete, then delete the explosion if self.frame_index >= len(self.images): self.kill() else: self.image = self.images[self.frame_index] # create sprite groups enemy_group = pygame.sprite.Group() bullet_group = pygame.sprite.Group() grenade_group = pygame.sprite.Group() explosion_group = pygame.sprite.Group() item_box_group = pygame.sprite.Group() decoration_group = pygame.sprite.Group() water_group = pygame.sprite.Group() exit_group = pygame.sprite.Group() # create empty tile list world_data = [] for row in range(ROWS): r = [-1] * COLS world_data.append(r) # load in level data and create world with open(f"level{level}_data.csv", newline="") as csvfile: reader = csv.reader(csvfile, delimiter=",") for x, row in enumerate(reader): for y, tile in enumerate(row): world_data[x][y] = int(tile) print(world_data) world = World() player, health_bar = world.process_data(world_data) run = True while run: clock.tick(fps) draw_bg() world.draw() health_bar.draw(player.health) # show ammo draw_text("AMMO:", font, WHITE, 10, 35) for x in range(player.ammo): screen.blit(bullet_img, (90 + (x * 10), 40)) # show grenade draw_text("GRENADES: ", font, WHITE, 10, 65) for x in range(player.grenades): screen.blit(grenade_img, (130 + (x * 15), 66)) player.update() player.draw() for enemy in enemy_group: enemy.ai() enemy.update() enemy.draw() # update and draw groups bullet_group.update() grenade_group.update() explosion_group.update() item_box_group.update() decoration_group.update() water_group.update() exit_group.update() bullet_group.draw(screen) grenade_group.draw(screen) explosion_group.draw(screen) item_box_group.draw(screen) decoration_group.draw(screen) water_group.draw(screen) exit_group.draw(screen) # update player actions, 1 is run, 0 = idle, 2 = in air if player.alive: # shoot bullet if shoot: player.shoot() elif grenade and grenade_thrown == False and player.grenades > 0: grenade = Grenade(player.rect.centerx + (0.5 * player.rect.size[0] * player.direction), player.rect.top, player.direction) grenade_group.add(grenade) # reduce grenades player.grenades -= 1 grenade_thrown = True if player.in_air: player.update_action(2) elif moving_left or moving_right: player.update_action(1) else: player.update_action(0) screen_scroll = player.move(moving_left, moving_right) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False # keyboard presses if event.type == pygame.KEYDOWN: if event.key == pygame.K_a: moving_left = True if event.key == pygame.K_d: moving_right = True if event.key == pygame.K_SPACE: shoot = True if event.key == pygame.K_q: grenade = True if event.key == pygame.K_w and player.alive: player.jump = True if event.key == pygame.K_ESCAPE: run = False # keyboard button released if event.type == pygame.KEYUP: if event.key == pygame.K_a: moving_left = False if event.key == pygame.K_d: moving_right = False if event.key == pygame.K_SPACE: shoot = False if event.key == pygame.K_q: grenade = False grenade_thrown = False pygame.display.update() pygame.quit() i have looked at this code for days but cant seem to find out the problem exactly. so, the question once again is how to properly arrange the enemies on the screen at their various predefined positions and not directly on top of my player.
Cannot see bullets when game is running
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().
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) # [...]
A Level Space invaders project issues
My enemy sprites are cut in half and one row is lower than the other. pygame.init() done = False display_width = 800 display_height = 600 BASE_PATH = abspath(dirname(__file__)) FONT_PATH = BASE_PATH + '/fonts/' IMAGE_PATH = BASE_PATH + '/sprites/' SOUND_PATH = BASE_PATH + '/sounds/' SCORE_PATH = BASE_PATH + '/scores/' #-----------------------------------------------------------------------------# #Classes and Functions #objects all_sprites = pygame.sprite.Group() ################################################################################ #Enemy class #Creates class image and positons and size, true or false statments for movement and updating positions ############################################################################################## class Enemy(pygame.sprite.Sprite): def __init__(self,x,y,direction,enemy_type): pygame.sprite.Sprite.__init__(self) self.EnemyType = enemy_type self.Direction = direction if enemy_type == 1: enemy_image = pygame.image.load("sprites\\enemy1_1.png") self.Speed = 1 self.Score = 5 if enemy_type == 2: enemy_image = pygame.image.load("sprites\\enemy1_1.png") self.Score = 15 self.Speed = 1 if enemy_type == 3: enemy_image = pygame.image.load("sprites\\enemy1_1.png") self.Score = 10 self.Speed = 1 if enemy_type == 4: enemy_image = pygame.image.load("sprites\\enemy1_1.png") self.Score = 20 self.Speed = 1 if enemy_type == 5: enemy_image = pygame.image.load("sprites\\enemy1_1.png") self.Score = 25 self.Speed = 1 self.image = pygame.Surface([26, 50]) self.image.set_colorkey(BLACK) self.image.blit(enemy_image,(0,0)) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def move_enemy(self): if self.Direction == "right": self.rect.x += self.Speed if self.Direction == "left": self.rect.x -= self.Speed #draw image def draw(self, screen): screen.blit(self.image, self.rect) allEnemies = pygame.sprite.Group() a_enemies = Enemy(200,200,"right",1) allEnemies.add(a_enemies)''' ############################################################################################# #function: in game screen #draws and calls classes and any functions that will be needed when playing the game ########################################################################################### '''def screen_game(): global lives global score global gameDisplay game_screen = True #For X coords spawnPositions = [90,180,270,360,450,540,630] yCoord = 10 #creating enemies for n in range(5): for i in range(len(spawnPositions)): xCoord = spawnPositions[i] enemy_type = random.randint(1,5) enemy = Enemy(xCoord, yCoord,"right", enemy_type) allEnemies.add(enemy) yCoord = yCoord + 50 #creating one player player = Player(500,500, 'sprites\\ship.png') #game loop while game_screen: #handling events eventlist = pygame.event.get() for event in eventlist: #print(event) if event.type == pygame.QUIT: pygame.quit() quit() #handle arrow keys if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: player.handle_event(event) if event.key == pygame.K_RIGHT: player.handle_event(event) if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT: player.handle_event(event) if event.key == pygame.K_RIGHT: player.handle_event(event) #draw game display gameDisplay.fill(BLACK) #draw player class player.update() player.draw(gameDisplay) #update enemy positions loop = 0 for enemy in (allEnemies.sprites()): if enemy.rect.x < 0: enemy.rect.y = enemy.rect.y + 10 enemy.Direction = "right" if enemy.rect.x > 625: enemy.rect.y = enemy.rect.y + 10 enemy.Direction = "left" loop =+1 for enemy in (allEnemies.sprites()): enemy.move_enemy() #draw enemies allEnemies.draw(gameDisplay) #update display pygame.display.update() clock.tick(60) I've shortened the code down on here to only include what I think are the relevant sections. How can that be fixed?
I suspect that the Surface created in the sprite __init()__ is not large enough to hold the image. self.image = pygame.Surface([26, 50]) # <-- HERE self.image.set_colorkey(BLACK) self.image.blit(enemy_image,(0,0)) It's not really necessary to load the image, then blit it onto a surface, as the image is a surface: if enemy_type == 5: self.image = pygame.image.load("sprites\\enemy1_1.png") self.Score = 25 self.Speed = 1 self.image.set_colorkey(BLACK) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y Just to simplify this a bit, all the Enemy stats and images could be placed into a list: class Enemy(pygame.sprite.Sprite): def __init__( self, x, y, direction, enemy_type_code ): pygame.sprite.Sprite.__init__( self ) enemy_type = [ [ "sprites\\enemy1_1.png", 5, 1 ], # image, score, speed [ "sprites\\enemy1_1.png", 15, 1 ], [ "sprites\\enemy1_1.png", 10, 1 ], [ "sprites\\enemy1_1.png", 20, 1 ], [ "sprites\\enemy1_1.png", 25, 1 ] ] self.EnemyType = enemy_type self.Direction = direction self.Speed = enemy_type[enemy_type_code][2] self.Score = enemy_type[enemy_type_code][1] self.image = pygame.image.load( enemy_type[enemy_type_code][0] ) self.image.set_colorkey(BLACK) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y
Two enemy movement glitches
So this is my game I've bean working on and so have things are going very well, the player can move around and shoot down the boxes which are ment to be moving but theres these small glitches, but before I go on heres the code: import pygame, math, random, sys from pygame import * import random, math, cmath pygame.init() #variables end---------------------------------------------------------------- #imagers grass = "grass_shit.png" #grass image player_img = "shithead.png" #player name ali_img = "shit_head2.png" #alien image dead_screen = "dead_shit.png" cross_hair = "crosshair.png" playButton = "playbutton.png" #screen screen = pygame.display.set_mode((850, 640),0,32) #set screen background = pygame.image.load(grass).convert() #load image to screen health = 100 #mouse things crosshair = pygame.image.load(cross_hair).convert_alpha() #variables end---------------------------------------------------------------- pygame.mouse.set_visible(False) black = ( 0, 0, 0) white = ( 255, 255, 255) red = ( 255, 0, 0) blue = ( 0, 0, 255) player_x, player_y = 0, 0 move_player_x, move_player_y = 0, 0 move_ali_x, move_ali_y = 0, 0 class Block(pygame.sprite.Sprite): def __init__(self, color): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface([20, 15]) self.image.fill(color) self.rect = self.image.get_rect() def update(self): global move_ali_x global move_ali_y if block.rect.x < player_x: move_ali_x =+ 0.05 elif block.rect.x > player_x: move_ali_x =- 0.05 if block.rect.y < player_y: move_ali_y =+ 0.05 elif block.rect.y > player_y: move_ali_y =- 0.05 class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface([20,20]) self.image.fill(red) self.rect = self.image.get_rect() def update(self): pos = pygame.mouse.get_pos() self.rect.x = player_x self.rect.y = player_y class Bullet(pygame.sprite.Sprite): def __init__(self, mouse, player): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface([4, 10]) self.image.fill(black) self.mouse_x, self.mouse_y = mouse[0], mouse[1] self.player = player self.rect = self.image.get_rect() def update(self): speed = 10 range = 50000 distance = [self.mouse_x - self.player[0], self.mouse_y - self.player[1]] norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2) direction = [distance[0] / norm, distance[1] / norm] bullet_vector = [direction[0] * speed, direction[1] * speed] self.rect.x += bullet_vector[0] self.rect.y += bullet_vector[1] pygame.init() screen_width = 850 screen_height = 640 screen = pygame.display.set_mode([screen_width,screen_height]) all_sprites_list = pygame.sprite.Group() block_list = pygame.sprite.Group() bullet_list = pygame.sprite.Group() for i in range(5): block = Block(blue) block.rect.x = random.randrange(screen_width) block.rect.y = random.randrange(350) block_list.add(block) all_sprites_list.add(block) player = Player() all_sprites_list.add(player) done = False clock = pygame.time.Clock() score = 0 player.rect.y = 370 # -------- Main Program Loop ----------- while not done: # --- Event Processing for event in pygame.event.get(): if event.type == pygame.QUIT: done = True elif event.type == pygame.MOUSEBUTTONDOWN: bullet = Bullet(event.pos, [player.rect.x, player.rect.y]) bullet.rect.x = player.rect.x bullet.rect.y = player.rect.y all_sprites_list.add(bullet) bullet_list.add(bullet) if event.type== pygame.KEYDOWN: if event.key==K_a: move_player_x=-4 elif event.key==K_d: move_player_x=+4 elif event.key==K_w: move_player_y=-4 elif event.key==K_s: move_player_y=+4 if event.type== pygame.KEYUP: if event.key==K_a: move_player_x=0 elif event.key==K_d: move_player_x=0 elif event.key==K_w: move_player_y=0 elif event.key==K_s: move_player_y=0 # --- Game logic all_sprites_list.update() player_x += move_player_x player_y += move_player_y block.rect.y += move_ali_y block.rect.x += move_ali_x for bullet in bullet_list: block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True) for block in block_hit_list: bullet_list.remove(bullet) all_sprites_list.remove(bullet) score += 1 print( score ) if bullet.rect.y < -10: bullet_list.remove(bullet) all_sprites_list.remove(bullet) if player.rect.colliderect(block.rect): health =- 35 mouse_x, mouse_y = pygame.mouse.get_pos() mouse_x -= crosshair.get_width() / 2 mouse_y -= crosshair.get_height() / 2 screen.blit(background,(0,0)) all_sprites_list.draw(screen) screen.blit(crosshair,(mouse_x, mouse_y)) pygame.display.flip() pygame.display.update() clock.tick(20) pygame.quit() So glitch number one: only one of the boxers moves, I cant figure out why it only one of them is moving towards the player, all the boxers are meant to move towards the player as this is hoping to become a zombie shooter. Glitch two: At a random point the box that does move does stops moving in all directions but one, so lets say this happens when the box in in the center of the screen, if the player goes to the left of the box, nothing, but when the player moves to thr right of the player it moves right, but only right not up or down, and this seams to happen at soem point everytime. Well thats it, hope you can help thanks heaps stackoverflow
Your code should looks like this: 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) #imagers IMAGE_GRASS = "grass_shit.png" #grass image IMAGE_PLAYER = "shithead.png" #player name IMAGE_ALI = "shit_head2.png" #alien image IMAGE_DEAD_SCREEN = "dead_shit.png" IMAGE_CROSSHAIR = "crosshair.png" IMAGE_PLAYBUTTON = "playbutton.png" #~ IMAGE_GRASS = "ball3.png" #grass image #~ IMAGE_PLAYER = "ball2.png" #player name #~ IMAGE_ALI = "ball3.png" #alien image #~ IMAGE_DEAD_SCREEN = "ball3.png" #~ IMAGE_CROSSHAIR = "ball1.png" #~ IMAGE_PLAYBUTTON = "ball3.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, 15]) 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 = 100 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 = -4 elif event.key == pygame.K_d: self.move_x = +4 elif event.key == pygame.K_w: self.move_y = -4 elif event.key == pygame.K_s: self.move_y = +4 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 = 10 self.max_range = 50 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 Game(): def __init__(self): pygame.init() screen_width = 850 screen_height = 640 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() # --- create sprites --- self.background = Background() self.player = Player(self.screen.get_rect(), 0, 370) self.all_sprites_list.add(self.player) for i in range(5): 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.crosshair = Crosshair() #----- font = pygame.font.SysFont("", 72) self.text_pause = font.render("PAUSE", -1, RED) self.text_pause_rect = self.text_pause.get_rect(center=self.screen.get_rect().center) # center text #----- self.score = 0 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) for block in block_hit_list: self.bullet_list.remove(bullet) self.all_sprites_list.remove(bullet) self.score += 1 print self.score if bullet.rect.y < -10: self.bullet_list.remove(bullet) self.all_sprites_list.remove(bullet) if pygame.sprite.collide_rect(self.player, block): self.player.health =- 35 # -------- Main Program Loop ----------- def run(self): clock = pygame.time.Clock() RUNNING = True PAUSED = False while RUNNING: # --- events --- for event in pygame.event.get(): if event.type == pygame.QUIT: RUNNING = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: RUNNING = false elif event.key == pygame.K_SPACE: PAUSED = not PAUSED elif event.type == pygame.MOUSEBUTTONDOWN: self.bullet_create(self.player, event.pos) # send event to player self.player.event_handler(event) # send event to crosshair for mousebuttondown #if not PAUSED: # self.crosshair.event_handler(event) # --- updates --- if not PAUSED: self.all_sprites_list.update() self.bullets_update() self.crosshair.update() # --- draws --- self.background.draw(self.screen) self.all_sprites_list.draw(self.screen) self.crosshair.draw(self.screen) if PAUSED: self.screen.blit(self.text_pause, self.text_pause_rect.topleft) pygame.display.update() # use flip() OR update() # --- FPS --- clock.tick(20) # --- quit --- pygame.quit() #---------------------------------------------------------------------- Game().run() Changes: player can move but can leave screen press space to pause game - but you can still move cursor and fire :) bullet has max range - than it is removed i change bullet vetor calculations because value was rounded to integer every frame and bullet trajectory was incorrect bullet never change trajectory when player is moving all code is in classes except some constant values. I add class Crosshair and Background you can see how class (Player) handle events in event_handle I use pygame.Rect() (screen.get_rect(), image.get_rect()) to get rect.top, rect.left, rect.center, rect.centerx, rect.topleft, etc. There is still many things to do. ps. if someone needs images 'ball1.png', 'ball2.png', 'ball3.png' to run this example you can find it in answer to Space invaders project Pygame- window and sprite class - python