Pygame splash screen crashes game - python

This has been edited, the original post was about blitting the splash screens
I'm working on a simple game using pygame, the game is almost complete however i'm having some issues with the splash screen. The current issue is that when the game is run, the splash screens blit like they are supposed to, however if the user clicks anywhere on the screen or tries to exit the game, it crashes. Does anybody know a way around this issue, what i am hoping for is that the user would even be able to exit the game or even skip the splash screen whilst they are being displayed.
def main():
'''Here the game is being initialised'''
pygame.init() #Initialising Pygame
pygame.key.set_repeat(1, 20) #Registers event every 20MS if a key is held down
countFont = pygame.font.Font(None,18) #Font being set
statusFont = pygame.font.Font(None,18) #Font being set
screen = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])
pygame.display.set_caption('Do Not Get Capped')
#Drawable surface
background = pygame.Surface(screen.get_size())
#Used for converting color maps
background = background.convert()
#Splashscreen
#image fades in
for i in range (225):
background.fill((0,0,0))
image = pygame.image.load("splash_screen1.png")
image.set_alpha(i)
logoimage = screen.blit(image,(0,0))
pygame.display.flip()
pygame.time.delay(2000)
for i in range (225):
background.fill((0,0,0))
image = pygame.image.load("splash_screen2.png")
image.set_alpha(i)
logoimage = screen.blit(image,(0,0))
pygame.display.flip()
pygame.time.delay(4000)
'''The main function which is called at the end of this code'''
class Game():
'''This class's purpose is to keep track of the current score'''
def __init__(self):
self.score=0
self.goalNumbers=0
class Gun(pygame.sprite.Sprite):
'''This is the gun that the user controls'''
def __init__(self):
'''This is the class contructor'''
pygame.sprite.Sprite.__init__(self)
self.image=pygame.image.load("turret.png") #Loading the gun's image
self.rect = self.image.get_rect() #Getting the image's Rect
self.rect.x = 240 #Setting the rect's X position
self.rect.y = 630 #Setting the rect's Y position
def moveGun(self,orientation):
'''This function allows the gun to move on the screen.
If the orientation is facing left and the gun is 5 pixels
away from the wall, the gun is moved left & vice-a-versa'''
if orientation=="left" and self.rect.x>5:
self.rect.x-=5
if orientation=="right" and self.rect.x<(480-self.rect.width):
self.rect.x+=5
class Projectile(pygame.sprite.Sprite):
'''This class sets up the projectile/bullets that are controlled
by the user'''
def __init__(self,gun):
pygame.sprite.Sprite.__init__(self)
self.image=pygame.image.load("bullet.png")
self.rect=self.image.get_rect()
'''The code below places the projectile on top of the gun'''
self.rect.x=gun.rect.x+(gun.rect.width/2)-(self.rect.width/2)
self.rect.y=gun.rect.y-gun.rect.height
def updateProjectile(self):
'''This checks if the projectile has reached the top of the screen
if it hasn't it will continue to move up. If it has it will be deleted'''
if self.rect.y>0-self.rect.height:
self.rect.y-=5
else:
self.kill()
class Objects(pygame.sprite.Sprite):
'''This class creates the objects, they are loaded from the computer
and assigned to variables'''
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.obj=random.randint(1,3)
if self.obj==1: imagefile="capped"
if self.obj==2: imagefile="notcapped1"
if self.obj==3: imagefile="notcapped2"
self.image=pygame.image.load(imagefile+".png")
self.rect=self.image.get_rect()
self.rect.y=-0-self.rect.height
self.rect.x=(random.randint(2,44)*10)
def updateProjectile(self,game):
'''This function allows for the objects to move down the screen'''
if self.rect.y<640:
self.rect.y+=7 #This controls the amount of pixels the objects move down thus contrlling the speed
else:
if self.obj==1:
'''Here the code is tracking the users score'''
game.score+=10 #This adds 10 to the game's score
game.goalNumbers+=1
else:
game.score-=50
self.kill()
def shot(self,game):
'''This function updates the score as well as removing the objects when they are hit by a projectile'''
if self.obj == 1:
game.score-=50
else:
game.score+=10
self.kill()
# Create initial object instances
'''Here i am creating objects based on the classes i created'''
game=Game()
gun=Gun()
sprites=pygame.sprite.Group()
sprites.add(gun)
obstacles=pygame.sprite.Group()
projectiles=pygame.sprite.Group()
'''This variable will be used to control when to come out of the loop, i will state when this happens belows'''
finish=False
clock=pygame.time.Clock() #Initialising the clock
tick=0
'''This is the start of the main while loop, this loop will continue
until the variable 'finish' becomes false'''
while finish == False:
clock.tick(30) #Loop will run 30 times a second
tick+=1
screen.fill(bColour)
'''Here the main events are being run'''
for event in pygame.event.get():
if event.type==pygame.QUIT:
'''If the user clicks the exit button, the finish variable is made True,
this means that rather than exiting the game, the user's score is displayed after
which the game closes'''
finish = True
if event.type==pygame.KEYDOWN:
'''Here the script is checking for KEYDOWN events, these are events triggered
when the user presses on a keyboard key. In this case events are triggered when the left, right
and space keys are pressed.'''
if event.key==pygame.K_LEFT:
gun.moveGun("left") #If this is activated the 'orientation' changes to 'left' which shunts the gun 5 pixels to the left
if event.key==pygame.K_RIGHT:
gun.moveGun("right") #'Orientation' changes to 'right' which shunts the gun 5 pixels to the right
if event.key==pygame.K_SPACE:
'''This triggers the projectiles function'''
projectile=Projectile(gun)
projectiles.add(projectile)
'''This controls the projectiles and objects moving around the window'''
for projectile in projectiles:
projectile.updateProjectile()
for obstacle in obstacles:
obstacle.updateProjectile(game)
if tick>60:
'''This controls at what rate the objects fall which is now once every two
seconds, this is because the loop runs in 30 second intervals and the
clock is ticking at 60 seconds'''
if len(obstacles)<10:
obstacle=Objects()
obstacles.add(obstacle)
tick=0
collisions=pygame.sprite.groupcollide(obstacles,projectiles,False,True)
'''Here the script is checking whether the objects are hit by a projectile
if they are, the 'shot' function is triggered'''
if collisions:
for obstacle in collisions:
obstacle.shot(game)
'''This block of code constantly updates the player's scores'''
scoreText=countFont.render('Your current score is:'+str(game.score),True,(255,255,255),bColour)
screen.blit(scoreText,(0,620))
statusText=statusFont.render('You have '+str(10-game.goalNumbers)+' more tries',True,(255,255,255),bColour)
screen.blit(statusText,(0,10))
'''This code below updates and blits the objects to the screen'''
sprites.draw(screen)
projectiles.draw(screen)
obstacles.draw(screen)
pygame.display.flip()
if game.goalNumbers>=10:
'''This if statement is checking whether 'obj1' has touched the floor 10 times
and if it did, the finish variable is made true thus ending the game'''
finish=True
'''This is the last piece of code visible to the user,
what happens here is that the final message showing the final score is shown'''
scoreCountHolder=pygame.image.load("scoreframe.png")
scoreCountHolder.convert_alpha()
left=90
top=250
screen.blit(scoreCountHolder,(left,top))
countFont=pygame.font.Font(None,52)
statusText=countFont.render('Your Score:'+str(game.score),True,bColour,(255,255,255))
screen.blit(statusText,(105,300))
pygame.display.flip()
while True:
'''This waits for the user to quit the game'''
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
if __name__ == '__main__':
'''The main function being called'''
main()

When you have a pygame application, you take all events from the input queue.
The operating system, adds new events onto the queue, while your application removes them.
Since you do not remove the events, the operating system thinks that your application froze.
To fix this, you should call pygame.event.pump()
From the pygame docs:
For each frame of your game, you will need to make some sort of call
to the event queue. This ensures your program can internally interact
with the rest of the operating system. If you are not using other
event functions in your game, you should call pygame.event.pump() to
allow pygame to handle internal actions.
This function is not necessary if your program is consistently
processing events on the queue through the other pygame.eventpygame
module for interacting with events and queues functions.
There are important things that must be dealt with internally in the
event queue. The main window may need to be repainted or respond to
the system. If you fail to make a call to the event queue for too
long, the system may decide your program has locked up.

What happens is that you put a frame, Pygame then expects you to take the events that happened in the mean time out of its event queue. If you don't the OS thinks, that application got stuck!
You need to handle the events while you show the splash screen, if you want to allow the user to skip the flash screen.
Here's a way around that problem, it allows you to add specific event handling for splash screen:
class SplashScreen(object):
def __init__(self):
super().__init__()
# Use numbers for ordering, make them continuous.
self.image_dict = {
1: "splash_screen1.png",
2: "splash_screen2.png",
}
# Current image we are on!
self.current_index = min(self.image_dict)
# Last image
self.end_index = max(self.image_dict)
# Minimum alpha value
self.alpha_min = 0
# Maximum alpha value
self.alpha_max = 225
# Current alpha value
self.alpha = self.alpha_min
self.show = True
# I leave it to you to figure out this function.
def get_image(self):
image_name = self.image_dict[self.current_index]
image = pygame.image.load(image_name)
image.set_alpha(self.alpha)
self.alpha += 1
if self.alpha > self.alpha_max:
self.alpha = self.alpha_min
self.current_index += 1
if self.current_index == self.end_index:
self.show = False
return image
splash_screen = SplashScreen()
while True:
# The ever-green event handling loop!
for event in pygame.event.get():
...
if splash_screen.show:
# Splash screen stuff, one frame at a time
background.fill((0, 0, 0))
img = splash_screen.get_image()
screen.blit(img, (0, 0))
else:
# Game stuff, no need to call display.flip here, called at the end.
...
# Called at the end after frame is ready!
pygame.display.flip()
Left as an exercise
You should load and add the loaded images in the image_dict in __init__. It's not a good idea to keep reloading images from disk each time you blit them.

Related

Pygame object's previous images after moving still showing even though its been drawn over

So I'm trying to make it so that every second a new material is created at the coordinates of all the producers which is being done by the change event and my producer list but the materials when moving the previous position still remains even though I've blit the grid png. Apologies for bad spag
class Producer(pygame.sprite.Sprite):
def __init__(self,x,y):
super().__init__()
        self.image=pygame.image.load('images/producer.png').convert_alpha()
        self.image=pygame.transform.rotate(self.image,90)
        self.image=pygame.transform.scale(self.image, (40, 40))
        self.rect=self.image.get_rect(topleft=(x,y))
    def update(self):
        producer_group.draw(screen)
    def create_material(self,co):
        return Material(co)
class Material(pygame.sprite.Sprite):
    def __init__(self,co):
        global producer_info
        super().__init__()
        self.image=pygame.Surface((10,10))
        self.image.fill((255,0,0 ))
        self.rect=self.image.get_rect(center=co)
    def update(self):
        x,y=co[0],co[1]
        decimal_co=str(x)+'.'+str(y)
        this_producer_info=producer_info.get(decimal_co)
        self.rect.y-=5
        print('material moving')
in the game loop
for event in pygame.event.get():
    if event.type==pygame.QUIT:
        pygame.quit()
        exit()
    if event.type ==change_event:
        if game_state=='play':
            screen.blit(grid_surface,(0,100))
            producer_cos=list(producer_info.keys())
            for x in producer_cos:
                co = x.split('.')
                co[0]=int(co[0])
                co[1]=int(co[1])
                print(co)
                material_group.add(Producer.create_material('self',co))
play game state
elif game_state=='play':
    screen.blit(grid_surface,(0,100))
    #buttons
    settings_mini_button.draw()
    shop_button.draw()
    edit_button.draw()
    blueprints_button.draw()
    map_button.draw()
    #machine stuff
    producer_group.draw(grid_surface)
    producer_group.update()
    crafter_group.draw(grid_surface)
    #producer_group.update(grid_surface)
    #materials
    material_group.draw(grid_surface)
    material_group.update()
    screen.blit(grid_surface,(0,100))
    #copy screen
    play_bg=screen.copy()
The scene must be redrawn in each frame. You do not want to permanently change the grid_surface. Either you have to draw the objects on the screen instead of the grid_surface or you have to copy the grid_surface in each frame and draw on the copy of the grid_surface instead of the original:
elif game_state=='play':
producer_group.update()
material_group.update()
# clear the disaply
screen.fill(0)
# draw all things on the screen
settings_mini_button.draw()
shop_button.draw()
edit_button.draw()
blueprints_button.draw()
map_button.draw()
# copy grid_surface and draw objects on the copy
copy_of_grid_surface = grid_surface.copy()
producer_group.draw(copy_of_grid_surface)
crafter_group.draw(copy_of_grid_surface)
material_group.draw(copy_of_grid_surface)
# blit copy_of_grid_surface on the screen
screen.blit(copy_of_grid_surface, (0,100))

How do I use the clock/ticks function in Pygame to spawn another object after a certain amount of time?

class Sideways:
"""Overall class to manage game assets"""
def __init__(self):
"""Initialize the game and create game resources"""
pygame.init()
self.screen = pygame.display.set_mode((1200, 600))
self.screen_rect = self.screen.get_rect()
pygame.display.set_caption("Pew Pew")
self.bg_color = (204, 255, 255)
self.ship = Ship(self)
self.moving_up = False
self.moving_down = False
self.moving_left = False
self.moving_right = False
self.bullets = pygame.sprite.Group()
self.aliens = pygame.sprite.Group()
FIRE_EVENT = pygame.USEREVENT + 1 # This is just a integer.
pygame.time.set_timer(FIRE_EVENT, 1000) # 1000 milliseconds is 1 seconds.
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == FIRE_EVENT: # Will appear once every second.
self._create_fleet()
I'm trying to spawn another ship in pygame after a certain interval of time.
I just learned about the clock/ticks function from my previous question being directed to another thread that showed me it. Thank you. I tried to incorporate that into my code during this section.
However, when I run it, the game freezes up and crashes as if it's spawning too many things at the same time to handle and overloads. How would I manage to use this function correctly?
You must create the objects in the application loop, but not in a separate loop. This extra loop freezes your system. In general, if you want to control something over time in pygame, you have two options:
Use pygame.time.get_ticks() to measure time and and implement logic that controls the object depending on the time.
Use the timer event. Use pygame.time.set_timer() to repeatedly create a USEREVENT in the event queue. Change object states when the event occurs.
For example see Spawning multiple instances of the same object concurrently in python or create clock and do action at intervals and many more similar answers.

Overlay tiles onto sprite in pygame

I am creating a tile-based 2d overworld for a game - heavily influenced by Pokemon - using pygame/python, Tiled for .tmx files, and the tmx library by Richard Jones. The code I'm using is mostly based on this wonderful demo of Pallet Town in python.
The game runs just fine, however, I am having problems with making tiles on the map (e.g. houses, trees) overlap the player sprite when it would make sense for the player sprite to disappear behind them. For example: in the image here, principles of depth perception would tell us that the house in the foreground should occlude the player in the background, but because the map is 2D there is no depth and therefore no occlusion. I would love to add depth, but seeing as I'm very new to pygame (and python in general), I'm at a loss at how to draw the relevant foreground objects over the sprite.
Luckily I'm not alone in this problem and plenty of documentation on possible solutions exist. For example:
this StackExchange question
this LibGDX tutorial
this Unity tutorial
However, this code isn't typically written for python and I'm not sure how to implement it in my situation. Sorting/drawing by z position (or by a 'depth' property) seems like the most sensible thing to do, but looking at the tmx library I can only find x and y values mentioned. Adding the player sprite to an empty object layer in Tiled is also a solution, but once again I'm unsure of how to do this and all my attempts have led to error messages. (Attempts not detailed here because I honestly don't know what I did and it didn't work anyway.)
My current code is as follows:
class Player(pygame.sprite.Sprite):
def __init__(self, location, collStart, orientation, *groups):
super(Player, self).__init__(*groups)
self.image = pygame.image.load('sprites/player.png')
self.imageDefault = self.image.copy()
self.rect = pygame.Rect(location, (26,26))
self.collider = pygame.Rect(collStart, (13,13))
self.orient = orientation
self.holdTime = 0
self.walking = False
self.dx = 0
self.step = 'rightFoot'
# Set default orientation
self.setSprite()
self.speed = pygame.time.get_ticks() + 50 # slows down walking speed
by .5 sec (current time + 50 ms)
def setSprite(self):
# this function contains information about where to find which sprite
in the sprite sheet, probably not relevant here.
def update(self, dt, game):
key = pygame.key.get_pressed()
if pygame.time.get_ticks() >= self.speed:
self.speed = pygame.time.get_ticks() + 50
# Setting orientation and sprite based on key input, removed the
#code here because it wasn't relevant
#[....]
# Walking mode enabled if a button is held for 0.1 seconds
if self.holdTime >= 100:
self.walking = True
lastRect = self.rect.copy()
lastColl = self.collider.copy() # collider covers the bottom section of the sprite
# Code for walking in the direction the player is facing, not relevant here
#[....]
# Collision detection:
# Reset to the previous rectangle if player collides
# with anything in the foreground layer
if len(game.tilemap.layers['triggers'].collide(self.collider,
'solid')) > 0:
self.rect = lastRect
self.collider = lastColl
# Area entry detection, loads dialog screen from the dialog file:
elif len(game.tilemap.layers['triggers'].collide(self.collider,
'entry')) > 0:
entryCell = game.tilemap.layers['triggers'].find('entry')[0]
game.fadeOut()
run()
pygame.quit()
quit()
return
if self.dx == 16:
# Makes the player appear to take steps w/ different feet, not relevant here
#[....]
# After traversing 32 pixels, the walking animation is done
if self.dx == 32:
self.walking = False
self.setSprite()
self.dx = 0
game.tilemap.set_focus(self.rect.x, self.rect.y)
class Game(object):
def __init__(self, screen):
self.screen = screen
def initArea(self, mapFile):
"""Load maps and initialize sprite layers for each new area"""
self.tilemap = tmx.load(mapFile, screen.get_size())
self.players = tmx.SpriteLayer()
self.objects = tmx.SpriteLayer()
# In case there is no sprite layer for the current map
except KeyError:
pass
else:
self.tilemap.layers.append(self.objects)
# Initializing player sprite
startCell = self.tilemap.layers['triggers'].find('playerStart')[0]
self.player = Player((startCell.px, startCell.py), (startCell.px,
startCell.bottom-4),
startCell['playerStart'], self.players)
self.tilemap.layers.append(self.players)
self.tilemap.set_focus(self.player.rect.x, self.player.rect.y)
def main(self):
clock = pygame.time.Clock()
self.initArea('test tilemap.tmx')
while 1:
dt = clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
return
self.tilemap.update(dt, self)
screen.fill((0,0,0))
self.tilemap.draw(self.screen)
pygame.display.flip()
Once again, I'm using the tmx library found here. Maybe something needs to be changed there? Hopefully, someone can help me figure this out. It's definitely possible, as shown by this pokemon clone in python (no source code available, sadly).
Also, first-time StackOverflow user so let me know if I'm committing any faux-passes :)
Figured it out! As suggested by Kingsley in the comments, the solution was to change the draw order of the layers. Layers were being drawn in order of a list in the Layers class, with the player sprite having the highest index and thus being drawn on top of everything else. Moving the player between the background and foreground layer in the list made it appear behind the foreground objects.
To do this I added the following code to the initArea function in the Game class:
def initArea(self, mapFile):
"""Load maps and initialize sprite layers for each new area"""
self.tilemap = tmx.load(mapFile, screen.get_size())
self.players = tmx.SpriteLayer()
self.objects = tmx.SpriteLayer()
# Initializing player sprite
startCell = self.tilemap.layers['triggers'].find('playerStart')[0]
self.player = Player((startCell.px, startCell.py), (startCell.px, startCell.bottom-4),
startCell['playerStart'], self.players)
foregroundItem = self.tilemap.layers.__getitem__("foreground") # finds the layer called foreground
foregroundIndex = self.tilemap.layers.index(foregroundItem) # finds the position of the foreground layer in the Layers list (Layers class specified in .tmx file)
self.tilemap.layers.insert(foregroundIndex-1, self.players) # move the Player layer one layer below the foreground layer
self.tilemap.set_focus(self.player.rect.x, self.player.rect.y)
I'll experiment a bit more tonight, but for now this solution seems to work. Thanks for the help!

How to blit a new background image after a certain amount of time?

I have a background image currently in the game and I would like to change the image after 30 seconds. What would be the best way to do this, a function? A loop? or a pygame function such as the pygame wait function?
def main():
#Loading the music for the title screen of the game and playing it infintely.
sound = pygame.mixer.Sound('C:\\Users\\Joseph Molina\\Desktop\\CST\\KeyGen.ogg')
sound.play(loops = -1)
while True:
global total_frames
process(bug,FPS, total_frames, SCREENHEIGHT)
#LOGIC
bug.motion(SCREENWIDTH, SCREENHEIGHT)
Enemy.movement(SCREENWIDTH)
BugProjectile.movement()
total_frames += 1
#Bliting the image of the background into the screen at the given coordinates
screen.blit(backgroundImg, (0,0))
#Draws all the sprites to the screen
BaseClass.allsprites.draw(screen)
i = 0
if i < 255:
i += 5
if i > 255:
secondImg = pygame.image.load('C:\\Users\\Joseph Molina\\Desktop\\CST\\anything.jpg')
screen.blit(secondImg, (0,0))
#pygame.tick(1000)
#Makes sure that everything is being drawn on the screen
pygame.display.flip()
#How many frames are going to be in a second
clock.tick(FPS)
Create an event using pygame.time.set_timer():
pygame.time.set_timer()
repeatedly create an event on the event queue
set_timer(eventid, milliseconds) -> None
Set an event type to appear on the event queue every given number of milliseconds. The first event will not appear until the amount of time has passed.
Every event type can have a separate timer attached to it. It is best to use the value between pygame.USEREVENT and pygame.NUMEVENTS.
To disable the timer for an event, set the milliseconds argument to 0.
and when the event occurs, just change backgroundImg to another Surface.
def main():
CHANGEEVENT = pygame.USEREVENT+1
pygame.time.set_timer(MOVEEVENT, 30000)
#Loading the music for the title screen of the game and playing it infintely.
sound = pygame.mixer.Sound('C:\\Users\\Joseph Molina\\Desktop\\CST\\KeyGen.ogg')
sound.play(loops = -1)
while True:
if pygame.event.get(CHANGEEVENT ):
backgroundImg = get_another_image()
...

Pygame Inquiry- Generating Multiple Sprites in Same Class

Unimportant Preamble:
Hello, I'm using Python and Pygame to create a game. This is for the purpose of improving my programming skills rather than a serious attempt at game creation. I've taken a break from Python lately for Objective C, but I'm now returning to it. This is a problem that I was having before I took a brief break, and I've returned to a question that was originally puzzling me. I've spent quite a while researching it, and I have a suspicion I've come across the solution and merely failed to understand it. I apologize for some of the bad naming conventions/lack of comments. I'm working on improving that.
Substance of Question:
Anyway, I've attached the four images I'm using. The program uses a simple function to position various Tiles on the screen. The mouse cursor is a sword. It is the entire image, but I'll be changing that later. I've made the program type "blue" in the shell whenever the cursor collides with a Tile. My goal is to have this happen when it collides with "ANY" tile of that color.
Long-term, I want to be able to modify the properties of these tile sprites. Various game-pieces would interact, and I would need to save the state of each sprite. I'd also be setting interactions for the other sprites.
Right now the sprites are all generating images, but my collision rectangle for the Tile is simply moving after each image is generated. I suppose that makes sense given the code, but I need a way to multiple sprites, each with a rectangle for collision.
Thanks
EDIT: I was unable to add images due to a new-user restriction. They are available enter link description here I think I read somewhere that people can (and do) edit posts here. So if anyone who the ability to move the images into this thread is welcome to do so.
import random,math,sys,os
import pygame
from pygame.locals import *
pygame.init() #Initializing Pygame
#Colors
black=(0,0,0)
#Screen
screen=pygame.display.set_mode((1200,800),0,0)
pygame.display.set_caption("Nero's Sandbox")
pygame.mouse.set_visible(False)
clock=pygame.time.Clock()
fps=40
#Game Functions:
def terminate():
pygame.quit()
sys.exit()
def numgen(x,y):
return random.randint(x,y)
#Loop Variables
tri=2
#Groups:
allsprites = pygame.sprite.Group()
alltiles = pygame.sprite.Group()
allmice = pygame.sprite.Group()
#Mouse Classes
class Pointy(pygame.sprite.DirtySprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('redsword.png').convert() #31x32 image
self.image.set_colorkey(black)
self.rect=self.image.get_rect()
self.set=pygame.sprite.Group()
self.add(allmice, allsprites, self.set)
pygame.sprite.RenderPlain((self.set,allmice,allsprites))
def update(self):
screen.fill(black)
alltiles.draw(screen)
if event.type == pygame.MOUSEMOTION:
pos = pygame.mouse.get_pos()
self.rect.topright = pos
self.set.draw(screen)
#Tile Sprites - only one rect is being recognized.
class Tile(pygame.sprite.Sprite):
def __init__(self, graphic):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(graphic).convert()
self.image = pygame.transform.scale((self.image),(50,50))
self.rect=self.image.get_rect()
self.add(alltiles, allsprites)
self.set=pygame.sprite.RenderPlain((self))
def update(self, x, y):
pos = (x,y)
self.rect.topleft = pos
#Micers
pointy1=Pointy()
#Game Loops
while True: #Ensures all loops within program are constantly called when conditions are met.
screen.fill(black)
while tri==2:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
pygame.display.flip()
x = 0
y = 50
w = 0
while x!=600:
x=x+50
w = w+1
if w%2==0:
purpletile1=Tile('purplesquare.png')
purpletile1.set.update(x,y)
purpletile1.set.draw(screen)
else:
c=numgen(1,2)
if c==1:
bluetile1=Tile('lightbluesquare.png')
bluetile1.set.update(x,y)
bluetile1.set.draw(screen)
if c==2:
redtile1=Tile('redsquare.png')
redtile1.set.update(x,y)
redtile1.set.draw(screen)
if x>=600 and y!=450:
if y<450:
x = 0
y = y+50
w=w-1
if y>=450:
tri=3
while tri==3:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
alltiles.draw(screen)
pointy1.set.update()
pointy1.set.draw(screen)
pygame.display.flip()
clock.tick(fps)
if pygame.sprite.collide_rect(pointy1,bluetile1):
print('blue')
I had this same problem myself! I did some debugging, and it appeared that all instances of my class shared the same instance of pygame.Rect()
You may want to change the line:
pygame.sprite.Sprite.__init__(self)
to
super.__init__(self)
This way, pygame.sprite.Sprite's init will set attributes to your tile. I could be wrong, I'm not entirely familiar with python's inheritance syntax, but that is the way I do it.
I could also be the get_rect that is causing the same rectangle to be used for all classes, but that doesn't seem to be likely.
I hope that I was some help, and just remember that pygame.Rect is an object, so somehow you are instantiating only once.

Categories

Resources