Get a sprite to follow/chase another in Livewires python? - 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 )

Related

How to get location of a sprite in pygame?

I am making a game in Python using Pygame. I have put a condition where if the player character goes on a specified tile than the score will increment by 1. but I am not able to get it done. because I am not able to get the position of the player character.for example if player_position == (the specified tile) : than score=score+1. please help me with this.
Have you tried using one of the "collide" functions? You could make the tile a sprite, too, and detect the collision. It might not be exactly what you're looking for, but it could work.
This would return True when two sprite arguments collide.
pygame.sprite.collide_rect()

Pygame: Racing Game Collsions

I am relatively new to Pygame and trying to make a top-down racing game. Everything has currently been made and is ready to go! However, I am unable to make proper collision detection between walls and background of the "level".
What I want to happen is that the car cannot leave the boundaries of the track it is pushed back onto the track and speed is reduced. Previously this was attempted with pygame.sprite.collide_rect to no luck.
Here is a screenshot of the first track within the game and one of the cars in-game. A background will be added at a later date.
Track Screenshot
Any advice on which functions to use would be much appreciated! Would be possible to even use .collidepoint like done in menus?
Thanks,
Adam.
What you could do is, check if the two images overlap, but one condition: the image of the track must be full opacity, and everything else transparent. Then use this code to check if overlapping.
Car_mask = pygame.mask.from_surface(CarImage)
Track_mask = pygame.mask.from_surface(TrackImage)
offset_x, offset_y = (Car.x - Track.y), (Car.y - Track.y)
if (Track_mask.overlap(Car_mask, (offset_x,offset_y)) != None):
print("overlaps")
else:
#Push Car Back On Track, Slow Speed Stuff
#Cause it not touching track at all.

Blitting a Pygame Tile-map Efficiently

My game map is a 2d-matrix that consists of different tiles (ex. map[y][x] = tile). Each tile has an image, and a rectangle. Currently the map is nearly 1000 tiles in size, and it takes quite some time to blit every one of them to the screen.
My current goal is to find a way to reduce the amount of time it takes to access each item of the matrix, and blit only the necessary tile-objects to the screen. Here is my main obstacle in trying to find a solution:
- Because it is a side-scrolling game, none of the tiles are static (the rectangles are always being adjusted with the player's movement, thus making it mandatory to re-blit the entire screen).
Here is generally how the map functions in the game:
For tile in tile matrix: blit tile to screen
Blit player and NPCs
Update player position
If player moves: adjust all tiles (camera system)
I'm looking for more efficient ideas of doing the same thing. As I said above, blitting every darn tile takes a lot of time, and to add to that, I'm not sure how to selectively blit different tiles when they are constantly changing location.
All ideas are welcome. Thank you.
When you're iterating over your tiles you can do a test to check if the current tile is contained within the camera's view port, if it is you can draw, otherwise you can skip blitting the tile.
for tile in tiles:
if camera.viewport.contains(tile.rect):
tile.draw()
The contains method is determining if a rectangle is inside another. You'll also need to use 2 different frames of reference, screen space and world space.

directing a mass of enemies at once

I am working on a simple 2d game where many enemies continually spawn and chase the player or players in python + pygame. A problem I ran into, and one many people that have programmed this type of game have run into is that the enemies converge very quickly. I have made a temporary solution to this problem with a function that pushes any two enemies randomly apart if they are too close to each other. This works well but is about an O(n^2) algorithm which is run every frame and at high enemies the program starts to slow down.
When my program runs with this function the enemies seem to form round object I nicknamed a "clump". The clump seems to usually ecliptic but may actually be more complex (not symmetrical) because as the player moves the enemies are being pulled in different directions. I do like the way this clump behaves, however I am wondering if there is a more efficient way to calculate it. Currently every enemy in the clump (often >100) is first moved in the direction of the player, and then pushed apart. If there was instead a way to calculate the figure that the clump creates, and how it moves it would save a lot of computation.
I am not exactly sure how to approach the problem. It may be possible to calculate where the border of the figure moves, and then expand it to make sure the area stays the same.
Also my two functions currently being used to move enemies:
def moveEnemy(enemy, player, speed):
a = player.left-enemy.left
b = player.top-enemy.top
r = speed/math.hypot(a,b)
return enemy.move(r*a, r*b)
def clump(enemys):
for p in range(len(enemys)):
for q in range(len(enemys)-p-1):
a = enemys[p]
b = enemys[p+q+1]
if abs(a.left-b.left)+abs(a.top-b.top)<CLUMP:
xChange = (random.random()-.5)*CLUMP
yChange = ((CLUMP/2)**2-xChange**2)**.5
enemys[p] = enemys[p].move(int(xChange+.5), int(yChange + .5))
enemys[p+q+1] = enemys[p+q+1].move(-int(xChange+.5),-int(yChange+.5))
return enemys
Edit: some screen shots of how the clump looks:
http://imageshack.us/photo/my-images/651/elip.png/
http://imageshack.us/photo/my-images/832/newfni.png/
http://imageshack.us/photo/my-images/836/gamewk.png/
The clump seems to be mostly a round object just stretched (like an eclipse but may be stretched in multiple directions), however it currently has straight edges due to the rectangular enemies.
There are several ways to go about this, depending on your game. Here are some ideas for improving the performance:
Allow for some overlap.
Reduce your distance checking to be done after a fixed number of frames.
Improve your distance checking formula. If you are using the standard distance formula, this can be optimized in many ways. For one, get rid of the square root. Precision doesn't matter, only the relative distance.
Each unit can keep track of a list of nearby units. Only perform your calculations between the units in that list. Every so often, update that list by checking against all units.
Depending on how your game is setup, you can split the field up into areas, such as quadrants or cells. Units only get tested against other units in that cell.
EDIT: When the units get close to their target, it might not behave correctly. I would suggest rather than having them home-in on the exact target from far away, that they actually seek a randomized nearby target. Like an offset from their real target.
I'm sure there are many other ways to improve this, it is pretty open ended after all. I should also point out Boids and flocking which could be of interest.
You could define a clump as a separate object with a fixed number of spacial "slots" for each enemy unit in the clump. Each slot would have a set of coordinates relative to the clump center and would either be empty or would hold a reference to one unit.
A new unit trying to join the clump would move towards the innermost free slot, and once it got there it would "stay in formation", its position always being the position of the slot it occupied. Clumps would have a radius much larger than a single unit, would adjust position to avoid overlapping other clumps or loose units that weren't trying to join the clump, etc.
At some point, though, you'd need to deal with interactions for the individual units in the clump, though, so I'm not sure it's worthwhile. I think Austin Henley's suggestion of splitting the field up into cells/regions and only testing against units in nearby cells is the most practical approach.
I think you're looking for flocking.
The best intro to flocking / steering behavior movement: http://www.red3d.com/cwr/steer/ . See the attached paper red3d paper. And the related OpenSteer

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