[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Native PyGame method for automatically scaling inputs to a surface resolution?



Thank you for all your answers. I condensed my reaction in a single
mail:

Julian Marchant <onpon4@xxxxxxxxx> wrote:

> What is the purpose to having calculations done with a size that's 10
> times larger? If it's just precision, the solution could be simply to
> use floats for the calculations and convert to ints as necessary.

That was just an example. The general idea is that when you write the
physics of a game (and even more a simulation) you normally model the
reality as-is, but represent it scaled (an projected) onto your
computer screen. So: your speed would be 10.2m/s in all the
internal calculation (and not 2.5789px/(1/FPS)).

> One last possibility that I can think of is to scale up your graphics
> for 1000x1000 and then scale the window surface...

In my specific application I am representing objects on 6.400.000.000
square metres, with a resolution to the centimetre. Unless I'm going to
run it on the K computer it's not a viable solution.

Christopher Night <cosmologicon@xxxxxxxxx> wrote:

> Yeah short answer no. However, I think the answers you've gotten from
> StackOverflow have not been terribly helpful. They seem to suggest
> "don't do scaling in pygame". This is silly, I do scaling in pygame
> all the time. There's no reason you'd need to work in screen
> coordinates.

Yep, still I appreciated the fact they took the time to answer!

> I use wrappers. Let me point out there's a total of 9 functions in
> pygame.draw. You seem to be going to a lot of effort to avoid writing
> 9 one-line functions. (And I usually only ever use about 3 or 4 in
> any one application.) Writing the wrappers is the best way, and I
> don't think you should have dismissed it so quickly.

I never counted the number of functions actually. Good to know. :o

> Since this is a very common problem, I wonder if there is an
> established pattern that elegantly solves this problem that I failed
> to find.

We are in two then! :)

> I could simply decorate the existing middleware functions, but the
> problem is that those functions also work with the same parameters
> being list or Vector2D too, and ...

Totally on the same line, although writing a decorator that need to
check special cases all the time is going to have a performance hit,
and writing more than one decorator does seem like silly. 

> I hope you find a solution that satisfies you. It's not that there
> aren't plenty of solutions!

So far I settled with a util function ``sc()`` that accepts scalars or
iterables and returned them scaled. Using a deep copy and
initialisation I could also create a sort of closure, de-facto using
the same syntax for all surfaces but getting scaled to the right amount
according to the target surface [so far I don't need it, though].

Greg Ewing <greg.ewing@xxxxxxxxxxxxxxxx> wrote:

> Don't forget that function calls are expensive in Python, as
> is doing piecemeal arithmetic.
> 
> Most other graphics systems these days provide a facility for
> applying a transformation to coordinates before drawing, and
> I don't think it's unreasonable to suggest that PyGame should
> do the same. Having it done for you in C would be more efficient
> than doing it in Python.

I'm totally with you on this. The behaviour that I envisage would be an
optional keyword argument ``scale=1.0`` for rectangles (and surfaces).
In order to further optimise execution time, PyGame could initialise
objects with the scaling procedure only when ``scale != 1 ``.

Christopher Night <cosmologicon@xxxxxxxxx> wrote:

I think I missed some mail, as there is quoted text in here that I
didn't see in original, however...

> While that is roughly true, it's a very, very general statement to
> the point where I would say that avoiding function calls on principle
> is premature optimization. Keep in mind that the operation you're
> wrapping - a draw call - is expensive in the first place. Anyway, a
> quick profile suggests that for a small circle you can potentially
> gain a 7% speedup by avoiding this function call, and a 14% speedup
> avoiding both the function and the arithmetic:

My point wasn't really the fact that I'm lacking speed. For me it is
more a question of good code design. I think that having to scale
manually at each operation on a given surface (or having to wrap
decorate functions all the time) is suboptimal (DNRY). Besides, while
speed is not my immediate concern, I do think that at library-level
speed should (is) one of the designing principles.

> You can decide whether that's worth it for you to avoid this function
> call. For me, if my game is slow enough that I have to avoid function
> calls to get reasonable performance, it means I'm doing something
> else wrong. :) If performance is the goal here, I still think it's a
> large amount of effort for a relatively modest gain.

Everything is relative: 14% is the difference between dying 80 and 69
years old. I'm not so sure if I would call that "modest"! ;)
 
> For what it's worth, I would also welcome native-pygame wrappers that
> apply a linear transformation. But whether pygame *should* have them
> wasn't the question, as I understood it. And I can scrape by without
> them.

You are right: that wasn't the question, yet I think that having them
*would* be a good thing. "Battery included" is one of the designing
principles of anything pythonic, and scaling to screen resolution is
definitively a pattern common enough to deserve consideration, IMO.

If that is ok with you, I will eventually prepare a writeup of this
thread, post on SO and mark it as accepted answer.

hank you all for you contributions,

/mac