Pygame blitting only updated surfaces - python-3.x

Right now I have an x by y array to hold integers that decide which tile to draw to the screen. (The integers choose which tile in my tile_arr to blit)
For better performance, I only want the ints that changed to be blit'ed again.
EXAMPLE 1:
For example right now I have something like:
tile_arr = [image1,image2,image3,image4]
arr = [[2,2,2],[2,2,2],[2,2,2]]
Then depending on what the user does, some values in arr might change, so lets say:
arr[0][0]=1
arr[2][1]=1
Which would give us the array:
arr=[[1,2,2],[2,2,2],[2,1,2]]
now when blitting to the screen, I would blit images from the tile_arr: image numbers 1,2,2 to the top row, 2,2,2, to the middle row, and 2,1,2 to the bottom row. When I blit the array, I use a screen.blit for each value or arr, that's nine blits. I would rather only do two blits. (Use screen.blit only twice)
EXAMPLE 2:
tile_arr = [green.bmp, red.bemp, blue.bmp]
feild_arr = [[0,0,0], [0,0,0], [0,0,0]]
Output:
G G G
G G G
G G G
User changes feild_arr to [[1,0,1], [0,2,0], [0,1,2]]
Output:
R G R
G B G
G R B
Now I only want to call sceen.blit() 5 times, leaving the 4 Green sqaures green, because nothing changed.
I thought of making another array, which would be just a copy of the first. Then run through it and compare to the new array to see what changed, but I think there is a better and faster way to this. Now the example is only 3x3 so making a duplicate array isn't too bad, but I'm working with a lot bigger arrays, and when you're blitting a 30x20 array, I need all the shortcuts I can get.
How do I only blit when the interger values in an array have been changed, and skip (don't blit) the values that have not changed?

You can use screen.blit only once, calling with a list of the rectangles that changed.
I think the best aproach is to create you own class deriving from DirtySprite:
class Cell: pygame.sprite.DirtySprite
which already has attributes for holding an image and a rectangle and you can add an attributes to hold the number and a method to change de number that will set it as dirty.
Then you can use LayeredDirty class to render the dirty sprites on the screen.

Related

Computing the area filled by matplotlib.pyplot.fill(...)

I'd like to compute the area inside of a curve defined by two vectors a and b. For your reference the curve looks something like this (pyplot.plot(a,b)):
I saw matplotlib has a fill functionality that let you fill the area enclosed by the curve:
I'm wondering, there's any way to obtain the area filled using that same function? It would be very useful as the other way I'm thinking of computing that area is through numerical integration, much more cumbersome.
Thank you for your time.
If you really want to find the area that was filled by matplotlib.pyplot.fill(a, b), you can use its output as follows:
def computeArea(pos):
x, y = (zip(*pos))
return 0.5 * numpy.abs(numpy.dot(x, numpy.roll(y, 1)) - numpy.dot(y, numpy.roll(x, 1)))
# pyplot.fill(a, b) will return a list of matplotlib.patches.Polygon.
polygon = matplotlib.pyplot.fill(a, b)
# The area of the polygon can be computed as follows:
# (you could also sum the areas of all polygons in the list).
print(computeArea(polygon[0].xy))
This method is based on this answer,
and it is not the most efficient one.

Is there an option to find array inside array?

i need to build a function that can set in which part the big circle belong to (top , bottom, undermined),
the minimum size of the circle is 3x3.
black color = 1
white color = 0
for example:
https://serving.photos.photobox.com/17525810496b857f6fc6a1bd5b21ad9fba80f1e6c878dc45d05764a04f861e026fb52115.jpg "example images"
i thought to split my image to half
(image[0:len(image)/2] and image[len(image)/2:]) ( the numbers of row is even)
and find a way to looking for array inside array, ( a minimum of 3x3) to find solution to this problem, but i dunno how to realize it.

Searching through a multi-branch graph and returning a path [C#]

In my situation I have territory objects. Each territory knows what other territories they are connected to through an array. Here is an visualization of said territories as they would appear on a map:
If you were to map out the connections on a graph, they would look like this:
So say I have a unit stationed in territory [b] and I want to move it to territory [e], I'm looking for a method of searching through this graph and returning a final array that represents the path my unit in territory [b] must take. In this scenario, I would be looking for it to return
[b, e].
If I wanted to go from territory [a] to territory [f] then it would return:
[a, b, e, f].
I would love examples, but even just posts pointing me in the right direction are appreciated. Thanks in advance! :)
Have you heard of Breadth-First Search (BFS) before?
Basically, you simply put your initial territory, "a" in your example, into an otherwise empty queue Q
The second data structure you need is an array of booleans with as many elements as you have territories, in this case 9. It helps with remembering which territories we have already checked. We call it V (for "visited"). It needs to be initialized as follows: All elements equal false except the one corresponding to the initial square. That is for all territories t, we have V[t] = false, but V[a] = true because "a" is already in the queue.
The third and final data structure you need is an array to store the parent nodes (i.e. which node we are coming from). It also has as many elements as you have territories. We call it P (for "parent") and every element points to itself initially, that is for all t in P, set P[t] = t.
Then, it is quite simple:
while Q is not empty:
t = front element in the queue (remove it also from Q)
if t = f we can break from while loop //because we have found the goal
for all neighbors s of t for which V[s] = false:
add s into the back of Q //we have never explored the territory s yet as V[s] = false
set V[s] = true //we do not have to visit s again in the future
//we found s because there is a connection from t to s
//therefore, we need to remember that in s we are coming from the node t
//to do this we simply set the parent of s to t:
P[s] = t
How do you read the solution now?
Simply check the parent of f, then the parent of that and then the parent of that and so on until you find the beginning. You will know what the beginning is once you have found an element which has itself as the parent (remember that we let them point to itself initially) or you can also just compare it to a.
Basically, you just need a empty list L, add f into it and then
while f != a:
f = P[f]
add f into L
Note that this obviously fails if there exists no path because f will never equal a.
Therefore, this:
while f != P[f]:
f = P[f]
add f into L
is a bit nicer. It exploits the fact that initially all territories point to themselves in P.
If you try this on paper with you example above, then you will end up with
L = [f, e, b, a]
If you simply reverse this list, then you have what you wanted.
I don't know C#, so I didn't bother to use C# syntax. I assume that you know it is easiest to index your territories with integers and then use an array to access them.
You will realize quite quickly why this works. It's called breadth-first search because you consider only neighbors of the territory "a" first, with trivially shortest path to them (only 1 edge) and only once you processed all these, then territories that are further away will appear in the queue (only 2 edges from the start now) and so on. This is why we use a queue for this task and not something like a stack.
Also, this is linear in the number of territories and edges because you only need to look at every territory and edge (at most) once (though edges from both directions).
The algorithm I have given to you is basically the same as https://en.wikipedia.org/wiki/Breadth-first_search with only the P data structure added to keep track where you are coming from to be able to figure out the path taken.

How to pull tuples out of a list and make a turtle connect it as coordinates?

Write a function called connectTheDots that takes in a list of tuples as its input and an optional color input as well. The default color value should be black. Each tuple is a coordinate pair (x, y) for a turtle. The function will have the turtle trace out a picture by starting at the first coordinate and then moving to each coordinate in turn.
Your function should do the following:
a. Create a turtle, setting the turtle’s color and speed appropriately
b. Check if the input list is empty: if it is empty then nothing else should happen!
c. Without leaving a line behind, move the turtle to the first location given in the list. Then start leaving a line again. Note: recall how to pull values out of a list, and also know that the goto method can take a single (x, y) tuple as its input: myTurtle.goto( (25, 25) ) will move myTurtle to x = 25 and y = 25.
d. After the turtle is at the starting coordinate, move it to each coordinate in the list in turn.
This is what I have been able to do so far:
def connectTheDots(list1, color ="black"):
myTurtle = turtle.Turtle()
myTurtle.speed(1)
myTurtle.goto(list1[0])
for x,y in list1[1:]: #I'm unsure if this is correct
myTurtle.goto(x,y)
You have most of what you need but are probably making it more complicated than needed and are missing some small details.
For step "a" you need to explicitly set the color (you passed it in just fine). You are probably better off using a symbolic speed instead of a numeric one.
For step "b", if you have a proper for ... in loop, you don't need to explicitly check if the list is empty as the loop won't run if it is. Your splitting off the first item myTurtle.goto(list1[0]) works against you here as there may not be one, causing an IndexError.
For step "c" you need to add another command. Turtles start life in the center of the screen with their pens down. You need to raise the pen up after creating your turtle. But you don't need to explicitly move to the starting position, let your loop handle that.
The trick we'll use for step "c" and step "d" is to put the pen down after the goto() in the loop. The first time, this actually puts the pen down, after that, it's a harmless no-op:
import turtle
def connectTheDots(coordinates, color="black"):
myTurtle = turtle.Turtle()
myTurtle.speed("slowest")
myTurtle.color(color)
myTurtle.penup()
for coordinate in coordinates:
myTurtle.goto(coordinate)
myTurtle.pendown() # redundant after first iteration
dots = ((34, 56), (100, 240), (230, 105), (34, 56))
connectTheDots(dots, "green")
turtle.done()
If it bothers you that we're putting the pen down unnecessarily in the loop, then we can replace myTurtle.pendown() with:
if not myTurtle.isdown():
myTurtle.pendown()

Finding the bounds of an area covered by n of m rectangles

I have a set of m non-rotated, integer (pixel) aligned rectangles, each of which may or may not overlap. The rectangles cover thousands of pixels. I need to find the minimum sized bounding box that covers all areas that are covered by n of the m rectangles.
A (dirty) way of doing this is to paint a canvas that covers the area of all the targets. This is O(mk) where m is the number of rectangles and k is the number of pixels per rectangle. However since k is much greater than m I think there is a better solution out there.
This feels like a dynamic programming problem...but I am having trouble figuring out the recursion.
Solution which is better but still not great:
Sort the start and end points of all the rectangles in the X direction O(mlogm), iterate and find the x positions that may have over n rectangles, O(m) loop. For each x position that may have over n rectangles, take the rectangles at that position and sort the starts and stops at that position (O(mlogm)). Find the region of overlap, keep track of the bounds that way. Overall, O(m^2logm).
Hello MadScienceDreams,
Just to clarify, the bounding box is also non-rotated, correct?
If this is the case, then just keep track of the four variables: minX, maxX, minY, maxY–representing left-most, right-most, top-most, and bottom-most pixels–that define the bounding box, loop through each of the rectangles updating the four variables, and defining the new bounding box given those four variables.
EDIT
It looks like you are asking about finding the bounds of some subset of rectangles, not the whole set.
So you have M rectangles, and you choose N rectangles from them, and find the bounds within that.
Even in this situation, looping through the N rectangles and keeping track of their bound would be at most O(m), which isn't bad at all.
I feel that I must be misunderstanding your question since this response isn't what you are probably looking for; is your question actually trying to ask how to precompute the bounds so that given any subset, know the total bounds in constant time?
Is this defines your question? For bounding box => #rect_label >= n
How about we starts with one box and find the next box that has nearest furthest corner from it. Now we have a region with two box. Recursively find the next region, until we have n boxes.
While we need to start on every box, we only need to actively work on the currently smallest regions. The effect is we start from the smallest cluster of boxes and expand out from there.
If n is closer to m than 0, we can reverse the search tree so that we start from the omni-all-enclosing box, chopping off each bordering box to create the next search level. Assuming we only actively work on the smallest remaining region, effect is we chop off the emptiest region first.
Is it too complicated? Sorry I can't remember the name of this search. I'm not good at maths, so I'll skip the O notation. >_<
I propose the following algorithm :
prepareData();
if (findBorder('left')) {
foreach (direction in ['top', 'right', 'bottom']) {
findBorder(direction)
}
} else noIntersectionExists
prepareData (O(mlogm)):
Order vertical bounds and horizontal bounds
Save the result as:
- two arrays that point to the rectangle (arrX and arrY)
- save the index as a property of the rectangle (rectangle.leftIndex, rectangle.topIndex, etc.
findBorder(left): // the other direction are similar
best case O(n), worst case O(2m-n)
arrIntersections = new Array;
//an intersection has a depth (number of rectangles intersected), a top and bottom border and list of rectangles
for(i=0; i < 2*m-n-1; i++){ // or (i = 2*m-1; i > n; i--)
if(isLeftBorder(arrX[i])){
addToIntersections(arrX[i].rectangle, direction);
if(max(intersections.depth) = n) break;
} else {
removeFromIntersections(arrX[i].rectangle, direction);
}
}
addToIntersections(rectangle, direction): // explanations for direction=left
Best case: O(n), worst case: O(m)
hasIntersected = false;
foreach(intersection in intersection){
if(intersect(intersection, rectangle)){
hasIntersected = true
intersections[] = {
depth: intersection.depth,
bottom: min(intersection.bottom, rectangle.bottom),
top: max(...)}
intersection.depth++
intersection.bottom = max(intersection.bottom, rectangle.bottom)
intersection.top = max(...)
}
}
if(!hasIntersected)
intersections[]={depth:1, bottom:rectangle.bottom, top:rectangle.top}
This gives an overall order between O(n^2) and O(m*(m-n/2))
I hope my pseudo code is clear enough

Resources