My class isn't defined. Python Pygame - python-3.x

I was just starting a rougelike game in python pygame when I came across an error I didn't under stand.
Here's the code:
Main.py
import pygame
import Textures
pygame.init()
Tiles_Size = 32
BLACK = (0, 0, 0)
def create_window():
global window
window = pygame.display.set_mode((800,600),pygame.HWSURFACE|pygame.DOUBLEBUF)
pygame.display.set_caption('RPG')
create_window()
isRunning = True
while isRunning:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a: #Switch to K_A rather than pygame.K_a
isRunning = False # for glitch! :)
window.fill(BLACK)
for x in range(0, 640, Tiles.Size):
for y in range(0, 480, Tiles.Size):
window.blit(Tiles.Wood, (x, y))
pygame.quit()
Textures.py
import pygame
pygame.init()
class Tiles:
Size = 32
def Load_Texture(file, Size):
bitmap = pygame.image.load(file)
bitmap = pygame.transform.scale(bitmap, (Size, Size))
surface = pygame.Surface((Size, Size), pygame.HWSURFACE|pygame.SRCALPHA)
surface.blit(bitmap, (0, 0))
return surface
Wood = Load_Texture("Graphics\\wood.jpg", Size)
That's all the code I have and the files go as follows
Graphics
wood.jpg
main.py
textures.py
So the error was quite odd. When I ran the main.py file, the error was rather weird. With the variables Tiles.Size and Tiles.Wood, it said the Tiles class in the textures.py file was not defined when it quite clearly is there! I got stuck with this glitch for a while and gave up. Then I looked at it again and I still can't find the error. The Error was:
Traceback (most recent call last):
File "C:\Users\*********\Desktop\PygameRPG\Main.py", line 26, in <module>
for x in range(0, 640, Tiles.Size):
NameError: name 'Tiles' is not defined
That's my Error.
Some help would be great!

You imported Textures.py in main.py but you forgot something! If you want to do this:
for x in range(0, 640, Tiles().Size):
You should neither do this:
from textures import *
nor change the code to this:
for x in range(0, 640, textures.Tiles().Size):
You also forgot parentheses. Now, try this codes as this, it must work:
main.py:
import pygame
import textures
pygame.init()
Tiles_Size = 32
BLACK = (0, 0, 0)
def create_window():
global window
window = pygame.display.set_mode((800,600),pygame.HWSURFACE|pygame.DOUBLEBUF)
pygame.display.set_caption('RPG')
create_window()
isRunning = True
while isRunning:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a: #Switch to K_A rather than pygame.K_a
isRunning = False # for glitch! :)
window.fill(BLACK)
for x in range(0, 640, textures.TilesClass().Size):
for y in range(0, 480, textures.TilesClass().Size):
window.blit(textures.TilesClass().Wood, (x, y))
textures.py:
import pygame
pygame.init()
class TilesClass:
Size = 32
def Load_Texture(file, Size):
bitmap = pygame.image.load(file)
bitmap = pygame.transform.scale(bitmap, (Size, Size))
surface = pygame.Surface((Size, Size), pygame.HWSURFACE|pygame.SRCALPHA)
surface.blit(bitmap, (0, 0))
return surface
Wood = Load_Texture("Graphics\\wood.jpg", Size)

Related

Pygame limiting collision targets [duplicate]

I have made a list of bullets and a list of sprites using the classes below. How do I detect if a bullet collides with a sprite and then delete that sprite and the bullet?
#Define the sprite class
class Sprite:
def __init__(self,x,y, name):
self.x=x
self.y=y
self.image = pygame.image.load(name)
self.rect = self.image.get_rect()
def render(self):
window.blit(self.image, (self.x,self.y))
# Define the bullet class to create bullets
class Bullet:
def __init__(self,x,y):
self.x = x + 23
self.y = y
self.bullet = pygame.image.load("user_bullet.BMP")
self.rect = self.bullet.get_rect()
def render(self):
window.blit(self.bullet, (self.x, self.y))
In PyGame, collision detection is done using pygame.Rect objects. The Rect object offers various methods for detecting collisions between objects. Even the collision between a rectangular and circular object such as a paddle and a ball can be detected by a collision between two rectangular objects, the paddle and the bounding rectangle of the ball.
Some examples:
pygame.Rect.collidepoint:
Test if a point is inside a rectangle
repl.it/#Rabbid76/PyGame-collidepoint
import pygame
pygame.init()
window = pygame.display.set_mode((250, 250))
rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(100, 100)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
point = pygame.mouse.get_pos()
collide = rect.collidepoint(point)
color = (255, 0, 0) if collide else (255, 255, 255)
window.fill(0)
pygame.draw.rect(window, color, rect)
pygame.display.flip()
pygame.quit()
exit()
pygame.Rect.colliderect
Test if two rectangles overlap
See also How to detect collisions between two rectangular objects or images in pygame
repl.it/#Rabbid76/PyGame-colliderect
import pygame
pygame.init()
window = pygame.display.set_mode((250, 250))
rect1 = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
rect2 = pygame.Rect(0, 0, 75, 75)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
rect2.center = pygame.mouse.get_pos()
collide = rect1.colliderect(rect2)
color = (255, 0, 0) if collide else (255, 255, 255)
window.fill(0)
pygame.draw.rect(window, color, rect1)
pygame.draw.rect(window, (0, 255, 0), rect2, 6, 1)
pygame.display.flip()
pygame.quit()
exit()
Furthermore, pygame.Rect.collidelist and pygame.Rect.collidelistall can be used for the collision test between a rectangle and a list of rectangles. pygame.Rect.collidedict and pygame.Rect.collidedictall can be used for the collision test between a rectangle and a dictionary of rectangles.
The collision of pygame.sprite.Sprite and pygame.sprite.Group objects, can be detected by pygame.sprite.spritecollide(), pygame.sprite.groupcollide() or pygame.sprite.spritecollideany(). When using these methods, the collision detection algorithm can be specified by the collided argument:
The collided argument is a callback function used to calculate if two sprites are colliding.
Possible collided callables are collide_rect, collide_rect_ratio, collide_circle, collide_circle_ratio, collide_mask
Some examples:
pygame.sprite.spritecollide()
repl.it/#Rabbid76/PyGame-spritecollide
import pygame
pygame.init()
window = pygame.display.set_mode((250, 250))
sprite1 = pygame.sprite.Sprite()
sprite1.image = pygame.Surface((75, 75))
sprite1.image.fill((255, 0, 0))
sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
sprite2 = pygame.sprite.Sprite()
sprite2.image = pygame.Surface((75, 75))
sprite2.image.fill((0, 255, 0))
sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
all_group = pygame.sprite.Group([sprite2, sprite1])
test_group = pygame.sprite.Group(sprite2)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
sprite1.rect.center = pygame.mouse.get_pos()
collide = pygame.sprite.spritecollide(sprite1, test_group, False)
window.fill(0)
all_group.draw(window)
for s in collide:
pygame.draw.rect(window, (255, 255, 255), s.rect, 5, 1)
pygame.display.flip()
pygame.quit()
exit()
For a collision with masks, see How can I make a collision mask? or Pygame mask collision
See also Collision and Intersection
pygame.sprite.spritecollide() / collide_circle
repl.it/#Rabbid76/PyGame-spritecollidecollidecircle
import pygame
pygame.init()
window = pygame.display.set_mode((250, 250))
sprite1 = pygame.sprite.Sprite()
sprite1.image = pygame.Surface((80, 80), pygame.SRCALPHA)
pygame.draw.circle(sprite1.image, (255, 0, 0), (40, 40), 40)
sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(80, 80)
sprite1.radius = 40
sprite2 = pygame.sprite.Sprite()
sprite2.image = pygame.Surface((80, 89), pygame.SRCALPHA)
pygame.draw.circle(sprite2.image, (0, 255, 0), (40, 40), 40)
sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(80, 80)
sprite2.radius = 40
all_group = pygame.sprite.Group([sprite2, sprite1])
test_group = pygame.sprite.Group(sprite2)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
sprite1.rect.center = pygame.mouse.get_pos()
collide = pygame.sprite.spritecollide(sprite1, test_group, False, pygame.sprite.collide_circle)
window.fill(0)
all_group.draw(window)
for s in collide:
pygame.draw.circle(window, (255, 255, 255), s.rect.center, s.rect.width // 2, 5)
pygame.display.flip()
pygame.quit()
exit()
What does this all mean for your code?
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. The position of the rectangle can be specified by a keyword argument. For example, the centre of the rectangle can be specified with the keyword argument center. These keyword arguments are applied to the attributes of the pygame.Rect before it is returned (see pygame.Rect for a list of the keyword arguments).
See *Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
You do not need the x and y attributes of Sprite and Bullet at all. Use the position of the rect attribute instead:
#Define the sprite class
class Sprite:
def __init__(self, x, y, name):
self.image = pygame.image.load(name)
self.rect = self.image.get_rect(topleft = (x, y))
def render(self):
window.blit(self.image, self.rect)
# Define the bullet class to create bullets
class Bullet:
def __init__(self, x, y):
self.bullet = pygame.image.load("user_bullet.BMP")
self.rect = self.bullet.get_rect(topleft = (x + 23, y))
def render(self):
window.blit(self.bullet, self.rect)
Use pygame.Rect.colliderect() to detect collisions between instances of Sprite and Bullet.
See How to detect collisions between two rectangular objects or images in pygame:
my_sprite = Sprite(sx, sy, name)
my_bullet = Bullet(by, by)
while True:
# [...]
if my_sprite.rect.colliderect(my_bullet.rect):
printe("hit")
From what I understand of pygame you just need to check if the two rectangles overlap using the colliderect method. One way to do it is to have a method in your Bullet class that checks for collisions:
def is_collided_with(self, sprite):
return self.rect.colliderect(sprite.rect)
Then you can call it like:
sprite = Sprite(10, 10, 'my_sprite')
bullet = Bullet(20, 10)
if bullet.is_collided_with(sprite):
print('collision!')
bullet.kill()
sprite.kill()
There is a very simple method for what you are trying to do using built in methods.
here is an example.
import pygame
import sys
class Sprite(pygame.sprite.Sprite):
def __init__(self, pos):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 20])
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect()
self.rect.center = pos
def main():
pygame.init()
clock = pygame.time.Clock()
fps = 50
bg = [255, 255, 255]
size =[200, 200]
screen = pygame.display.set_mode(size)
player = Sprite([40, 50])
player.move = [pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN]
player.vx = 5
player.vy = 5
wall = Sprite([100, 60])
wall_group = pygame.sprite.Group()
wall_group.add(wall)
player_group = pygame.sprite.Group()
player_group.add(player)
# I added loop for a better exit from the game
loop = 1
while loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = 0
key = pygame.key.get_pressed()
for i in range(2):
if key[player.move[i]]:
player.rect.x += player.vx * [-1, 1][i]
for i in range(2):
if key[player.move[2:4][i]]:
player.rect.y += player.vy * [-1, 1][i]
screen.fill(bg)
# first parameter takes a single sprite
# second parameter takes sprite groups
# third parameter is a do kill command if true
# all group objects colliding with the first parameter object will be
# destroyed. The first parameter could be bullets and the second one
# targets although the bullet is not destroyed but can be done with
# simple trick bellow
hit = pygame.sprite.spritecollide(player, wall_group, True)
if hit:
# if collision is detected call a function in your case destroy
# bullet
player.image.fill((255, 255, 255))
player_group.draw(screen)
wall_group.draw(screen)
pygame.display.update()
clock.tick(fps)
pygame.quit()
# sys.exit
if __name__ == '__main__':
main()
Make a group for the bullets, and then add the bullets to the group.
What I would do is this:
In the class for the player:
def collideWithBullet(self):
if pygame.sprite.spritecollideany(self, 'groupName'):
print("CollideWithBullet!!")
return True
And in the main loop somewhere:
def run(self):
if self.player.collideWithBullet():
print("Game Over")
Hopefully that works for you!!!
Inside the Sprite class, try adding a self.mask attribute with
self.mask = pygame.mask.from_surface(self.image)
and a collide_mask function inside of the Sprite class with this code:
def collide_mask(self, mask):
collided = False
mask_outline = mask.outline()
self.mask_outline = self.mask.outline()
for point in range(len(mask_outline)):
mask_outline[point] = list(mask_outline[point])
mask_outline[point][0] += bullet.x
mask_outline[point][1] += bullet.y
for point in range(len(self.mask_outline)):
self.mask_outline[point] = list(mask_outline[point])
self.mask_outline[point][0] += self.x
self.mask_outline[point][1] += self.y
for point in mask_outline:
for self_mask_point in self.mask_outline:
if point = self_mask_point:
collided = True
return collided

Pygame is not displaying a grid or fps counter

I am trying to make a rpg but i always get the issue when pygame dose not display I am using a youtube video to help my make this rpg but Its just not working the creator made a color module to help but it just dose not work I know there are better ways of making a fps counter feel free to improve it
import pygame, sys, time
from Scripts.UltraColor import *
pygame.init()
cSec = 0
cFrame = 0
FPS = 0
tile_size = 32
fps_font = pygame.font.Font("C:\\Windows\\Fonts\\Verdana.ttf", 20)
def show_fps():
fps_overlay = fps_font.render(str(FPS), True, Color.Goldenrod)
window.blit(fps_overlay, (0,0))
def create_window():
global window, window_height, window_width, window_title
window_width, window_hight = 800, 600
window_title = "RPG"
pygame.display.set_caption(window_title)
window = pygame.display.set_mode((window_width, window_hight), pygame.HWSURFACE|pygame.DOUBLEBUF)
def count_fps():
global cSec, cFrame, FPS
if cSec == time.strftime("%S"):
cFrame += 1
else:
FPS = cFrame
cFrame = 0
cSec = time.strftime("%S")
create_window()
isRunning = True
while isRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
isRunning = False
# LOGIC
count_fps()
# Render Graphics
window.fill(Color.Black)
# - Render Sinple Terrain Grid
for x in range(0, 640, tile_size):
for y in range(0, 480, tile_size):
pygame.draw.rect(window, Color.White, (x, y, tile_size + 1, tile_size + 1), 1)
show_fps()
pygame.display.update
pygame.quit()
sys.exit()
You need to add parentheses behind pygame.display.update to call this function and update the display: pygame.display.update()
I also recommend to use a pygame.time.Clock to limit the frame rate and get the fps. Calling clock.tick(FPS) makes sure that the game doesn't run faster than this frame rate. In the show_fps function you can just call clock.get_fps() to get the current frame rate.
import pygame
def show_fps(window, clock):
fps_overlay = FPS_FONT.render(str(clock.get_fps()), True, GOLDENROD)
window.blit(fps_overlay, (0, 0))
pygame.init()
FPS_FONT = pygame.font.SysFont("Verdana", 20)
GOLDENROD = pygame.Color("goldenrod")
tile_size = 32
window = pygame.display.set_mode((800, 600), pygame.HWSURFACE|pygame.DOUBLEBUF)
clock = pygame.time.Clock()
FPS = 60
isRunning = True
while isRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
isRunning = False
# Render Graphics
window.fill((50, 50, 50))
# Render Simple Terrain Grid
for x in range(0, 640, tile_size):
for y in range(0, 480, tile_size):
pygame.draw.rect(
window, (255, 255, 255),
(x, y, tile_size+1, tile_size+1), 1)
show_fps(window, clock)
clock.tick(FPS)
pygame.display.update()
pygame.quit()

How to detect collision/mouse-over between the mouse and a sprite?

Goal: to know when a sprite is clicked / active with the mouse
Using: Python 3.2 64bit, Pygame 1.92 64bit, windows 7 64bit
I spend 6 hours to no avail...I've tried :
s.rect.collidepoint(pygame.mouse.get_pos())
s.collidepoint(pygame.mouse.get_pos())
s.sprite.spritecollide(pygame.mouse.get_pos())
s.spritecollide(pygame.mouse.get_pos())
s.sprite.collide_rect(pygame.mouse.get_pos())
s.collide_rect(pygame.mouse.get_pos())
I've also tried turning the mouse location, which I really don't want to do, like someone else mentioned here on another post, into a sprite and collide like that with the same results ;(
I'm able to successfully mouse-collide with an image, but as soon as I turn the image into a sprite class, it becomes a nightmare...what's wrong with the sprite class? Or am I wasting time trying to use sprites for the nice collision features and just use images with rect collision instead?
Keep on getting the AttributeError: 'Sheldon' object has no attribute 'Rect' (s.Rect.collidepoint)
or AttributeError: 'tuple' object has no attribute 'collidepoint' (s.collidepoint)
or AttributeError: 'Rake' object has no attribute 'sprite' (s.sprite.collidepoint)
Since I'm new to python/pygame, should I be putting this detection in an Update/Render method in the sprite class itself, or am I using the wrong event polling???
I haven't bothered trying to recode the mousedown/up/dragging since I can't even get the mouse-over to work
Hopefully this time the post gets a working response...the others didn't ;(
Thanks for your help.
Code:
import pygame
from pygame import *
from pygame.locals import *
from pygame.sprite import *
class Sheldon(Sprite):
def __init__(self):
Sprite.__init__(self)
self.image = transform.scale(image.load('sheldon.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
class Rake(Sprite):
def __init__(self):
Sprite.__init__(self)
self.image = transform.scale(image.load('rake.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
class Sprite_Mouse_Location(Sprite):
def __init__(self,x,y):
Sprite.__init__(self)
self.rect = pygame.Rect(x,y,1,1)
print(self.rect)
pygame.init()
window = display.set_mode( (800,600) )
sheldon = Sheldon()
sheldon.rect = (10,10)
all_sprites = Group(sheldon)
rake = Rake()
rake.rect = (400,250)
all_sprites.add(rake)
x,y = pygame.mouse.get_pos()
mouse_sprite = Sprite_Mouse_Location(x,y)
running = True
while running == True:
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYUP and event.key == K_ESCAPE :
pygame.quit()
elif event.type == MOUSEMOTION :
for s in all_sprites :
if pygame.sprite.collide_rect(s,mouse_sprite):
print("hit")
window.fill( (0,0,0) )
all_sprites.update()
all_sprites.draw(window)
display.update()
You don't need Sprite_Mouse_Location.
BTW: to set position you need
rake.rect.topleft = (400, 250)
# or
rake.rect.x = 400
rake.rect.y = 250
not
rake.rect = (400, 250)
because it replace pygame.Rect() with tuple
Example code:
I use Surface instead of image.load() so everyone can run it without images.
import pygame
# --- constants --- (UPPER_CASE names)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
# --- classes --- (CamelCase names)
class Sheldon(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((230, 310))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def check_click(self, mouse):
if self.rect.collidepoint(mouse):
print("hit RED")
class Rake(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((230, 310))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def check_click(self, mouse):
if self.rect.collidepoint(mouse):
print("hit GREEN")
# --- main --- (lower_case names)
# - init -
pygame.init()
window = pygame.display.set_mode((800,600))
# - objects -
sheldon = Sheldon(10, 10)
#sheldon.rect.topleft = (10, 10)
rake = Rake(400, 250)
#rake.rect.topleft = (400, 250)
all_sprites = pygame.sprite.Group()
all_sprites.add(sheldon, rake)
# - mainloop -
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT or \
(event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
for s in all_sprites:
s.check_click(event.pos)
window.fill(BLACK)
all_sprites.update()
all_sprites.draw(window)
pygame.display.update()
# - end -
pygame.quit()
There are a lot of things that are going on with your code. Coding can be hard at first, but keep sticking to! You'll better as long as you keep trying and don't give up! Your error is occurring because above the loop, you are setting your various sprites' rect variables to tuples instead of rects. Rects are not tuples, they have a bunch of variables that tuples don't have and collide_rect needs some of those variables. I put a couple comments in the code below about your other questions.
import pygame
from pygame import *
from pygame.locals import *
from pygame.sprite import *
class Sheldon(Sprite):
def __init__(self):
Sprite.__init__(self)
self.image = transform.scale(image.load('sheldon.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
class Rake(Sprite):
def __init__(self):
Sprite.__init__(self)
self.image = transform.scale(image.load('rake.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
class Sprite_Mouse_Location(Sprite):
def __init__(self,x,y):
Sprite.__init__(self)
self.rect = pygame.Rect(x,y,1,1)
print(self.rect)
pygame.init()
window = display.set_mode( (800,600) )
sheldon = Sheldon()
sheldon.rect = (10,10) # (10,10) is not a rect!
# pygame.Rect(0,0,10,10) is a rect!
all_sprites = Group(sheldon)
rake = Rake()
rake.rect = (400,250) # Same as above comment.
all_sprites.add(rake)
x,y = pygame.mouse.get_pos() # If you are going to make the mouse
mouse_sprite = Sprite_Mouse_Location(x,y) # a sprite, then update your mouse position in the loop.
running = True
while running == True:
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYUP and event.key == K_ESCAPE :
pygame.quit()
elif event.type == MOUSEMOTION :
# You could have this instead.
# mouse_sprite.rect.x, mouse_sprite.rect.y = pygame.mouse.get_pos()
# Then move the for loop below to be out of the event loop.
for s in all_sprites :
if pygame.sprite.collide_rect(s,mouse_sprite):
print("hit")
window.fill( (0,0,0) )
all_sprites.update()
all_sprites.draw(window)
display.update()
I'd also recommend going through a pygame tutorial as well as looking at other people's pygame code and trying to understand it line by line. Both those tips helped me out. Good luck.
thanks to alanxoc3 and a new day, code working
posting here because I'm sure another newbie is going to want to do this type of mouse click
# to create a group of sprites and use the mouse over them individually
import pygame
from pygame import *
from pygame.locals import *
from pygame.sprite import *
class Sheldon(Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self,self.groups) #have to have groups here, not documented well
self.image = transform.scale(image.load('sheldon.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
def clickCheck(self,smouse):
if pygame.sprite.collide_rect(smouse, self): #could not use sritecollison because it would flag whole group
print('hit sheldon') # this if the check mouse that its working
#------------------------------------------
class Rake(Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self,self.groups)
self.image = transform.scale(image.load('rake.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
def clickCheck(self,smouse):
if pygame.sprite.collide_rect( smouse, self ):
print('hit rake')
#-------------------------------------------
class Sprite_Mouse_Location(Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.rect = pygame.Rect( 0 , 0 , 1 , 1 ) # no updating needed here
#--------------------------------------------
pygame.init()
window = display.set_mode( (800,600) )
mouse_sprite = Sprite_Mouse_Location() # had to create a mouse as sprite to use the sprite collision feature
all_sprites = pygame.sprite.Group() # have to declare first, no well documented
Sheldon.groups = all_sprites # better than all_sprites = Group(sheldon), and can be assigned before instantiation of sheldon!!!
sheldon = Sheldon()
sheldon.rect = (10,10,230,310)
Rake.groups = all_sprites
rake = Rake()
rake.rect = (400,250,230,310)
running = True
while running == True:
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYUP and event.key == K_ESCAPE :
pygame.quit()
elif event.type == MOUSEBUTTONDOWN:
if event.button == 1:
mouse_sprite.rect.x , mouse_sprite.rect.y = pygame.mouse.get_pos() # have to have this to update mouse here or get wrong location
for s in all_sprites: #can't have outside the event or it will continuously check
s.clickCheck(mouse_sprite)
window.fill( (0,0,0) )
all_sprites.update() # have to have this for group sprites
all_sprites.draw(window) # have to have this for sprites
display.flip()

Python /Pygame blitting multiple image to list coordinates

So i'm making a space game where you have a open world to explore (A black Screen)
and i wanna create planets(Blit images to screen) around the universe(from a list).
This is my code currently
star = pygame.image.load("star.png")
planets = random.randrange(100,500) #<------#####NOT IMPORTANT#######
positions = [(300,50),(400,27),(900,55)] #<------
position = ()
positions has coorinates where images should be blitted
but when i blit them
for position in positions:
ikkuna.blit(star, position)
it blits the first one or nothing and does not crash
why?
################################################-
Here is the full code if it helps (there is bits of the finish language in there hope it does not bother)
"ikkuna = screen (leveys,korkeus) = (width,hight) toiminnassa = in action"
import pygame
import random
import time
import sys
import math
pygame.init()
White = (255,255,255)
red = (255,0,0)
kello = pygame.time.Clock()
star = pygame.image.load("star.png")
planets = random.randrange(100,500)
positions = [(300,50)]
position = ()
tausta_vari = (255,255,255)
(leveys, korkeus) = (1000, 1000)
ikkuna = pygame.display.set_mode((leveys, korkeus))
pygame.display.set_caption("SpaceGenerationTest")
######################################################################
toiminnassa = True
while toiminnassa:
for event in pygame.event.get():
if event.type == pygame.QUIT:
toiminnassa = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_g:
print("Generating World....")
print(planets)
for position in positions:
ikkuna.blit(star, position)
print("hello")
There's some problems with your code:
Your not updating the display, which means that all your changes won't be visible. Use pygame.display.update() or pygame.display.flip() at the end of the game loop to update the screen.
When you're mixing English and Finnish it becomes very inconsistent and hard to follow, especially for people who don't speak Finnish. Try to use English, even when you're just practicing.
Your full example only contain one position in the list, thus it's only creating one star at one position.
Pressing the 'g'-key won't generate any planets. You might want to introduce a boolean variable like in the example below.
I changed your code to english and made some adjustment so it's more consistent.
import pygame
import random
pygame.init()
WHITE = (255, 255, 255)
RED = (255, 0, 0)
# I changed the background color to black, because I understood it as that is what you want.
BACKGROUND_COLOR = (0, 0, 0) # tausta_vari
clock = pygame.time.Clock() # kello
star = pygame.Surface((32, 32))
star.fill((255, 255, 255))
planets = random.randrange(100, 500)
positions = [(300, 50), (400, 27), (900, 55)]
WIDTH, HEIGHT = (1000, 1000) # (leveys, korkeus)
screen = pygame.display.set_mode((WIDTH, HEIGHT)) # ikkuna
pygame.display.set_caption("SpaceGenerationTest")
display_stars = False
running = True # toiminnassa
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_g:
print("Generating World....")
print(planets)
display_stars = True
screen.fill(BACKGROUND_COLOR)
if display_stars:
for position in positions:
# This will create 3 stars because there're 3 elements in the list positions.
# To create more stars you'll need to add more in the list positions.
screen.blit(star, position)
pygame.display.update()
Your blitting all your images to the exact same position: positions = [(300, 50)], so the last image covers all the other images up. Also, you may not know this, but to display anything in pygame you have to either call pygame.display.flip() or pygame.display.update() after you finish drawing. I made a few revisions to your code, so the stars should show-up:
import pygame
import random
import time
import sys
import math
def main():
pygame.init()
White = (255,255,255)
red = (255,0,0)
kello = pygame.time.Clock()
star = pygame.image.load("star.png")
planets = random.randrange(100,500)
positions = [(300,50), (310, 60), (320, 80), (607, 451), (345, 231)]
tausta_vari = (255,255,255)
(leveys, korkeus) = (1000, 1000)
ikkuna = pygame.display.set_mode((leveys, korkeus))
pygame.display.set_caption("SpaceGenerationTest")
######################################################################
toiminnassa = True
while toiminnassa:
for event in pygame.event.get():
if event.type == pygame.QUIT:
toiminnassa = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_g:
print("Generating World....")
print(planets)
ikkuna.fill((0, 0, 0)) # fill the screen with black
for position in positions:
ikkuna.blit(star, position)
print("Hello")
pygame.display.flip() # updating the screen
if __name__ == '__main__': # are we running this .py file as the main program?
try:
main()
finally:
pg.quit()
quit()
~Mr.Python

PyQt4 video player crashes when moving window

I've written a simple PyQt4 GUI that plays an OpenCV VideoCapture. This requires converting frames from numpy arrays to QImages. I'm using OpenCV so that I can detect circles using my findCircles method.
However, when I pass my frames to findCircles, the program crashes when the window is moved. This problem does not occur when I don't search for circles. I don't understand why this is happening, as I'm under the impression that the work is being done on a different thread than the GUI since I call findCircles from the run method of a QThread.
Note that I don't receive a normal error message in the console; Python crashes like such:
Here is the video file I've been using to test my player. I'm running Python 2.7.6 on Windows 8.1.
import sys
import cv2.cv as cv, cv2
from PyQt4.Qt import *
import time
def numpyArrayToQImage(array):
if array != None:
height, width, bytesPerComponent = array.shape
bytesPerLine = bytesPerComponent * width;
cv2.cvtColor(array, cv.CV_BGR2RGB, array)
return QImage(array.data, width, height, bytesPerLine, QImage.Format_RGB888)
return None
def findCircles(frame):
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blurredFrame = cv2.medianBlur(grayFrame, 3)
circles = cv2.HoughCircles(blurredFrame, cv.CV_HOUGH_GRADIENT, 1, 30, param1=50, param2=30, minRadius=30, maxRadius=35)
if circles is not None:
for i in circles[0]:
cv2.circle(frame, (i[0], i[1]), i[2], (255, 0, 0), 1) # Perimeter
cv2.circle(frame, (i[0], i[1]), 3, (0, 255, 0), -1) # Center
class VideoThread(QThread):
frameProcessed = pyqtSignal(QImage)
def __init__(self, video, videoLabel):
QThread.__init__(self)
self.video = video
self.fps = self.video.get(cv.CV_CAP_PROP_FPS)
self.frameCount = self.video.get(cv.CV_CAP_PROP_FRAME_COUNT)
self.startingSecond = 0
self.videoLabel = videoLabel
def run(self):
clockAtStart = time.clock()
while True:
runtime = self.startingSecond + (time.clock() - clockAtStart)
currentFrame = int(runtime * self.fps)
if currentFrame < self.frameCount - 1:
self.video.set(cv.CV_CAP_PROP_POS_FRAMES, currentFrame)
frame = self.video.read()[1]
findCircles(frame) # Removing this line removes the issue
self.frameProcessed.emit(numpyArrayToQImage(frame))
time.sleep(.02)
else:
break
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.initUI()
#pyqtSlot(QImage)
def updateVideoLabel (self, image):
self.videoLabel.setPixmap(QPixmap.fromImage(image))
self.videoLabel.update()
def initUI(self):
self.setGeometry(300, 300, 500, 375)
self.setMinimumHeight(250)
self.createWidgets()
self.addWidgets()
def startNewVideo(self):
self.video = cv2.VideoCapture(unicode(QFileDialog.getOpenFileName(self, "Open video").toUtf8(), encoding="UTF-8"))
self.videoThread = VideoThread(self.video, self.videoLabel)
self.videoThread.frameProcessed.connect(self.updateVideoLabel)
self.playVideoFrom(0)
def playVideoFrom(self, frame):
self.videoThread.startingSecond = frame / self.videoThread.fps
self.videoThread.start()
def createWidgets(self):
self.populateMenuBar()
self.videoLabel = QLabel()
self.videoLabel.setStyleSheet('background-color : black;');
def populateMenuBar(self):
self.menuBar = self.menuBar()
fileMenu = QMenu('File', self)
openAction = QAction('Open video...', self)
openAction.triggered.connect(self.startNewVideo)
fileMenu.addAction(openAction)
self.menuBar.addMenu(fileMenu)
def addWidgets(self):
mainLayout = QVBoxLayout()
mainLayout.addWidget(self.videoLabel, 1)
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
centralWidget.setLayout(mainLayout)
if __name__ == '__main__':
app = QApplication(sys.argv)
player = MainWindow()
player.show()
sys.exit(app.exec_())
I've tested your program, and it crashes when it finds no circles as indicated in the error message:
Traceback (most recent call last):
File "test_opencv_tkinter.py", line 53, in run
findCircles(frame) # Removing this line removes the issue
File "test_opencv_tkinter.py", line 26, in findCircles
if len(circles) > 0:
TypeError: object of type 'NoneType' has no len()
I've made some changes in the findCircles(frame) function, as follows, and it runs without error, even when I move the window around on the screen.
def findCircles(frame):
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blurredFrame = cv2.medianBlur(grayFrame, 3)
circles = cv2.HoughCircles(grayFrame,cv.CV_HOUGH_GRADIENT,1,20,
param1=50,param2=30,minRadius=0,maxRadius=0)
if circles == None:
print "no circles found"
return
if len(circles) > 0:
print "found circles ", len(circles[0])
for i in circles[0]:
cv2.circle(frame, (i[0], i[1]), i[2], (255, 0, 0), 1) # Perimeter
cv2.circle(frame, (i[0], i[1]), 3, (0, 255, 0), -1) # Center

Resources