How do i instance sprites in Pygame? Do i need too? - python

So im working on a game for some coursework in my computing course, im almost finished but for the life of me i cant get multiple of the Spider sprite to spawn in at the correct locations or reset properly between levels. I've tried adding different instances to groups before but i always get a different error with each method that i try. the code is below and im fairly new to pygame so sorry for the messy code..
#
class Spider(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load( 'Assets/Level-Assets/Level 1/Enemies/Spider_Down.png')
self.rect = self.image.get_rect()
self.Health = 3
self.Spawned = False
self.range = 100
self.Gravity= 6
self.pos_difference = 0
self.Active = False
self.Fall = False
self.Spiders = []
##################################################################################################################
def Set_Position(self):
if self.Spawned == False:
self.rect.center = (World.mapx, World.mapy)
Enemies.add(self)
self.Spawned = True
else:
self.rect.center = self.rect.center
######################################################################################################################
def update(self):
self.pos_difference = Player.rect.centery - self.rect.centery
if Player.rect.centerx >= self.rect.centerx -4 or Player.rect.centerx >= self.rect.centerx + 4:
if Player.rect.centery > self.rect.centery:
if self.pos_difference < 200:
self.Active = True
self.Fall = True
if self.Active == True:
if self.Fall == True:
self.rect.centery += self.Gravity
This is the code for the Spider, its not actually doing anything until it is called within the World class, which is where i believe the majority of the problem is...
def DisplayWorld(self):
self.MapLoad = False
for Row in range(len(self.newMap)):
for Col in range(len(self.newMap[Row])):
self.mapx = Col * 64
self.mapy = ((Row + self.Height_modifier) * 64)
self.tile_pos = (self.mapx, self.mapy )
if int(self.newMap[Row][Col]) == 1:
self.rect = self.Brick_Center.get_rect(left = (self.mapx) , bottom = (self.mapy))
self.World_sprites.add(World)
self.Camera_Pos_Check()
Player.Collision_Check()
Spider.Collision_Check()
Shoot.Collision_Check()
self.World_sprites.draw(screen)
elif int(self.newMap[Row][Col]) == 2:
Enemies.add(Spider(screen))
def main():
play = True
while play:
if pygame.key.get_pressed()[pygame.K_ESCAPE]:
play = False
if not Sprites.sprites():
Sprites.add(Player,Spider)
print(Sprites)
clock.tick(CLOCKRATE)
pygame.mouse.set_visible(False)
for event in pygame.event.get():
if event.type == pygame.QUIT:
play = False
screen.blit(bgi,(0,0))
screen.blit(bgi,(0,500))
World.findLevel()
Sprites.update()
Enemies.draw(screen)
Sprites.draw(screen)
if Shoot.bullet == True:
Shoot.update()
for b in range(len(Shoot.bullets)):
screen.blit(Shoot.image, (Shoot.bullets[b][0],Shoot.bullets[b][1]))
UI.Health_Display()
pygame.display.flip()
Sprites = pygame.sprite.Group()
Enemies = pygame.sprite.Group()
UI = User_Interface()
World = World()
Player = Proto()
Shoot = Shoot()
Portal = Portals()
Spider = Spider()
main()

I've found your problem: you overwrite your Spider class by an instance of it (Spider()) and then give it the same name. Thus you're consistently adding the same single spider to your enemies list. Instead, you should remove this definition on the bottom of your file and where ever you're adding the (multiple) spider(s), you should create this instance.
In a more general remark, it is considered bad style (and not too great for performance) to use global variables as widely as you do. It'd be much better to pass them around between functions and classes. Also, the CamelCase capitalization you use for all of your variables is commonly only used for classes. I'd recommend checking up on pep8 to learn more about how to use common Python styles. It makes these kinds of problems easier to spot, less likely to occur, and simplifies the reading for anyone involved. Using these points properly might even improve your grade significantly ;).

Related

How to not initialize the def init every time

this code is by tech with tim but i am trying to tweak it, i am trying to make the rotation velocity vary everytime.
import pygame
import time
import math
from utility import scale_image, blit_rotate_center
rotation_speed=2
Joystickx=0
GRASS = scale_image(pygame.image.load("Sprites/grass.png"),2.5)
TRACK = scale_image(pygame.image.load("Sprites/track.png"),0.7)
TRACK_BORDER = scale_image(pygame.image.load("Sprites/track-border.png"),0.7)
Car = scale_image(pygame.image.load("Sprites/F1.xcf"),0.1)
FINISH=pygame.image.load("Sprites/finish.png")
WIDTH, HEIGHT= TRACK.get_width(), TRACK.get_height()
WIN = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("F1")
FPS = 60
class AbstractCar:
def __init__(self,max_vel,rotation_vel):
self.img=self.IMG
self.max_vel=max_vel
self.vel = 0
self.rotation_vel = rotation_vel
self.angle = 90
self.x, self.y = self.START_POS
def rotate(self, left=False, right=False):
if left:
self.angle += self.rotation_vel
print(self.angle)
elif right:
self.angle -= self.rotation_vel
print(self.angle)
def draw(self):
blit_rotate_center(WIN, self.img,(self.x, self.y), self.angle)
class PlayerCar(AbstractCar):
IMG = Car
START_POS = (180,200)
def draw(win,images, player_car):
for img, pos in images:
win.blit(img,pos)
player_car.draw()
pygame.display.update()
run=True
clock = pygame.time.Clock()
images = [(GRASS, (0,0)),(TRACK,(0,0))]
def rotate():
global rotation_speed
global Joystickx
rotation_speed+=2*Joystickx
rotation_speed*=0.9
while run:
clock.tick(FPS)
rotate()
player_car = PlayerCar(4, rotation_speed)
draw(WIN, images, player_car)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
break
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
player_car.rotate(left=True)
Joystickx=-1
elif keys[pygame.K_d]:
player_car.rotate(right=True)
Joystickx=1
else:
Joystickx=0
pygame.quit()
however, every time the class is ran, the code will set self.angle to 90, i do not want that to happen, what can i do to not let the def init run as that will set the self.angle to 94 instead remembering the last self.angle
This is OOP (Object Oriented Programming) thing. I really suggest you to look it up, it's not an easy topic at first, but it's also not that hard to understand everything in it, it's just the first time is hard.
So, the __init__ is the constructor of your AbstractCar class. This will always run when you make a new object from this class.
The simple way to fix this is to place the line where you define your car a bit above, outside the while loop and to keep the rotation_vel updated, we make a new method in the AbstractCar class and call it instead:
class AbstractCar:
def set_rotation_vel(self, new_rotation_vel):
self.rotation_vel = new_rotation_vel
[...]
player_car = PlayerCar(4, rotation_speed)
while run:
clock.tick(FPS)
rotate()
player_car.set_rotation_vel(rotation_speed)
draw(WIN, images, player_car)

pygame image.blit not working from one class but is working from the other [duplicate]

This question already has answers here:
Why is nothing drawn in PyGame at all?
(2 answers)
Why is my PyGame application not running at all?
(2 answers)
Closed 11 months ago.
I have wrecked my mental health going over and over and over this code. I have created two classes that are nearly identical yet my images from the second class are not rendering on the screen even though my first class's images are rendering perfectly fine. I've went over and over them to see if I can spot the difference between them that could be causing this but so far nothing. I've also tried swapping class one's image for class two's image and it renders the image perfectly fine from class one, so not an issue with the image itself. I'm lost. Any help from the good people here on stack would be beyond greatly appreciated. I'm sure its something stupidly simple that I'm overlooking but if I look over this code anymore I will go permanently cross-eyed.
Here is the snippet. TIA.
class one:
def __init__(self, num_value, bool, x, y):
self.num_value = num_value
self.bool = bool
self.x = x
self.y = y
self.one_image = pygame.image.load(os.path.join('Program_Assets', 'one.png'))
self.image_size = (250, 350)
self.one_image = pygame.transform.scale(self.one_image, self.image_size)
if bool == False:
self.one_image = pygame.transform.rotate(self.one_image, 90)
_VARS['surf'].blit(self.one_image, (self.x, self.y))
if (self.num_value == "1k"):
self.num_value = 1000
elif (self.num_value == "2k"):
self.num_value = 2000
elif (self.num_value == "10k"):
self.num_value = 10000
def setxy(self, x, y):
self.x, self.y = x, y
_VARS['surf'].blit(self.one_image, (self.x, self.y))
def getxy(self):
return self.x, self.y
class two:
def __init__(self, bool, x, y):
self.bool = bool
self.x = x
self.y = y
self.two_image = pygame.image.load(os.path.join('Program_Assets', 'two.png'))
self.image_size = (265, 175)
self.two_image = pygame.transform.scale(self.two_image, self.image_size)
if bool == True:
self.two_image = pygame.image.load(os.path.join('Program_Assets', 'two_alt.png'))
self.two_image = pygame.transform.scale(self.two_image, self.image_size)
_VARS['surf'].blit(self.two_image, (self.x, self.y))
def setxy(self, x, y):
self.x, self.y = x, y
_VARS['surf'].blit(self.two_image, (self.x, self.y))
def getxy(self):
return self.x, self.y
# GLOBAL VAR, Using a Dictionary.
_VARS = {'surf': False}
# This is the main loop, it constantly runs until you press the Q KEY
# or close the window.
# CAUTION: This will run as fast as your computer allows,
# if you need to set a specific FPS look at tick methods.
def main():
pygame.init() # Initial Setup
_VARS['surf'] = pygame.display.set_mode(SCREENSIZE)
is_running = True
# The loop proper, things inside this loop will
# be called over and over until you exit the window
clock = pygame.time.Clock()
t1 = two(True, 250, 350)
o1 = resistor("10k", True, 10, 10)
o2 = resistor("10k", False, 10, 200)
o1_selected = False
o2_selected = False
t1_activated = False
while is_running:
_VARS['surf'].fill(WHITE)
drawGrid(8)
o1_x, o1_y = o1.getxy()
o2_x, o2_y = o2.getxy()
t1_x, t1_y = t1.getxy()
clock.tick(30)
pygame.display.update()
pygame.quit()
if __name__ == '__main__':
main()
EDIT: just posted the loop this time -- all I did here was add your setxy()'s so that the blit ran -- again I get all the images...
Of course to get it work work on my system I had to use different images, add a SCREENSIZE, and WHITE. I commented out the drawGrid. I also have an event handler to QUIT -- but that should have nothing to do with displaying the images.
I did not make any intentional changes to your logic - just what was needed to get a display.
while is_running:
_VARS['surf'].fill(WHITE)
#drawGrid(8)
o1_x, o1_y = o1.getxy()
o2_x, o2_y = o2.getxy()
t1_x, t1_y = t1.getxy()
o1.setxy(o1_x, o1_y)
o2.setxy(o2_x, o2_y)
t1.setxy(t1_x, t1_y)
clock.tick(30)
pygame.display.update()
for event in pygame.event.get():
# print(pygame.event.event_name(event.type))
if event.type == pygame.QUIT:
is_running = False
print("Exit...")
I finally figured it out. The program was calling the other two images further down in my while loop via:
o1.setxy(o1_x, o1_y)
o2.setxy(o2_x, o2_y)
My first clue at this was when I set my pygame.display.update() nearer the top of my while loop based on some of the comments and suggestions I received here. When I ran my code with pygame.display.update() at the top of my while loop I lost my o1 and o2 images. Based on this finding I suspected that the images were being rendered somewhere further down in my while loop. It was at this point I noticed the o1.setxy & o2.setxy and finally had my Eureka! moment. I promptly added a
t1.setxy(t1_x, t1_y)
and voila! I now have a third image for my instance of my two class!!! Mental health is partially intact now and my eyes are no longer crossed. Thank you all so much for your help in flushing this out and achieving my renders.

Is there a way to change my_sprite or my_group to change the animation displayed?

I'm making animated sprites in pygame, and would like help finding a way to flip from one to the other? The current code looks something like this:
class normal(pygame.sprite.Sprite):
def __init__(self):
#etc, list of images to create the animation
class tall(pygame.sprite.Sprite):
def __init__(self):
#rinse and repeat with a different set of images
I already have an idea for how to trigger the change via keystroke. But I'm not sure which variable to change, and to what. When I try to change with the following code, nothing happens
fps = 25
pygame.init()
my_sprite = normal()
my_group = pygame.sprite.Group(my_sprite)
#etc until we get to the part where it changes
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
if my_sprite == normal():
my_sprite = tall()
fps = 30
else:
my_sprite = normal()
fps = 25
I'm not sure exactly what isn't working in my code as it doesn't come back with an error. Can someone point me in the right direction?
It's not working because when the code calls normal() it's creating a new instance of an object. So the call:
if my_sprite == normal():
Is saying "is my existing sprite object == this new sprite object", which is never true. You can use the python function to type() of the object to do the same thing, or add your own type-function as I have presented in the code below.
I would track the state of the sprite inside the class, and use some functions grow() and shrink() to change the size automatically.
class GrowingSprite( pygame.sprite.Sprite, x, y ):
def __init__( self ):
#etc, list of images to create the animation
self.image_short = ... # load "short" image
self.image_tall = ... # load "tall" image
# Set the initial state
self.image = self.image_short # start short
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
self.state = 'short'
def getState( self ):
return self.state
def grow( self ):
self.state = 'tall'
self.image = self.image_tall
current_x = self.rect.centerx # preserve existing location
current_y = self.rect.centery
self.rect = self.image.get_rect()
self.rect.center = ( current_x, current_y )
def shrink( self ):
self.state = 'short'
self.image = self.image_short
current_x = self.rect.centerx # preserve existing location
current_y = self.rect.centery
self.rect = self.image.get_rect()
self.rect.center = ( current_x, current_y )
I found a workaround that is a bit redundant, but it makes it possible to expand it in case there are more groups
It requires making two groups that can be pulled back and fourth, and changing the foo.draw(screen) to the new group. This is how it looks
nml_sprite = normal()
tal_sprite = tall()
tg = 1 #this is nothing more than a switch to trigger the change
tal_group = pygame.sprite.Group(tal_sprite)
nml_group = pygame.sprite.Group(nml_sprite)
cursprite = nml_group #this variable determines which sprite set is loaded
...
...
if event.key == pygame.K_RETURN:
if tg == 1:
curspt = tal_group
tg = 2
else:
curspt = nml_group
tg = 2
...
...
nml_group.update()
tal_group.update()
curspt.draw(screen)
...

I cant figure out this space key and attack animation

I decided to add the attack images into the walking ones to see what happened and I got them to load up.
I have been attempting to break it down and piece it back together to try and find what I have been doing wrong and it may be an issue of my experience.
I have butchered my code trying to figure this out after someone gave me an explanation about my classes. I thought maybe I should try and set it up as global, and then I realize there's something I'm not doing right. I don't want someone to just write the code for me I should mention. But an explanation for why I am screwing up would be nice.
Some tutorials are helping me but not as much as when someone tells me where specifically where I went wrong. I think I made more progress there.
##a simple punch without the whole animation atm
class attacks(object):
attack = pygame.image.load("atk3.png")
def __init__(self, x, y, width, height, attack):
self.x = x
self.y = y
self.width = width
self.height = height
self.attackCount = 0
def draw(self, win):
## is it my redraw method?
if (self.attack):
if self.attackCount + 1 >= 9:
win.blit(attack, self.attackCount//3(self.x, self.y))
self.attackCount += 1
So with the class set up here im sure that something is wrong, ive been diving through forums and I know something is not right. I dont know what though.
def redrawGameWindow():
global walkCount
global attackCount
win.blit(bg, (0, 0))
if walkCount +1 >= 27:
walkCount = 0
bob.draw(win)
jerk.draw(win)
for attack in attacks:
attack.draw(win)
pygame.display.update()
#While true
#This calls the classes created
bob = player(100, 200, 128, 128)
jerk = enemy(500, 200, 164, 100, 600)
attacks = []
run = True
while run:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
#attempting to make this into a bool that changes the value
if not(bob.attacking):
if keys[pygame.K_SPACE]:
bob.attacking = True
bob.standing = False
bob.left = False
bob.right = False
if keys[pygame.K_LEFT] and bob.x > bob.vel:
bob.x -= bob.vel
bob.left = True
bob.right = False
bob.standing = False
elif keys[pygame.K_RIGHT] and bob.x < 800 - bob.width - bob.vel:
bob.x += bob.vel
bob.right = True
bob.left = False
bob.standing = False
else:
bob.standing = True
bob.walkCount = 0
if not(bob.isJump):
if keys[pygame.K_UP]:
bob.isJump = True
bob.right = False
bob.left = False
bob.walkCount = 0
else:
if bob.jumpCount >= -10:
neg = 1
if bob.jumpCount < 0:
neg = -1
bob.y -= (bob.jumpCount ** 2) * 0.5 * neg
bob.jumpCount -= 1
else:
bob.isJump = False
bob.jumpCount = 10
redrawGameWindow()
pygame.quit()
Im almost sure my True loop has nothing to do with it now since im able to run walk and jump. And when I press space it loads a frame thats not an attack one so i know for sure something is happening when I hit space
one of the errors I have found is that you are telling pygame to load multiple images however, you have only loaded one
class attacks(object):
attack = pygame.image.load("atk3.png")#< ----- you are only loading one
def __init__(self, x, y, width, height, attack):
#[...]
and you are telling it to go in a cycle to blit different images in a group
def draw(self, win):
## is it my redraw method?
if (self.attack):
if self.attackCount + 1 >= 9:
win.blit(attack, self.attackCount//3(self.x, self.y))# you only have one image yet you are trying to blit multiple
self.attackCount += 1
another error is your attack varible. to know when you luanch an attack you do it like this
class attacks(object):
attack = pygame.image.load("atk3.png")
def __init__(self, x, y, width, height,#attack <----- this attack shoudnt be here):
self.x = x
self.y = y
self.width = width
self.height = height
self.attackCount = 0
self.punchisluacnhed = false
def draw(self, win):
if (self.punchisluacnhed):
if self.attackCount + 1 >= 9:
win.blit(self.attack, self.attackCount//3(self.x, self.y))
self.attackCount += 1
#B.T.W the attack image in the draw function should have self before it since you called it in a class not in the initilization i.e import pygame etc
If you want the character to punch when a button is pressed you would put it in a function like this
if keys[pygame.K_SPACE]:
bob.punchisluacnhed = True
bob.standing = False
bob.left = False
bob.right = False
to tell it to stop you put an else stateent an set every thing to false except from the standing value

Why is this small (155 lines-long) Pacman game on Python running so slow?

I have already cut everything I could from the main loop. I also optimized collisions for dynamic and static objects, reducing considerably the number of iterations. But it is still slow on his machine. I'll post the entire file for the case someone wants to test it, but you can just jump to the main loop at "while Exit==false:".
import pygame
from pyeuclid import Vector2
from math import sin,cos,pi
from random import random
class Thing:
def __init__(self,pos):
self.pos = pos
things.append(self)
def update(self): pass
def draw(self,img): pass
def collide(self,who): pass
class DynamicThing(Thing):
def __init__(self,pos):
Thing.__init__(self,pos)
self.vel = Vector2(0,0)
self.lastPos = pos
self.col = (255,255,0)
self.r = 12
dynamic_things.append(self)
def update(self):
self.lastPos = self.pos
self.pos = self.pos + self.vel
def draw(self,img):
pygame.draw.circle(img, (0,0,0), [int(n) for n in self.pos], self.r, self.r)
pygame.draw.circle(img, self.col, [int(n) for n in self.pos], self.r-2, self.r-2)
def collide(self,obj):
Thing.collide(self,obj)
if isinstance(obj,Wall):
self.pos = self.lastPos
class Wall(Thing):
def draw(self,img):
x,y = self.pos.x, self.pos.y
pygame.draw.rect(img, (90,90,200), (x-16,y-16,32,32), 0)
class Pacman(DynamicThing):
def __init__(self):
DynamicThing.__init__(self,Vector2(32*9+16,32*12+16))
self.col = (255,255,0)
def update(self):
DynamicThing.update(self)
if (keyPressed[pygame.K_LEFT]): self.vel.x = -1
if (keyPressed[pygame.K_RIGHT]): self.vel.x = 1
if (keyPressed[pygame.K_DOWN]): self.vel.y = 1
if (keyPressed[pygame.K_UP]): self.vel.y = -1
if (self.vel.x==-1 and not keyPressed[pygame.K_LEFT]): self.vel.x = 0
if (self.vel.x==1 and not keyPressed[pygame.K_RIGHT]): self.vel.x = 0
if (self.vel.y==1 and not keyPressed[pygame.K_DOWN]): self.vel.y = 0
if (self.vel.y==-1 and not keyPressed[pygame.K_UP]): self.vel.y = 0
def collide(self,obj):
DynamicThing.collide(self,obj)
if isinstance(obj,Ghost):
self.pos = Vector2(32*9+16,32*12+16)
class Ghost(DynamicThing):
def __init__(self):
DynamicThing.__init__(self,Vector2(32*9+16,32*10+16))
self.col = (int(random()*255),int(random()*255),int(random()*255))
self.vel = Vector2(0,-2)
def update(self):
DynamicThing.update(self)
if random()<0.01:
self.vel = [Vector2(2,0),Vector2(-2,0),Vector2(0,2),Vector2(0,-2)][int(random()*4)]
def collide(self,obj):
DynamicThing.collide(self,obj)
if isinstance(obj,Wall):
self.vel = [Vector2(2,0),Vector2(-2,0),Vector2(0,2),Vector2(0,-2)][int(random()*4)]
def thingAtPos(pos):
tile_pos = Vector2(int(pos.x/32),int(pos.y/32))
return map[tile_pos.y][tile_pos.x]
# initializate stuff
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([32*19,32*22])
points_in_unit_circle_border = [Vector2(cos(float(a)/8*2*pi),sin(float(a)/8*2*pi)) for a in xrange(8)]
things = []
dynamic_things = []
exit = False
map = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1],
[1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1],
[1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1],
[1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1],
[1,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1],
[1,1,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1,1,1],
[1,1,1,1,0,1,0,1,1,0,1,1,0,1,0,1,1,1,1],
[1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1],
[1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,1],
[1,1,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1,1,1],
[1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,1],
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1],
[1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1],
[1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1],
[1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1],
[1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1],
[1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]
#create pacman, walls, ghosts
pacman = Pacman()
for y in xrange(len(map)):
for x in xrange(len(map[y])):
if (map[y][x]==1):
map[y][x] = Wall(Vector2(x*32+16,y*32+16))
for i in xrange(4):
Ghost()
while exit==False:
clock.tick(45)
screen.fill([255,255,255])
keyPressed = pygame.key.get_pressed()
# events
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
exit = True
# more ghosts
if random()<0.001: Ghost()
# updates e draws
for thing in things:
thing.update()
thing.draw(screen)
# collisions
for A in dynamic_things:
#dynamic vs dynamic
for B in dynamic_things:
if A!=B and abs(A.pos-B.pos)<(A.r+B.r):
A.collide(B)
B.collide(A)
#dynamic vs walls
for circle_point in points_in_unit_circle_border:
thing_in_a_border = thingAtPos(A.pos+circle_point*12)
if isinstance(thing_in_a_border,Wall):
A.collide(thing_in_a_border)
pygame.display.flip()
pygame.quit ()
You are redrawing and fliping the whole screen in every loop. I didn't test your program, but on the pacman I know, there are only 5 moving sprites on the screen, you should try to only blit those every frame (and of course if something else changes, that too). And don't display.flip(), just update the areas of the screen that you changed (that normally speeds up a lot).
Of course you need to stop blanking the screen every frame for that, and there will be much management of what to update. There is some extra support for dirty sprites in pygame http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.DirtySprite that help you with that. Or you could maybe just update all 'active' sprites by blanking the position they where and redrawing them in the new position (and obviously everything that also is in those two areas). Collect the effected rects in a list and pass that to update_rects() instead of flipping the screen. There should be no need in drawing the walls in a pacman game in every frame...
Probably not a big source of slowness, but "while exit==False:" requires a little more bytecode to execute than "while not exit:".

Categories