to elaborate, I'm currently creating a maze layout using wall sprites. however, I want the maze to be invisible when I am actually playing the game, while still able to be able to have collision detection. Is this possible in any way? Thanks.
Are you using images to show your walls? Because if you are, you can use a program called paint.net to create a transparent sprite. Just create a file with the desired dimensions and use the eraser tool to make the whole thing transparent (click on the little squiggly arrow up at the top to make it easier). Save it as a png in your pygame folder and you have a transparent square.
Related
I am making a randomized spinner in pygame, but the only method I've found is to constantly redraw the whole screen. Is there a way that doesn't use this, it becomes extremely laggy.
You can not. why do you want that? It is common to redraw the entire scene in each frame. Of course you can try to redraw just a rectangular section of the background. However, this is usually not worth the effort.
The pygame way to do this is to pass a list of rectangular areas to pygame.display.update(). If rectangles are passed to pygame.display.update() then not the entire display will be redrawn, just the specified areas::
Update portions of the screen for software displays
[...]
You can pass the function a single rectangle, or a sequence of rectangles. It is more efficient to pass many rectangles at once than to call update multiple times with single or a partial list of rectangles.
e.g.:
while run:
# [...]
screen.blit(background, (0, 0))
screen.blit(image1, bounding_rect1)
screen.blit(image2, bounding_rect2)
pygame.display.update([bounding_rect1, bounding_rect2])
That is how computer animation works, you're redrawing the screen on every frame. Every game practically works the same way. I am not sure what graphics pipeline pygame uses but in OpenGL you usually initialize all your geometry outside of the render loop and then use pointers to batch-process everything in the render-loop so you're not duplicating a lot of boilerplate code or making duplicate objects every frame.
A related question has been answered here:
https://gamedev.stackexchange.com/questions/125546/what-is-the-best-way-to-handle-the-actual-render-loop
I would like to draw directly to the screen from Python 3. For example, I would like to create a rectangle around a few icons on my desktop.
EXAMPLE
Or draw a line on the screen etc.
What are the libraries I should look up in order to do this? I prefer the performance wise solutions.
I'm preparing exercises for school classes involving Python's turtle library.
The students are already drawing terrific pictures, but I want them to be able to detect existing pictures and colours in order to modify the behaviour of their program.
For example I would like to provide them with code which draws a maze using turtle, and then they can write the code to navigate the turtle around the maze (don't worry, I'll start simpler).
Is there a way to detect the colour of the pixels already drawn by the turtle?
Thanks!
Turtle uses Tkinter canvas, which you can get using turtle.getcanvas(), and according to this you cannot read the colour of a pixel without using a workaround of converting the canvas to a picture (bitmap) and read the bitmap.
You could try to keep an open array to work as the bitmap of your canvas and update it yourself as you draw new elements on the canvas, although that seems impractical unless the maze is simple and 'squary'.
I would use an array keep all x and y that is used for the maze in an array like stated above. Then have a size of a box around the turtle defined for detecting purposes.
I have two objects troll and pig. I'm detecting collisions between these two characters with Pygame's colliderect function. collisions for this works perfectly, however I am unable to remove the object from the screen when a collision occurs. When a troll collideswith a pig, I want the pig to disappear from the screen. I set an image for both of these and bit them, is there a way to un-blit? Ive tried pygame.image.set_alpha(255) (which set full transparency of an image) function to no avail.
Any suggestions?
Can't you just stop drawing the pig? Each frame you fill the screen with the background, so it won't be visible.
I am working on a game that has destructible terrain (like in the game Worms, or Scorched Earth) and uses pixel perfect collision detection via masks.
The level is a single surface and how it works now is that I create a copy every frame, draw all sprites that need drawing on it, then blit the visible area to the display surface.
Is there any way to avoid copying the whole level surface every frame and still be able to use the pixel perfect collision tools found in pygame?
I tried blitting the level surface first, then blitting every sprite on the screen (with their blit coordinates adjusted by the camera, except for the player character whose coordinates are static), but in that case the collision detection system falls apart and I can't seem to be able to fix it.
UPDATE
I have managed to make it work the following way:
When drawing the sprites, I convert their game world coordinates (which are basically coordinates relative to the origin of the level bitmap) to screen coordinates (coordinates relative to the camera, which is the currently visible area of the level).
During the collision detection phase I use the coordinates and bounding boxes that are positioned relative to the level surface; so just like above. The thing is that the camera's position is bound to the player's position which is not and should not have been a static value (I am really not sure how I managed to not realize that for so long).
While this fixes my problem, the answer below is a much more comprehensive look on how to improve performance in a situation like this.
I am also open to suggestions to use other libraries that would make the ordeal easier, or faster. I have thought about pyglet and rabbyt, but it looks like the same problem exists there.
This is an issue that used to come up a lot in the days before graphics accelerators, when computers were slow. You basically want to minimize the work required to refresh the screen. You are on the right track, but I recommend the following:
Keep a copy of the background available offscreen, as you are doing
now.
Allocate a working bitmap that is the same size as the screen.
For each sprite, compute the bounding rectangle (bounding box) for
its new and old positions.
If the new and old bounding boxes overlap, combine them into one
larger box. If they do not overlap, treat them separately.
Group all the bounding boxes into sets that overlap. They might all
end up in one set (when the sprites are close to each other), or
each bounding box might be in a set by itself (when the sprites are
far apart).
Copy the background to regions of the working bitmap corresponding
to each bounding box set.
Copy the sprites for each set to the working bitmap in their new
positions (in the correct z-order, of course!).
Finally, copy the finished offscreen bitmap to the display surface,
set bounding box by set bounding box.
This approach minimizes the amount of copying that you have to do, both of background and sprite. If the sprites are small relative to the display area, the savings should be significant. The worst case is where the sprites are all arranged on a diagonal line, just barely overlapping each other. In this case, you might want to switch to a more generalized bounding shape than a box. Take a look at QuickDraw Regions for an example: Wikipedia Discussion Patent Source.
Now, you may be thinking that the work to group the bounding boxes into sets is a O(n^2) operation, and you would be right. But it grows only with the square of the number of sprites. 16 sprites implies 256 comparisons. That's probably less work than a single sprite blit.
I focused on minimizing the pixel copying work. I must admin I am not familiar with the particulars of your collision detection library, but I get the idea. Hopefully that is compatible with the algorithm I have proposed.
Good luck. If you finish the game and post it online, put a link to it in your question or a comment.