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

Author Topic: Transformation issue  (Read 7266 times)

0 Members and 2 Guests are viewing this topic.

igor

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Transformation issue
« on: July 05, 2013, 01:33:58 pm »
I'm try to implement animation class via sfml.TransformableDrawable. In main script I wrote animation.position = (400, 400), but nothing happen with render position. I think that my implementation of draw method is wrong, but I don't know how make it right. Yes, documentation  explains how drawable and transformable linked with each other, but it is still  the dark forest for me.

Here my draw method implementation:

def draw (self, target, states):
        # argument by reference -> states will be modified !!!
        states.transform.combine(self.transformable.transform)
        target.draw(self._sprite)
 

P.S.: sorry I'm  accidentally added poll.
« Last Edit: July 05, 2013, 01:36:44 pm by igor »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Transformation issue
« Reply #1 on: July 05, 2013, 01:37:50 pm »
target.draw(self._sprite)

Should be

target.draw(self._sprite, states)
Laurent Gomila - SFML developer

igor

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: Transformation issue
« Reply #2 on: July 05, 2013, 03:54:58 pm »
Yes, but in the C++ documentation:

 
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const

states passed by value, but in Python all arguments passed by reference and states must be saved.
But if I make copy of states it's don't work (just black window, without render):
def draw (self, target, states):
        new_states = copy.copy(states)
        new_states.transform.combine(self.transformable.transform)
        target.draw(self._sprite, new_states)
 
By the way fixed version, also don't work, moreover after few frames program freeze and crash.:
def draw (self, target, states):
        states.transform.combine(self.transformable.transform)
        target.draw(self._sprite, states)
 
Here code of animation.py module:
import sfml as sf

class Animation(sf.TransformableDrawable):
        _timer = sf.Clock()
        def __init__ (self, sprite, duration):
                sf.TransformableDrawable.__init__(self)
                self._sprite = sprite
                self._frame = 1
                self._frames_count = sprite.texture.width // sprite.texture.height
                self._frame_size = sprite.texture.height
                self._sprite.texture_rectangle = sf.Rectangle((0, 0), (self._frame_size, self._frame_size))
                self._rate = duration // self._frames_count
                self.is_run = False
        def start (self):
                self._last_time = Animation._timer.elapsed_time.milliseconds
                self._frame = 1
                self.is_run = True
        def stop (self):
                self.is_run = False
        def update (self):
                if self.is_run:
                        # set number of renderable frame
                        current_time = Animation._timer.elapsed_time.milliseconds
                        elapsed_time = current_time - self._last_time
                        if elapsed_time >= self._rate:
                                offset = (elapsed_time // self._rate) % self._frames_count
                                self._frame = (self._frame + offset) % self._frames_count      
                                self._last_time = current_time
                        # set renderable frame on sprte
                        frame_pos = (self._frame_size*self._frame-1, 0)
                        frame_size = (self._frame_size, self._frame_size)
                        self._sprite.texture_rectangle = sf.Rectangle(frame_pos, frame_size)
        def draw (self, target, states):
                states.transform.combine(self.transformable.transform)
                target.draw(self._sprite, states)
 
Code of main script:
import sfml as sf
from animation import Animation

def main ():
        wnd = sf.RenderWindow(sf.VideoMode(800, 800), "Anim test")
        texture = sf.Texture.from_file("boxes.png")
        sprite = sf.Sprite(texture)
        animation = Animation(sprite, 1000)
        animation.position = (400, 400)
        animation.start()
        while wnd.is_open:
                for event in wnd.events:
                        if type(event) is sf.CloseEvent:
                                wnd.close()
                wnd.clear(sf.Color.BLACK)
                animation.update()
                wnd.draw(animation)
                wnd.display()

if __name__ == '__main__':
        main()
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Transformation issue
« Reply #3 on: July 05, 2013, 04:09:40 pm »
Now it's specific to Python and/or the SFML binding, I can't help more, sorry.
Laurent Gomila - SFML developer

Sonkun

  • Moderator
  • Full Member
  • *****
  • Posts: 241
    • View Profile
Re: Transformation issue
« Reply #4 on: July 05, 2013, 10:50:18 pm »
I forgot to implement the __copy__ method of sf.RenderStates. Try a manual copy and tell me if it works:

def copy_renderstates(renderstates):
        ret = sf.RenderStates()
        ret.blend_mode = renderstates.blend_mode
        ret.shader = renderstates.shader
        ret.texture = renderstates.texture
        ret.transform = renderstates.transform
        return ret

Thanks for reporting this bug :)
Interested in using SFML with Python ? Try out its Python binding!

igor

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: Transformation issue
« Reply #5 on: July 06, 2013, 05:56:30 am »
Fix: both Laurent fixed draw method and draw method with manual copying, no longer produce a crash, but animation still drawn at left top corner.

Update: crashes don't occur only when I run script under IDLE.

Manual copying version:
def draw (self, target, states):
        def copy_renderstates(renderstates):
                ret = sf.RenderStates()
                ret.blend_mode = renderstates.blend_mode
                ret.shader = renderstates.shader
                ret.texture = renderstates.texture
                ret.transform = renderstates.transform
                return ret
        new_states = copy_renderstates(states)
        new_states.transform.combine(self.transformable.transform)
        target.draw(self._sprite, states)
 

Laurent fixed version:
def draw (self, target, states):
    states.transform.combine(self.transformable.transform)
    target.draw(self._sprite, states)
 

Update: I remade Animation class in sf.Transformable in an internal attribute style, and it's work, but looks ugly... Thus it's a bug most probably in the sf.TransformableDrawable.
« Last Edit: July 08, 2013, 08:11:06 am by igor »

igor

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: Transformation issue
« Reply #6 on: July 08, 2013, 08:53:20 am »
Success! I was able to make Animation class which inherited from sfml.TransformableDrawable, and it work right! I use standart  draw method, but states.transform.combine(self.transformable.transform) replacing states.transform.combine(self.transform):
def draw (self, target, states):
        states.transform.combine(self.transform)
        target.draw(self._sprite, states)