Cameras
-
Attachments Take Screenshot Add FileNo attachmentsAssociations Associate with New Ticket Associate with Existing TicketNo associationsActivity
-
By kne on Apr 14, 2008 @ 06:12am UTC *
Ack!
No, no, no… The current implementation (r 149) of the cameras is wrong. It’s much too difficult.
With the addition of that class, we now have:- Screen coordinates (in pixels and in meters)
- World coordinates (in pixels and in meters)
- Camera coordinates (in pixels and in meters)
That’s an incredibly large and confusing amount. I’ll talk a bit more about the problem I still have with allowing pixels a bit later.
You have to remember that the focus of the camera is likely always going to be on an object. While it’s fine to have facilities to arbitrarily move the camera, I don’t see it as being widely used, and it certainly has no place in a basic demo.
To make it easier for calculations, the camera could/should store the center of the screen in world coordinates along with the origin of the screen in world coordinates (i.e., if the origin of the screen is the top left, where exactly is the top left of the screen in the world—the center doesn’t make it very convenient to calculate coordinates from).
This is how I see that things should go…
Drawing:for each object:
screen_location = camera.to_screen(object.world_location)
object.draw(screen_location, camera.zoom, rotation)The renderer can take care of the scaling/zooming (opengl, cairo, and sdl should have no problem with this).
If the user wants to click to center the screen, it should be as simple as this:
click(x, y):
world_location=camera.to_world( (x, y) )
camera.pan_to( world_location )We can of course make it smoothly pan from the current position to the next if that’s what the user wants.
Pixel Values
Back to the topic of allowing input to the functions with pixel values:
Now, if you want to still use the input of pixels, we have to talk about whether or not they are “actual pixels” or “scaled pixels”. Imagine, now, that you have yet another type of input, scaled pixels. Guess what becomes necessary everywhere?
if self.parent.input == INPUT_PIXELS_SCALED:
... everywhere. Imagine if I store my data in world coordinates, so I set the input to INPUT_METERS. Then someone draws on the screen, I have to set to INPUT_PIXELS_SCALED because there might be a scaling factor involved. That’s fine.However, now imagine that I store my objects in pixels. If for some reason the scaling factor of the camera is not at 1, the objects that are added to the world will now be scaled by that factor! So, INPUT_PIXELS for loading, INPUT_PIXELS_SCALED for user-drawn objects. Confused? I sure am.
Imagine, instead, that now we only allow adding objects in world coordinates. I store my objects in world coordinates. The user draws something on the screen, so I call the camera class and ask it where he drew in the world. I add the object based on exactly where the camera said it was. Simple as that. There’s no confusion as to what goes in and what comes out of the functions whatsoever.
Sure, it might seem convenient to have these options, but the more added, the more confusing it gets.
Camera Classes
On to the topic of camera classes. As it is, the camera class is heading toward being a monolithic class that takes care of everything. If we make individual classes for each type of camera that we can think of, it makes it much easier to separate what’s going on. The added benefit is that the user can create their own camera class and track things as they please, assuming there’s not a pre-made one that does what they need.world.camera = elements.Camera.TrackBody(body, offset_from_center, speed)
world.camera = elements.Camera.TrackMouse(to_world(mousex, mousey)) # requires manual updating of position
world.camera = elements.Camera.Fixed(world_x, world_y)
world.camera = myCamera() # implements all of the necessary functionsWell, what do you say?
-
By crazy-chris on Apr 24, 2008 @ 08:30pm UTC *
- → status changed from New to Test
what we have now is an example implementation, although things are still a bit messy. for example that we store lengths as meters and positions in pixels, and a few other things.
Ii would love hear a comment from ken on the camera status quo and on suggestions on how to improve it! Thanks :)
http://trac2.assembla.com/elements/browser/elements/elements/camera.py
-
By crazy-chris on Apr 24, 2008 @ 08:30pm UTC *
- → milestone changed from Drawing Techniques to Public Release of Version 0.1
-
The game world is currently limited to what can be drawn on the extents of the window. For actual games, it’s obvious that the screen needs to track various objects, the mouse, etc.
So, my proposal is to have a sort of camera-class that is called on every physics update (or perhaps on every event, as for mouse movement). We can have several types of classes, these few immediately came to mind:
“Track an object at the center, losely track an object at the center, always look at a certain point, and tracking a certain object at an offset on the screen (so you can have your ‘mario’ not in the middle, but somewhere near the ground or so), and then perhaps limits to how far down it’ll go (wrt the bounds of the world), ... “
These could be individual classes that implement:
to_world/to_screen – coordinate conversions
update() – to update the current object / set new mouse coordinates
pause() – pause the camera at the current point
set_focus() – set the focus on a new object (as supported, not for mouse)
set_parameter() – for losely/lazily tracking objects, set the speed at which it does that
and more as I think of it…
It might also be nice to abstract the current world’s ppm into this and allow for dynamic zooming. Though perhaps the ppm could stay as it is, and we just have another scaling factor for the camera. We’ll see!