Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Subclassing Drawable  (Read 7052 times)

0 Members and 1 Guest are viewing this topic.

Cheery

  • Newbie
  • *
  • Posts: 5
    • View Profile
Subclassing Drawable
« on: January 08, 2011, 06:02:50 pm »
I wanted to draw 9-patches so I created a class for it by subclassing Drawable so it'd work like usual sprites.

Only later I noticed there's lots of methods for doing transformations with the drawable. How to get them affect my sprite patch?

Code: [Select]
# -*- coding: utf-8 -*-
from PySFML import sf

class Patch(sf.Drawable):
    def __init__(self, image):
        sf.Drawable.__init__(self)
        self.image = image
        width = image.GetWidth()
        height = image.GetHeight()
        for x in range(1, width):
            if image.GetPixel(x, 0).a > 0:
                right = x + 1
            if image.GetPixel(width - x, 0).a > 0:
                left = width - x
        for y in range(1, height):
            if image.GetPixel(0, y).a > 0:
                bottom = y + 1
            if image.GetPixel(0, height - y).a > 0:
                top = height - y
        row = 1, left, right, width
        col = 1, top, bottom, height
        self.sprites = [sf.Sprite(image) for _ in range(9)]
        self.borders = top-1, height-bottom, left-1, width-right
        for i in range(9):
            x, y = i % 3, i / 3
            rect = sf.IntRect(
                row[x],
                col[y],
                row[x+1],
                col[y+1]
            )
            self.sprites[i].SetSubRect(rect)
        self.position = 0, 0
        self.Resize(width, height)

    def Resize(self, width, height):
        self.width = width
        self.height = height
        top, bottom, left, right = self.borders
        row = [left, width - left - right, right]
        col = [top, height - top - bottom, bottom]
        for i in range(9):
            x, y = i % 3, i / 3
            self.sprites[i].Resize(row[x], col[y])
        self.SetPosition(*self.position)

    def SetPosition(self, x, y):
        self.position = x, y
        top, bottom, left, right = self.borders
        row = [x, x+left, x+self.width-right]
        col = [y, y+top, y+self.height-bottom]
        for i in range(9):
            x, y = i % 3, i / 3
            self.sprites[i].SetPosition(row[x], col[y])

    def Render(self, target):
        for sprite in self.sprites:
            target.Draw(sprite)

Cheery

  • Newbie
  • *
  • Posts: 5
    • View Profile
Nevermind
« Reply #1 on: January 08, 2011, 07:21:52 pm »
I just decided to drop sprites and applied little bit of opengl.

Code: [Select]
# -*- coding: utf-8 -*-
from PySFML import sf
from OpenGL.GL import (
    glBegin,
    glDisable,
    glEnd,
    glTexCoord2f,
    glTranslatef,
    glVertex2f,
    GL_TEXTURE_2D,
    GL_QUADS,
)

class Patch(sf.Drawable):
    def __init__(self, image):
        sf.Drawable.__init__(self)
        self.SetImage(image)
   
    def SetImage(self, image):
        self.image = image
        width = image.GetWidth()
        height = image.GetHeight()
        for x in range(1, width):
            if image.GetPixel(x, 0).a > 0:
                right = x + 1
            if image.GetPixel(width - x, 0).a > 0:
                left = width - x
        for y in range(1, height):
            if image.GetPixel(0, y).a > 0:
                bottom = y + 1
            if image.GetPixel(0, height - y).a > 0:
                top = height - y
        row = 1, left, right, width
        col = 1, top, bottom, height
        self.borders = top-1, height-bottom, left-1, width-right
        self.subrects = [
            sf.IntRect(
                row[i%3],
                col[i/3],
                row[i%3+1],
                col[i/3+1],
            )
            for i in range(9)
        ]
        self.width = width
        self.height = height

    def Resize(self, width, height):
        self.width = width
        self.height = height

    def Render(self, target):
        image = self.image
        width = self.width
        height = self.height
        top, bottom, left, right = self.borders
        row = [0, left, self.width-right, self.width]
        col = [0, top, self.height-bottom, self.height]

        if image and image.GetWidth() and image.GetHeight():
            image.Bind()
            for i, subrect in enumerate(self.subrects):
                x = i%3
                y = i/3
                rect = image.GetTexCoords(subrect)
                glBegin(GL_QUADS)
                glTexCoord2f(rect.Left,  rect.Top);    glVertex2f(row[x],   col[y])
                glTexCoord2f(rect.Left,  rect.Bottom); glVertex2f(row[x],   col[y+1])
                glTexCoord2f(rect.Right, rect.Bottom); glVertex2f(row[x+1], col[y+1])
                glTexCoord2f(rect.Right, rect.Top);    glVertex2f(row[x+1], col[y])
                glEnd()
        else:
            glBegin(GL_QUADS)
            glVertex2f(0,     0)
            glVertex2f(0,     height)
            glVertex2f(width, height)
            glVertex2f(width, 0)
            glEnd()

bastien

  • Full Member
  • ***
  • Posts: 231
    • View Profile
    • http://bastien-leonard.alwaysdata.net
Subclassing Drawable
« Reply #2 on: February 08, 2011, 08:33:00 am »
There's no need to inherit Drawable, actually I believe that Laurent didn't intend end-users to do it at all.
Check out pysfml-cython, an up to date Python 2/3 binding for SFML 2: https://github.com/bastienleonard/pysfml-cython

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Subclassing Drawable
« Reply #3 on: February 08, 2011, 11:52:29 am »
Quote from: "bastien"
There's no need to inherit Drawable, actually I believe that Laurent didn't intend end-users to do it at all.
Then he wouldn't write the following in the documentation: ;)
Quote
Deriving your own class from sf::Drawable is possible [...]. To create a derived drawable class, all you have to do is to override the virtual Render function.

One of the main benefits of creating your own drawable class is that you can build hierarchies of drawable objects. Indeed, when you draw a drawable inside the Render function of another drawable, the former inherits the transformations and color of the latter and combines them with its own attributes. This way, you can apply global transformations/color to a set of drawables as if it was a single entity.

However, the real problem is not to use Drawable as a base class for drawable objects, but to make everything drawable. A player, a projectile etc. don't have to inherit Drawable, if you separate graphics and logics.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

 

anything