I have a list of rects, just by saying a = [] then doing a.append(pygame.Rect(1,1,32,32)). I can draw this easily by just doing
for blocks in a:
pygame.draw.rect(screen, WHITE, blocks)
But when I do
for blocks in a:
if blocks.colliderpoint(pygame.mouse.get_pos()):
#code
An error occurs, saying it must be an Rect like style. I don't understand
if blocks.colliderpoint(pygame.mouse.get_pos()):
maybe because of the typo?
Change .colliderpoint into .collidepoint and try again. That should do.
Related
I have two objects:
#Object1
enemigo=pygame.image.load("enemigo.png").convert_alpha()
enemigo=pygame.transform.scale(enemigo, (100, 100))
enemigo_rectangulo=enemigo.get_rect(center=(1000, 100))
#Object2
enemigo2=pygame.image.load("enemigo2.png").convert_alpha()
enemigo2=pygame.transform.scale(enemigo2, (140, 140))
enemigo_rectangulo2=enemigo2.get_rect(center=(1400, 50))
And I want to make an if statement if they collide with a third object. This code actually works but is too long:
if personaje_rectangulo.colliderect(enemigo_rectangulo) or personaje_rectangulo.colliderect(enemigo_rectangulo2):
And there's an error when I try to write:
if personaje_rectangulo.colliderect(enemigo_rectangulo, enemigo_rectangulo2):
So, what is wrong? Is there a shorter way to write it?
The first thing you can do is use shorter variable names, such as personaje and enemigo.
Additionally, break the statement into smaller pieces by using variables:
hit_enemy1 = personaje_rectangulo.colliderect(enemigo_rectangulo)
hit_enemy2 = personaje_rectangulo.colliderect(enemigo_rectangulo2)
if hit_enemy1 or hit_enemy2:
pass
Alternatively, if you store all of the enemies in a list, you can use any():
if any(personaje_rectangulo.colliderect(enemigo_rectangulo) for enemigo_rectangulo in todos_enemigos):
pass
Now this is also getting long so creating a function to help can shorten the line of code:
def collision(person, enemy):
return person.colliderect(enemy)
if any(collision(person, enemy) in todos_enemigos):
pass
Another solution is to create a Enemy class which encapsulates the data and behavior of an enemy. This is a bit more advanced, but definitely a good exercise to learn what classes are and how to use them.
Use collidelist():
Test whether the rectangle collides with any in a sequence of rectangles. The index of the first collision found is returned. If no collisions are found an index of -1 is returned.
if personaje_rectangulo.collidelist([enemigo_rectangulo, enemigo_rectangulo2]) >= 0:
Hey I've been stuck on this issue for quite a while and was hoping someone could help me out:
I'm using pyglet and have got all of the code working in my project (even what I was having the issue with) then I restarted my computer and suddenly it didn't work...
This is the loop that is instantiating my 'Letter' objects:
main_st = ut.makeString("EXNXYXAXDAADUXMDXLGEQTAQXDDQSVXUTSXKHXHRXYFUXLXJUTHXYVADSUXKHUQUIXSJHXHDPKXFQUXILNXORMXRPL")
letter_list = []
for i in range(len(main_st)):
letter_list.append(l.Letter(pyglet.resource.image("Letters/" + main_st[i] + ".png"),main_st[i],10,10))
And this is the Letter class constructor Letter is a subclass of pyglet.sprite.Sprite:
def __init__(self,im,iden,xx,yy):
super(Letter,self).__init__(img=im,x=xx,y=yy)
At no point in the program do I modify the x and y coordinates of sprite but when I go to draw them, no matter what I put in for xx and yy they're always drawn in the same place on the window UNLESS I do a very large number for yy, and in those cases it simply disappears (I assume it's outside of the window).
I'm having each letter flash on the screen for 1 second and in order to do that here's my on_draw method
def on_draw():
background.draw()
if not key_manager.cur_letter == None:
key_manager.cur_letter.draw()
(only key_manager.cur_letter gets drawn and that switches every second).
The problem might be related to older versions.
But after calling super(Letter, self)... you could do:
def __init__(self,im,iden,xx,yy):
super(Letter,self).__init__(img=im,x=xx,y=yy)
self.x = xx
self.y = yy
And that should do the trick.
I'm making a 2-d game using Pygame.
I want to add particle effects into the game I'm working on. I want to do things like spawn smoke, fire, blood, etc. I'm curious is there an easy way to do this? I don't really know even where to start.
I just need a base case I could expand upon..
Pls Help.
You might want to just make a class made of rects that go up and randomly go to the right or left each time it is updated for the smoke. Then make a ton of them whenever you want it. I'll try to make an example code below, but I can't guarntee it will work. You can make similar classes for the other particle effects.
class classsmoke(pygame.Rect):
'classsmoke(location)'
def __init__(self, location):
self.width=1
self.height=1
self.center=location
def update(self):
self.centery-=3#You might want to increase or decrease this
self.centerx+=random.randint(-2, 2)#You might want to raise or lower this as well
#use this to create smoke
smoke=[]
for i in range(20):
smoke.append(classsmoke(insert location here))
#put this somewhere within your game loop
for i in smoke:
i.update()
if i.centery<0:
smoke.remove(i)
else:
pygame.draw.rect(screen, GREY, i)
Another option would be to make the class just a tuple, like this:
class classsmoke():
'classsmoke(location)'
def __init__(self, location):
self.center=location
def update(self):
self.center[1]-=3
self.center[0]+=random.randint(-2, 2)
#to create smoke
smoke=[]
for i in range(20):
smoke.append(classsmoke(insert location here))
#put inside game loop
for i in smoke:
i.update()
if i.centery<0:
smoke.remove(i)
else:
pygame.draw.rect(screen, GREY, (i.center[0], i.center[1], 1, 1))
Or, to avoid classes completly:
#to create smoke:
smoke=[]
for i in range(20):
smoke.append(insert location here)
#put within your game loop
for i in smoke:
i[1]-=3
i[0]+=random.randint(-2, 2)
if i[1]<0:
smoke.remove(i)
else:
pygame.draw.rect(screen, GREY, (i[0], i[1], 1, 1))
Pick your preference, and do something similar for other particle effects.
Check the Library for particle effects PyIgnition
I'm having problems with my tile renderer, which goes through a text file and finds characters, converting them into rects. My problem is that only the most recent tile / rect is counted for collisions.
A video of my problem: http://youtu.be/7wAHp-vgrLU
My code works like this:
wall = pygame.draw.rect(screen, (40,40,40), (current_tile_x,current_tile_y,tile_size,tile_size), 0)
if wall.colliderect(collision) == 1:
print "Collision!"
The player's rect is defined as collision. The problem I think is that for every wall tile, the var wall gets overwritten, so how would I go about fixing this?
You just answered yourself, you should make a iterable with all rects to be tested:
#load all the rects in one list for example
walls = get_wall_list() #returns a list [rect0,rect1,rectn]
for wall in walls:
if wall.colliderect(collision): #'if True == 1:' works as the same 'if True:'
print "Collision!"
I have tried a for loop with the blit and draw methods and using different variables for " PlayerSprite " and " Treegroup "
for PlayerSprite in Treegroup:
surface.blit(PlayerSprite,(random.randrange(100,500),random.randrange(100,600)))
also tried
SPRITES=[]
for Sprites in range(10):
Sprites= PlayerSprite
SPRITES.append(Sprites)
all I get are errors
screen=pygame.display.set_mode((640,480))
background1=pygame.image.load("C:\Pygame-Docs\examples\data\Random Map.bmp")
class Tree1(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image=pygame.image.load('C:\Pygame-Docs\examples\data\Tree 1.bmp')
self.image=self.image.convert()
self.rect=self.image.get_rect()
self.rect.centerx=random.randrange(10,100)
self.rect.centery=random.randrange(10,100)
# Makes a group of trees
Howmanytrees=random.randrange(5,10)
Trees=[]
for tree in range(Howmanytrees):
trees=Tree1()
Trees.append(trees)
# Howmany groups
for Treegroup in range(10):
Treegroup=Trees
# Places groups
PlayerSprite=pygame.sprite.Group(Treegroup)
# keeps loop ( game ) going until canceled
keepgoing=True
while keepgoing:
for event in pygame.event.get():
if event.type==pygame.QUIT:
keepgoing=False
# actually draws screen
screen.blit(background1,(0,0))
PlayerSprite.draw(screen)
pygame.display.flip()
This code only displays 5 to 10 trees " Trees=[] "
and nothing else. I have worked on this problem for over a week , read many tutorials, looked on many websites, nothing seems to work. I must be overlooking or missing somethig. I thought this would be easy!
Thanks so much!
As far as I understand what you want to achieve, the below code should help you. I kept it very very simple regarding python syntax, as you seems to be a newbie (for experienced programmers: yes, what I wrote below is horrible python code, but I believe the OP can understand it and it may help).
The key is that if you want to get several groups of trees, you must have a loop within a loop. The inner loop put the trees inside the group, and the outer loop put several groups. Of course you can (and should) certainly hide the inner loop behind some function or class.
# Howmany groups ? say 3
trees_groups = []
number_of_groups = 3
for _ in range(number_of_groups):
# Choose a base position for my group of trees
base_x = random.randrange(0,530)
base_y = random.randrange(0,370)
# Makes a group of trees
trees=[]
number_of_trees = random.randrange(5,10)
for _ in range(number_of_trees):
one_tree = Tree1()
trees.append(one_tree)
for tree in trees:
tree.rect.centerx += base_x
tree.rect.centery += base_y
trees_groups.append(tree)
# Places groups
PlayerSprite=pygame.sprite.Group(trees_groups)
Some after notes:
And as other posters said, you should not use capitalized variables as you do. The python usage is to keep them for classes
Also looping using range when the base variant is not used is bad practice. I emphasized this by using underline as a variable name for the loop variant when it is not used.
I would use randint and move_ip to get what you want. Here is a code snippet from my own game that works just as well:
self.rect.move_ip(random.randint(minX, maxX), random.randint(minY, maxY))
the four variables minX, maxX, minY, maxY form a rectangle where the sprite can be placed. In your case, the trees would be placed along the entire screen, but with a reduced max X and Y range so trees won't clip through the bottom of the screen.
Also, use a Group class to store your trees rather than a list. A list stops the spawning of multiple trees, while a Group does. Here is how to call it:
Treegroup = pygame.sprite.Group
and to add a sprite to the group:
Treegroup.add(Tree1(screen))
Make sure the class itself has screen in its init, like so:
def __init__(self, screen)
Once that's done, your code should look something like this:
for Treegroup in range(10):
Treegroup.add(Tree(screen))
[...]
class Tree(pygame.sprite.Sprite):
def __init__(self, screen):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_image('tree.png', -1)
self.rect.move_ip(random.randint(0, 800), random.randint(0, 600))
self.area = screen.get_rect()
It doesn't really make much sense to me.
for tree in range(Howmanytrees):
trees=Tree1()
Trees.append(trees)
Your loop here is doing nothing at all. tree should be a number between 0 and Howmanytrees. Again, the following block isn't indented so it's not part of the loop. Even so, the block still wouldn't work. Also, you're confusing yourself and us with variable names. Trees is the object? trees is the list? Don't do this. Seriously.
No idea what the following code is up to.
# Howmany groups
for Treegroup in range(10):
Treegroup=Trees
Create your SpriteGroup passing in the aforementioned trees list? Or am I missing something :) TreeGroup = Trees 10 times is just going to do that 10 times. You are not using the loop variant. The only thing that modifies during the loop. Even so, this entire block of code is useless.
while keepgoing:
for event in pygame.event.get():
if event.type==pygame.QUIT:
keepgoing=False
This is going to cause a nice infinite loop. It is evaluating the keepgoing variable constantly. This will never get set to false unless the user quits, but also it will never display anything on the screen. Lose this. Use this instead:
for event in pygame.event.get():
if event.type == QUIT:
return
This will not cause an infinite loop as there are only so many events to be processed per tick. Then the program will loop around and do the process or updating, rendering and getting input again.