It’s Over

September 14, 2010

Yes, it’s over. Hopefully only GSOC, not the actual pygamedraw project.
I know, it has been a while since the last blog post here, and also since the last commit on bitbucket, but there are things behind the monitor, and so my free-time became very limited at the beginning of September.
However, I think I created a stable code base that can now be used to implement more and more features easily. I mean, hey, its open source, why don’t you get a copy of the repo and add one feature by yourself? Push it back and I (/we) will add it if its not completely rubbish. Some more developers/contributors would help this project (and pygame2 in general) and could speed up the development a lot.

Ok, here a quick overview about my last changes at the end of the “official” part: I mostly fixed a lot of bugs and incomplete or not working code. Namely the ellipse drawing method, the line drawing method and line-ending attribute handling and some small bugs in examples, pens etc.
Then I added another example to test and show the new features of the line drawing algorithm interactively and also started with some anti-aliasing test implementations.

Next steps would be:

  • implement final antialiasing
  • test and complete ellipse drawing method for all kinds of parameter combinations/sub-methods
  • fix/implement issues at bitbucket/tickets
  • implement more complex stuff like curves(bezir, splines/b-splines/nurbs?)
  • port the code (or slow parts of it) to C
  • …(your idea here)

Maybe you could do one of these points?


Attribute handling

June 27, 2010

One new aspect I’ve already mentioned in another post is that common drawing options like width, aa, rounded corners or color (for some pens) are stored as attributes of pen objects to keep parameter lists of shape methods short. But now, you need a few lines each time you want to draw a new shape with other options:

pen = SolidPen(color=pygame2.Color(20, 210, 50))
pen.width = 5
pen.rect(screen, any_rect)
pen.color = pygame2.Color(120, 250, 250)
pen.width = 3
pen.rect(screen, any_other_rect)

Ok, this can be really annoying. Therefore I added a way to use these options (which are still object attributes) also as keyword parameters:

pen = SolidPen(color=pygame2.Color(20, 210, 50))
pen.width = 5
print pen.width # output: 5
pen.rect.screen, any_rect) # draws rect with width=5
pen.rect(screen, any_other_rect, width=3) # draws rect with width=3
print pen.width # output: 5
# set pen.width = 1 (the actual attribute) and then draw the rect
pen.rect(screen, a_third_rect, width=1, apply=True)
print pen.width # output: 1

Thus, you can use keyword parameters to change options, but you don’t have to.  To draw some shapes all in one color you set it once and then don’t need to repeat yourself over and over again.


Yay, it works! Drawing broad lines the pygamedraw way

June 23, 2010

The the basic shape algorithms are mostly implemented and I get more and more to the parts of implementing new features and improving stuff. Today I worked one the Pen.line() method or more specifically the drawing of broad poly-lines through more than two points.

First, lets have a look how the current implementation does it:

drawing a long line with pygame.draw.lines and width = 20Well, that’s just a multiple call of pygame.draw.line() which is also badly implemented as it simply adds half of the width on both sides to either the x or y values of the endpoints (and thus different angles result in different line widths). This is just ugly and nearly unusable.

So I had to fix that and do a bit more than calling Pen.line(surf, point1, point2). But what? There are quite a few ways how to draw the corners and so I added the next attribute to the Pen class, called line_style.

Currently there are 4 different line styles (and no more planned because I cannot think of any further (useful) style(s), but if you do, please tell me and I may think about it): DENTED_VERT, SHARP_VERT, FLAT_VERT and ROUND_VERT.

First of all, I did some studies and tests and thought about lines and how to draw and connect them to nice-looking polylines:

I started with a simple row of single line elements.

Then reduced it to pure data.

Some more tests and a first, ugly hacked version ensued. Then I rewrote it and did a cleaner implementation using an own Vert class to hold the data and do some calculations.

At the end, it looks like this:

Pen.line_style = DENTED_VERT

Pen.line_style = SHARP_VERT (yes, I know there is still a small pixel bug)

Pen.line_style = FLAT_VERT

Pen.line_style = ROUND_VERT

I also added a first style for line endings (more styles will come later):

Pen.line_style = ROUND_VERT Pen.line_start = ROUND_ENDING Pen.line_ending = ROUND_ENDING

Yay, that’s a lot better and more flexible than the current pygame/sdl implementation and thas is what this whole GSoC project is all about! 🙂


From Mask to Surface

June 2, 2010

The first simple shape methods have been implemented as well as some easy Pens. So far, writing an own/new Pen class is as easy as planned. Here are some images of a circle rendered with different Pens (this is directly taken from the allinone example included with the source, so feel free to view it “live”):

SolidPen - one solid color for all pixels

BlendPen - one rbga color blended in the background image

MyColorPen - an easy example for a custom Pen

TexturePen - shape filled with an image based texture

texture image used for the first example

TexturePen - just another texture (note: the texture can be exactly positioned with the texture offset)

texture image used for the second example


Step 1: Get the basics working

May 31, 2010

Currently I’m working on the very basic features that are also supported by the original pygame.draw module. When looking over these old functions (and its results), I discover more and more blemishes.

One example is pygame.draw.rect, the simplest drawing function of the whole module, you may say, but its a bit tricky, because you have to decide how a passed rect defines the pixels to draw. To be exact, I’m talking about drawing rects of a certain width. Draw around the actual rect or inside or outside? I wanted to see how the current draw module does it:

rect outline behavior

how pygame.drw.rect draws rects with certain widths

As you can see, it draws around the actual rect, ie. +width/2 and -width/2. So far, so good. But now have a look at the corner. A few pixels are missing there! It seems, it’s not a rect but just 4 lines between the vertices of the rect.

I’m going to implement this (position of the line, not the missing pixels) as default behavior, but may add alternatives like completely inside or completely outside:

rect outline position


This would also apply to other shape outlines like ellipses but I’m not sure if this would be really useful, though.


Masks as intermediate

May 8, 2010

One of the first things I knew about the structure of the new draw module was that I wanted to separate the definition of shapes and the actual drawing because shapes won’t change but the drawing methods and algorithms should be changeable. To easily implement this and also get a comfortable api that makes it easier to deal with (lots of?) optional parameters I decided to use an object-oriented approach and write a base class that defines the shapes and child classes that implement different algorithms by overwriting a certain method of the base class.

Now I needed some interface, a way to pass shapes to the draw method without drawing it.

First I thought I could call the draw method per pixel and directly set pixels on the destination surface like just passing the position of a pixel (that should be set) to the draw method, that then would calculate the color and set the pixel on the surface.

Then I started thinking about algorithms to define shapes and it became clear that it is a lot easier to operate on a “neutral” place where you just have two options per pixel:  to set or not to set, to draw or not to draw, to be or not to be. And this is exactly what masks are made for!

On a regular surface with any initial image data you don’t know if you have set a certain pixel or not because you don’t know the color it had before you started drawing. Of course it may be possible somehow and you could use a list of affected pixels and their initial color and then … but its easier and cleaner to use masks that are optimized and thus fast enough.

So the basic api layout will look something like this:

class Pen(object):
    base class that defines all shape methods
    - do not use directly! -
    def line(self, surf, ...):
        # ...

    # ... (more methods to draw all kinds of shapes)

    def draw_mask(self, surf, mask, offset):
        draw ``mask`` onto ``surf`` with the given ``offset``
        - to be overwritten by child classes -
        raise NotImplementedError

class PlainColorPen(object):
    fill shapes with a plain color
    def __init__(self, color):
        self.color = color

    def draw_mask(self, surf, mask, offset):
        # ...

class TexturedPen(object):
    create textured shapes
    def __init__(self, texture):
        # ...

    def draw_mask(self, surf, mask, offset):
        # ...

# ... (more XXXPen classes)

Getting Started

April 28, 2010

I’ve got a project blog and a project at bitbucket.org with mercurial repository, issue tracker and wiki.

I also got svn access to the pygame repository, but I’d like to have an own, separate repo as well to play around without being able to break something but my own code. Nonetheless I’ll commit to the pygame repo from time to time if it’s worthwhile. Another nice side-effect of the project at bitbucket is to have an issue tracker and a wiki this way.

Then, I tried to install pygame reloaded and after installing some dependencies and getting a few “gcc failed with exit code 1” I disabled SDL_MIXER and SDL_IMAGE and it worked.

Going to read docs, play with pygame2 and think about concepts now…

… and to learn for last written exam next week.