updating chosen elements in Pygame - python

I am working on animation of Fourier Transform in python, pygame. I want the result to look more or less as following:
https://www.youtube.com/watch?v=ACvXAjZE9jQ
I need to update the screen in order to constantly draw arms, or links in their new positions. However, updating the screen erases the graph drawn by the arms. I am drawing it by putting small dots in time intervals.
Would anyone have any suggestion how to deal with this dilemma or propose another solution?
My first idea was to add all the points coordinates to the list and draw them all together at every update, but the operation quickly becomes too inefficient and the animation keeps slowing dowm.

My first idea was to add all the points coordinates to the list and draw them all together at every update
This is the usual approach. However, I suggest converting the coordinates to int before adding them to the list, and only adding coordinate tuples that are not already in the list. This means that a new position must be compared with the last position before it is added. With this approach, the list should not become so long that the application slows down significantly. e.g.:
def appendPoint(point_list, x, y):
new_point = round(x), round(y)
if not point_list or point_list[-1] != new_point:
point_list.append(new_point)

Related

How can I make a rectangle in pygame be able to check for other rectangles around it?

As part of my current pygame project (I am very new to pygame), I have created multiple rectangles that move at random around the screen. As one of the features of this game, I want to make it so if one rectangle is close enough to another one, it moves towards it. Another feature I want to add is that rectangles cannot collide with each other, but I don't want to just do the regular
if rectangle1.colliderect(rectangle2):
rectange.x -= 10 # That is, it's previous position
because it will make the animations look odd.
The main way I can see to solve these problems is to use some sort of function that could check if a rectangle.x - 30 is another rectangle (or something similar), but I am unaware of one that exists.
I have attempted to look through google, but I haven't found anything as all the posts are different problems that aren't quite the same.
Thank you for any responses!
Use inflate to create a rectangle that is larger than the original one and surrounds it. Use this rectangle to find other rectangles in range:
test_rect = rect1.inflate(dist, dist)
if test_rect.colliderect(rect2):
# [...]

Separating an unknown amount of coordinates in a list into seperate coordinates

I am trying to create a program that will let a simulated robot move around a space and go around obstacles in the most efficient way possible. I have a list of obstacles hard coded into the code and I have to separate those points into separate variables, but there can be an unlimited amount of obstacles in the list. Each obstacle will have a row and column number, which is how I am determining how the robot will move.
I have tried to create a list and then taken the length of that list and used that to separate the different coordinates in the list, but since there is supposed to be a random amount of obstacles, the code would have to be changed every time another obstacle is added.
obstacles = [(2,3),(3,5),(5,2)]
#list of the obstacle coordinates
length = range(0,len(obstacles))
obs1,obs2,obs3,obs4=[obstacles[i] for i in length]
#Seperation of the coordinates into groups
obsRow,obsCol=obs1
#Seperation into the row and column of the coordinates
This function is giving an output, but the output only works when the number of obstacles in the list is equal to the amount of obstacles with the number after them (ex: obs1). I want this function to work no matter how many obstacles are in the list without changing the function.
If you are dealing with a potentially infinite number of spaces and obstacles you may want to look into A* pathfinding. It's a way to find the most efficient route without exhaustively trying every possible combination (see. The Travelling Salesman problem).
The following article provides an example of how you would solve a similar problem in Python alongside the relevant theory to understand the concepts behind the solution.

Modify polygons so that they don't overlap and area stays the same

I have a set of polygons and they can overlap with each other, like this:
I want to modify them in such a way that they don't overlap and the resulting surface area stays the same. Something like this:
It is okay if the shape or the position changes. The main thing is that they should not overlap with each other and the area should not change much (I know the area changed a little in the second image but I drew it manually thus let's just assume that the areas did not change).
I am trying to do it programmatically with the help of Python. Basically I stored polygons in a PostGIS database and with the help of a script I want to retrieve them and modify them.
I am very new to GIS and thus this seems like a difficult task.
What is the correct way of doing it? Is there an algorithm that solves this kind of problems?
Take a look at ST_buffer and try passing a signed float as the second argument (degrees to reduce radius by)
SELECT buffer(the_geom,-0.01) as geom
Be careful with negative buffers as you could run into issues if the buffer size exceeds the radius, see here.
Here is what I did:
Iterated over all the polygons and found overlapping polygons. Then, I moved the polygon in different directions and found the best moving direction by calculating the minimum resulting overlapping area. Then I simply moved the polygon in that best direction until there is no overlapping area.

Get the current coordinates of an item on a Canvas widget given its item handle?

From reading the docs (http://effbot.org/tkinterbook/canvas.htm#reference), there doesn't appear to me to be a way to do this. Just wanted to make sure I hadn't made a mistake. (I.e. one would have to internally store the coordinates of various items in a program if one wanted to do boundary checking, for example. [e.g. Check, before moving an oval, that it will not bump into a wall, represented by a line on the current canvas, the coordinate information of which is also stored.])
Use the coords method:
coords = the_canvas.coords(item_id)

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

Categories