[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?



On Fri, Sep 30, 2011 at 10:38 AM, Mac Ryan <quasipedia@xxxxxxxxx> wrote:
If you are going to use scaled surface you *must* specify the dimension
of what you are drawing.

There are plenty of good reasons you might need a line that's visible regardless of the dimensions. Here's a screenshot from a game I made where you're able to zoom in and out:

http://media.pyweek.org/dl/13/unifac13/screenshot-20110917193243.png

You can see red lines that represent lasers, and blue circles that represent shields. Most of the graphical elements resize when you zoom in and out, but the thickness of the lines and the circles do not, even though the endpoints of the lines and the center and radius of the circles scale appropriately. This is what I wanted when I made the game. I didn't want lasers that become invisible when you zoom out. I don't care if it's "unrealistic" in whatever sense. It's more important that they be visible to the player than that they be properly scaled in thickness.

Another example off the top of my head is pathfinding. If you give orders to a unit to move from one point to another, and you want to highlight the path that unit is going to take, that's not an in-game object, that's a marker for the player, and it needs to be visible to the player even if you're zoomed out. If you draw it with lines, you want those lines to be visible.

If you're familiar with OpenGL, which fully supports the scaling mechanism you desire, this is exactly what you get when you call glBegin(GL_LINES): lines of 1 pixel in thickness, regardless of your scale. When you specify glLineWidth, you specify it in *pixels*, not in unscaled units. Similarly with GL_POINTS: you get points of 1 pixel, regardless of scale.

 if you are going to draw something that does need not to be
scaled, it would be a better solution (at least IMO) to simply bit a
non-scaled image on the scaled one.

That seems like a huge pain to me for something as simple as drawing a line.
 

> consider the filled, closed polygon from (10, 99.6) to (90, 99.6) to (50,
> 200). Would drawing that cause any pixels on the 100x100 screen to be
> lit up or not?

About (b): maybe I am missing the point as it seems obvious to me that
it shouldn't. Unless you want to do something like smoothscale does (and
thus using intensity as a mean to simulate fractions of a pixel) all the
points, once scaled, are outside the surface... did I misunderstand

You're saying that all the points, once scaled, are obviously outside the surface. That's what I'm disagreeing with: I'm saying it's not obvious, and asking you to justify that statement. I'm making the argument that anything within the rectangle (0,0) to (100, 100) should scale to a point inside the surface, including (10, 99.6). You're saying that points within the rectangle (-0.5, -0.5) to (99.5, 99.5) should scale to points inside the surface. Thus, for instance, you think that filling the polygon going from (10, -0.4) to (90, -0.4) to (50, -100) *should* light up some pixels, whereas I think it obviously shouldn't, because all those points are in the fourth quadrant.

Not that it's the most important thing in the world, but I think that OpenGL agrees with me. Here's a program that creates a scaled surface extending from (0,0) to (1000, 1000), with a canvas size of 100x100 pixels (so the scale factor is 0.1). It then draws the following horizontal lines:

Red line at y = -4 (will appear if we're rounding but not if we're truncating)
Blue line at y = 6 (will appear)
White line a y = 500 (will appear)
Red line at y = 996 (will appear if we're truncating but not if we're rounding)
Blue line at y = 1004 (will not appear)

When I run the script, I see a blue line at top and a red line at bottom, which is the correct behavior if we're truncating. But feel free to tell me if there's something wrong with this experiment.

import pygame
from pygame.locals import *
from OpenGL.GL import *

pygame.init()
screen = pygame.display.set_mode((100, 100), OPENGL | DOUBLEBUF)
glOrtho(0, 1000, 1000, 0, 0, 1)

ys = [-4, 6, 500, 996, 1004]
colors = [(1,0,0), (0,0,1), (1,1,1), (1,0,0), (0,0,1)]
for y, color in zip(ys, colors):
    glColor3fv(color)
    glBegin(GL_LINES)
    glVertex2f(100, y)
    glVertex2f(900, y)
    glEnd()

pygame.display.flip()
while not any(e.type in (KEYDOWN, QUIT) for e in pygame.event.get()):
    pass


-Christopher