This is my first game, and I've run up on some problems. I have all the files I need. The pygame window opens up like it is going to start the game, then it just gives me the beach ball of death! lol! The error codes are below. Any help would be greatly appreciated!
Traceback (most recent call last):
File "/Users/mhallfamily/Desktop/Python Folder/Skier.py", line 81, in <module>
skier = SkierClass()
File "/Users/mhallfamily/Desktop/Python Folder/Skier.py", line 12, in __init__
self.image = pygame.image.load ("skier_down.png")
error: Couldn't open skier_down.png
Here is my program!
#First Game!!!!
import pygame, sys, random
skier_images = ["skier_down.png", "skier_right1.png",
"skier_right2.png", "skier_left2.png",
"skier_left1.png"]
class SkierClass (pygame.sprite.Sprite):
def __init__(self) :
pygame.sprite.Sprite.__init__(self)
import os
print (os.getcwd(), os.path.exists("skier_down.png"))
self.image = pygame.image.load ("skier_down.png")
self.rect = self.image.get_rect ()
self.rect.center = [320, 100]
self.angle = 0
def turn(self, direction) :
self.angle = self.angle + direction
if self.angle < -2: self.angle = -2
if self.angle > 2: self.angle = 2
center = self.rect.center
self.image = pygame.load(skier_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
speed = [self.angle, 6 - abs(self.angle) *2]
return speed
def move (self, speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 20: self.rect.centerx = 20
if self.rect.centerx < 620: self.rect.centerx = 620
class ObsticalsClass (pygame.sprite.Sprite):
def __init__(self, image_file, location, type) :
pygame.sprite.Sprite.__init__ (self)
self.image_file = image_file
self.image = pygame.image.load(image_file)
self.location = loacation
self.rect = self.image.get_rect()
self.rect.center = location
self.type = type
self.passed = False
def scroll (self, t_ptr):
self.rect.centery = self.location[1] - t_ptr
def creat_map(start, end):
obsticals = pygame.sprite.Group()
grates = pygame.sprite.Group()
locations = []
for i in range (10):
row = random.randit (start, end)
col = random.randit (0, 9)
location = [col * 64 + 20, row * 64 + 20]
if not (location in locations) :
locations.append(location)
type = random.choice(["tree", "flag"])
if type == "tree": img = "skier_tree.png"
elif type == "flag": img = "skier_flag.png"
obstacle = ObstacleClass (img, location, type)
obstacles.add(obstacle)
return obstacles
def animate ():
screen.fill ([255, 255, 255])
pygame.display.update (obstacles.draw(screen))
screen.blit (skier.image, skier.rect)
screen.blit(score_text, [10 ,10])
pygame.display.flip()
def updateObstacleGroup (map0, map1):
obstacles = pygame.sprite.Group()
for ob in map0: obstacles.add (ob)
for ob in map1: obstacles.add (ob)
return obstacles
pygame.init()
screen = pygame.display.set_mode ([640, 640])
clock = pygame.time.Clock()
skier = SkierClass()
speed = [0, 6]
map_position = 0
points = 0
map_position = 0
map0 = create_map (20, 29)
map1 = create_map (10, 19)
activeMap = 0
obstacles = updateObstacleGroup (map0, map1)
font = pygame.font.Font (None, 50)
while True:
clock.tick (30)
for event in pygame.event.get ():
if event.type == pygame.QUIT: sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed = skier.turn (-1)
elif event.key == pygame.K_RIGHT:
speed = skier.turn (1)
skier.move (speed)
map_position += speed [1]
if map_position >=640 and activeMap == 0:
activeMap = 1
map0 = creat_map (20, 29)
obstacles = updateObsstacleGroup (map0, map1)
if map_position >=640 and activeMap == 0 :
activeMap = 0
for ob in map0:
ob.location[1] = ob.location [1] -1280
map_position = map_position - 1280
map1 = create_map (10, 19)
obstacles = updateObstaclesGroup (map0, map1)
for obstacles in obstacles:
obstacles.scroll (map_position)
hit = pygame.sprite.spritecollide (skier, obstacles, False)
if hit:
if hit [0] .type == "tree" and not hit [0] .passed:
points - 100
skier.image = pygame.image.load ("skier_crash.png")
animate()
pygame.time.delay(1000)
skier.angle = 0
speed = [0, 6]
hit[0] .passed = True
elif hit [0] .type == "flag" and not hit [0] .passed:
points += 10
obstacles.remove (hit[0])
score_text = font.render ("Score: " +str(points), 1, (0, 0, 0))
animate ()
I am assuming you have a folder named images that has those images you have downloaded. Make sure that folder is saved in the same place where your code is. If that's the case, try just putting image/ before each of the image name.
For example rename "skier_crash.png" to
"images/skier_crash.png"
Hope that helps!
Related
I've made a game in pygame and I want to make it possible to have a high score thaat will be displayed at the the top of the show_go_screen. I just need a simple solution - I don't need to write who has the highest score, just the number itself at the top of the show_go_screen. I know there are already questions about this on Stack Overflow but the solutions don't work for me.
code:
# Pygame template
# Attributions
# (Heart) Icons made by Freepik from www.flaticon.com
# (Play)Background vector created by freepik - www.freepik.com
# (GameOver)Background vector created by pikisuperstar - www.freepik.com
# (Backing)Frozen Jam by tgfcoder <https://twitter.com/tgfcoder> licensed under CC-BY-3 <http://creativecommons.org/licenses/by/3.0/>
# (Graphics)Art by Kenney.nl
# Imports
import pygame as pg
import random
from os import path
# images / sound
img_dir = path.join(path.dirname(__file__), 'img')
snd_dir = path.join(path.dirname(__file__), 'snd')
# Constants
WIDTH = 500
HEIGHT = 700
FPS = 60
POWERUP_TIME = 60000
ENCO_TIME = 40000
# Define Colors
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
MAGENTA = (255, 0, 255)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
CYAN = (0, 255, 255)
GREENISH_BLUE = (0, 255, 180)
# Initialize pygame and create window
pg.init()
pg.mixer.init()
screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption("Galaxy Shooters")
clock = pg.time.Clock()
score = 0
# save score
# import shelve
# d = shelve.open('score.txt') # here you will save the score variable
# d['highscore'] = score # thats all, now it is saved on disk.
# d.close()
font_name = pg.font.match_font('arial')
def draw_text(surf, text, size, x, y):
font = pg.font.Font(font_name, size)
text_surface = font.render(text, True, CYAN)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
def spawnmob():
m = Mob()
all_sprites.add(m)
mobs.add(m)
def draw_shield_status_bar(surf, x, y, pct):
if pct < 0:
pct = 0
BAR_LENGTH = 100
BAR_HEIGHT = 10
fill = (pct / 100) * BAR_LENGTH
outline_rect = pg.Rect(x, y, BAR_LENGTH, BAR_HEIGHT)
fill_rect = pg.Rect(x, y, fill, BAR_HEIGHT)
pg.draw.rect(surf, GREENISH_BLUE, fill_rect)
pg.draw.rect(surf, WHITE, outline_rect, 2)
def draw_lives(surf, x, y, lives, img):
for i in range(lives):
img_rect = img.get_rect()
img_rect.x = x + 30 * i
img_rect.y = y
surf.blit(img, img_rect)
class Player(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.transform.scale(player_img, (50, 38))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = 20
# pg.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT - 10
self.speedx = 0
self.shield = 100
self.shoot_delay = 370
self.last_shot = pg.time.get_ticks()
self.lives = 3
self.hidden = False
self.hide_timer = pg.time.get_ticks()
self.power = 1
self.power_time = pg.time.get_ticks()
def update(self):
# Timeout for powerups
if self.power >= 2 and pg.time.get_ticks() - self.hide_timer > POWERUP_TIME:
self.power -= 1
self.power_time = pg.time.get_ticks
# Unhide if necessary
if self.hidden and pg.time.get_ticks() - self.hide_timer > 1000:
self.hidden = False
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT - 10
self.speedx = 0
keystate = pg.key.get_pressed()
if keystate[pg.K_LEFT]:
self.speedx = -5
if keystate[pg.K_RIGHT]:
self.speedx = 5
if keystate[pg.K_SPACE]:
self.shoot()
self.rect.x += self.speedx
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.left < 0:
self.rect.left = 0
def powerup(self):
self.power += 1
self.power_time = pg.time.get_ticks()
def shoot(self):
now = pg.time.get_ticks()
if now - self.last_shot > self.shoot_delay:
self.last_shot = now
if self.power == 1:
laser = Laser(self.rect.centerx, self.rect.top)
all_sprites.add(laser)
lasers.add(laser)
random.choice(shoot_sounds).play()
if self.power >= 2:
laser1 = Laser(self.rect.left, self.rect.centery)
laser2 = Laser(self.rect.right, self.rect.centery)
all_sprites.add(laser1)
all_sprites.add(laser2)
lasers.add(laser1)
lasers.add(laser2)
random.choice(shoot_sounds).play()
def hide(self):
self.hidden = True
self.hide_timer = pg.time.get_ticks()
self.rect.center = (WIDTH / 2, HEIGHT + 200)
class Mob(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image_orig = random.choice(meteor_images)
self.image_orig.set_colorkey(BLACK)
self.image = self.image_orig.copy()
self.rect = self.image.get_rect()
self.radius = int(self.rect.width * .85 / 2)
# pg.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-150, -40)
self.speedy = random.randrange(1, 8)
self.speedx = random.randrange(-3, 3)
self.rot = 0
self.rot_speed = random.randrange(-8, 8)
self.last_update = pg.time.get_ticks()
def rotate(self):
now = pg.time.get_ticks()
if now - self.last_update > 50:
self.last_update = now
self.rot = (self.rot + self.rot_speed) % 360
new_image = pg.transform.rotate(self.image_orig, self.rot)
old_center = self.rect.center
self.image = new_image
self.rect = self.image.get_rect()
self.rect.center = old_center
def update(self):
self.rotate()
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.right < -25 or self.rect.left > WIDTH + 20:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
class Laser(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = laser_img
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedy = -10
def update(self):
self.rect.y += self.speedy
# Kill it if moves off the top of the screen
if self.rect.bottom < 0:
self.kill()
class Explosion(pg.sprite.Sprite):
def __init__(self, center, size):
pg.sprite.Sprite.__init__(self)
self.size = size
self.image = explosion_anim[self.size][0]
self.rect = self.image.get_rect()
self.rect.center = center
self.frame = 0
self.last_update = pg.time.get_ticks()
self.frame_rate = 75
def update(self):
now = pg.time.get_ticks()
if now - self.last_update > self.frame_rate:
self.last_update = now
self.frame += 1
if self.frame == len(explosion_anim[self.size]):
self.kill()
else:
center = self.rect.center
self.image = explosion_anim[self.size][self.frame]
self.rect = self.image.get_rect()
self.rect.center = center
class Pow(pg.sprite.Sprite):
def __init__(self, center):
pg.sprite.Sprite.__init__(self)
self.type = random.choice(['shield', 'laser', 'star'])
self.image = powerup_images[self.type]
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.center = center
self.speedy = 4
def update(self):
self.rect.y += self.speedy
# Kill it if moves off the bottom of the screen
if self.rect.top > HEIGHT:
self.kill()
class Enco(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = draw_text(screen, (random.choice(encos), 37, WIDTH / 2, HEIGHT/ 4))
self.rect = self.image.get_rect()
self.hidden = True
self.hide_timer = pg.time.get_ticks()
def hide(self):
self.rect.y = HEIGHT - 40
self.rect.x = WIDTH / 2
def show_go_screen():
screen.blit(background2, background_rect2)
draw_text(screen, str(score), 25, WIDTH / 2, 10)
draw_text(screen, " Guardians of the Galaxy ", 37, WIDTH / 2, HEIGHT / 4)
draw_text(screen, "Arrow Keys move, Spacebar to shoot", 29, WIDTH / 2, HEIGHT / 2)
draw_text(screen, "Press any key to BEGIN", 22, WIDTH / 2, HEIGHT * 3/ 4)
pg.display.flip()
print(d)
waiting = True
while waiting:
clock.tick(FPS)
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
if event.type == pg.KEYUP:
waiting = False
# Load all game graphics
background = pg.image.load(path.join(img_dir, "2397814.jpg")).convert()
background_rect = background.get_rect()
background2 = pg.image.load(path.join(img_dir, "2474216.jpg")).convert()
background_rect2 = background2.get_rect()
pg.transform.scale(background, (500, 700))
player_img = pg.image.load(path.join(img_dir, "playerShip3_blue.png")).convert()
heart_img = pg.image.load(path.join(img_dir, "heart.png")).convert()
mini_heart_img = pg.transform.scale(heart_img, (23, 23))
mini_heart_img.set_colorkey(BLACK)
laser_img = pg.image.load(path.join(img_dir, "laserBlue01.png")).convert()
meteor_images = []
meteor_list = ['meteorBrown_big1.png', 'meteorBrown_big2.png', 'meteorBrown_big3.png',
'meteorBrown_med1.png','meteorBrown_small1.png','meteorBrown_small2.png',
'meteorBrown_tiny2.png',]
for img in meteor_list:
meteor_images.append(pg.image.load(path.join(img_dir, img)).convert())
explosion_anim = {}
explosion_anim['lg'] = []
explosion_anim['sm'] = []
explosion_anim['player'] = []
for i in range(9):
filename = 'regularExplosion0{}.png'.format(i)
img = pg.image.load(path.join(img_dir, filename)).convert()
img.set_colorkey(BLACK)
img_lg = pg.transform.scale(img, (75, 75))
explosion_anim['lg'].append(img_lg)
img_sm = pg.transform.scale(img, (32, 32))
explosion_anim['sm'].append(img_sm)
filename = 'sonicExplosion0{}.png'.format(i)
img = pg.image.load(path.join(img_dir, filename)).convert()
img.set_colorkey(BLACK)
explosion_anim['player'].append(img)
powerup_images = {}
powerup_images['shield'] = pg.image.load(path.join(img_dir, 'shield_silver.png')).convert()
powerup_images['laser'] = pg.image.load(path.join(img_dir, 'bolt_gold.png')).convert()
powerup_images['star'] = pg.image.load(path.join(img_dir, 'star_silver.png')).convert()
encos = ("Nice Job!", "You're rocking it man!", " Great!", "What a blast!", "Good one!", "Those asteroids stand no chance against you!"
"You're the master!")
# Load all game sounds
laser_powerup = pg.mixer.Sound(path.join(snd_dir, 'Laser_Powerup.wav'))
shield_powerup = pg.mixer.Sound(path.join(snd_dir, 'Shield_Powerup.wav'))
shoot_sounds = []
for snd in ['Laser_Shoot.wav', 'Laser_Shoot2.wav']:
shoot_sounds.append(pg.mixer.Sound(path.join(snd_dir, snd)))
expl_sounds = []
for snd in ['Expl.wav', 'Expl2.wav']:
expl_sounds.append(pg.mixer.Sound(path.join(snd_dir, snd)))
player_die_sound = pg.mixer.Sound(path.join(snd_dir, 'rumble1.ogg'))
pg.mixer.music.load(path.join(snd_dir, 'tgfcoder-FrozenJam-SeamlessLoop.ogg'))
pg.mixer.music.set_volume(0.7)
pg.mixer.music.play(loops = -1)
# Game loop
game_over = True
running = True
while running:
if game_over:
show_go_screen()
game_over = False
# Sprite groups
all_sprites = pg.sprite.Group()
mobs = pg.sprite.Group()
lasers = pg.sprite.Group()
powerups = pg.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(8):
spawnmob()
score = 0
# Keep loop running at the right speed
clock.tick(FPS)
# Events
for event in pg.event.get():
# Check for closing window
if event.type == pg.QUIT:
running = False
# Update
all_sprites.update()
# Check to see if a laser hit a mob
hits = pg.sprite.groupcollide(mobs, lasers, True, True)
for hit in hits:
score += 50 - hit.radius
random.choice(expl_sounds).play()
expl = Explosion(hit.rect.center, 'lg')
all_sprites.add(expl)
if random.random() > 0.93:
pow = Pow(hit.rect.center)
all_sprites.add(pow)
powerups.add(pow)
spawnmob()
# Check to see if a mob hit the player
hits = pg.sprite.spritecollide(player, mobs, True, pg.sprite.collide_circle)
for hit in hits:
player.shield -= hit.radius * 2
expl = Explosion(hit.rect.center, 'sm')
all_sprites.add(expl)
spawnmob()
if player.shield <= 0:
player_die_sound.play()
death_expl = Explosion(player.rect.center, 'player')
all_sprites.add(death_expl)
player.hide()
player.lives -= 1
player.shield = 100
# Check to see if player hit a powerup
hits = pg.sprite.spritecollide(player, powerups, True)
for hit in hits:
if hit.type == 'shield':
pow.kill()
player.shield += random.randrange(10, 30)
shield_powerup.play()
if player.shield >= 100:
player.shield = 100
if hit.type == 'laser':
player.powerup()
laser_powerup.play()
if hit.type == 'star':
player.lives += 1
if player.lives >= 3:
player.lives = 3
# If the player died and the explosion finished playing
if player.lives == 0 and not death_expl.alive():
game_over = True
# Render
screen.fill(BLACK)
screen.blit(background, background_rect)
all_sprites.draw(screen)
draw_text(screen, str(score), 25, WIDTH / 2, 10)
draw_shield_status_bar(screen, 5, 5, player.shield)
draw_lives(screen, WIDTH - 100, 5, player.lives, mini_heart_img)
if score == 500:
draw_text(screen, "Nice Job!", 37, WIDTH / 2, HEIGHT / 2)
now = pg.time.get_ticks()
last.enco = pg.time.get_ticks()
if now - last.enco == ENCO_TIME:
hide_enco
# *After* drawing everything, flip the display
pg.display.flip()
pg.quit()
thanks!
Create a variable called highscore then then when the player looses, check if the current score is higher than highscore and if it is, then assign the score to highscore. Then you can just easily add a label with the highscore variable as a text
score = 0
highscore = 0
# save score
# import shelve
# d = shelve.open('score.txt') # here you will save the score variable
# d['highscore'] = score # thats all, now it is saved on disk.
# d.close()
# A lot of your code
def show_go_screen():
screen.blit(background2, background_rect2)
draw_text(screen, str(highscore), 50, WIDTH / 2, 10) #change the x value accordingly
# more of your code
while running:
if game_over:
show_go_screen()
game_over = False
# Sprite groups
all_sprites = pg.sprite.Group()
mobs = pg.sprite.Group()
lasers = pg.sprite.Group()
powerups = pg.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(8):
spawnmob()
if score > highscore:
highscore = score
score = 0
# the rest of your code
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
I am new to pygame and I am trying to make a game where the player has to bypass some enemy's to get to a point where you can go to the next level. I need the enemy's to walk back and forward on a predetermined path but I can't figure out how to do it. So I was wondering if there is an easy way to do this?
This is my code.
import pygame
import random
import os
import time
from random import choices
from random import randint
pygame.init()
a = 0
b = 0
width = 1280
height = 720
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Game")
done = False
n = 0
x = 0
y = 0
x_wall = 0
y_wall = 0
clock = pygame.time.Clock()
WHITE = (255,255,255)
RED = (255,0,0)
change_x = 0
change_y = 0
HW = width / 2
HH = height / 2
background = pygame.image.load('mountains.png')
#player class
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("character.png")
self.rect = self.image.get_rect()
self.rect.x = width / 2
self.rect.y = height / 2
#enemy class
class Enemy(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("enemy.png")
self.image = pygame.transform.scale(self.image, (int(50), int(50)))
self.rect = self.image.get_rect()
self.rect.x = width / 3
self.rect.y = height / 3
#wall class
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("wall.png")
self.image = pygame.transform.scale(self.image, (int(50), int(50)))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
#wall movement
def update(self):
self.vx = 0
self.vy = 0
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.vx = 5
self.vy = 0
elif key[pygame.K_RIGHT]:
self.vx = -5
self.vy = 0
if key[pygame.K_UP]:
self.vy = 5
self.vx = 0
elif key[pygame.K_DOWN]:
self.vy = -5
self.vx = 0
self.rect.x = self.rect.x + self.vx
self.rect.y = self.rect.y + self.vy
#player sprite group
sprites = pygame.sprite.Group()
player = Player()
sprites.add(player)
#enemy sprite group
enemys = pygame.sprite.Group()
enemy = Enemy()
enemy2 = Enemy()
enemys.add(enemy, enemy2)
#all the wall sprites
wall_list = pygame.sprite.Group()
wall = Wall(x_wall, y_wall)
wall2 = Wall((x_wall + 50), y_wall)
wall3 = Wall((x_wall + 100), y_wall)
wall4 = Wall((x_wall + 150), y_wall)
wall5 = Wall((x_wall + 200), y_wall)
wall6 = Wall((x_wall + 250), y_wall)
#add all the walls to the list to draw them later
wall_list.add(wall, wall2, wall3, wall4, wall5, wall6)
#add all the walls here to fix the collision
all_walls = (wall, wall2, wall3, wall4, wall5, wall6)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
sprites.update()
wall_list.update()
enemys.update()
#collision between player and and walls
if player.rect.collidelist(all_walls) >= 0:
print("Collision !!")
player.rect.x = player.rect.x - player.vx
player.rect.y = player.rect.y - player.vx
#fill the screen
screen.fill((0, 0, 0))
#screen.blit(background,(x,y))
#draw the sprites
sprites.draw(screen)
wall_list.draw(screen)
enemys.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Here is the download link with the images if you want to run it:
https://geordyd.stackstorage.com/s/hZZ1RWcjal6ecZM
I'd give the sprite a list of points (self.waypoints) and assign the first one to a self.target attribute.
In the update method I subtract the self.pos from the self.target position to get a vector (heading) that points to the target and has a length equal to the distance. Scale this vector to the desired speed and use it as the velocity (which gets added to the self.pos vector each frame) and the entity will move towards the target.
When the target is reached, I just increment the waypoint index and assign the next waypoint in the list to self.target. It's a good idea to slow down when you're getting near the target, otherwise the sprite could get stuck and moves back and forth if it can't reach the target point exactly. Therefore I also check if the sprite is closer than the self.target_radius and decrease the velocity to a fraction of the maximum speed.
import pygame as pg
from pygame.math import Vector2
class Entity(pg.sprite.Sprite):
def __init__(self, pos, waypoints):
super().__init__()
self.image = pg.Surface((30, 50))
self.image.fill(pg.Color('dodgerblue1'))
self.rect = self.image.get_rect(center=pos)
self.vel = Vector2(0, 0)
self.max_speed = 3
self.pos = Vector2(pos)
self.waypoints = waypoints
self.waypoint_index = 0
self.target = self.waypoints[self.waypoint_index]
self.target_radius = 50
def update(self):
# A vector pointing from self to the target.
heading = self.target - self.pos
distance = heading.length() # Distance to the target.
heading.normalize_ip()
if distance <= 2: # We're closer than 2 pixels.
# Increment the waypoint index to swtich the target.
# The modulo sets the index back to 0 if it's equal to the length.
self.waypoint_index = (self.waypoint_index + 1) % len(self.waypoints)
self.target = self.waypoints[self.waypoint_index]
if distance <= self.target_radius:
# If we're approaching the target, we slow down.
self.vel = heading * (distance / self.target_radius * self.max_speed)
else: # Otherwise move with max_speed.
self.vel = heading * self.max_speed
self.pos += self.vel
self.rect.center = self.pos
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
waypoints = [(200, 100), (500, 400), (100, 300)]
all_sprites = pg.sprite.Group(Entity((100, 300), waypoints))
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
all_sprites.update()
screen.fill((30, 30, 30))
all_sprites.draw(screen)
for point in waypoints:
pg.draw.rect(screen, (90, 200, 40), (point, (4, 4)))
pg.display.flip()
clock.tick(60)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
Instead of the waypoints list and index I'd actually prefer to use itertools.cycle and just call next to switch to the next point:
# In the `__init__` method.
self.waypoints = itertools.cycle(waypoints)
self.target = next(self.waypoints)
# In the `update` method.
if distance <= 2:
self.target = next(self.waypoints)
Use a list to have him walk back and forth.
class Enemy(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("enemy.png")
self.image = pygame.transform.scale(self.image, (int(50), int(50)))
self.rect = self.image.get_rect()
self.rect.x = width / 3
self.rect.y = height / 3
#x or y coordinates
self.list=[1,2,3,4,5]
self.index=0
def update(self):
# patrol up and down or left and right depending on x or y
if self.index==4:
#reverse order of list
self.list.reverse()
self.index=0
#set the x position of the enemy according to the list
self.rect.x=self.list[self.index]
self.index+=1
I am working with a sprite group which contains 60 sprite objects.
each object represents a asteroid image and all images displayed after each other in the right order creates an animation of a rotating asteroid, in other words i am iterating through the sprite group as seen in code below.
Evcerything works fine until the objects passes the screen height and resets at the top again and the objects then starts appearing at random locations in the x direction. The screen now seem to blit each sprite at random locations and the asteroid now just flickers back and forth horizontally.
Is there a way to get the same new random x location for all the sprites after asteroid obj passes the screen instead of giving each sprite in the group a new x value?
Any suggestions?
import pygame
import sys
import os
import random
import time
import math
black = (0, 0, 0)
white = (255, 255, 255)
red = (200, 40, 60)
green = (50, 180, 50)
blue = (50, 30, 200)
skyblue = (135, 206, 250)
silver = (192, 192, 192)
darkgray = (47, 79, 79)
vegasgold = (197, 179, 88)
nightblue = (25, 25, 112)
steelblue = (70, 130, 180)
deepblue = (0, 26, 51)
screen_width = 1920
screen_height = 1080
half_width = screen_width/2
half_height = screen_height/2
screen = pygame.display.set_mode([screen_width, screen_height])
Title = pygame.display.set_caption('Space Mash')
clock = pygame.time.Clock()
class Spaceship(pygame.sprite.Sprite):
def __init__(self, width=30, height=30, color=white):
super(Spaceship, self).__init__()
self.image = pygame.Surface([width, height])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = 0
def center_set_position(self, x, y):
self.rect.x = x - self.rect.center[0]
self.rect.y = y - self.rect.width
def rotate_ship(self, dg):
self.image = pygame.transform.rotate(self.image, dg)
def set_image(self, filename):
self.image = pygame.image.load(filename)
self.rect = self.image.get_rect()
def draw_ship(self):
screen.blit(self.image, [self.rect.x, self.rect.y])
player_spaceship = Spaceship()
player_spaceship.set_image("main_ship.png")
player_spaceship.center_set_position(half_width, screen_height)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player_spaceship)
class Asteroids(pygame.sprite.Sprite):
def __init__(self, nr):
super(Asteroids, self).__init__()
self.image = pygame.image.load('Asteroid_{0}.png'.format(nr))
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = 0
def update(self):
self.rect.y += 5
if self.rect.y > screen_height + 50:
self.rect.y = -50
self.rect.x = random.randrange(0, (screen_width - (self.rect.width))
asteroids_list = pygame.sprite.LayeredUpdates()
for i in range(1, 61):
asteroid = Asteroids(nr=i)
asteroids_list.add(asteroid)
all_sprites_list.add(asteroid)
class Stars(pygame.sprite.Sprite):
def __init__(self):
super(Stars, self).__init__()
self.image = pygame.Surface([1, 1])
self.image.fill(white)
self.rect = self.image.get_rect()
stars_group = pygame.sprite.Group()
def making_star_objects():
for i in range(100):
x_loc = random.randint(0, screen_width - 1)
y_loc = random.randint(0, screen_height - 1)
star = Stars()
star.rect.x = x_loc
star.rect.y = y_loc
stars_group.add(star)
def gameloop():
ending = False
x_change = 0
y_change = 0
making_star_objects()
frame = 0
while not ending:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x_change = 10
elif event.key == pygame.K_LEFT:
x_change = -10
elif event.key == pygame.K_UP:
y_change = -8
elif event.key == pygame.K_DOWN:
y_change = 8
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
x_change = 0
elif event.key == pygame.K_LEFT:
x_change = 0
player_spaceship.rect.x += x_change
player_spaceship.rect.y += y_change
if frame > 59:
frame = 0
asteroids_list.update()
asteroids_hit_list = pygame.sprite.spritecollide(player_spaceship, asteroids_list, False)
screen.fill(deepblue)
stars_group.draw(screen)
screen.blit(asteroids_list.get_sprite(frame).image, (asteroids_list.get_sprite(frame).rect.x,
asteroids_list.get_sprite(frame).rect.y))
frame += 1
player_spaceship.draw_ship()
pygame.display.update()
clock.tick(30)
pygame.quit()
quit()
gameloop()
You can add a Class variable property and store the first coordinate X assigned, then reuse the value when you need it. It will be accessible from all the objects, since is a class global variable.
If you assign the value to the variable by this way, it will be the same (if you don't change it) during all the execution of the program, because it's value is assigned when the class is created.
rectXCopy = random.randrange(0, (screen_width - (self.rect.width))
Finaly, your class will become like this:
class Asteroids(pygame.sprite.Sprite):
rectXCopy = random.randrange(0, (screen_width - (self.rect.width))
def __init__(self, nr):
super(Asteroids, self).__init__()
self.image = pygame.image.load('Asteroid_{0}.png'.format(nr))
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = 0
self.rectYCopy = 0
self.copied = False
def update(self):
self.rect.y += 5
if self.rect.y > screen_height + 50:
self.rect.y = -50
self.rect.x = self.rectXcopy
The problem is that you have all the animation frames as separate sprite objects in your asteroids_list sprite group. They all have their own rects and if you update one of them, the others aren't affected. So when the sprites leave the screen you set them all to different random positions.
I recommend to create only one asteroid object, put the images into a list or dict (whatever you prefer) and then just change the image of this single asteroid sprite in its update method to create the animation.
# Put the images / pygame.Surfaces into a global constant list.
ASTEROID_FRAMES = [surface1, surface2] # etc. (use a list comprehension)
class Asteroids(pygame.sprite.Sprite):
def __init__(self, nr):
super(Asteroids, self).__init__()
self.image = ASTEROID_FRAMES[0]
self.rect = self.image.get_rect(topleft=(0, 0))
self.frame = 0
def update(self):
self.rect.y += 5
if self.rect.y > screen_height + 50:
self.rect.y = -50
self.rect.x = random.randrange(0, (screen_width - (self.rect.width)))
# Update the image (this is frame rate bound, but you can also
# add a timer to change the frame after some time has passed).
self.frame += 1
# Keep the index in the correct range.
self.frame %= len(ASTEROID_FRAMES)
self.image = ASTEROID_FRAMES[self.frame]
I'm new to Python and I entered in the code from the book I purchased to learn about it. I am trying to make the basic Skiers pygame, and every time I run the module, the pygame window pops up black then says "not responding"
I'm using Windows 8, Python 2.5.7 and here is the code. Any help would be appreciated!
import pygame, sys, random
skier_images = ["skier_down.png", "skier_right1.png", "skier_right2.png", "skier_left2.png", "skier_left1.png"]
class SkierClass(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("skier_down.png")
self.rect = self.image.get_rect()
self.rect.center = [320, 100]
self.angle = 0
def turn(self, direction):
self.angle = self.angle + direction
if self.angle < -2: self.angle = -2
if self.angle > 2: self.angle = 2
center = self.rect.center
self.image = pygame.image.load(skier_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
speed = [self.angle, 6 - abs(self.angle) * 2]
return speed
def move(self, speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 20: self.rect.centerx = 20
if self.rect.centerx > 620: self.rect.centerx = 620
class ObstacleClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, type):
pygame.sprite.Sprite__init__(self)
self.image_file = image_file
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.center = location
self.type = type
self.passed = False
def update(self):
global speed
self.rect.centery -= speed[1]
if self.rect.centery < -32:
self.kill()
def create_map():
global obstacles
locations = []
for i in range(10):
row = random.randint(0, 9)
col = random.randint(0, 9)
location = [col * 64 + 20, row * 64 + 20 + 640]
if not (location in locations):
locations.append(location)
type = random.choice(["tree", "flag"])
if type == "tree": img = "skier_tree.png"
elif type == "flag": img = "skier_flag.png"
obstacle = ObstacleClass(img, location, type)
obstacles.add(obstacle)
def animate():
screen.fill([255, 255, 255])
obstacles.draw(screen)
screen.blit(skier.image, skier.rect)
screen.blit(score_text, [10, 10])
pygame.display.flip()
pygame.init()
screen = pygame.display.set_mode([640, 640])
clock = pygame.time.Clock()
skier = SkierClass()
speed = [0, 6]
obstacles = pygame.sprite.Group()
map_position = 0
points = 0
create_map()
font = pygame.font.Font(None, 50)
running = True
while running:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed = skier.turn(-1)
elif event.key == pygame.K_RIGHT:
speed = skier.turn(1)
skier.move(speed)
map_position += speed[1]
if map_position >=640:
create_map()
map_position = 0
hit = pygame.sprite.spritecollide(skier, obstacles, False)
if hit:
if hit[0].type == "tree" and not hit[0].passed:
points = points - 100
skier.image = pygame.image.load("skier_crash.png")
animate()
pygame.time.delay(1000)
skier.image = pygame.image.load("skier_down.png")
skier.angle = 0
speed = [0, 6]
hit[0].passed = True
elif hit[0].type == "flag" and not hit[0].passed:
points += 10
hit[0].kill()
obstacles.update()
score_text = font.render("Score: " +str(points), 1, (0, 0, 0))
animate()
pygame.quit()
I downloaded the code, ran it, added random image so it don't throw error and the problem seems to be here:
pygame.sprite.Sprite__init__(self) line 31
you missed dot between Sprite and __init__
so the line should look like:
pygame.sprite.Sprite.__init__(self) #added dot