I am currently creating a game where each enemy has a specific AI. Each enemy is given an AI and statistic changes(health, damage, etc.). However, I also need to assign these enemies to an NPC slot before the game's main loop is run. The problem comes in because I need to identify the x-value and y-value of the enemy so the game knows where to place them. If I keep the x- and y-values as a parameter in the AI class, I have to repeatedly redefine them when I put them in an NPC slot(my slots are labelled 'NPC1', 'NPC2', and so on).
class PeonGrounded(object):
def __init__(self, x, y, width, height, vel, aggrorange, health=20.0, kb=10, jumplength=10.0, jumpheight=2.0,
jumpmomentum=0.25):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = vel
self.direction = 'R'
self.standing = True
self.health = health
self.canMove = True
self.jumplength = jumplength
self.isJump = False
self.canJump = True
self.kb = kb
self.jumpheight = jumpheight
self.jumpmomentum = jumpmomentum
self.neg = 1
self.aggrorange = aggrorange
self.aggroed = False
I now want to be able to define some parameters(everything but x, y, width, height) but leave others blank for defining later.
Related
This question already has answers here:
How can I make a sprite move when key is held down
(6 answers)
Closed 1 year ago.
Hi am new fairly new to programming so I tried to learn by making my hands dirty. I tried making a simple box game program all was working fine until I made my player Class which inherit from the base class of Box_User for some reasons my box(player class object) is no longer moving I tried to see what it prints and it seems like none of the keys work when I press them
Can anyone explain what happened?
import pygame
pygame.init()
# Classes
class Window():
def __init__(self, width, height):
self.width = width
self.height = height
self.window_init() # this functions is to get the window up
def window_init(self):
self.window = pygame.display.set_mode((self.width, self.height)) # this is the main window
self.background = pygame.Surface((self.window.get_size())) # this one is named background but should be use like the main window
self.background.fill((255, 255, 255))
#staticmethod
def draw_objects_to_Screen():
win.window.blit(win.background, (0,0))
win.window.blit(box.box, (box.pos_x - scroll[0], box.pos_y + scroll[1])) # the scroll is used to make it look like its moving
win.window.blit(box2.box, (box2.pos_x - scroll[0], box2.pos_y + scroll[1]))
pygame.display.update()
class Box_User():
jump = 10
jump_status = False
def __init__(self, x, y, height, width):
self.pos_x = x
self.pos_y = y
self.box_height = height
self.box_width = width
self.box = pygame.Surface((self.box_height, self.box_width))
self.color = (0, 20, 0)
self.draw_box()
def draw_box(self):
pygame.draw.rect(self.box, self.color, pygame.Rect(self.pos_x, self.pos_y, self.box_height, self.box_width))
#staticmethod
def _jump():
if Box_User.jump >= -10:
box.pos_y -= (Box_User.jump * abs(Box_User.jump)) * 0.3
scroll[1] += (Box_User.jump * abs(Box_User.jump)) * 0.3
Box_User.jump -= 1
else:
Box_User.jump = 10
Box_User.jump_status = False
class Player(Box_User):
key_pressed = pygame.key.get_pressed()
def __init__(self, x, y, height, width):
super().__init__(x, y, height, width)
# self.pos_x = x
#self.pos_y = y
def movements(self):
if self.key_pressed[pygame.K_a]:
self.pos_x -= 5
if self.key_pressed[pygame.K_d]:
self.pos_x += 5
# place here things that you dont want to move while the box is jumping
if not self.jump_status:
if self.key_pressed[pygame.K_w]:
self.jump_status = True
else:
self._jump() # the box jumps here
class Auto_Box(Box_User):
def __init__(self, x, y, height, width):
super().__init__(x, y, height, width)
pass
# Variables
# window
win = Window(700, 500)
clock = pygame.time.Clock()
FPS = 60
# boxes
box = Player(30, 200, 64, 64)
box2 = Box_User(300, 200, 100, 120)
# The Scroll which controls the things when the box is moving
scroll = [0, 0]
# Functions
# Main Loop
def main():
run = True
while run:
clock.tick(FPS)
# value of the scroll is updated here
scroll[0] += (box.pos_x - scroll[0]-250)
#print("coordinate are")
#print(scroll)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
box.movements()
print(box.pos_x, box.pos_y)
Window.draw_objects_to_Screen()
if __name__ == "__main__":
main()
pygame.key.get_pressed() returns a list of booleans that represent the state of the keyboard when you call the function.
If you continually check that list, no keys will ever change state. It's just a list of Trues and Falses.
You need to reset the values of key_pressed in the loop, updating it with fresh values from pygame.key.get_pressed().
This should do the trick:
def movements(self):
self.key_pressed = pygame.key.get_pressed()
if self.key_pressed[pygame.K_a]:
self.pos_x -= 5
...
The key_pressed class variables is only initialized once. It is never changed. Therefore the pressed keys are not detected.
pygame.key.get_pressed() returns a iterable with the current state of all keyboard buttons. You must get the states of the keys in every frame:
class Player(Box_User):
def __init__(self, x, y, height, width):
super().__init__(x, y, height, width)
def movements(self):
# get the current states of the keys
self.key_pressed = pygame.key.get_pressed()
if self.key_pressed[pygame.K_a]:
self.pos_x -= 5
if self.key_pressed[pygame.K_d]:
self.pos_x += 5
# place here things that you dont want to move while the box is jumping
if not self.jump_status:
if self.key_pressed[pygame.K_w]:
self.jump_status = True
else:
self._jump() # the box jumps here
I am creating tetris using pygame. i want to use collision detection so that when the shape in play comes into contact with any other previously played shapes, i can stop the shape, as per the logic of tetris. i came across pixel perfect collision using masks. i have followed some tutorials online, however the pixel detection returns true every time a new shape comes into play, not when any shapes collide. sorry in advance for the long code, its the bare minimum for the code to actually and still containing the game element of it. i think there is something wrong with my approach which is causing this error. I basically have a function that everytime the shape in play comes into contact with the 'floor' that shape is held in that position and a new shape is created. i think ive overcomplicated it, in turn creating this error. thanks in advance
import pygame
import sys
import shapelogic
pygame.init()
screensize = width, height = 800, 595
screen = pygame.display.set_mode(screensize)
background_image =pygame.image.load("/Users/marceason/PycharmProjects/Tetris/Wooden_background.jpg").convert_alpha()
myshape = 0
stop_movement = 0
blit_count = 0
stored_shapes = pygame.sprite.Group()
stored_shapes_with_coords = []
extra_blit_required = False
index = 0
count = 0
listofshapes = []
class shapemanager():
def __init__(self):
self.listofshapes = []
def create_another_instance(self):
global count
count += 1
string = "Shape_{0},".format(count)
another_shape = Shape(string)
self.listofshapes.append(another_shape)
global index
object = self.listofshapes[index]
index += 1
return object
def load_shape(self):
shape = self.create_another_instance()
shape.load_shapes()
class Shape(pygame.sprite.Sprite):
def __init__(self, name):
pygame.sprite.Sprite.__init__(self)
self.name = name
self.x = 50
self.y = 100
self.move_event = pygame.USEREVENT + 1
self.reached_bottom_event = pygame.USEREVENT + 2
self.one_sec_timer = 1000
self.half_sec_timer = 500
self.reachbottomflag = False
self.movement_possible = True
self.image = pygame.image.load(
"/Users/marceason/PycharmProjects/Tetris/Tetris_Shapes/Green_Shape_1_Position_1.png")
self.mask = pygame.mask.from_surface(self.image)
self.rect = self.image.get_rect()
def move_shape(self):
if self.movement_possible:
key_input = pygame.key.get_pressed()
if key_input[pygame.K_LEFT]:
self.x -= 16
if key_input[pygame.K_RIGHT]:
self.x += 16
if not self.reachbottomflag:
if key_input[pygame.K_DOWN]:
self.y += 16
def reachbottom(self):
if self.y >= 560:
self.reachbottomflag = True
def no_movement_possible(self):
self.movement_possible = False
def assign_shape():
global myshape
global stop_movement
myshape = sl.create_another_instance()
pygame.time.set_timer(myshape.move_event, myshape.one_sec_timer)
stop_movement = pygame.time.set_timer(myshape.reached_bottom_event, myshape.half_sec_timer)
def blit_used_shapes():
global screen
global blit_count
blit_count = len(stored_shapes_with_coords)
local_count = 0
while local_count < blit_count:
screen.blit(stored_shapes_with_coords[local_count][0], (stored_shapes_with_coords[local_count][1], stored_shapes_with_coords[local_count][2]))
local_count += 1
sl = shapemanager()
##### HERE IS THE PIXEL DETECTION #####
result = pygame.sprite.spritecollide(myshape, stored_shapes, False, pygame.sprite.collide_mask)
## Main loop ##
assign_shape()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
screen.blit(background_image, (0, 0))
screen.blit(myshape.image, (myshape.x, myshape.y))
myshape.move_shape()
key_input = pygame.key.get_pressed()
if key_input[pygame.K_SPACE]:
myshape.rotate_shape()
myshape.reachbottom()
if myshape.reachbottomflag:
if event.type == myshape.reached_bottom_event:
myshape.no_movement_possible()
stored_shape_tuple = [myshape.image, myshape.x, myshape.y]
stored_shapes_with_coords.append(stored_shape_tuple)
stored_shapes.add(myshape)
extra_blit_required = True
assign_shape()
####### PIXEL DETECTION IS HERE IN FOR LOOP ####
if result:
print("this should only execute when two shapes touch!!")
if extra_blit_required:
blit_used_shapes()
pygame.display.update()
The issue is that you are not updating the sprites rect attribute. The sprites rects all have position (0, 0) (since you do not set it in the call to self.image.get_rect()) and as a result the masks will all overlap and collide.
If you read the docs for pygame.sprite.collide_mask you will note that it says that your sprites need to have mask and rect attributes. You have a rect in your sprite and you set it in the __init__(), but you do not keep it updated when you move the sprite. You just change the x and y attributes without adjusting the rect position. The reason that the collide_mask wants a rect is that it uses that to determine the offset parameter for the pygame.mask.Mask.overlap() call that it uses. The important thing to realize is that masks themselves do not have a position, they need the rects to determine the relative positions of the masks.
This is similar to images/surfaces not having a position and needing a rect to track that for them.
On a separate issue, the way you are blit'ing the sprites to the screen makes no sense. You are not using the abilities of the sprite groups to draw and worse you are keeping the image, x and y of the sprite in a separate list and not containing it in the sprite itself. You should go look at some examples of pygame sprite based code. There are lots of examples out there.
import pygame
width = 500
height = 500
win = pygame.display.set_mode((width,height))
pygame.display.set_caption("Client")
clientNumber = 0
class Player():
def __init__(self,x,y,width,height,color,win):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.rect = (self.x,self.y,self.width,self.height)
self.val = 3
self.win = win
def draw(self):
pygame.draw.rect(self.win, self.color, self.rect)
def move(self):
keyPressed = pygame.key.get_pressed()
if keyPressed[pygame.K_LEFT]:
self.x = self.x - self.val
if keyPressed[pygame.K_RIGHT]:
self.x = self.x + self.val
if keyPressed[pygame.K_UP]:
self.y = self.y - self.val
if keyPressed[pygame.K_DOWN]:
self.y = self.y + self.val
def refreshWindow(win,player):
win.fill((255,255,255))
player.draw()
pygame.display.update()
def main():
player = Player(50,50,100,100,(0,255,0),win)
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
player.move()
refreshWindow(win,player)
main()
The code is updating self.x and self.y and key is being pressed, but the display is not changing the
position of the rectangle. I am new to this and was learning from a tutorial. My code is the exact as that tutorial guide but its not working. Like only its not displaying the updated version. The rest is working fine, i printed statements to verify that the window object is the same and if key was pressed and if x and y coordinates were being changed or not.
Though you have answered your question and fixed your issue I want to mention something. It is not a great idea to have your game object keep both a self.rect and separate self.x, self.y, self.width, self.height attributes as you are doing.
All those attributes are contained within the rect and keeping to separate versions of the same data just means that you have to be updating them both and is large potential for errors either because one or the other did not get updated, or because the state was checked before it got updated and so it contained an old value.
just use a Rect and access the x, y, width, height values as attributes in it like this self.rect.x, self.rect.y, self.rect.width, self.rect.height.
You should check the docs for Rect here and see how much more useful it is than working with separate x,y,width, and height values. For example being able to manipulate it by the center, or being able to directly test the right edge without having to add the width, etc.
The exception with respect to keeping a separate self.x and self.y is if you are having issues related to angular movement where your velocity could be fractional and need floating point accuracy for the positions, since Rects keep int values. In that case you would keep adjust the self.x += vel_x and self.y += vel_y and then immediately assign the x,y to the rect self.rect.topleft = round(self.x), round(self.y) and then use the rect for the rest. The x and y are just for the position accuracywhen you need fractional position adjustments, which does not apply here in your example.
Never mind, i fixed it. I was not changing the self.rect values. Although the tutorial didnt change it. Anyways, its working now.
I want to change an image of the object worker each time when it stops.
The class Worker is created based on the answer of #sloth in this thread.
class Worker(pygame.sprite.Sprite):
def __init__(self, image_file, location, *groups):
# we set a _layer attribute before adding this sprite to the sprite groups
# we want the workers on top
self._layer = 1
pygame.sprite.Sprite.__init__(self, groups)
self.image = pygame.transform.scale(pygame.image.load(image_file).convert_alpha(), (40, 40))
self.rect = self.image.get_rect(topleft=location)
# let's call this handy function to set a random direction for the worker
self.change_direction()
# speed is also random
self.speed = random.randint(1, 3)
def change_direction(self):
# let's create a random vector as direction, so we can move in every direction
self.direction = pygame.math.Vector2(random.randint(-1,1), random.randint(-1,1))
# we don't want a vector of length 0, because we want to actually move
# it's not enough to account for rounding errors, but let's ignore that for now
while self.direction.length() == 0:
self.direction = pygame.math.Vector2(random.randint(-1,1), random.randint(-1,1))
# always normalize the vector, so we always move at a constant speed at all directions
self.direction = self.direction.normalize()
def update(self, screen):
# there is a less than 1% chance every time that direction is changed
if random.uniform(0,1)<0.005:
self.change_direction()
# now let's multiply our direction with our speed and move the rect
vec = [int(v) for v in self.direction * self.speed]
self.rect.move_ip(*vec)
# if we're going outside the screen, move back and change direction
if not screen.get_rect().contains(self.rect):
self.change_direction()
self.rect.clamp_ip(screen.get_rect())
I try to create a cache of pre-loaded images
image_cache = {}
def get_image(key):
if not key in image_cache:
image_cache[key] = pygame.image.load(key)
return image_cache[key]
Then I assume that it is necessary to add the following code into def __init__:
images = ["worker.png", "worker_stopped.png"]
for i in range(0,len(images)):
self.images[i] = get_image(images[i])
and the following code into def update(self):
if self.direction.length() == 0:
self.image = self.images[1]
else:
self.image = self.images[0]
However, it does not seem to work properly. The old image worker.png does not disappear and the whole animation gets locked.
I think you should introduce some kind of state to indicate that the worker is running or not. Here's an example. Note the comments:
class Worker(pygame.sprite.Sprite):
# we introduce to possible states: RUNNING and IDLE
RUNNING = 0
IDLE = 1
def __init__(self, location, *groups):
# each state has it's own image
self.images = {
Worker.RUNNING: pygame.transform.scale(get_image("worker.png"), (40, 40)),
Worker.IDLE: pygame.transform.scale(get_image("worker_stopped.png"), (40, 40))
}
self._layer = 1
pygame.sprite.Sprite.__init__(self, groups)
# let's keep track of the state and how long we are in this state already
self.state = Worker.IDLE
self.ticks_in_state = 0
self.image = self.images[self.state]
self.rect = self.image.get_rect(topleft=location)
self.direction = pygame.math.Vector2(0, 0)
self.speed = random.randint(2, 4)
self.set_random_direction()
def set_random_direction(self):
# random new direction or standing still
vec = pygame.math.Vector2(random.randint(-100,100), random.randint(-100,100)) if random.randint(0, 5) > 1 else pygame.math.Vector2(0, 0)
# check the new vector and decide if we are running or fooling around
length = vec.length()
speed = sum(abs(int(v)) for v in vec.normalize() * self.speed) if length > 0 else 0
if length == 0 or speed == 0:
new_state = Worker.IDLE
self.direction = pygame.math.Vector2(0, 0)
else:
new_state = Worker.RUNNING
self.direction = vec.normalize()
self.ticks_in_state = 0
self.state = new_state
# use the right image for the current state
self.image = self.images[self.state]
def update(self, screen):
self.ticks_in_state += 1
# the longer we are in a certain state, the more likely is we change direction
if random.randint(0, self.ticks_in_state) > 30:
self.set_random_direction()
# now let's multiply our direction with our speed and move the rect
vec = [int(v) for v in self.direction * self.speed]
self.rect.move_ip(*vec)
# if we're going outside the screen, change direction
if not screen.get_rect().contains(self.rect):
self.direction = self.direction * -1
self.rect.clamp_ip(screen.get_rect())
I'm working on a natural selection simulator. I've asked a question pertaining to it before (How to test if areas overlap). Now I have a version of the code that I'd like to run but it does not. Instead of getting an error message, however, the window opens, but the simulation (that otherwise seems to me as though it should run) does not run.
It would seem to me that the problem has something to do with the initial spawn information not being passed into the main class for my organisms, but I can't be sure.
If anyone could identify why the code isn't working and tell me what I'd need to correct I'd really appreciate it.
UPDATE
The command line returns information that the code is running, so the problem must be that the display isn't working. It definitely has to do with my sprites because removing
self.image.fill(colors['hotpink2'])
self.image.set_colorkey(colors['hotpink2'])
self.mask = pygame.mask.from_surface(self.image)
from the init causes the rectangles to display briefly.
The updated code is as follows:
# Import libraries
import pygame, random, numpy
# Initialize PyGame
pygame.init()
# Define colors
colors = pygame.color.THECOLORS
# Set window dimensions
mapWidth = 800
mapHeight = 800
size = [mapWidth, mapHeight]
screen = pygame.display.set_mode(size)
# Display program title in window
pygame.display.set_caption("Natural Selection Game")
# Loop until user closes window
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# Generate IDs for organisms
def id_generator():
i = 0
while True:
i += 1
yield i
ids = id_generator()
# Prevent organisms from colliding with self
def collide(a, b):
if a.id == b.id:
return False
return pygame.sprite.collide_mask(a, b)
# ----- Organisms -----
class Organism(pygame.sprite.Sprite):
def __init__(self, width, height, x, y, changeX, changeY, lifespan, species):
# Make PyGame Sprite
pygame.sprite.Sprite.__init__(self, organisms)
self.id = next(ids)
# Set dimensions
self.width = width
self.height = height
# Set starting point
self.x = x
self.y = y
# Set motion type
self.changeX = changeX
self.changeY = changeY
# Set lifespan
self.lifespan = lifespan
# Set species
self.species = species
if species == 'paper':
self.color = colors['red']
elif species == 'rock':
self.color = colors['green']
elif species == 'scissors':
self.color = colors['blue']
# Set age at birth
self.age = 0
# Recognize collisions as to produce only one offspring
self.colliding = set()
# Sprite body
self.rect = pygame.rect.Rect(x, y, width, height)
self.image = pygame.Surface((width, height))
self.image.fill(colors['hotpink2'])
self.image.set_colorkey(colors['hotpink2'])
# Draw
pygame.draw.ellipse(self.image, self.color, [self.x, self.y, self.width, self.height])
self.mask = pygame.mask.from_surface(self.image)
# Randomly generate traits for first generation
#classmethod
def initialSpawn(cls):
# Set dimensions for first generation
width = random.randrange(5,50)
height = random.randrange(5,50)
# Set starting point for first generation
x = random.randrange(0 + width, 800 - width)
y = random.randrange(0 + height, 800 - height)
# Set motion type for first generation
changeX = random.randrange(0,6)
changeY = random.randrange(0,6)
# Set lifespan for first generation
lifespan = random.randrange(300,700)
# Set species for first generation
species = random.choice(['paper', 'rock', 'scissors'])
return cls(width, height, x, y, changeX, changeY, lifespan, species)
# Inherit and/or mutate traits for offspring
def reproduce(self, collidee):
# Set dimensions for offspring
width = random.choice(self.width, collidee.height)
height = random.choice(self.width, collidee.height)
# Set starting points for offspring
x = random.choice(self.x, collidee.x)
y = random.choice(self.y, collidee.y)
# Set motion type for offspring
changeX = random.choice(self.changeX, collidee.changeX)
changeY = random.choice(self.changeY, collidee.changeY)
# Set lifespan for offspring
lifespan = numpy.mean(self.lifespan, collidee.lifespan)
# Set species for offspring
species = self.species
return width, height, x, y, changeX, changeY, species
def update(self):
# Update age
self.age += 1
# Update movement
self.rect.move_ip(self.changeX, self.changeY)
# Manage bouncing
if self.rect.left < 0 or self.rect.right > mapWidth:
self.changeX *= -1
if self.rect.top < 0 or self.rect.bottom > mapHeight:
self.changeY *= -1
# Death from aging
if self.age > self.lifespan:
print (self.id, ' died of age')
self.kill()
return
# Check if collided with another organism of same species for mating or predation
collidee = pygame.sprite.spritecollideany(self, organisms, collide)
# Check the prerequisites for mating:
# - Not already colliding
# - Same species
# - No overpopulation
if collidee and not collidee.id in self.colliding and self.species == collidee.species and len(self.organisms) < 100:
# Keep track of the current collision, so this code is not triggerd throughout duration of collision
self.colliding.add(collidee.id)
collidee.colliding.add(self.id)
print (self.id, ' mated with ', collidee.id)
# The fun part! ;)
self.reproduce(collidee)
# Check the prerequisites for predation:
# - Not already colliding
# - Different species
elif collidee and not collidee.id in self.colliding and self.species != collidee.species:
if self.species == 'paper' and collidee.species == 'rock':
collidee.kill()
self.lifespan += 100
elif self.species == 'rock' and collidee.species == 'scissors':
collidee.kill()
self.lifespan += 100
elif self.species == 'scissors' and collidee.species == 'paper':
collidee.kill()
self.lifespan += 100
else:
# Organism is single and ready to mingle
self.colliding = set()
# Organism group
organisms = pygame.sprite.Group()
# Initial spawner
for i in range(15):
organisms.add(Organism.initialSpawn())
# ----- Simulation -----
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Logic
organisms.update()
# Draw screen
screen.fill(colors['white'])
# Draw organisms
organisms.draw(screen)
# FPS
clock.tick(60)
# Update drawings
pygame.display.flip()
pygame.quit()
You're calling a class method Organism.initialSpawn() which returns width, height, x, y, changeX, changeY, lifespan, species but you don't do anything with it. It just goes directly to garbage collection.
You're probably trying to create a new organism from the variables you're given, and add those in the pygame.sprite.Group. This can be done like this:
# Organism group
organisms = pygame.sprite.Group()
# Initial spawner
for i in range(15):
temp = Organims(*Organism.initialSpawn())
organisms.add(temp)
Although, your initialSpawn() method has the wrong syntax. All methods in a class needs self as first parameter unless something else is specified. I would make it a class method and instead of returning a bunch of variables that you use to create a new Organism, you just return a new Organism directly.
class Organism(pygame.sprite.Sprite):
# Randomly generate traits for first generation
#classmethod
def initialSpawn(cls):
# Set dimensions for first generation
width = random.randrange(5,50)
height = random.randrange(5,50)
# Set starting point for first generation
x = random.randrange(0 + width, 800 - width)
y = random.randrange(0 + height, 800 - height)
# Set motion type for first generation
changeX = random.randrange(0,6)
changeY = random.randrange(0,6)
# Set lifespan for first generation
lifespan = random.randrange(300,700)
# Set species for first generation
species = random.choice(['paper', 'rock', 'scissors'])
if species == 'paper':
color = colors['red']
elif species == 'rock':
color = colors['green']
elif species == 'scissors':
color = colors['blue']
return cls(width, height, x, y, changeX, changeY, lifespan, species)
# Organism group
organisms = pygame.sprite.Group()
# Initial spawner
for i in range(15):
organisms.add(Organism.initialSpawn())
EDIT: Okay, I looked closer on your code and you have lots of errors.
Need to put self in your __init__ method as first parameter.
In __init__, you have an unidentified function add(organisms). Remove that.
In __init__, you're creating a color variable based on a condition but you don't use it. Instead you're trying to use an attribute self.color which you don't have. Change the variables color to attributes self.color.
In __init__, you're trying to access the class Surface by typing pygame.surface.Surface. There's no module surface and the class is in the pygame module. Just type pygame.Surface instead.
Add a decorator #classmethod and cls for InitialSpawn as I did above.
In InitialSpawn, remove the if-statements where you set color, because you don't need it. It's just unnecessary code.
In update, change self.change_x and self.change_y to self.changeX and self.changeY in reproduce metod. Be consistent.
In update, change self.organisms to just organisms. It's a global variable and not an attribute.
In update, mate is an undefined variable. Don't know what you're trying to do so I don't know how to fix that.
Those were the errors I found just using Pycharm. Change to an IDE that can detect errors (like Pycharm) when coding and it'll help you tremendously.