Some basic questions from beginner

Started by
5 comments, last by Servant of the Lord 11 years ago

First of all, hello everyone.

I have already made some super-basic 2D games like TicTacToe, snake and pong. I think I am starting to understand how simple games work. Collision detection in pong is simple, because there is only one ball and 2 objects that it can hit. But when I think about some simple 2D shooter game i feel confused.. Let's say I have my character, some enemies and some platforms, on which I can jump.. How am I supposed to check the collision of every object ( me, all bullets flying, all enemies and all platforms ). When I have 1 enemy and many bullets I can store the bullets in the array and then use loop to check the collision between the enemy and every element of the array. When I have many enemies and many bullets I can use double loop.. this is the way I see it, I have no idea if it is correct. But what if I have many elements of different types? Enemies, trees, fences, cars etc.. This topic really confuses me.. I hope everything is clear.

Second question, programming side:

In my poorly written code I am mostly using numbers instead of const variables..


// this is my code
enemy array[10];

// this is the experienced programmers code
const int MAX_ENEMIES=10;
enemy array[MAX_ENEMIES];

what is the point of doing it?

Advertisement

First, about your second question, see the recent thread here.

Secondly, about the first question(s):

You only need to check for collision with surrounding entities. If entityA is only 50 units wide, and entityB is only 100 units wide, then if their distance between each other is more than 100, you don't need to check anything else.

Also, you can partition up your loaded area into sections (think of each section as a 'bucket' of entities), if myEntity is in section7, it only needs to check for collisions against other entities in section7, and maybe a few of the sections next to section7 (incase myEntity is on the edge of both sections).

Further, look into std::vector for your entities and bullets. Twenty thousand bullets or more won't be a problem, but if you have them as a local variable of some function, they very well could be. std::vector stores its memory internally as non-local (dynamic) memory, "on the heap", whereas local variables are stored "on the stack", and the stack has limited memory.

Furtherly also, treat your bullets as a point (x,y) instead of a rect (x,y,width,height), and it'll be easier to check collision for.

Rect to rect collision is simple, but if you are hurting for performance, point to rect collision is even simpler. And when you multiply that collision by twenty thousand bullets, once per frame, you might save quite a bit.

Alsoly further, who says you need to check every bullet every frame? wink.png

If it's really a problem, and you have literally over half a million bullets, you could always update half one frame, and half the next frame, or divide the work up in some other method.

Finally, don't worry about performance until your program starts to slow down. Pre-mature optimization slows down your development time, even if it speeds up your program's execution time.

When speed really is noticeably a problem, then use a profiler, and it'll tell you exact what parts of your code are running too slow. People are often surprised at what the real slowdown in their code is - humans are fairly bad at guessing where the slow parts are, but a computer will tell you exactly where they are.

Your focus shouldn't be on fast code, but on clean, easy to read, easy to expand code, in my opinion. smile.png

Thanks a lot for the fast response, it seems clear now. I know about the Vector but I never had to use it. I made this topic because when something bothers me I can't stop thinking about it :D I am coding the Pong game while thinking about hundreds of other things.

Now I see that games are much more complicated than I thought..

Again, thanks a lot :)

You had another question in there I missed:

But what if I have many elements of different types? Enemies, trees, fences, cars etc.. This topic really confuses me.. I hope everything is clear.

What is a tree? What is an enemy? What is a fence? What is a car?

I see:

  • A rectangle (includes position and size)
  • Possibly a velocity (for continuing movement)
  • An image
  • Logic

All four (tree, enemy, fence, car) have the exact same 'pieces'. The only thing that changes is what image, and what logic.

Trees and fences have a velocity of zero.

So create your 'Entity' as one single type of entity, and initialize them with different values:

Entity = {rectangle{pos,size}, image, velocity, typeOfEntity};
 
Entity myCar(car_size, "CarImage.png", TYPE_CAR);
Entity myTree(tree_size, "TreeImage.png", TYPE_TREE);
Entity myFence(fence_size, "FenceImage.png", TYPE_FENCE);
Entity myEnemy(enemy_size, "EnemyImage.png", TYPE_ENEMY);
 
...add all of them to your single array (std::vector) of entities...

Figure out what's the same between the objects, and add it to your Entity class. Anything that's not the same, separate it out.

If you're using C++, you can use polymorphism here for handling the logic, but that might be a bit advanced.

Instead, how about having an 'UpdateEntity()' function, which checks what TYPE of an entity it is, and then calls separate more-specializes functions like "UpdateCar()" and "UpdateEnemy()"?

There are many other methods or techniques (polymorphism, function pointers, components), but I don't want to throw too much at you at one time, so I'm trying to use language features that I'm guessing you already know about. If you have any questions, keep on asking.

I'm not sure whether you're using 'C', C++, or some other language, but the concepts are the same for most languages, even if the syntax looks different.

Thanks a lot for the fast response, it seems clear now. I know about the Vector but I never had to use it. I made this topic because when something bothers me I can't stop thinking about it biggrin.png I am coding the Pong game while thinking about hundreds of other things.

Now I see that games are much more complicated than I thought..
Again, thanks a lot smile.png

Games are 'complex': "Consisting of many different and connected parts.",
but they aren't 'obfuscated': "obscure, unclear, or unintelligible."

They are confusing when you look at the big picture, but when you break things down into bite-sized pieces, then they become much easier to understand.

There are alot of features in your programming language you don't yet know, but those are just tools to make things simpler for you. If you aren't familiar with the tools yet, they might accidentally make things seem even more confusing.

Games are complex because they involve thousands of tiny pieces that interact. But if you build a game, one simple piece at a time, you'll understand the completed project when it's finished. Trying to look at the big picture can be overwhelming. Trying to look at every tiny piece at the same time can also be overwhelming. But focusing on one tiny piece at a time, you can build amazing things.

The more completed projects you have, the more you understand the inner workings, and the more you take groups of tiny pieces and wrap them into re-usable bigger blocks for your next project. The bigger blocks are the tools. After hundreds of programmers realize they're using almost exactly the same bigger blocks, then we standardize them are use them as short-hand for communicating with each other, which can accidentally create confusion for newer programmers. But everything everything everything is really just tiny pieces put together one by one. It just takes time to learn! And you learn by reading, asking, and doing. smile.png

Yep, I am using C++, but I still don't know much about OO part of this language. In my programs I use just simple classes, constructors, destructors and friend classes. I am reading a C++ book, so eventually I will learn the more advanced techniques.

I have one more question, this time about the game loop..

I know it should look like this:


while(gameRunning)
{
   handle_events();
   logics();
   rendering();
}

handling events is just taking the player input?

rendering.. this is obvious

but the logic part bothers me.. I see it as a main part of the loop, where most things happen. Calculating collision, velocities, tons of other stuff and at the end changing the coordinates of the objects. But finally I come to the point, where I have no idea where to move the objects and where to calculate stuff.

This particular area (big picture game arcitecture) isn't my strong suit.
I like to separate the main loop it into four categories, but I haven't done so for long enough to know whether it's better or worse.

while(gameRunning):

  • Handle events (any outside input):
    • ?Player input (from keyboard, mouse, gamecontroller, etc...)
    • Network data packets (if this is an online game)
    • Messages from the operating system (like when the [x] button is hit in the corner of a window)
  • Game logic:
    • Thinking (based on the current state of the game):
      • AI thinking (Did my target change or move? Recalculate my path. Am I now in range? Attack)
      • World thinking (Did something die? Remove it. Did the player enter a new area? Load it)
      • Did any timers reach zero? React to it.
    • Updating (based on the passage of time):
      • Continuing motion (if objects have velocities, update their positions based off of the velocities)
      • Updating the physics (applying gravity and whatnot)
      • Advance the frames of animations.
      • Countdown any timers needed by game logic.
  • Rendering (for 2D games. For 3D games the order is drastically different):
    • Draw or clear background
    • Draw world
    • Draw entities (sometimes intermingled with the 'draw world')
    • Draw GUI

These three/four areas don't have to actually be functions. This is breaking it down into separate 'systems' or 'chunks' to think about it and to mentally separate the parts that shouldn't know about each other. Data needs to be shared between these "systems" (for lack of a better word), but each system should be blind to the fact that the other systems exist. Rendering doesn't need to know that Physics exist, just what the current location (the data) of the objects are. Physics don't need to know that the Rendering exists, just where the objects and collision boxes are. Neither need to know that network packets or keyboards exist. But any data that more than one requires needs to be shared instead of duplicated. Rendering and Physics both need to know the position of an object, but only Rendering needs to know about the object's texture/image, and only Physics needs to know about the object's 'weight' in the game world.

We might, for the purpose of discussing it, simplify it as:


int main()
{
    GameData data;
    Initialize(&data);

    LoadGame(&data.playerGame);
    LoadArea(&data.world, data.playerGame.nameOfCurrentArea);

    while(gameRunning)
    {
        handle_events(&data);
        thinking(&data);
        updating(&data, amountOfTimePassed);
        rendering(&data.world);
    }

    SaveGame(&data.playerGame);
    FreeResources(&data);

    return 0;
}


But that's for illustrations. It's the ideas that are meant to be conveyed, not the exact layout of the code that matters.
You don't actually need a specific function with the name 'handle_events', but it is important that the handling of events (however and wherever they are handled) is separate from the drawing of the world.

For example, it's not important to save the player's game immediately after exiting the main loop. In fact, you usually don't want to. (What if the player doesn't want to save?). Saving and loading games is usually done inside the main loop, in response to the player clicking some Save Game button.

But it is important that your game data isn't global, but rather is passed in as a parameter (taken by reference, const reference, or pointer) to the systems that need it.

This (the big picture of game architecture) is an area that I'm still learning about and still growing in! How you actually implement the code for the various systems can be done in many ways, and sometimes depends on the nature of the game. But hey, if your game's innards become messy while working on the game, complete the game and use the knowledge you gained to refine your methods for the next game. For each game you actually complete, you are able to write the next game's architecture better.

This topic is closed to new replies.

Advertisement