Moving Sprite groups - python

I've been reading the Pygame documentation for Sprite Groups, on its section for sprites it says:
The groups are designed for high efficiency in removing and adding
Sprites to them. They also allow cheap testing to see if a Sprite
already exists in a Group. A given Sprite can exist in any number of
groups. A game could use some groups to control object rendering, and
a completely separate set of groups to control interaction or player
movement. Instead of adding type attributes or bools to a derived
Sprite class, consider keeping the Sprites inside organized Groups.
This will allow for easier lookup later in the game.
My aim is to get movement on sprite groups, but I can't find any examples online. Is it possibly to move all or some individual sprites in a sprite group, If so how?

To move all Sprites in a Group, just use a simple for loop:
for spr in my_sprites_that_shall_move:
spr.rect.move_ip(d_x, d_y)
The Group class does not conatin any functionality to control the movement of its Sprites

Related

Display a sprite with no image - PyGame

I am working on a game project meant for learning and I was thinking if I create a sprite without a set image. I need this because I have an ideea to keep the value of the rect tiles that need collision in a sprite group. Is it possible?
Create a list of sprites excluding the invisible sprite(s):
all_sprites_list.draw(screen)
Then for collision just make a barrier list and put your invisible sprites that need collision in it.

pygame sprite collision on left

I want to do special collisions with pygame. I have a Ball sprite and a Block sprite and I want to know on which side of the block the ball has collided.
Maybe it's possible with pygame.sprite.groupcollide() and a custom collided as they call it. But I found no answser for that question. Is there any way to do it ?
Yes, it is possible. You are correct about the collided argument too.
What you need to do is write a function that will take 2 sprites and return a boolean value.
In this function you can then check on which side they have collided, and inform the sprites of the collision, or even return true only when a certain type of collision has happened.
Since every sprite has a rect attribute, you can check there way of movement as well as their positions to see where they have collided.
For example, if we have two sprites, A,B one going up and the other going left, they can collide in two ways. You can test if A has collided from the top, if after the collision, the second sprite is higher than A.
Heres a link to the pygame documentation I found:
pygame documentation
If your using a browser with a search page function search for:
pygame.sprite.spritecollide()
Im not too good with pygame, but understand the basics. I think the correct function is
pygame.sprite.collide_mask()
Which as the docs say:
"Returns first point on the mask where the masks collided, or None if there was no collision.
Tests for collision between two sprites, by testing if thier bitmasks overlap. If the sprites have a “mask” attribute, that is used as the mask, otherwise a mask is created from the sprite image. Intended to be passed as a collided callback function to the *collide functions. Sprites must have a “rect” and an optional “mask” attribute.
You should consider creating a mask for your sprite at load time if you are going to check collisions many times. This will increase the performance, otherwise this can be an expensive function because it will create the masks each time you check for collisions."
Hope it helped.
-Harry

Get a sprite to follow/chase another in Livewires python?

I am trying to make a top down shooter style game and am having a hard time getting a sprite to "chase" the player's sprite.
Take a look at seek behavior will work for chasing. http://gamedev.tutsplus.com/tutorials/implementation/understanding-steering-behaviors-seek/
If you don't want that, you can use vectors to get the direction from one unit to the other. ( Then scale the length / cap it )

How do you use circle-based collision with group collision methods in Pygame?

Having scoured the documentation and various tutorial sites, I still can't get my head around the way you modify the sprite.collide method with anything other than rectangular bounding-box collision detection.
I have a program which needs to detect collision between a sprite "Hook" and any one of a number of fish, stored in a sprite group called "fishies"
I can use:
for hit in pygame.sprite.spritecollide(self, self.fishies)
to return a list of colliding sprites using the bounding rectangles, but I want to use circles or masks.
The documentation says I can use:
pygame.sprite.spritecollide(self, self.fishies, False, collided = None)
where "collided" is a callback function. But I can't work out what that means. Simply writing:
pygame.sprite.spritecollide(sprite, group, dokill, pygame.sprite.collide_circle())
produces an error.
Can anyone help, or have I misunderstood how it is supposed to work?
I think you almost have it -- the problem is you're calling collide_circle instead of passing the function itself. Try something like this:
pygame.sprite.spritecollide(hook, fish, False, pygame.sprite.collide_circle)
The only difference in syntax is leaving off the parentheses. What pygame requires for the collided parameter is a function that takes two sprites and returns a boolean indicating whether or not they collided, so you can pass any function that collides two sprites, even a custom one.

Collide detection and masks in python 3.2.2

Me and my friend are currently trying to make a game. In this game we wish to have nice collision detection. But we cannot seem to find the way to update the masks in the definiton while loop. :S We have tested it alot of times, with different values and even some really unlogical stuff.
Each time we move the player, the game crashes when it collides with the mask. Its like the loop goes on forever, even though the player and the bush should be going away from eachother when we move the mask and the background.
def check_collision():
while pygame.sprite.collide_mask(player, rock):
bg.x -= 1 #the x-value of the background
rock.x -=1 #the x-value of the object
This is just collision when going left using the button "a".
We also move the background and all the sprites instead of the player.
We need to use masks.
We know that it checks the collision, but the mask wont update after bg.x and rock.x are changed.
We assume that this is because the images aren't moved on the screen. And therefore we have tried putting a blit inside the while loop. It still would not work.
Thank you for helping, and a final question, is there any way to manually move a mask/object?
First of all, collision detection using masks is very time-intensive. Whether or not your game has entered an infinite loop, the processing requirements of a bitmask-bitmask overlap check will make your game run far too slowly.
A simple optimization exists, however:
Any object which is able to collide with things must have some maximum size -- that is, you can find a rectangle which will always contain your player, and your boulder can fit inside another. Therefore, if your player's box doesn't collide with the boulder's box, they can't possibly overlap. Since you insist on collision masking, (which can add some realism to any pixelart game), you can compute the per-pixel collision whenever (and only whenever) the bounding boxes collide.
Now, on to your coding style: >:O
It is never a good idea to put a potentially infinite loop within a function which should ideally compute an instant collision check. In the best-case scenario (which is certainly achievable), you would have one function to check whether two objects collide, and tell you some more useful information (the position of one relative to the other, etcetera); while a separate method of every moving object would fix the collisions.
This would translate to something like:
class CollidingObject:
#This class controls an object which can move and fix collisions
def __init__(self):
self.x = 0 #add relevant initialization code here
self.y = 0
self.xVel = 0 # X and Y velocity (for movement)
self.yVel = 0
self.xSize = 0 # the width of the object in pixels
self.ySize = 0 # the height of the object in pixels
def iscolliding(self, other):
# using x and y as the center of the object,
# this returns an empty tuple if they don't collide
if ((self.xSize + other.xSize) / 2 <= abs(self.x - other.x)) and
((self.ySize + other.ySize) / 2 <= abs(self.y - other.y)): return ()
"""
use pygame collidemask here to compute whether they collide.
if they do, return a vector of 'other's' position relative to self.
(this can be used to decide how to separate the objects)
"""
def restitute(self, overlaps_with, distances):
"""
Given some objects which overlap, and a list of 2D vectors of their
relative distances, this separates them however much you like.
"""
pass
As to where your colision checking is done, that depends upon your implementation of object management basics. I will heretofore assume that all of your in-game objects are contained within an iterable; and that on every frame you iterate through your objects, once to render, once to move them -- a structure something like this:
while NOT_QUIT:
for object in objects:
object.draw_to_screen()
object.move() # moves the object -- collisions, etc in here
event_handling_stuff() # handles events
In this case, every object can compute collision checking for anything which follows it in objects. In doing so, each object can collect how far it has to move from each. Afterwards, each object can move to be as far from each collider as possible.
In a few games I've written, I'd make objects move farther apart the more overlapped they are, giving collisions an elastic quality which makes even very rough restitution algorithms look very sexy. Generally, you can tinker with constants once you have a working check going and that would be the least of your worries.
Hopefully this will have helped you two a little (I realize now I went off a bit on a tangent, but you were asking about how to do the wrong things more efficiently :P).
tl;dr: Don't try to fix collisions within your collision check function. Instead, separate it into one which finds all collisions to other objects, and another which fixes all collisions for an object at the same time.
Add other questions and I'll update (:.
UPDATE 1
Expanding here on the "vector of other to self" bit (which was explained a tad crudely:/)
Generally when two objects collide in real life, they bounce back somewhat in the direction they came from (when you drop a rubber bouncy ball on the floor, it bounces back from whence it came -- it doesn't just phaze through the floor). In most programming applications, you'd want to make bouncy balls (and other colliding things) behave in the same way (well, sometimes you might want the ball to phaze though the floor, but that's even easier than bouncing IMHO :P).
To know which way an object must bounce back, you have to know the direction from which it came. More strictly, you have to know the angle at which it collided. This is very easily found if you compare the distance and direction between the centers of each object during the collision. This will provide a pretty accurate representation of two objects bouncing, if the centers you are using are close enough to their centers of mass (in most games the middle of an object is an easy and good approximation).
So, since we don't need to worry about center of mass and all that, we just measure the vector distance between object positions:
#Continuing the previous example, we put some code like this in 'iscolliding' :)
if they collide (pygame mask stuff) :
x_distance = self.x - other.x
y_distance = self.y - other.y
return (x_distance, y_distance)
This code can give you the line along which each object should move to resolve the collision as fast as possible. The rest is a matter of accelerating each object along this line, making sure they don't go closer together (pay attention to signs), and tweaking constants to create a realistic effect.

Categories