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

Author Topic: Respecting naming conventions & other possible changes  (Read 15687 times)

0 Members and 1 Guest are viewing this topic.

piiichan

  • Newbie
  • *
  • Posts: 6
    • View Profile
Respecting naming conventions & other possible changes
« Reply #15 on: September 16, 2010, 05:45:20 am »
May I add my personal feelings about PySFML, after having used it for about 20 minutes.

So this is the point of view of a complete beginner with PySFML, but with good knowledge (not expert) in Python, and with a PyGame background.

Note: this is from a user point of view, I realize any of these may be hard / impossible to implement, or would need an update of the underlying C++ layer.

Also my goal is not to offend anyone, I find SFML and PySFML very easy to use, and efficient at the same time.
It's just, I feel that with a bit more love and polish on the Python side, PySFML could be even easier and Python friendly.

Use python naming convention.
For example use capitals for class names only,
we shouldn't write
Code: [Select]

sprite.SetPosition(10,10)

but
Code: [Select]

sprite.setPosition(10,10)
# or
sprite.setposition(10,10)
# or
sprite.set_position(10,10)



Don't use method calls for setting / getting simple attributes, use direct access.
For example, we shouldn't write
Code: [Select]

positionVariable = sprite.GetPosition(10,10)
sprite.SetPosition(10,10)

but
Code: [Select]

# get position
positionVariable = sprite.position
# set position
sprite.position = (10,10)
sprite.position.x = 20


Use tuples instead of classes that are used as simple data holders  without methods, like the Color class.
For example, we shouldn't write
Code: [Select]

window.Clear(sf.Color(100,100,100,255))

but
Code: [Select]

window.Clear((100,100,100,255))


Simpler module import.
As already pointed above, we shouldn't write
Code: [Select]

from PySFML import sf

but
Code: [Select]

import sf


Don't force us to create empty objects, just as placeholders; instead return them directly, ready to use.
For example, we shouldn't write
Code: [Select]

event = sf.Event()
while window.GetEvent(event):

but
Code: [Select]

for event in window.GetEvent():


As already pointed above, we shouldn't write
Code: [Select]

image = sf.Image()
image.LoadFromFile("imageFile.png")

but
Code: [Select]

image = sf.Image("imageFile.png")


Allow negative sprite scaling instead of the flip method
For example, we shouldn't write
Code: [Select]

sprite.FlipX(True)

but
Code: [Select]

sprite.SetScale(-1,1)
# ideally
sprite.scale.x = -1
# or
sprite.scale = (-1,1)


I will add more when I'll be more familiar with the rest of the API.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Respecting naming conventions & other possible changes
« Reply #16 on: September 16, 2010, 08:07:41 am »
I think most of these topics have already been discussed, and I agree with everything (I'm not a regular user of Python, though).

The negative sprite scale is a different thing, it is not specific to the Python binding and it was already discussed as well.
Laurent Gomila - SFML developer

piiichan

  • Newbie
  • *
  • Posts: 6
    • View Profile
Respecting naming conventions & other possible changes
« Reply #17 on: September 17, 2010, 12:44:55 am »
Thanks Laurent for your quick answer, I'm glad you've already taken those into consideration.

One more point that could be improved.

Allow centering of a Drawable (Sprite and String) around its position with a single instruction
We shouldn't write
Code: [Select]

spriteSize = sprite.GetSize()
sprite.SetCenter(spriteSize[0]/2, spriteSize[1]/2)

but something like
Code: [Select]

sprite.centerAtMiddle()

or even better, we could have acces to the middle of the Drawable at all time, automatically updated when resized.
Code: [Select]

# let's say our sprite is 30x20 pixels

# output (0,0), default center at top left corner
print sprite.center

# output (15,10)
print sprite.middle

# center sprite around its middle
sprite.center = sprite.middle

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Respecting naming conventions & other possible changes
« Reply #18 on: September 17, 2010, 08:03:38 am »
I think it's becoming too specific. It's already doable easily without an additional attribute, so why should I add it?

But maybe I'll add something close to this in SFML 2, like the bounding boxes of drawables.
Laurent Gomila - SFML developer

piiichan

  • Newbie
  • *
  • Posts: 6
    • View Profile
Respecting naming conventions & other possible changes
« Reply #19 on: September 17, 2010, 09:02:31 am »
Yes, I agree, it's very specific :)
Please just see these remarks as my personal opinion, and as a brainstorming for future API changes.

If you feel like "Gee, this guy must be lazy, it's just one more line of code",
then my answer is: I've been spoiled by the Python way of coding :D

Saves efforts for the API user
In the Python modules, classes are often designed so that there is a shortcut for the most common use cases. (Of course there must be a balance, otherwise the API will be cluttered.)

As an example, the unittest module in Python has shortcuts for many assertions that could be done with a regular assertTrue, like assertGreater, assertIn, assertIsNone etc...

In the end, all those small bits add up, and the programmer really feels at home, not having to write the same bits everywhere.

Readability
It also helps code readability, which as we all know as programmers, is very important.

For example, if we compare these two lines that do the same thing:
Code: [Select]

sprite.SetCenter(spriteSize[0]/2, spriteSize[1]/2)
sprite.centerAtMiddle()

notice the huge saving in readability on the second line(!)
and this is out of context, therefore still easy to read, but when deep inside hundreds of lines of code, the difference becomes really noticeable, it feels almost like you're reading pseudo-code.

Again, this is just my humble opinion.
I'm already very pleased with the current state of SFML :)

I'll use it for my next game.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Respecting naming conventions & other possible changes
« Reply #20 on: September 17, 2010, 09:25:10 am »
I understand your point of view and I agree with it.

However SFML is a low-level library, not a ready-to-use engine. Therefore it must provide basic building blocks, not functions-that-do-what-you-want-in-one-call.

And SFML doesn't focus on a particular thing, it's very generic and it can potentially be used for a wide range of applications. So if I started to provide such functions, the API would quickly become bloated.

That's the reason why I'm not happy with the current state of the graphics module: its API is not low-level enough, it provides ready-to-use drawables instead of generic building-blocks that can be used to draw anything. I'm currently trying to find a better API for SFML 2 :)
Laurent Gomila - SFML developer

piiichan

  • Newbie
  • *
  • Posts: 6
    • View Profile
Respecting naming conventions & other possible changes
« Reply #21 on: September 17, 2010, 09:56:42 am »
Got it.

But if you go even lower, why would people keep using the graphics module of SFML instead of OpenGL or DirectX directly?

Beliar

  • Newbie
  • *
  • Posts: 27
    • View Profile
Respecting naming conventions & other possible changes
« Reply #22 on: September 17, 2010, 10:06:21 am »
Quote from: "Laurent"

[...]
That's the reason why I'm not happy with the current state of the graphics module: its API is not low-level enough, it provides ready-to-use drawables instead of generic building-blocks that can be used to draw anything. I'm currently trying to find a better API for SFML 2 :)


I hope that doesn't mean that all the drawables (sprite, shape, ...) will be removed as those are things i like about SFML.
Debuggers don't remove bugs. They only show them in slow motion.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Respecting naming conventions & other possible changes
« Reply #23 on: September 17, 2010, 10:07:13 am »
Quote
But if you go even lower, why would people keep using the graphics module of SFML instead of OpenGL or DirectX directly?

Because it would still be much higher and easy to use ;)

Here I'm only talking about drawables, all other classes will remain the same.

I don't know yet how I'll modify these classes, but I'd like to keep things as simple as before *but* with extra flexibility in case it doesn't suit all users' needs.
SFML needs a lower-level concept of "drawable stuff", like a vertex array where one can directly manipulate the position, color and texture coordinates of every point, and that can be optimized/compiled in case its contents never change.

Quote
I hope that doesn't mean that all the drawables (sprite, shape, ...) will be removed as those are things i like about SFML.

No, I think I'll keep them, but built on top of the lower-level concept.
Laurent Gomila - SFML developer

bastien

  • Full Member
  • ***
  • Posts: 231
    • View Profile
    • http://bastien-leonard.alwaysdata.net
Respecting naming conventions & other possible changes
« Reply #24 on: October 29, 2010, 04:36:36 am »
For creating images and such, I would suggest two approaches:

Use a single constructor with optional parameters:

Code: [Select]
def __init__(self, path=None, buf=None):
    if path is None and buf is None:
        raise SomeException

    if path is not None:
        # ...

    if buf is not None:
        # ...


Use it like this:

Code: [Select]
Image(path='/some/path')
Image(buf=[])
Image()  # Raises an exception


In my opinion the problem with this approach is that the constructor does two very different things, and I'm a big fan of the “do one thing and do it well” approach. Also, you need to use keyword parameters in order to be explicit.

The second is to use class/static methods:

Code: [Select]
class Image(object):
    def __init__(self):
        # don't do anything, or raise NotImplementedError to make it somewhat private

    @staticmethod
    def load_from_file(self, path):
        # ...

    @staticmethod
    def load_from_memory(self, buf):
        # ...


I would use the second approach because it's more explicit, and there's a method for each concern.

If you're looking for ideas you should look at Pygame (http://www.pygame.org/docs/), it's a nice Python wrapper around SDL. It provides a lot of features that piichan talked about.
Check out pysfml-cython, an up to date Python 2/3 binding for SFML 2: https://github.com/bastienleonard/pysfml-cython