Jump to content

  • Log In with Google      Sign In   
  • Create Account


Servant of the Lord

Member Since 24 Sep 2005
Online Last Active Today, 07:54 PM

#5047795 Some basic questions from beginner

Posted by Servant of the Lord on 28 March 2013 - 04:49 PM

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




#5047792 Some basic questions from beginner

Posted by Servant of the Lord on 28 March 2013 - 04:38 PM

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.




#5047790 Some basic questions from beginner

Posted by Servant of the Lord on 28 March 2013 - 04:21 PM

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




#5047670 How do you manage two vector from two different api's(Box2D and SFML)

Posted by Servant of the Lord on 28 March 2013 - 09:56 AM

wintertime's solution is a good one - I was making the mistake of assuming that performance was already a problem.


Both Box2D and SFML are open source. Recompile one of them to use the other's vector.

this a good idea but, it'll be a problem with me since sfml using template to define it's vector and i'm still don't know how to use it. moreover b2vec2 using struct to define it's vector and of course it'll make me confusing


Just use SFML's sf::Vector2f typedef, and it'll work fine. The fact that SFML's vector struct/class is a template doesn't harm anything.

For example, if SFML had a templated struct like this:
template <typename Type>
struct MyStruct
{
    Type x;
    Type y;
};
Then it's really, as the name implies, just a "template" that the actual struct is generated from.

Doing this:
MyStruct<int> myIntStruct;
Tells it to generate a struct, using the template, with 'int' instead of 'Type', like this:
/* template <typename Type> */
struct MyStruct_ForInts 
{
    /* Type */ int x;
    /* Type */ int y;
};

MyStruct_ForInts myIntStruct;
Then they can create a second almost-identical struct, with floats instead:
MyStruct<float> myFloatStruct;
Which creates:
struct MyStruct_ForFloats
{
    float x;
    float y;
};

MyStruct_ForFloats myFloatStruct;
The actual name is generated by the compiler, but MyStruct<float> is the generated "name" of the class type that you, as the programmer, use in your code. So you don't actually use 'MyStruct_ForFloats variableName;', you use 'MyStruct<float> variableName;'

This is just to explain templates - I'd still use wintertime's suggestion.


#5047475 How to create a more efficient Health System for my character

Posted by Servant of the Lord on 27 March 2013 - 08:57 PM

Try something like:
if( hit )
{
    health -= 1;

    if( health <= 0)
    {
        dead = true;
    }
}
Later, when it's time to draw:
//First draw the "Life" text or image.
DrawText("Life:", x, y);
//...or...
DrawImage(LifeTextImage, x, y);

for(int heart = 0; heart < health; heart++)
{
    heartOffsetX = (heart * (heartWidth + spaceBetweenHearts));
    DrawImageOnScreen(HeartImage, (distanceFromLeftOfScreen + heartOffsetX), distanceFromTopOfScreen);
}
Re-use the heart image and just draw it multiple times and shift the image over each time.


#5046384 Smart pointer obligating heap allocation when not needed..what am I doing wrong?

Posted by Servant of the Lord on 24 March 2013 - 06:54 PM

SiCrane is saying you can use the second template parameter of smart pointers to give a fake custom deleting function (in this case, a functor), so shared_ptr can work with stack-allocated variables.
 
//Functor for pretending to delete a block of stack-allocated memory, instead of using the default deleter provided by smart pointers.
//This can be passed as the second parameter of a smart pointer.
struct do_not_delete
{
    do_not_delete() { }
    
    void operator()(void*) const
    {
        //Do nothing. Let the stack free the memory when it's ready.
    }
};

{
	std::string onTheStack = "Test";
	{
		std::shared_ptr<std::string> mySharedPtr(&onTheStack, do_not_delete());	
		std::cout << *mySharedPtr << std::endl;
	}
	//mySharedPtr goes out of scope here, and calls 'do_not_delete(ptr)' to free the memory,
	//but do_not_delete doesn't free it, safely letting the stack-allocated memory continue to exist.

	std::cout << onTheStack << std::endl; //The stack-allocated memory continues to work just fine.
}
(I'm using C++11's standard shared pointers, but it should be roughly the same for boost smart pointers)

Ofcourse, now you have to be sure that 'onTheStack' lasts longer than 'mySharedPtr', or hard-to-track bugs result.

However, I think your low level functions shouldn't take pointers at all! I think almost every function should take parameters by const reference, unless something else is required. Then, whether you pass in actual stack-allocated or heap-allocated, it doesn't matter, and the function doesn't care.
void myFunc(const std::string &str);

std::string stackAllocated;
myFunc(stackAllocated);

std::shared_ptr<std::string> heapAllocatedShared = std::make_shared<std::string>();
myFunc(*heapAllocatedShared);

std::unique_ptr<std::string> heapAllocatedUnique = make_unique<std::string>();
myFunc(*heapAllocatedUnique);
You said that your low-level system "shares" data. Does it 'own' the data, or just 'use' the data? If it doesn't own it, it shouldn't be a shared_ptr, because shared_ptr means shared ownership. If something else owns it higher up, just use references or raw pointers lower down, unless it is possible for the lifetime of the system's access to the pointers to extend beyond the lifetime of the data passed in. If the lower down system uses it, but does not own it, and is likely to keep the pointer around for longer than the lifetime of the memory allocated, it might be worth considering whether that lower-level system should actually own it, with higher level code creating the object and giving up ownership of it to the lower system. Or maybe the lower-level system actually is doing more than it should be doing? Software architecture-design isn't my strong point.


#5046200 Coping files around help.

Posted by Servant of the Lord on 24 March 2013 - 06:48 AM

boost::filesystem has alot of cross-platform functions for file management.

 

boost::filesystem::copy_file(source, destination, error);




#5046145 Are pointers initialized to nullptr in a vector?

Posted by Servant of the Lord on 24 March 2013 - 12:15 AM

They should be default initialized to 0 or nullptr, yes.
 
If it's a vector of ints, then each element should be the same value as doing:

int myInt = int();
assert(myInt == 0);

(without the assert, which is just to illustrate)
 
For a vector of pointers, they should be initialized with their default constructor:

int *myIntPtr = /* however you're supposed to default-initialize them - I'm not sure */;

 
Test this:

#include <iostream>

typedef int *IntPointer; //Just so I get the initialization syntax correct.

int main(int argc, char *argv[])
{
    int intA; //Not garunteed to be initialized.
    int intB = int(); //Default initialized.
    
    std::cout << intA << " - " << intB << std::endl;
    
    int *intPtrA;
    int *intPtrB = IntPointer();
	
    std::cout << intPtrA << " - " << intPtrB << std::endl;
	
    return 0;
}

These will either output:

0 - 0
0 - 0

 

Or:

2293640 - 0      //The first value being whatever random piece of memory was left there, but the second still being 0.
0x35434 - 0x0


Depending on whether your compiler is default-constructing everything or not (sometimes done for debugging purposes to help catch mistakes).

 

std::vector::resize() - "If [the second argument is] not specified, the default constructor is used instead."

 

The default constructor for ints is 0 and for pointers is null (whether explicitly 0 or nullptr, I'm not sure, but it probably doesn't matter).

Also see this: http://stackoverflow.com/a/937257/1177073 , where someone actually quotes the standard.




#5046140 [Question] Creating a windows application in c++?

Posted by Servant of the Lord on 23 March 2013 - 11:59 PM

The first time I encountered Win32 I sincerely contemplated firebombing the MS campus.

 

It's second nature now, but there should at least be a warning label IMO.

 

What's second nature? Win32, or desiring to incinerate Microsoft? laugh.png




#5046057 [Question] Creating a windows application in c++?

Posted by Servant of the Lord on 23 March 2013 - 03:34 PM

Nope. Try Qt or wxWidgets. wink.png

 

Win32 will certainly work, but it'll be alot of pain. Whatever you do, there'll be a learning curve, but IMO, Win32 is so low level that it's more of a learning wall than a curve.

Qt and wxWidgets are at a higher level of abstraction that makes it easier to get things up and running, while still retaining the same flexibility and power, with the added benefit of being cross-platform to Windows, Macintosh, and Linux.

 

Your mileage may vary.




#5046036 How do you benchmark your game?

Posted by Servant of the Lord on 23 March 2013 - 01:50 PM

Profiling helps identify bottlenecks, when looking to optimize. Profilers tell you the average amount of time a function takes, and even more importantly, the number of times it is called during a specific program run. Saving 10ms on a function that is only called 20 times a frame isn't as good as saving 1 ms on a function that is called two hundred thousand times a frame.




#5045827 Class instances gone wrong!

Posted by Servant of the Lord on 22 March 2013 - 07:46 PM

A semi-serious issue with your code is that class objects aren't officially fully 'constructed' until you exit the constructor, so having your entire game loop within a constructor isn't a great idea - it might work, or might not. Chances are it'd probably usually work most of the time, but 'most of the time' isn't a good habit to get into with C++. smile.png 
It's like playing Russian roulette - even if you have 1000 empty chambers, and only one chamber with a bullet in it, a smart programmer will tell you that that you shouldn't have any bullets in it, and a smarter programmer will tell you that it's better not to play Russian roulette at all.
 
Your main loop, in this case, should look like this:

int main( int argc, char* argv[] )
{
    game_app_t game; //No need to use dynamic allocation at all. 
    game.do_main_loop(); //Call 'glutMainLoop();' after your constructor has fully finished.
    return 0;
}



#5045674 Am I thinking about r-values correctly?

Posted by Servant of the Lord on 22 March 2013 - 12:45 PM

Trying to refresh and lock-in my understanding. If I do this:
std::string DoSomething(std::string &&text)
{
	std::string newText = text;
	
	//...alter 'newText'
	
	return newText;
}

std::string strA;
strB = DoSomething(strA); //Copies 'strA'. 'strA' is not altered.
strC = DoSomething(std::move(strA)); //Moves 'strA' into 'strC', avoiding a copy, but 'strA' is now undefined.
strD = DoSomething("string literal"); //Uses move semantics, avoiding a copy.
Am I correct in thinking an lvalue passed into this function taking an rvalue, would not modify the original variable?

Do I even need to do "std::string newText = text;"? Do rvalue references, passed an lvalue, become lvalue references, or lvalues?
Basically, does rvalue references decay into pass-by-reference, or pass-by-value, when given a non-const lvalue or lvalue reference.


#5045664 Need help understanding odd C++ semantic

Posted by Servant of the Lord on 22 March 2013 - 12:16 PM

__declspec (dllexport) works with GCC also, when compiling on Windows.




#5045040 Article Inspiration

Posted by Servant of the Lord on 20 March 2013 - 04:43 PM

There also ought to be 'roadmaps', which are linked paths that take you from one article series to another, even if the series are made by different authors.






PARTNERS