2/17/08

SceneCamera class nears completion

Here is a video demonstrating the features of the SceneCamera class as it nears completion:


direct link

All SceneCameras will by default perform a translation of the subject (e.g., follow it's X/Y position), and all SceneCameras have the ability to scale (zoom in/out). In addition to these two default behaviors there are two optional properties to specify camera style.

Rotate with subject: If this property is True, it causes the SceneCamera to lock rotation with its subject. This creates a camera style whereby the subject appears fixed and the entire Scene rotates. In the video, the SceneCamera on the right side rotates with it's subject. The SceneCamera on the left side has this property set to False, creating an opposite effect (the Scene appears fixed and the subject rotates).

Clamp to Scene: If this property is True, the SceneCamera is not permitted to exit the perimeter of the Scene. In the video, the left side has this property set to True, and it is False on the right side.

Finally, there is a 3rd SceneCamera moving around the perimeter of the Screen to demonstrate the "game object" nature of SceneCameras. Like a Sprite, a SceneCamera can easily be any size, and can move around the Screen without disturbing it's ability to view a subject.

What I will be adding next is a property for Chase lag, so the SceneCamera can be given a variable amount of imprecision when following its subject. Once this is done, the SceneCamera class should be adequately functional.

10 comments:

Tom said...

I just discovered your series not too long ago and have been following it comprehensively since the weekend, adding to your samples where my explorative nature takes me. I can't really tell you how much I appreciate following your samples and videos as I learn the ropes of XNA and .NET development. I particularly appreciate your inheritance implementation, which, coming from VB6, I've had some bother pursuing myself. I'm very eager to see where your project goes. Rest assured, I'll be along for the ride.

Matt Worden said...

Your cameras be slick! :-)

It's interesting to see the direction you're taking, since I started about in the same place, conceptually, but have gone a different direction with the cameras in my project.

Looks like your approach makes multi-camera "split screen" type games easier to handle.

Do your cameras draw directly to the screen? Or do they draw to a texture (render target), which is then drawn to the screen?

-Matt

emachine74 said...

Thanks ;) I was using targets initially, and then just to educate myself a bit I changed them to draw through viewports, which is what you see running in the video. Without the overhead of targets, drawing directly to the display buffer through a viewport performed considerably better. The big downside is that it's not really compatible with the "matrix cascade", since I don't think you can transform a viewport (I would love to be wrong about that though).

Viewports had such a significant difference in performance that I'm still motivated to use them when at all possible, and my guess is that 90-degree, 0 rotation 100% scale cameras might be the norm most of the time, in typical scenarios anyway. So I will probably implement both viewport- and renderTarget-based rendering methods on cameras, so that anytime the cam's tree node matrix changes the can can decide to use either viewport mode (if the resultant matrix rotation = 0 & scale = vector2.one), otherwise, renderTarget mode, so that its output can be rasterized & transformed prior to hitting the display buffer.

Tom, always glad to hear about someone getting something out of the blog. Once you get into the swing of .NET, you will hate the idea of going back to VB6! I will continue to try and brush up against the OOP/VB.NET logistics as I go along with the XNA stuff, hopefully without boring folks with too much "101" stuff. I've got an entire movement automation system which I still need to get around to showing you guys, which allows you to script sprite activities over time, such as changing tint, alpha, texture, moving around (linear, bezier curves), rotate, change origin etc. etc. There's a lot of class inheritance as well as interfaces and type predicates in that system, which should also provide some real-world examples of how those are neat ways to help organize, simplify and reuse code.

If I didn't have a day job taking up all my time and energy I might get more done around here :)

Matt Worden said...

Okay ... another question ... Are you essentially re-drawing each object for each camera? I can't see any way of getting around that.

-Matt

emachine74 said...

Yea - when multiple cameras see the same content, that content gets re-drawn by each camera.

The cameras function independently of each other; each one determines it's own "visible" content, and then draws that content to the screen with a unique matrix.

In the event two cameras overlap, some or all content ends up on the visibility lists of both cameras - those objects are subsequently drawn twice; once by the first camera using it's matrix, then again by second camera and its matrix.

Tom said...

I was going to ask how you handled sprite rotation, but you answered my question already. I wondered if you transformed each sprite by the camera's view matrix, which is obviously not nearly as efficient as transforming the render target. I'm becoming more and more eager to see your next installment.

I've been deviating a bit from your lessons. I split your DrawMatrix method to handle transformation propagation on a per-sprite basis (view code). I did something similar in the DrawColor property method.

What I haven't gotten to work is a frame timer. I've disabled vsync for both the graphics device and game class, changed all the presentation parameters to the fastest settings, even set it to run full-screen just to be safe. It seems to be working because my cumulative timer is running faster, but when I use the frame interval to calculate FPS, I always end up with 60. Any chance you've experimented with this?

emachine74 said...

Is your Game.IsFixedTimestep property True? This property of the XNA Game class works in conjunction with the TargetElapsedTime property to control the frequency of Updates. The idea is similar to how VSync works in conjunction with your monitor to control the frequency of Draws.

Game Timing in XNA Game Studio 2.0

Personally I found it easier to learn stuff in a predictable, consistent, "update-then-draw" environment, without XNA tossing in extra updates or draws (and I still haven't encountered a reason to turn it on).

Tom said...

No, I have the fixed time step disabled, along with anything else that would lock the frame rate. As I said, my on-screen timer runs faster than normal, but my frame rate is locked at 60, which leads me to believe I'm not calculating it correctly, but that doesn't make sense because I use the same interval to calculate elapsed time.

I want to know how fast the program is running under the hood so I know how much leeway I have to add more features, and what impact each feature has. I'll work it out somehow. I wanted to get around using temporary variables to hold previous times, since XNA seems to keep track of its own timing, but it looks like I'll have to resort to old-school methods. This would be a good opportunity to make a "game timer" class.

emachine74 said...

I calculate FPS in a pretty archaic fashion: fps component

As for the on-screen timer & calculating elapsed times, I'm struggling to visualize what may be going on there - how are you using the gameTime object? Can you give an example?

Tom said...

Okay, I got it working, thanks to your example. Getting 140 FPS without any optimizations.