5.00 a.m. questions [solved]

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
Clodi
Posts: 175
Joined: November 18th, 2012, 7:47 pm

5.00 a.m. questions [solved]

Post by Clodi » December 19th, 2012, 4:39 am

Hi,

I have a pretty simple game here with a few pretty nasty issues.
I'd be glad if the more expert out there could give a look at my game.cpp and see what's wrong. Also, along with issues, I have a few questions and doubts about my game and game programming techniques that I'd like to clear/answer.




1) When you set an initial velocity at random wth a chance to get 0, How can you prevent it to be precisely zero?
eg.

Code: Select all

		//enemy initial velocity is random (-4,+4)
		EnemyBox[ index ].vx = ( rand() % 9 ) - 4.;
		EnemyBox[ index ].vy = ( rand() % 9 ) - 4.;
I tried with a while loop. "while it's zero, reset ..sort of thing" it didn't work for shit :D




2) How can I organise my code a bit better?
The code itself is fine and I know how to write and use functions quite well. However, as the game increases in size, I find my game.cpp full of functions and I was only wondering if there is a better/smarter way to put certain functions (collisions.. etc..) inside a group, a bigger thing of some sort.



3) I watched the lesson about "classes" a couple of days ago for the first and last time, so, even if I didn't understand much, I will watch it again a couple of times until I get it.
Anyway, I'd like to discuss a point first: how is a class different from a structure?
"objects" are instances of classes/structures. Is the private/public thing the only (big) difference?
Or is it me who not to have even understood structures correctly?



4) Why in the game here attached do my enemies explode twice instead of doing it once as I want??? It pisses me off. I swear I looked at the code so many times I could recite it out loud in front of a hundred people.

[my enemies have 100 health and are "alive". When they collide they lose their health, and then it's when the explosion starts. When the explosion ends, their status becomes "dead" and they are dead for good. I don't get what's wrong in the code]




5) In this very game, I was trying to make a function that takes two Boxes as input. "Box" is a user-defined type that I made.
When I tried to pass a Box to the function, the expression was something very much like:

Code: Select all

for ( int index = 0; index < somenumber; index ++ )
{
      EnemyBox[ index ].x = someothernumber;
}
When I try to pass that Box, that instance, that object to the function, the compiler does not allow and says something like: "Do you mean: -> " And since I'm aware I didn't get pointers, and I also remember Chili talking about this "->" I was wondering if you can please tell me what it is and how you use it. I can't remember when exactly Chili talks about that and it would take litterally hours to fetch that little piece of wisdom 8-)

Clodi
Attachments
Clodi Game.rar
(126.83 KiB) Downloaded 180 times
Last edited by Clodi on January 26th, 2013, 7:53 pm, edited 1 time in total.

indus
Posts: 35
Joined: November 7th, 2012, 12:35 am

Re: 5.00 a.m. and still programing! I need serious help.

Post by indus » December 19th, 2012, 11:56 am

Hi there. Your game is getting better and better :)
For the velocities you could use do while loop for example. Smth like

Code: Select all

do {
	EnemyBox[ index ].vx = ( rand() % 9 ) - 4.;
} while (EnemyBox[ index ].vx == 0);
Than do it for both. The difference between do while and while loop is that in the do while loop you execute the statement at least once and than you check if condition is true.

The answer on the second question is your third one. You should use classes. For example you could make a class Box now. And add to it some methods like collisiondetection for example. Something like
bool collidesWith (Box b) and so on.

Your explosion logic is pretty complicated :) In the ComposeFrame you have a for loop which goes through all the enemies and checks if they`re alive and their health is 0. But both of your boxes fulfill this condition. So you execute twice the DrawCircle and increase the explosionindex two times per frame.
One other thing there I think could be better is use nested if statements. You check twice if enemybox is alive so you could do

Code: Select all

if(alive)
{
    if(health >0)
   {
       // draw enemy
   }
   else
   {
       // draw explosion
   }
}
Im not sure if I understand your last question. Seems like you make function foo(Box a, Box b) and than try to access your array of Boxes in the game. Maybe you could post the code.


Edit: My explanation pretty on the explosion was pretty awful xD Ill try to put an example.
So lets say you have 5 enemies and 1 and 3 collide. Your for loop does the following
index 0 -> draw box
index 1 -> drawCircle and explosionIndex = 1
index 2 -> draws box
index 3 -> drawCircle and explosionIndex = 2
index 4 -> draws box
than draw frame
.
.
.
index 0 -> draw box
index 1 -> drawCircle and explosionIndex = 24
index 2 -> draws box
// now ( ExplosionIndex < EXPLOSIONRANGE ) is false so
index 3 -> EnemyBox[ 3 ].IsAlive = false and ExplosionIndex = 0
index 4 -> draws box
draw frame
and this is where the bug is hidden. Because EnemyBox[ 1 ].IsAlive is still true and its health is still 0
it goes on like this
index 0 -> draw box
index 1 -> drawCircle and explosionIndex = 1
.
.
.
and draws once more explosion.

And another way of doing the iteration of the two for loops without bothering if you compare the object to itself is

Code: Select all

    for (int i = 0; i < nEnemyBox - 1; i++)
        for (int z = i + 1; z  < nEnemyBox; z++)
            // comparison

Clodi
Posts: 175
Joined: November 18th, 2012, 7:47 pm

Re: 5.00 a.m. and still programing! I need serious help.

Post by Clodi » December 19th, 2012, 2:21 pm

fuck sake!!!!!

Indus, thank you sooooooooo000oo00ooo much, you found the bug!!!
yes, you are perfectly right, I just checked with the debugger. I would have never found it without your help :D
I was already accepting that bug as an 'unwanted mandatory feature' haunting my little game :)

Thank you so much for your comments on my game and the answers to all other questions.. I was hoping to maybe get a couple of them answered or so.. but you nailed all of them.

I also forgot the do/while and while/do difference. I mean, I know it, but I never thought of a situation where you have to use one and not the other. Now it seems like I just stumped into one.

I look forward to understand (really understand) pointers and classes to start getting serious. :)

Again, thank you very much.

Zionich
Posts: 24
Joined: December 11th, 2012, 12:57 am

Re: 5.00 a.m. and still programing! I need serious help.

Post by Zionich » December 19th, 2012, 6:05 pm

Wow, love the comments in your code. I could learn from that detail =)

Game is awesome. I love the explosions.

Clodi
Posts: 175
Joined: November 18th, 2012, 7:47 pm

Re: 5.00 a.m. and still programing! I need serious help.

Post by Clodi » December 19th, 2012, 8:13 pm

Thanks Zionich :)
..you'll see, I'll make it look even prettier :D

Clodi
Posts: 175
Joined: November 18th, 2012, 7:47 pm

Re: 5.00 a.m. and still programing! I need serious help.

Post by Clodi » December 20th, 2012, 4:14 pm

Thanks again Indus,

All fixed now :D (surprisingly enough.. it took me a while..)

JerryTheBig
Posts: 33
Joined: July 27th, 2012, 12:48 pm

Re: 5.00 a.m. and still programing! I need serious help.

Post by JerryTheBig » December 20th, 2012, 6:36 pm

Post your new code please. It is really good stuff to learn new problem solution. Thanks

Clodi
Posts: 175
Joined: November 18th, 2012, 7:47 pm

Re: 5.00 a.m. and still programing! I need serious help.

Post by Clodi » December 21st, 2012, 8:01 pm

Sure!

All right. If you played my little game you know the drill already. You are a little square and whilst fetching your target, other squares (enemies) are in the way to hit you and kill you. The point is that I wanted to make the game look a bit more fancy and therefore decided to make enemies collide with each other as well as with the target and player.

The effect of two colliding enemies would be an explosion.
My explosion is a circle being drawn on screen with radius 0.
The Radius grows at 1 Pixel per Frame up to 20.

The explosion was something like..

Code: Select all

if ( Index < 20 )
{
gfx.DrawCircle( x,y,Index,255,255,255 );
Index ++;
}
So, my code was something like:

Code: Select all

	//loop through all enemies enemies
	for ( int index = 0; index < nEnemyBox; index++ )
		{
			//search for ALIVE enemies
			if ( EnemyBox[ index ].IsAlive == true )
			{
				//only draw enemies with some health left
				if ( EnemyBox[ index ].health > 0 )
				{
					gfx.DrawBox( EnemyBox[ index ].x,EnemyBox[ index ].y,EnemyBox[ index ].size,EnemyBox[ index ].Red,EnemyBox[ index ].Green,EnemyBox[ index ].Blue );
				}

				//make explosion
				else if ( Index < EXPLOSIONRANGE )
				{
					gfx.DrawCircle( ( EnemyBox[ index ].x + ( EnemyBox[ index ].size / 2 ) ),( EnemyBox[ index ].y + ( EnemyBox[ index ].size / 2 ) ),SecondGuyExplosionIndex,255,255,255 );
					ExplosionIndex ++;
				}

				//after explosion, resets counters and KILL enemy
				else
				{
                                        ExplosionIndex = 0;
				}
			}
	    }
Explosions did not work out well at all and Indus just found out why.
The enemies are revived once at a time but they die in couples!! an enemy can't magically disappear and collide with himself. So, when the two happy guys enter their loop, they 'share' the explosion counter.
'ExplosionIndex' increases two times per frame, and this gives extra speed to what's happening.
Two explosion with radius increasing 2 pixels per frame (instead of 1) is what we get.

Now, if this was the only issue I would have never realised that the code was wrong and Indus wouldn't have looked at my code and I would still have the bug. The major bug is that there is a third explosion occurring. It happens because of the shit idea of making the two guys share the counter and because of how incredibly complicated and intrinsically wrong my logic is.

When the 2 guys collide, they enter the explosion loop.
The first one grows the counter to 1, the second one to 2, etc..
The loop runs all the way about 20 times..
The first one grows the counter to 19, the second one to 20..
20 is NOT lower than 20 so the first colliding guy exits the loop AND RESETS the counter.
..Therefore the second guy will explode again (this time at 1 per frame :D)

Now, since I am not smart but rather stupid, I didn't find a proper solution, but a decent one.
My solution is: when two guys collide, I remember their index and then I make two different explosions for each of them (getting rid of all of that crappy Alive-AlmostAlive-Dead logic thing..)

Now the code is:

Code: Select all

//loop through all enemies enemies
	for ( int index = 0; index < nEnemyBox; index++ )
		{
			//search for ALIVE enemies
			if ( EnemyBox[ index ].IsAlive == true )
			{
				//only draw enemies with some health left
				if ( EnemyBox[ index ].health > 0 )
				{
					gfx.DrawBox( EnemyBox[ index ].x,EnemyBox[ index ].y,EnemyBox[ index ].size,EnemyBox[ index ].Red,EnemyBox[ index ].Green,EnemyBox[ index ].Blue );
				}

				//make the first collider explode
				else if ( index == FirstGuyColliding && FirstGuyExplosionIndex < EXPLOSIONRANGE )
				{
					gfx.DrawCircle( ( EnemyBox[ index ].x + ( EnemyBox[ index ].size / 2 ) ),( EnemyBox[ index ].y + ( EnemyBox[ index ].size / 2 ) ),FirstGuyExplosionIndex,255,255,255 );
					FirstGuyExplosionIndex ++;
				}

				//make the second colliding enemy explde
				else if ( index == SecondGuyColliding && SecondGuyExplosionIndex < EXPLOSIONRANGE )
				{
					gfx.DrawCircle( ( EnemyBox[ index ].x + ( EnemyBox[ index ].size / 2 ) ),( EnemyBox[ index ].y + ( EnemyBox[ index ].size / 2 ) ),SecondGuyExplosionIndex,255,255,255 );
					SecondGuyExplosionIndex ++;
				}

				//after explosion, resets counters and KILL enemy
				else
				{
					FirstGuyColliding = NENEMYBOX + 1;
					SecondGuyColliding = NENEMYBOX + 1;
					FirstGuyExplosionIndex = 0;
					SecondGuyExplosionIndex = 0;
					EnemyBox[ index ].IsAlive = false;
				}
			}
	    }
The code works nicely and it looks nicer too.
I lose that bug and I lose that Alive-AlmostAlive-Dead thing. The problem is that there is another minor bug but it's not worth any of my time. (I spent about a day designing this explosion thing)
It's so irrelevant that if you play the game and I don't tell you that there is a bug, you are very much likely not to spot it.
In the occurrence of multiple collisions at the same time (or within 20/mylaptopframepersec seconds)
the first collision will show up and properly, the others will be completely ignored.
In fact I suck at coding! :mrgreen:
No.. seriously.. it's still not perfect but it works.

Post Reply