Game Design Questions (low level-ish)

Started by
18 comments, last by Jossos 11 years ago

I'm not sure if this is really a beginner topic or not, but since I'm not really experienced, I thought I'd post in beginners section just to be safe from ridicule.

I'm writing some practice applications and am having a blast. I'm wanting to build some neat game-apps (mostly just experimenting right now) and I do want to get some good game design in whatever I do. These are questions I have, and any answers would be great!

Question 1: Animation

Is it possible to export animations from 3ds Max? Also, how would this work? I've messed around with .obj files, and I can load in an object with textures into my application, but I am unsure how to do animation. Do I need some kind of bone system - or perhaps a bunch of .obj's with difference vertex positions for each frame? I prefer the vertex positions per frame, as the bone stuff seems like it might make the computer do a little more math than I'd like it to.

Question 2: Data Structure(s)

I'd like to make a RTS, which means I need a lot of "Units" (I'd likely make unit objects) and I'd like a lot of these, hundreds, maybe thousands. As you can tell, I have no grasp on what's feasible here, in terms of how it's usually done in games, so I'd like to know if I'm way off, or if there's a special way to do it.

In all honesty, I plan to have all units contained in a <vector> and loop through each one, progressing its state forward a frame (like walking, or attacking)

Question 3: Visual Studio - DLL's and .libs

I'm quite use to having a bunch of .h and .cpp files all in a project, and compiling the whole thing into an exe (with .obj's and png's in the same directory). Should I have bunches of my code put into a seperate file and export as DLL? I haven't done this before, so is there anything I need to know about this? (I think exporting a dll is pretty easy, just have to change a setting)

Question 4: Input to Logic

- Solved

Question 5: Mouse/screen coords to the 3d world

- Solved

Question 6: Mouse/screen projection is off

So I got the program to cast a ray from the mouse into the 3d world - However it's off by a few pixels, and this seems to occur in the actual 3d world.

The cyan-Hlighlighted square should be directly underneath the mouse.

Below I have drawn the mouse position into this screen capture of my program (because printscr doesnt copy the cursor)

myappnotworking.jpg

As you can see it's off by a fair margain, but it's pretty damn close. I mean, I can use this program and it's quite nice, but the offset doesn't make any sense.

Here's the code to convert mouse coords into 3d world coords


vector3d GetOGLPos(int x, int y, float z)
{
GLint viewport[4]; // contains x, y, width and height
GLdouble modelview[16]; // modelview matrix information
GLdouble projection[16]; // projection matrix information


glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);


GLfloat winX, winY, winZ;
    GLdouble posX, posY, posZ;


winX = (GLdouble)x;
winY = (GLdouble)viewport[3] - (GLdouble)y;
winZ = (GLdouble)z;


    gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);


    return vector3d(posX, posY, posZ);
}

it's used like so:


// mousePosNear and mousePosFar are of type "vector3d"

mousePosNear = GetOGLPos(m_mouseX, m_mouseY, 0.0);
mousePosFar = GetOGLPos(m_mouseX, m_mouseY, 1.0);

I'm not sure if I should provide other details, such as the rayplane function that these values are used in. Let me know if you want that code aswell to help solve this

Question 7: Deciding what tiles to draw

Actually this problem seems like it should be relatively easier Since I already have the rayplane function done, but I can't figure out how to do this in 3d (the 3d math just does my head in)

I figured It would be something like casting a ray from each corner of the screen and getting the returned tile... and then I don't know what to do from there.

Advertisement

Question 1: Animation

Is it possible to export animations from 3ds Max? Also, how would this work? I've messed around with .obj files, and I can load in an object with textures into my application, but I am unsure how to do animation. Do I need some kind of bone system - or perhaps a bunch of .obj's with difference vertex positions for each frame? I prefer the vertex positions per frame, as the bone stuff seems like it might make the computer do a little more math than I'd like it to.

.obj files are really easy representation laking animation and more advanced topics. Either use collada or FBX as export format and take a look at libraries such like assimp to get the files into your game.

Vertex blending/animation is only useful for a very limited area of animation (most often facial expressions), so there's not really a way to avoid skeletal animation system when doing animations in 3d.

Question 2: Data Structure(s)

I'd like to make a RTS, which means I need a lot of "Units" (I'd likely make unit objects) and I'd like a lot of these, hundreds, maybe thousands. As you can tell, I have no grasp on what's feasible here, in terms of how it's usually done in games, so I'd like to know if I'm way off, or if there's a special way to do it.

In all honesty, I plan to have all units contained in a and loop through each one, progressing its state forward a frame (like walking, or attacking)

That's a good way to start, but eventually you need to utilize other data structures which will be more suitable for special cases (e.g. sweep'n'prune for physics, oct-tree for rendering etc.). If you are a beginner, start small and don't target too high (e.g. start with 20 units instead of 20k). You will be surprised at how powerful modern computers are, so if you don't have too much experiences, start, make errors and learn from them, this is a very important process.

so there's not really a way to avoid skeletal animation system when doing animations in 3d.

I was thinking maybe I could do all the animation inside 3ds max with bones and ik's etc, and then just export the end result (vertex positions) of each frame. I don't know if this is possible, but I don't see why not.

I was thinking maybe I could do all the animation inside 3ds max with bones and ik's etc, and then just export the end result (vertex positions) of each frame. I don't know if this is possible, but I don't see why not.

There is a number of reasons. If you have a look at how big a high (and even low) poly model file can get, you'll see why. For a 10 second animation â 60 frames it would take an enormous amount of memory. Not talking about loading time - you would have to load the whole model for every step of the animation, which eigther takes up gigs of ram for each model or requires loading data from the disk every frame, which is a very bad thing to have and will make your game virtually unplayable.

Next thing, you want smooth interpolation based on the target PCs frame rate - if you'd e.g really export a 10 second character animation the way you wanted to do, just think about how you would (not be able to) handle animation on one PC that runs the game at 500 FPS and another one that only has 15 FPS. Skeletal animation takes (almost) automatically care of this, while with your approach this would be nearly impossible/even harder to achieve than just implementing SA.

If thats not enough, think about if you have a standard walk animation and then want your character to turn his head on one occassion. SA you can blend different animations. but with the way you suggested, you'd have to dublicate the walk animation with his head turned exactly at the right moment - stepping back to the memory workload I talked about earlier, I suppose you plan on shipping your game on a 1 TB HDD? ;)

Short answer - no, this is not at all possible, even if modeling software would support it (which it, fortunately, in my knowledge doesn't).

I was thinking maybe I could do all the animation inside 3ds max with bones and ik's etc, and then just export the end result (vertex positions) of each frame.

It is often a performance/memory issue. Take a 3k character with 1000 animation frames and 100 bones.

1. bone version:

100 bones * 1000 frames = 100 * (1x quaternion + 1x position) * 1000 = 100k * (7 floats) = 100k * 28 bytes = 2.8m bytes

2. vertex version

3000 vertices * 1000 frames = 3000 * (1x position) * 1000 = 3000k * 12 bytes = 36m bytes

Factor ~12x

Besides the memory consumption, which scales really badly with the number of vertices (current gen main characters often have more then 10k vertices), you would need to upload the modified vertices to the GPU each frame (slower then just uploading 100 bones) or you would need to store all the vertices on the GPU.

This should only be an option if you target really low-poly, low animation models (like the minecraft creeps).

Question 2

Just use a vector and you should be fine, one really simple trick in your case then is to flag destroyed objects as killed

instead of removing them from the vector and then replace them when you create new ones instead of adding to the end

Question 3

Making use of DLL is not as easy as just changing the project options because you must make export functions and create interfaces if you want to use

classes for example

Just keep everything in one project until you get a better idea of how you can separate the things in your game

One project is gets you really far anyway just harder to make use of what you did in future projects but do not think too much about that.

Blekinge Institute of Technology
Twitter [twitter]devmoon[/twitter]
Homepage http://devmoon.se
Stream http://twitch.tv/devmoon

Question 2: Data Structure(s)
I'd like to make a RTS, which means I need a lot of "Units" (I'd likely make unit objects) and I'd like a lot of these, hundreds, maybe thousands. As you can tell, I have no grasp on what's feasible here, in terms of how it's usually done in games, so I'd like to know if I'm way off, or if there's a special way to do it.
this question should be answered first, as the answer affects the answers to the other questions.
what's feasible? Total War titles routinely have 4000 units in combat at once, all on the screen at once.
no special trick, they just don't spend a lot of clock cycles drawing individual units.
I would probably use a target list of some sort (IE a database), with an active field in each record. this serves the same purpose as a "killed" flag in a vector.
special data structures could be used as needed for sweep & prune, octree drawing, etc, if required.
i would probably implement it as a flat file database: a static array of structs, or an array allocated on the heap at program start. this eliminates all malloc, free, new, and dispose type overhead, as well as the possibility of memory leaks, null pointers, etc. It also eliminates the overhead of traversing trees and linked lists, and/or chasing object pointers. IE keep it simple as possible. simple = fast. if you eventually want to do lots of units, you'll want fast.

Question 1: Animation
Is it possible to export animations from 3ds Max? Also, how would this work?
4 ways to go here (there may be more):
1. export skinned mesh and skeleton animation from 3dsmax to some format and then into your game and use it. here i'm talking about 3rd party tools and custom code. apparently a number of developers do this, as they are dissatisfied with the build-in animation capabilities of their graphics library (directx).
2. export to .x format, and use directx routines to load and draw, as per the directx skinned mesh demo and tutorials found online. if you want a list of the skinned mesh tutorials, i just found them yesterday.
3. slice unit models into separate limb meshes and use a limb animation system. this will let you draw more units at the same level of detail, with the downside of no blended seams between limb meshes. careful modeling of limbs can minimize this. if you want lots of units, and you never see them really close up, this may be a good option. In my experience, a limb system is typically 7 times faster than a skinned mesh system. so if you can draw 100 units at a decent frame rate using skinned meshes, you can draw about 800 limb based models at about the same frame rate.
4. render 3d models (including animation frames) to sprites, and draw units using sprites. this is the absolute fastest method. the downside is you only have a finite number of viewing angles in your sprite sets. but the renders can be arbitrarily complex.
in cases 1, 2, and 3, we're talking VERY low poly models. When Total war switched from sprites to 3d models, each unit has something like 50 to 100 triangles each. how many triangles per unit you can do will be a function of the total number of units, skinned mesh vs limb system, the speed of your code, how much other stuff you draw, and how much simulation your game does.

Should I have bunches of my code put into a separate file and export as DLL?
DLLs are primarily intended for code sharing. they can also be used as a means of code reuse and easy updates in the field. its unlikely you'll have 2 copies of the game running at once, so no code sharing. you only have one project so far, so no need for reuse. and you're not about to release, so no concerns about easy updates in the field. so DLLs are an unnecessary complication at this stage.
code reuse can also be gotten in easier ways, if you don't need update in the field capability. perfect example, i sliced the built-in modeler and animation editor in my main project into its own .cpp and .h file. now i link it into all my titles and have a built-in modeler and animation editor in each of them.
as for easy updates in the field, you're talking about downloading and installing a zipped DLL vs a zipped EXE. not much of a difference there.
DLLs seem to be one of those things that everyone thinks they need when they don't really understand their intended purpose, which is to save ram when 2 apps use the same chunk of code. instead of linking the same code (such as msvb runtime) into two apps, and having two copies of that code in memory at once when both apps happen to be running at the same time, they both use the same DLL in ram. as a game, odds are only things like MSVB runtime will be good candidates for DLLs in your app. and there, if you statically link, it loads faster, and its one less file to deal with on the user's PC (can't get erased, corrupted, overwritten due to name collision, etc). the cost is the additional ram footprint of the DLL in question. but again, you're a game, not a regular app, so odds are you'll be the only open app most or all of the time, so again, not much opportunity for code sharing.
many things in the computing world (like DLLS) seem neat and make sense - except for games, due to the unique nature and requirements of games vs apps.

Question 4: Input to Logic
I'd like to have all of my logic and graphics separate from Input. How should I do this?
your example looks just fine.
for input, you'll be checking the state of keys, buttons, mouse position, etc.
"separate" can mean a couple things here.
1. i check input in one place, and act on it in another place.
2. keyboard / mouse button bindings.
case 1: i check input in one place, and act on it in another place. i've never been able to see a clear advantage to this. it requires you to store the results of your input checks for later use. unless the checks are slow, its usually easier to simply perform them as needed when needed, and get and process input all at once.
case 2: keyboard / mouse button bindings. you have a lookup table that assigns keys (such as W) to actions (such as move forward). when you need to process input, instead of checking for "W", you check for "key assigned to move_forward".

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Just as a small observation, what you're calling "logic.cpp" is in fact the input portion of your program. This would run in the input function of your game loop, while logic is a separate function of the game loop that would run after the input.

If thats not enough, think about if you have a standard walk animation and then want your character to turn his head on one occassion. SA you can blend different animations. but with the way you suggested, you'd have to dublicate the walk animation with his head turned exactly at the right moment - stepping back to the memory workload I talked about earlier, I suppose you plan on shipping your game on a 1 TB HDD? ;)

Short answer - no, this is not at all possible, even if modeling software would support it (which it, fortunately, in my knowledge doesn't).

While I agree that skeletal animation is the best way to go about this (and all your reasons why are valid), interpolating between keyframes of the model was a common way of doing 3D animations in the early days of 3D. In these days the poly count and number of animations was minuscule compared to today's standards so the memory problems could be worked around.

Some games even animated different body parts separately and stitched the models together (to enable combining animations such as looking a different direction while walking). I believe I read somewhere that the first Tomb Raider did this. One of the problems with this method though is that it creates seams in the model that were sometimes visible depending on the situation (while not specifically mentioned I would imagine that clothing would be used to hide the seams as best as possible.

While I agree that skeletal animation is the best way to go about this (and all your reasons why are valid), interpolating between keyframes of the model was a common way of doing 3D animations in the early days of 3D. In these days the poly count and number of animations was minuscule compared to today's standards so the memory problems could be worked around.

Interesing to know, I though keyframe interpolation was only used for e.g. technical mechanisms etc...

Question 5: Mouse/screen coords to the 3d world

So I've kinda done some of the harder work already. Here is my application so far:

myprog.jpg



A ray is cast from the camera in whatever direction it's pointing and highlights whatever tile it hits. In a way, you could imagine that the mouse pointer is always in the centre of the screen.



How would I add to this code to instead have the mouse highlight the tiles(as in, wherever the mouse is on screen, translate that into the 3d world). I can already get the mouse coords on the screen using an SDL function, just need to know the math.

-Also, if I've not provided sufficent information for this problem (like if you want to see my rayplane function) please let me know. I'm not sure what information is relevant here.



Some Info:



class smCamera
{
private:
vector3d loc;
float camPitch, camYaw;



the vector3d loc is just the camera location. It has floats x, y and z



camPitch is the up and down rotation, and camYaw is the left and right rotation. These are applied graphically like so:



glTranslatef(0.0, 0.0, -(player->cam->getCamY())); // Distance up from the ground
glRotatef(player->cam->getPitch(), 1.0, 0.0, 0.0); // I have this set at -45 to look down
glRotatef(-(player->cam->getYaw()), 0.0, 1.0, 0.0); // I increase this with the shift keys
glTranslatef(-(player->cam->getCamX()), 0.0, -(player->cam->getCamZ())); // translate the world

Help is greatly appreciated!

You need to unproject your mouse position. I can't tell you how it exactly works with OpenGL, but I can give you some DirectX-code with a little explanation, you should be able to figure out the rest yourself:


	//todo: access camera differently
	const Camera* pCamera = m_pGfx3D->GetCamera();

	//todo: access cursor differently
	Vector2 mousePos = Input::GetMousePos();
        //translate mouse coordinates to scene area
	mousePos.x -= m_pArea->GetX();
	mousePos.y -= m_pArea->GetY();
	D3DXVECTOR3 vMouse((float)mousePos.x, (float)mousePos.y, 0.0f);
	D3DXVECTOR3 vMouse2((float)mousePos.x, (float)mousePos.y, 1.0f);
	const D3DVIEWPORT9& ViewPort(m_pGfx3D->GetViewport());

	D3DXMATRIX mWorld;
	D3DXMatrixIdentity(&mWorld);

	D3DXVECTOR3 vP1, vP2;
	D3DXVec3Unproject(&vP1, &vMouse, &ViewPort, &pCamera->GetProjectionMatrix(), &pCamera->GetViewMatrix(), &mWorld); 

	D3DXVec3Unproject(&vP2, &vMouse2, &ViewPort, &pCamera->GetProjectionMatrix(), &pCamera->GetViewMatrix(), &mWorld); 

	D3DXVECTOR3 vDist = vP2;
	vDist -= vP1;
	D3DXVec3Normalize(&vDist, &vDist);

	const Ray mouseRay(vP1, vDist);

You basically create two points from the mouse, one on the near and one on the far clip plane. Now given the view matrix, projection matrix, viewport and (most likely identity) world matrix you can unproject these two points to their location in the world. You then construct your ray from these two points an voîla, you're done.

This topic is closed to new replies.

Advertisement