I am currently designing basic pygame projects. Random projects actually, which are just random ideas pop into my head during common daytime. One of them is a wall clock. Where I use sin, cos functions to draw hour hand, minute hand etc..
As a result of these functions, I obtain float values. Which pygame does not allow. So I round and int() all values before using them in drawing functions. This makes sense because of pixels can't be partially filled. However, I think this results in bad drawings.
The Image above is the clock drawn by the pygame module. As you see the handles are somewhat leaning. Not straight.
I also implemented this in codeskulptor. Which is a python2 environment for basic game(or any graphical) programming. Has nice and clear functions, very easy to use indeed. The float values I use in that no needs conversion and accepted directly. I do not know how it handles it, but it is clearly better. Obviously not just rounding and integering(does this word exist ?) values. Let me show you the clock drawn in codeskuptor:
As you can see, the edges are more smooth. The lines does not end sloped, but straight. It is clearly a better drawing than the pygame one.
But the thing is, codeskuptor does not implement many modules and built-in functions that is harder than beginning level knowledge. Also it doesn't support a well-known compiler(basically not a python module). So can't work on computer and can not be compiled with py2exe, pyinstaller as such.
So I wan't to implement all this in pygame, and get smooth results just like in codeskulptor. Maybe a better way to handle float points for drawing. Any idea or knowledge in this area would be greatly appreciated.
My code for codeskuptor(Does not show realtime)
My code for pygame
The codes does not supply proper commenting because they were just a late-night fun nothing more. I'll explain any necessary parts.
To summarize the comments above, the issue you've noticed here is antialiasing. For the lines, pygame provides the aaline function, which can be used to draw a single line. Unfortunately, this does not support a varying thickness. Potential workarounds could be drawing a line of the correct thickness and drawing an aaline on either side of it, or drawing the line using an aapolygon (from the gfxdraw module).
The standard draw module does not include antialiased circles, but you can use another function from gfxdraw to draw an antialiased circle, aacircle.
It is important to note that the gfxdraw module is labeled "experimental", so the functions are not guaranteed to persist across versions of pygame. But for your quick projects that might not be a concern.
As for CodeSkulptor, they are rendering the lines on an HTML5 <canvas> element, which according to this question has anti-aliasing turned on by default.
Related
How could I make something simple like for example crosshair for FPS game (not actually going to do that, just took this as an example). Or how can I set color for some pixels on screen, or something similar. What would be the best way to approach this problem?
You can use OpenCV, that is one of the most useful Computer Vision libraries for Python. You can do whatever you want with images, screencaptures, videos, etc.
But I believe that some prior experience with NumPy library is needed, since OpenCV is heavily dependent on it.
I am making a tile based game, and the map needs to be rendered every frame. Right now, each tile is 32X32, and the visible map is 28X28 tiles. The performance is dreadful. I recently made it only render the visible tiles, but this still did not improve the FPS much. Right now I'm looking for a way to speed up the rendering. I attribute the slowness to the way I am rendering ; every tile is individually blitted to the screen. What would be a more effective was of doing this?
In pygame (afaik), updating the screen is always one hell of a bottle neck. Since I could not see your code, I don't know, how you are updating the screen. Only blitting the the sprites that changed is a start, but you need to only update those parts that changed, on the screen.
Basically it is the difference between using display.flip() or using update_rects() with only the changed rects. I know, that does not help at all, when you are scrolling the map.
Take a look at this question: Why is this small (155 lines-long) Pacman game on Python running so slow?, it has a similiar topic.
One thing I tried when I had a map compiled of tiles and some sprites on it, I tried always having a precompiled image of the map for an area containing the currently displayed part and some 200 or so pixels around that, so that I could blit the prepared "ground" (still only in updated parts) without the need of blitting all those tiles contained in it. That, of course, is quite some thinking you have to put into that, espacially if you have multiple layers and parts of the map that can be above your active sprites. It is interesting to think and work that through, but I cannot tell you, how much you will gain by that.
One totally different possible solution: I began with pygame once (since I did SDL in C++ prior to that). Recently I was directed to another python gaming library: pyglet. This does not suffer from the problems of updating the whole screen as much as pygame (I think it's because of usage of OpenGL acceleration; it still works on my not at all accelerated eee-Netbook). If you are not bound to pygame in any way, it might be interesting to take a look at pyglet.
My question is simple: What is the difference between using pygame.draw and pygame.gfxdraw? I've looked on the pygame documentation, but no one has told what the difference between them is.
The draw function is a bit more stable, and also a bit faster that gfxdraw, although gfxdraw has more options, not only along the lines of antialiasing, but also drawing shapes. pygame.draw has only nine functions, whereas pygame.gfxdraw has 22 options, which include all 9 of the options supplied by draw. I recommend using gfxdraw even though its is "experimental" because it has more capabilities.
gfxdraw allows anti-aliasing for all shapes, where drawonly adds antialiasing to lines. I use gfxdraw by default. It has been marked 'experimental' for a long time now, but I've not had any issues.
Disclaimer: I Don't use pygame!
According to the gfxdraw doc page, it "Wraps SDL_gfx primatives", and so offers it as an API for those already familiar with it. It also appears to offers a little bit more than the more primitive normal draw. There also appears to be a few semantic differences here and there, so you'll need to compare each to its closest counterpart, and not assume anything.
As a final note, gfxdraw is experimental, and you should always take that into consideration before using it.
I hope this helps! :)
This question is related to this other one.
In my program (which uses pygame to draw objects on the video) I have two representation of my world:
A physical one that I use to make all the calculations involved in the simulation and in which objects are located on a 1000x1000 metres surface.
A visual one which I use to draw on the screen, in which my objects are located in a window measuring 100x100 pixels.
What I want to achieve is to be able to pass to my pygame drawing functions (which normally accept inputs in pixels) my physical/real-word coordinates. In other words, I would like to be able to say:
Draw a 20m radius circle at coordinates (200m, 500m)
using the precise pygame syntax:
pygame.draw.circle(surface, (255,255,255), (200,500), 20)
and get my circle of 2px radius at centred on pixels (20,50).
Please note that this question is about a native pygame way to do this, not some sort of workaround to achieve that result (if you want to answer that, you should take a look to the question I already mentioned) instead.
Thanks in advance for your time and support.
There is no native pygame way to do this.
You may be misunderstanding the function of pygame. It is not for drawing vector objects. It is for writing pixels into video surfaces.
Since you have vector objects, you must define how they will be converted into pixels. Doing this is not a workaround - it's how you are intended to use pygame.
Since it seems that PyGame developers do not hang around here too much, I brought the question to the Pygame mailing list where it originated a monster thread and the issue has been debated at large.
The summary would be:
At present there is not such a feature.
There is interest to implement it, or at least to try to implement it...
...although is not a priority of the core devs in any way
There is more than one way to skin a cat:
should be the scaling happen both ways (inputting coordinates and reading them)?
how to deal with lines that have no thickness but that should be visible?
how to deal with visibility of objects at the edge of the image? which of their points should be taken as reference to know if a pixel should be lit or not for them?
and more (see linked thread).
Background
I have been asked by a client to create a picture of the world which has animated arrows/rays that come from one part of the world to another.
The rays will be randomized, will represent a transaction, will fade out after they happen and will increase in frequency as time goes on. The rays will start in one country's boundary and end in another's. As each animated transaction happens a continuously updating sum of the amounts of all the transactions will be shown at the bottom of the image. The amounts of the individual transactions will be randomized. There will also be a year showing on the image that will increment every n seconds.
The randomization, summation and incrementing are not a problem for me, but I am at a loss as to how to approach the animation of the arrows/rays.
My question is what is the best way to do this? What frameworks/libraries are best suited for this job?
I am most fluent in python so python suggestions are most easy for me, but I am open to any elegant way to do this.
The client will present this as a slide in a presentation in a windows machine.
The client will present this as a slide in a presentation in a windows machine
I think this is the key to your answer. Before going to a 3d implementation and writing all the code in the world to create this feature, you need to look at the presentation software. Chances are, your options will boil down to two things:
Animated Gif
Custom Presentation Scripts
Obviously, an animated gif is not ideal due to the fact that it repeats when it is done rendering, and to make it last a long time would make a large gif.
Custom Presentation Scripts would probably be the other way to allow him to bring it up in a presentation without running any side-programs, or doing anything strange. I'm not sure which presentation application is the target, but this could be valuable information.
He sounds like he's more non-technical and requesting something he doesn't realize will be difficult. I think you should come up with some options, explain the difficulty in implementing them, and suggest another solution that falls into the 'bang for your buck' range.
If you are adventurous use OpenGL :)
You can draw bezier curves in 3d space on top of a textured plane (earth map), you can specify a thickness for them and you can draw a point (small cone) at the end. It's easy and it looks nice, problem is learning the basics of OpenGL if you haven't used it before but that would be fun and probably useful if your in to programing graphics.
You can use OpenGL from python either with pyopengl or pyglet.
If you make the animation this way you can capture it to an avi file (using camtasia or something similar) that can be put onto a presentation slide.
It depends largely on the effort you want to expend on this, but the basic outline of an easy way. Would be to load an image of an arrow, and use a drawing library to color and rotate it in the direction you want to point(or draw it using shapes/curves).
Finally to actually animate it interpolate between the coordinates based on time.
If its just for a presentation though, I would use Macromedia Flash, or a similar animation program.(would do the same as above but you don't need to program anything)