[OpenGL/C++] How to move the camera in Orthographic Projection?

Started by
5 comments, last by RobTheBloke 12 years, 8 months ago
Hey all. I'm pretty stuck on this issue at the moment.

I'm using OpenGL and C++ to make a side-scrolling game. I'm using Object Orientated programming to get the job done, so it's not a ton of code all done in the main cpp file. So far, I've got a Space Invaders scene set up all fully controllable, but want to be able to move the camera based on the player's position. It's probably down to my lack of OpenGL knowledge as to why it's not working, but I've attempted so far to just do a glTranslate() by itself and this does nothing. I've done a push-pop sandwich and this does nothing either. What I want to happen is get the camera to translate from side to side when the player is at a certain point near the edge of the screen.

I'm not entirely sure what other information to give so anything you guys also need to know feel free to give me a shout and I'll gladly post it.
Advertisement
Assuming that you're using the legacy matrix stacks: The general do-it of rendering is:

1. Be sure that the MODELVIEW matrix stack is active (i.e. invoke glMatrixMode(GL_MODELVIEW) is necessary).
2. Set-up the VIEW portion of the MODELVIEW matrix. The view matrix is the inverse of the camera matrix. I.e. when you want to translate the camera 5 units in x direction, you have to specify a translation by -5 units in x direction for the view matrix. You have to invoke glLoadIdentity() first if you use any of GL's transformation routines besides glLoadMatrix.
3. Invoke glPushMatrix() if appropriate.
4. Set-up the MODEL portion of the MODELVIEW matrix. This is unique for each model and defines where and how a model is placed in the world.
5. Render the model.
6. Invoke glPopMatrix() if appropriate.
7. Continue with 3 if there are more models to render.
I'm a little confused on where to put this code. Here's an unbelievably shoddy looking copy of my UML diagram

580647675.png

I've got Windows setting up the window itself, and then using OpenGL to render what goes on inside said window. This is done in the main class. In here all of the orthographic projection etc is set up. Here is a copy of the code that is used to generate the projection:

[source lang=cpp]
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;

default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
wglMakeCurrent(NULL, NULL); //This frees our rendering memory and sets
//everything back to normal
wglDeleteContext(g_hRC); // Delete our OpenGL Rendering Context
g_hRC=NULL;

if (g_hDC)
{
ReleaseDC(g_hWnd, g_hDC);
g_hDC=NULL;
}

g_hWnd=NULL;

PostQuitMessage(0);
break;
case WM_CREATE:

g_hDC= GetDC(hWnd);
bSetupPixelFormat(g_hDC); // call our pixel format setup function
g_hRC = wglCreateContext(g_hDC); // create rendering context
wglMakeCurrent(g_hDC, g_hRC); //and make it current

break;

case WM_SIZE:
int height,width;
height = HIWORD(lParam); // retrieve width and height
width = LOWORD(lParam);

if (height==0) // don't want a divide by zero
{
height=1;
}
glViewport(0, 0, width, height); // reset the viewport to new dimensions
glMatrixMode(GL_PROJECTION);//set projection as //current matrix

{
glLoadIdentity ();
float aspect=(float)width/(float)height;
float halfheight=10.0f; //set screen to display 10 units high
float heightwidth=aspect*halfheight; //width depends on screen aspect
gluOrtho2D(-heightwidth, heightwidth, -halfheight, halfheight);
}

glMatrixMode(GL_MODELVIEW); // set modelview matrix
glLoadIdentity(); // reset modelview matrix

return 0;
break;

default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
[/source]

The CGame's update and render methods are also done inside the main loop in the main class. CGame has a CLevel and handles its update and render methods. In the update method for CGame, it also calculates the delta timer (using CTimer) and grabs the input from the keyboard and mouse (using CInput). (this is all it does, for now). CLevel controls all of the CModel instantiations, as well as all of the update and render methods for said CModels. CEntity has some very basic AI stuff and general rendering code in order to display itself on the screen. It also owns a CMissile and update/renders that. The same is also true for CPlayer, except this also detects for user input so it can move and fire.

The one thing I just thought of is that the code used to create the projection isn't in a class of its own, it's coded right into the window creation at boot time, will this current implementation not allow me to move the camera? If not, where do I put this code you're talking about? In CLevel? In CPlayer?

Please also bear in mind this is my first foray into making a side scrolling game, I have a rough idea of how they work but I'm not that knowledgeable on how they work in practice, if someone thinks my approach is off (or needs adjusting) feel free to say.

Thanks for your quick response so far :)
The usual game loop is as follows:

1. Running w/o waiting (e.g. on events) until a quit condition is detected.
2. Determine new current timestamp as basis for animations and the physics loop.
3. Fetch (i.e. w/o blocking) and process all currently pending (and interesting) events.
4. Drive animations.
5. Drive physics simulations, if used at all; this is usually done in its own loop to ensure fixed time steps.
6. Finalize animations.
8. Render visual and aural representations.
9. Continue at 2.

The place for this loop is probably an object of the CGame class. The steps mentioned in my previous post are to be done at point 6 above, of course. Setting up the VIEW portion has to be done as preparation step on every frame. Setting the MODEL portion can be done by CModel. Setting the projection need usually be done only once and hence outside the loop.
do you really want to move the camera?

with arcade type games you would typically fix the camera and only move the objects in the scene so that they scroll past the screen

do you really want to move the camera?

with arcade type games you would typically fix the camera and only move the objects in the scene so that they scroll past the screen


My end game will be more similar to Super Mario Bros then Space Invaders (albeit far more modern looking), are you sure this is the correct course of action?

@haegarr - thanks. my only other problem now is that what OpenGL command do I need to invoke to actually move the camera? Is it just glTranslatef()? Or is it something else?
Is it just glTranslatef()?


yes.

This topic is closed to new replies.

Advertisement