[Tutor] Mapping memory coordinate to screen coordinates
dn
PyTutor at danceswithmice.info
Tue Dec 1 22:12:50 EST 2020
On 02/12/2020 13:10, Phil wrote:
> Thank you for looking at this lengthy example.
>
> Over the years I've used this scheme to display a memory grid using C++
> and more recently Python. The problem is that the x and y coordinates
> don't match the screen coordinates. The simple solution is to reverse
> either the grid or screen coordinates, however this leads to confusion.
> I'm currently working on, what to me, is a complex game board and I'm
> constantly running into bugs because I'm confusing the screen
> coordinates with the real coordinates and mental gymnastics is something
> the I'm struggling with as I age.
>
> I came across the following example a couple of days ago and it shows
> the problem perfectly. Can anyone suggest a logical solution where
> memory grid[x][y] is the same as screen grid[x]y]?
...
I've been using Python for a long time, but only looked at Turtles and
pygame quite recently. (second childhood perhaps?)
I'm (largely) ignoring the code (and thus the question as-asked), in
favor of examining the design issue which 'creates' these problems -
described as "reverse".
Pygame is a 'framework'. When we choose to utilise a framework (or in
making the choice of one over some-other) considerations should include
the assumptions and philosophies upon which the code has been built. For
example, mathematicians and physicists often tackle the same
calculations quite differently and with their own terminology for the
very same 'thing' - go figure! Best to choose something which 'speaks'
your own language, thinks the way you do, ...
In this case, pygame treats the Origin (co-ordinates: 0, 0) as the
top-left pixel of the screen. Many other graphics-tools place the Origin
at either the bottom-left, or at the center of, the
screen/window/surface/graph.
Accordingly, there is an implicit expectation that if we wish to model
something using pygame, we will accept that
characteristic/advantage/limitation! This, in the same way that we
(eventually) accept whichever side of a car has the steering-wheel,
whether the wind-shield-wipers or lights are on the left/right 'stalk',
and whether the key turns clockwise to lock - or anti-clockwise. (the
two cars I use most-often are opposites in the latter case. Grrrr!)
Almost all of us will accept the tool the way it is. Sure, there are
some who might rip the car apart in order to reassemble it 'perfectly',
but...
(see also "open source" and "forking" software!)
Accordingly, choice nr1: adapt your thinking to become compatible and
congruent with the philosophies and conventions of the tool. This the
other way around: find a tool that works the way you do...
However, it is difficult to see the world only one-way. Indeed, if/when
you move into 3-D graphics (and coordinates) there are two 'competing'
approaches: "left-handed" and (wait for it...) "right-handed" coordinate
systems. As you are probably thinking with the question above, sometimes
'the math' becomes a lot easier when we use one, rather than contorting
ourselves to cope with the other!
This is not limited to (computer)graphics by any means. How about the
famous "computer-error" where a space-mission went drastically wrong
because one team had been working in metric-units whilst their
colleagues used "imperial". Similarly, when will we all agree on Celsius
or Fahrenheit (etc) temperature scales; distances in feet or
meters/metres; colors represented as RGB[a] or HSL (also, etc) - and
the band marches on...
Thus, let's move to consider choice nr2. If you cannot, or will not,
alter your thinking to suit pygame; then just as the temperature
'problem' mentioned earlier is a very common 'my first program[me]'
assignment in schools, you could consider building an "interface".
This requires us to consider that there are two separate, but somehow
related, entities: the "grid" or 'map' of your world; and the pygame
surface. They will both represent exactly the same information, but the
former will be lists and values, but the latter screen-bytes/pixels.
NB on the subject of "related": the provided-code already confuses
because the grid has a width/height (and margins), quite different to
the 255x255 size of the surface! Would it be easier to grid only the
'working' part of the image?
Plus, each will (presumably) be a (logical) mirror-image of the other
(jargon: "reflection" about the horizontal/vertical center of the
grid/surface).
The purpose of the "interface" will be to take abstract-content from
your "grid" and have that displayed 'wrong-way up' on the screen.
Conversely, it will also need to take the likes of mouse-locations from
the surface, and re-compute them become 'equivalent' coordinates on the
grid.
Thus ( 0, 0 ) on your grid might become ( 0, surface_height ) in pygame,
and pygame's bottom-right pixel ( surface_width, surface_height ) will
become ( max_width, 0 ) on the grid.
Looking at the code-provided, I suggest that "the interface" be
implemented as two functions:
grid_to_surface( x:int, y:int )->Tuple( int ) # int or float
and
surface_to_grid( position:tuple )->Tuple( int )
Now, the calculations can be abstracted away from the "event loop", and
thus will be available for use in however-many cases without
code-repetition, eg if/when it is necessary to check if an object should
'bounce' of a wall or if a missile has impacted its target...
NB (WIDTH + MARGIN) and (HEIGHT + MARGIN) already appear more than once!
(worse: is expressed inconsistently).
NBB I would be thinking of using at least one class (to represent the
screen/surface "entity", ie including the set_mode() declaration and
other screen-parameters) as well as containing the encode/decode
interface routines (methods); if such suits your own way of
thinking/coding, and doesn't conflict with the procedural thinking
implicit in event-loops...
If some of the discussion (above) feels a little advanced for your
personal stage and progress with Python, then may I recommend adapting
yourself to "choice nr1" - even if more effort 'now', it will make your
continuing use of pygame less fraught!
If you already 'know the graphics' (perhaps even to the code-level/are
adapting to Python and/or pygame) but are being frustrated by the tool,
then "choice nr2" may be the way to go...
--
Regards =dn
More information about the Tutor
mailing list