TypeError: unbound method sprites() - python

For my advanced higher computing course I need to do a project, mines is making space invaders, I have never used python before and I am pretty happy with my progress so far, however I have recently encountered an error that I dont know how to deal with. The code is below.
import pygame
import random
import sys
# --- constants --- (UPPER_CASE names)
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
ORANGE = (255, 255, 0)
YELLOW = ( 0, 255, 255)
DISPLAY_WIDTH = 720
DISPLAY_HEIGHT = 720
FPS = 60
# --- classes --- (CamelCase names)
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images\\user1.gif").convert()
self.image = pygame.transform.scale(self.image, (50, 50))
self.rect = self.image.get_rect()
self.speed_x = 0
def update(self):
self.speed_x = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speed_x = -7
if keystate[pygame.K_RIGHT]:
self.speed_x = 7
self.rect.x += self.speed_x
if self.rect.right > DISPLAY_WIDTH:
self.rect.right = DISPLAY_WIDTH
if self.rect.left < 0:
self.rect.left = 0
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
class Mob(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images\\enemy1.gif").convert()
self.image = pygame.transform.scale(self.image, (50, 50))
self.rect = self.image.get_rect()
self.speed_x = 0
self.rect.x = random.randrange(0, DISPLAY_WIDTH - self.rect.width)
self.rect.y = random.randrange(-500, -40)
self.speedy = random.randrange(5, 11)
def update(self):
self.rect.y +=self.speedy
if self.rect.top > DISPLAY_HEIGHT + 10:
self.rect.x = random.randrange(0, DISPLAY_WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speed_y = random.randrange(5, 11)
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images\\laser1.gif").convert()
self.image = pygame.transform.scale(self.image, (15, 25))
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speed_y = -20
def update(self):
self.rect.y += self.speed_y
if self.rect.bottom < 0:
self.kill()
# --- functions --- (lower_case names)
# empty
# --- main --- (lower_case names)
# - init -
pygame.init()
pygame.mixer.init()
display = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT))
display_rect = display.get_rect()
# - objects and groups -
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
bullet_group = pygame.sprite.Group
player = Player()
player.rect.center = ((DISPLAY_WIDTH / 2), DISPLAY_HEIGHT/1.2)
all_sprites.add(player)
for z in range(8):
mob = Mob()
mobs.add(mob)
all_sprites.add(mob)
background = pygame.image.load("images\\background.jpg")
background = pygame.transform.scale(background, (DISPLAY_WIDTH, DISPLAY_HEIGHT))
# - other -
pygame.mixer.music.load("audio\\soundtrack.mp3")
pygame.mixer.music.play(-1)
pygame.mixer.music.set_volume(0.4)
# - mainloop -
crashed = False
clock = pygame.time.Clock()
while not crashed:
# - checks for a hit -
col = pygame.sprite.spritecollideany(player, mobs)
if col:
sys.exit()
col = pygame.sprite.groupcollide(mobs, bullet_group, True, True)
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shoot()
print(event)
# - updates (without draws) -
all_sprites.update()
# - draws (without updates) -
display.blit(background, (0, 0))
all_sprites.draw(display)
pygame.display.update()
# - FPS -
clock.tick(FPS)
# - end -
pygame.quit()
This is the error message I am receiving, any help would be great, thanks.
C:\Python27\python.exe "C:/Users/Iain/Desktop/Computing Project/Galaxian.py"
Traceback (most recent call last):
File "C:/Users/Iain/Desktop/Computing Project/Galaxian.py", line 132, in <module>
col = pygame.sprite.groupcollide(mobs, bullet_group, True, True)
File "C:\Python27\lib\site-packages\pygame\sprite.py", line 1382, in groupcollide
c = SC(s, groupb, dokillb, collided)
File "C:\Python27\lib\site-packages\pygame\sprite.py", line 1339, in spritecollide
for s in group.sprites():
TypeError: unbound method sprites() must be called with Group instance as first argument (got nothing instead)
Process finished with exit code 1

An "unbound method" is a method object that is obtained from a class. When called, it needs an instance of the class passed to it.
A "bound method" is a method that is bound to an instance of a class. It can be called "normally" since it already has the instance.
In your case, you have a simple typo. You have an unbound method, but it should have been a bound method. The message is misleading because the real problem is the argument you passed to pygame is incorrect.
On line 132 of your program, you call groupcollide. One of the arguments you provide is a variable named bullet_group.
The root cause of the problem is this line:
bullet_group = pygame.sprite.Group
You missed the parentheses, so as a result the name bullet_group refers to the class pygame.sprite.Group. You simply need to add the parentheses to call the class to create an instance of it.
bullet_group = pygame.sprite.Group()
You did this correctly on the preceding lines for mobs and all_sprites.

Related

add() argument after * must be an iterable, not int [duplicate]

Hello I am new to pygame and I am trying to write a shmup game.
However I am always having this error:
TypeError: add() argument after * must be an iterable, not int
self.add(*group)
This is the traceback of the error:
File "C:/Users/Pygame/game.py", line 195, in
player.shoot()
File "C:/Users/Pygame/game.py", line 78, in shoot
bullet = Bullets(self.rect.center,self.angle)
File "C:/Users/Pygame/game.py", line 124, in init
super(Bullets,self).init(pos,angle)
This is the code I have written so far, it works well however when the user wants to shoot the error is being raised.
import os
import pygame
import random
import math
WIDTH = 480
HEIGHT = 600
FPS = 60
#colors:
WHITE = (255,255,255)
BLACK = (0,0,0)
GREEN = (0,250,0)
RED = (255,0,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
#setup assets
game_folder = os.path.dirname("C:/Users/PygameP/")
img_folder = os.path.join(game_folder,"img")
#intialise pygame
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH,HEIGHT))
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((50,40))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH/2
self.rect.bottom = HEIGHT-10
#controls the speed
self.angle = 0
self.orig_image = self.image
#self.rect = self.image.get_rect(center=pos)
def update(self):
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.angle -= 5
self.rotate()
if keystate[pygame.K_RIGHT]:
self.angle += 5
self.rotate()
def rotate(self):
self.image = pygame.transform.rotozoom(self.orig_image, self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)
def shoot(self):
bullet = Bullets(self.rect.center,self.angle)
all_sprites.add(bullet)
bullets.add(bullet)
class Mob(pygame.sprite.Sprite):
def __init__(self):
super(Mob,self).__init__()
self.image = pygame.Surface((30,40))
self.image = meteor_img
self.image = pygame.transform.scale(meteor_img,(50,38))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = int(self.rect.width/2)
self.rect.x = random.randrange(0,WIDTH - self.rect.width)
self.rect.y = random.randrange(-100,-40)
self.speedy = random.randrange(1,8)
#updating the position of the sprite
def update(self):
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10:
self.rect.x = random.randrange(0,WIDTH - self.rect.width)
self.rect.y = random.randrange(-100,-40)
self.speedy = random.randrange(1,8)
class Bullets(pygame.sprite.Sprite):
def __init__(self,pos,angle):
super(Bullets,self).__init__(pos,angle)
# Rotate the image.
self.image = pygame.Surface((10,20))
self.image = bullet_img
self.image = pygame.transform.scale(bullet_img,(50,38))
self.image = pygame.transform.rotate(bullet_img, angle)
self.rect = self.image.get_rect()
speed = 5
self.velocity_x = math.cos(math.radians(-angle))*speed
self.velocity_y = math.sin(math.radians(-angle))*speed
#store the actual position
self.pos = list(pos)
def update(self):
self.pos[0] += self.velocity_x
self.pos[1] += self.velocity_y
self.rect.center = self.pos
if self.rect.bottom <0:
self.kill()
#load all game graphics
background = pygame.image.load(os.path.join(img_folder,"background.png")).convert()
background_rect = background.get_rect()
player_img = pygame.image.load(os.path.join(img_folder,"arrow.png")).convert()
bullet_img = pygame.image.load(os.path.join(img_folder,"bullet.png")).convert()
meteor_img = pygame.image.load(os.path.join(img_folder,"m.png")).convert()
#creating a group to store sprites to make it easier to deal with them
#every sprite we make goes to this group
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
bullets = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(8):
m = Mob()
all_sprites.add(m)
mobs.add(m)
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shoot()
#Update
all_sprites.update()
#checking if a bullet hits a mob
hits = pygame.sprite.groupcollide(mobs,bullets,True,True)
for hit in hits:
m = Mob()
all_sprites.add(m)
mobs.add(m)
hits = pygame.sprite.spritecollide(player,mobs, False,pygame.sprite.collide_circle)
#drawing the new sprites here
screen.fill(BLACK)
#show the background image
screen.blit(background,background_rect)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
Any comments?
You're passing the pos and the angle to the __init__ method of pygame.sprite.Sprite here,
super(Bullets,self).__init__(pos,angle)
but you can only pass sprite groups to which this sprite instance will be added. So just remove those arguments:
super(Bullets,self).__init__()

Pygame Collision Bug

I'm quite new to pygame and came across a bug that i just can't fix on my own. I'm trying to program a Flappy Bird game. The Problem is that the collision detection works, but it also messes with my sprites. If i manage to get past the first obstacle while playing, then the gap resets itself randomly. But the gap should always be the same, just on another position. If i remove the collision detection, it works perfectly fine. Any ideas?
import pygame
import random
randomy = random.randint(-150, 150)
class Bird(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((25,25))
self.image.fill((255,255,255))
self.rect = self.image.get_rect()
self.rect.center = (100, 200)
self.velocity = 0.05
self.acceleration =0.4
def update(self):
self.rect.y += self.velocity
self.velocity += self.acceleration
if self.rect.bottom > 590:
self.velocity = 0
self.acceleration = 0
class Pipe1(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((85, 500))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect()
self.rect.center = (500, randomy)
self.randomyupdate = random.randint(-150, 150)
def update(self):
self.rect.x -= 2
if self.rect.x < -90:
self.randomyupdate = random.randint(-150, 150)
self.rect.center = (450, self.randomyupdate)
class Pipe2(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((85, 500))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect()
self.rect.center = (500, (randomy +640))
def update(self):
self.rect.x -= 2
self.randomyupdate = Pipe1.randomyupdate
if self.rect.x < -90:
self.rect.center = (450, (self.randomyupdate + 640))
pygame.init()
pygame.mouse.set_visible(1)
pygame.key.set_repeat(1, 30)
pygame.display.set_caption('Crappy Bird')
clock = pygame.time.Clock()
Bird_sprite = pygame.sprite.Group()
Pipe_sprite = pygame.sprite.Group()
Bird = Bird()
Pipe1 = Pipe1()
Pipe2 = Pipe2 ()
Bird_sprite.add(Bird)
Pipe_sprite.add(Pipe1)
Pipe_sprite.add(Pipe2)
def main():
running = True
while running:
clock.tick(60)
screen = pygame.display.set_mode((400,600))
screen.fill((0,0,0))
Bird_sprite.update()
Pipe_sprite.update()
Bird_sprite.draw(screen)
Pipe_sprite.draw(screen)
The line im talking about:
collide = pygame.sprite.spritecollideany(Bird, Pipe_sprite)
if collide:
running = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.event.post(pygame.event.Event(pygame.QUIT))
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
Bird.rect.y -= 85
Bird.velocity = 0.05
Bird.acceleration = 0.4
Bird.rect.y += Bird.velocity
Bird.velocity += Bird.acceleration
pygame.display.flip()
if __name__ == '__main__':
main()
This has nothing to do with the collision detection, it has to do with the order of the sprites in the sprite group which can vary because sprite groups use dictionaries internally which are unordered (in Python versions < 3.6). So if the Pipe1 sprite comes first in the group, the game will work correctly, but if the Pipe2 sprite comes first, then its update method is also called first and the previous randomyupdate of Pipe1 is used to set the new centery coordinate of the sprite.
To fix this you could either turn the sprite group into an ordered group, e.g.
Pipe_sprite = pygame.sprite.OrderedUpdates()
or update the rect of Pipe2 each frame,
def update(self):
self.rect.x -= 2
self.rect.centery = Pipe1.randomyupdate + 640
if self.rect.x < -90:
self.rect.center = (450, Pipe1.randomyupdate + 640)
Also, remove the global randomy variable and always use the randomyupdate attribute of Pipe1.

Appending a csv file in python

So I am making a space invaders game in python, the game will take the score the player has achieved and will add it to a csv file. My code for the csv file is:
col = pygame.sprite.spritecollideany(player, mobs)
if col:
with open("rec_Scores.csv", "a", newline" ") as f:
w = csv.writer(f, dilimiter = ",")
for i in range(len(score)):
w.writerow(name[i], score[i]])
crashed = True
However, I get the error:
File "C:\Users\Harry\Desktop\Desktop\Computing Project\Galaxian.py", line 162
with open("rec_Scores.csv", "a", newline" ") as f:
^
SyntaxError: invalid syntax
I am really stuck with this problem and I have no idea how to solve it. Any help would be much appreciated. Here is my code because I am probably going about this in a completely idiotic way:
import pygame
import random
import sys
import csv
# --- constants --- (UPPER_CASE names)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
ORANGE = (255, 255, 0)
YELLOW = (0, 255, 255)
DISPLAY_WIDTH = 720
DISPLAY_HEIGHT = 720 # sets res for the screen
FPS = 60
# --- classes --- (CamelCase names)
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images\\user1.gif").convert()
self.image = pygame.transform.scale(self.image, (50, 50))
self.rect = self.image.get_rect()
self.speed_x = 0
def update(self):
self.speed_x = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speed_x = -10
if keystate[pygame.K_RIGHT]:
self.speed_x = 10
self.rect.x += self.speed_x
if self.rect.right > DISPLAY_WIDTH:
self.rect.right = DISPLAY_WIDTH
if self.rect.left < 0:
self.rect.left = 0
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullet_group.add(bullet)
class Mob(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.speed_y = random.randrange(5, 11)
self.image = pygame.image.load("images\\enemy1.gif").convert()
self.image = pygame.transform.scale(self.image, (50, 50))
self.rect = self.image.get_rect()
self.speed_x = 0
self.rect.x = random.randrange(0, DISPLAY_WIDTH - self.rect.width)
self.rect.y = random.randrange(-500, -40)
self.speedy = random.randrange(5, 11)
def update(self):
self.rect.y += self.speedy
if self.rect.top > DISPLAY_HEIGHT + 10:
self.rect.x = random.randrange(0, DISPLAY_WIDTH - self.rect.width)
self.rect.y = random.randrange(-500, -40)
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images\\laser1.gif").convert() # sets the laser to be the image laser1.gif
self.image = pygame.transform.scale(self.image, (15, 25)) # trasforms the size to fit the screen
self.rect = self.image.get_rect() # sets hit box up, will fit around the image
self.rect.bottom = y
self.rect.centerx = x
self.speed_y = -30
def update(self):
self.rect.y += self.speed_y
if self.rect.bottom < 0:
self.kill()
# --- functions --- (lower_case names)
# --- main --- (lower_case names)
score =0
name = raw_input("Enter your name: ")
# - init -
pygame.init()
pygame.mixer.init()
display = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT))
display_rect = display.get_rect()
# - objects and groups -
all_sprites = pygame.sprite.Group() # creates class that all sprites will be in
mobs = pygame.sprite.Group() # creates class that all mobs will be stored in
bullet_group = pygame.sprite.Group() # creates class that all bullets will be stored in
player = Player() # assigns the player variable to the player class
player.rect.center = ((DISPLAY_WIDTH / 2), DISPLAY_HEIGHT / 1.2) # sets the player to spawn at the bottom and in the middle of the screen
all_sprites.add(player) # adds player to the all_sprites group
for z in range(12): # spawns 13 enemies
mob = Mob()
mobs.add(mob)
all_sprites.add(mob)
# - other -
pygame.mixer.music.load("audio\\soundtrack.mp3")
pygame.mixer.music.play(-1) # sets music to play in an infinite loop
pygame.mixer.music.set_volume(0.2)
# - mainloop -
crashed = False
clock = pygame.time.Clock()
while not crashed:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LCTRL:
player.shoot()
print(event)
# - updates (without draws) -
all_sprites.update() # updates sprite positions without drawing them onto the screen
# - draws (without updates) -
background = pygame.image.load("images\\background.jpg") # assigns the picture to a variable called background
background = pygame.transform.scale(background, (DISPLAY_WIDTH, DISPLAY_HEIGHT)) # streches the picture to fit the screen
display.blit(background, (0, 0)) # displays the background image
all_sprites.draw(display) # draws all sprites onto the screen
font = pygame.font.SysFont("monospace", 15)
text = font.render("Score: " + str(score), True, BLACK)
display.blit(text, (0, 0))
pygame.display.update() # updates display
# - Checks for a hit -
col = pygame.sprite.groupcollide(mobs, bullet_group, True, True)
if col: # if col = true then
mob = Mob() # spawns new mob
mobs.add(mob)
all_sprites.add(mob)
score += 10
# - checks for a collision -
col = pygame.sprite.spritecollideany(player, mobs)
if col:
with open("rec_Scores.csv", "a", newline" ") as f:
w = csv.writer(f, dilimiter = ",")
for i in range(len(score)):
w.writerow(name[i], score[i]])
crashed = True
# - FPS -
clock.tick(FPS) # built in function to make the program stay below specified frame per second
# - end -
pygame.quit()
Thank you in advance for any help.
with open("rec_Scores.csv", "a", newline" ") as f:
Should be:
with open("rec_Scores.csv", "a") as f:
delimiter is misspelled as dilimiter but is unneeded anyway.
The f.writerow arguments are not quite what you want here.
Next time try making a working reproducer that has all bits of code needed to work including import statements.
Actual working version:
import csv
name=['foo','bar']
score=[12345,54321]
with open("rec_Scores.csv", "a") as f:
w = csv.writer(f)
for i in range(len(score)):
w.writerow([str(name[i]),str(score[i])])

TypeError: 'Alien' object is not iterable

I'm working on a space shooter and I've made the sprites and added some basic collision detection, but when I added in collision detection for whether or not an alien sprite collides with the player sprite, it gave me this error message:
Traceback (most recent call last):
File "main.py", line 93, in <module>
game.new()
File "main.py", line 33, in new
self.run()
File "main.py", line 45, in run
self.collision()
File "main.py", line 58, in collision
hits = pygame.sprite.spritecollide(self.player, self.alien, False)
File "C:\Users\sidna\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pygame\sprite.py", line 1525, in spritecollide
return [s for s in group if spritecollide(s.rect)]
TypeError: 'Alien' object is not iterable
Here's my code:
main.py
# IMPORTS
import pygame, random
from sprites import *
from config import *
# GAME
class Game():
def __init__(self):
# INIT PYGAME
pygame.init()
pygame.mixer.init()
pygame.display.set_caption(TITLE)
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
self.clock = pygame.time.Clock()
self.running = True
# NEW GAME
def new(self):
self.allSprites = pygame.sprite.Group()
self.allAliens = pygame.sprite.Group()
self.player = Player()
for i in range(ALIEN_AMOUNT):
self.alien = Alien()
self.allSprites.add(self.alien)
self.allAliens.add(self.alien)
self.allSprites.add(self.player)
self.run()
# RUN GAME
def run(self):
self.playing = True
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
self.collision()
# DRAW
def draw(self):
self.screen.fill(BLACK)
self.allSprites.draw(self.screen)
self.allAliens.draw(self.screen)
pygame.display.update()
# DETECT COLLISION
def collision(self):
# alien collision with player
hits = pygame.sprite.spritecollide(self.player, self.alien, False)
if hits:
running = False
# CHECK FOR EVENTS
def events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
if self.playing:
self.playing = False
self.running = False
# UPDATE GAME
def update(self):
self.allSprites.update()
self.allAliens.update()
# GAME OVER
def gameOver(self):
pass
# START SCREEN
def startScreen(self):
pass
# END SCREEN
def endScreen(self):
pass
game = Game()
game.startScreen()
while game.running:
game.new()
game.gameOver()
pygame.quit()
quit()
sprites.py
import pygame, random
from config import *
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("assets/img/player.png").convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT - 10
self.velX = 0
def animate(self):
self.rect.x += self.velX
def collision(self):
# collision with walls
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.left < 0:
self.rect.left = 0
def control(self):
self.velX = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.velX = -5
if keystate[pygame.K_RIGHT]:
self.velX = 5
def update(self):
self.animate()
self.collision()
self.control()
class Alien(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("assets/img/alien.png").convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.x = random.randrange(0, WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.velY = random.randrange(1, 4)
self.velX = random.randrange(-4, 4)
def animate(self):
self.rect.y += self.velY
self.rect.x += self.velX
def collision(self):
# collision with walls
if self.rect.top > HEIGHT + 10 or self.rect.left < -20 or self.rect.right > WIDTH + 20:
self.rect.x = random.randrange(0, WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.velY = random.randrange(1, 4)
self.velX = random.randrange(-4, 4)
def update(self):
self.animate()
self.collision()
config.py
# IMPORTS
import pygame
# ENTIRE GAME VARIABLES
TITLE = "Alien Invasion"
WIDTH = 360
HEIGHT = 570
FPS = 60
# ALIEN CONFIG
ALIEN_AMOUNT = 10
# COLORS
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
The problem is here:
hits = pygame.sprite.spritecollide(self.player, self.alien, False)
The spritecollide() function works like this (from the docs):
spritecollide(sprite, group, dokill, collided = None) -> Sprite_list
You put 'self.alien' as the second parameter, but spritecollide expects a group there. If you just want to collide two different sprites, you want to use collide_rect:
hits = pygame.sprite.collide_rect(self.player, self.alien)
You'll get back True/False whether the two sprites are colliding.
See here for details on all the various collision methods:
http://www.pygame.org/docs/ref/sprite.html

Spawning enemy sprites

For my computing project I need to make some sort of app or game. I decided I would make space invaders. I have managed to get the basics working, the player sprite would spawn I could move it and the background and music worked properly, but now when I have tried to create enemy sprites I keep getting this error:
C:\Python27\python.exe "C:/Users/Harry/Desktop/Computing Project/Galaxian.py"
Traceback (most recent call last):
File "C:/Users/Harry/Desktop/Computing Project/Galaxian.py", line 87, in <module>
mobs.add(Mob)
TypeError: unbound method add() must be called with Mob instance as first argument (got type instance instead)
Process finished with exit code 1
If anyone could help I would really appreciate it! Here is my code:
import pygame
import random
# --- constants --- (UPPER_CASE names)
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
ORANGE = (255, 255, 0)
YELLOW = ( 0, 255, 255)
DISPLAY_WIDTH = 720
DISPLAY_HEIGHT = 720
FPS = 60
# --- classes --- (CamelCase names)
class Player(pygame.sprite.Sprite):
# <-- empty line for readabelity
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images\\user1.gif").convert()
self.image = pygame.transform.scale(self.image, (50, 50))
self.rect = self.image.get_rect()
self.speed_x = 0
def update(self):
self.speed_x = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speed_x = -7
if keystate[pygame.K_RIGHT]:
self.speed_x = 7
self.rect.x += self.speed_x
if self.rect.right > DISPLAY_WIDTH:
self.rect.right = DISPLAY_WIDTH
if self.rect.left < 0:
self.rect.left = 0
class Mob(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((30, 40))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = random.randrange(0, DISPLAY_WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
def update(self):
self.rect.y +=self.speedy
if self.rect.top > DISPLAY_HEIGHT + 10:
self.rect.x = random.randrange(0, DISPLAY_WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
# --- functions --- (lower_case names)
# empty
# --- main --- (lower_case names)
# - init -
pygame.init()
pygame.mixer.init()
display = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT))
display_rect = display.get_rect()
# - objects -
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
player = Player()
player.rect.center = ((DISPLAY_WIDTH / 2), 650)
all_sprites.add(player)
for z in range(8):
mobs = Mob()
all_sprites.add(mobs)
mobs.add(Mob)
background = pygame.image.load("C:\\Users\\Harry\\Desktop\\Computing Project\\images\\background.jpg")
background = pygame.transform.scale(background, (DISPLAY_WIDTH, DISPLAY_HEIGHT))
# - other -
pygame.mixer.music.load("C:\\Users\\Harry\\Desktop\\Computing Project\\Audio\\music\\soundtrack.mp3")
pygame.mixer.music.play(-1)
pygame.mixer.music.set_volume(0.4)
# - mainloop -
crashed = False
clock = pygame.time.Clock()
while not crashed:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
print(event)
# - updates (without draws) -
all_sprites.update()
# - draws (without updates) -
display.blit(background, (0, 0))
all_sprites.draw(display)
pygame.display.update()
# - FPS -
clock.tick(FPS)
# - end -
pygame.quit()
TypeError: unbound method add() must be called with Mob instance as first argument (got type instance instead)
The problem is that you've called the add method and passed in the name of the class Mob but not an instance of Mob.
all_sprites.add(player)
for z in range(8):
mobs = Mob()
all_sprites.add(mobs)
mobs.add(Mob) # This is the class name
Depending on the interface of add() you'll probably want to do:
mob = Mob()
mobs.add(mob)
But it's a bit unclear here what you're trying to accomplish

Categories

Resources