• Advertisement

Archived

This topic is now archived and is closed to further replies.

what to do when.... (things go bad)

This topic is 5001 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

high, last night i decided to completely re-vamp my engine. basically, making every one of my classes inherit from a "world" class, so that i could group everything togeather nice and neat. anyway, everything worked great. except, for some VERY strange reason, only one of my enemies will fire his gun. i dont know why, its very weird. theres 3 enemies on the map, and only 1 is shooting... the other 2 enemies will still chase me, but wont shoot. i step through my code, and it looks exactly the same when a broken enemy is shooting and when the enemy that shoots is shooting.. anyway, should i sit here, tareing out my hair for possibly all night and into the next day, trying to figure out what the problem is? OR, should i roll back to the old code (only from last night but still hours worth of work).. what do you think? i mean, i hate not understanding how bugs work, you know? just wondering if i should stick it out and try to find out WHY this is happening, or should i roll back, and slowly add things making sure everything works (this could also turn up WHY..) thanks for advise!

Share this post


Link to post
Share on other sites
Advertisement
yeah, roll back and slowly add things up till everything works. maybe you missed a few classes and some of them don''t inherit from world? you could also windiff the files and see what exactly you changed and try to work out the effects of the changes.

good luck
VStrider.

Share this post


Link to post
Share on other sites
I''d go for a walk and maybe start thinking about dinner.

Failing that, when I make massive overhauls like that, I just put print statements everywhere, starting from the beginning. Put them in constructors too to make sure everybody gets built right, and put them in your Update()s as well.

Share this post


Link to post
Share on other sites
Forget about it. You'll solve the problem easily if you just leave it for a day and make sure NOT to think about it in any of your spare time.

Just make sure you understand your new architecture, and your subconsious will solve the problem for you.

[edited by - twix on June 8, 2004 8:16:53 PM]

Share this post


Link to post
Share on other sites
Mnh, it depends on you.

I have these kind of problems, and I solve it reading the old code and the new.
The most common cause of these kind of bugs are pointers to wrong code.
if I where you, Ill check my code and learn what Im doing wrong.

Share this post


Link to post
Share on other sites
Everything inherits from a "world" class?

That sounds like a very bad design that is going to bite you real hard down the line. Does the statement, "the player is a world," make sense? It could even be the source of the problem you''re describing, in some way or another.

Share this post


Link to post
Share on other sites
quote:
Original post by jpetrie
Everything inherits from a "world" class?

That sounds like a very bad design that is going to bite you real hard down the line. Does the statement, "the player is a world," make sense? It could even be the source of the problem you''re describing, in some way or another.

nahh, he''s probably just using an abstract class so he can upcast different classes. doesn''t really matter if he''s calling the class "world" or "object" or "myabstractclassthatdoesnothing".

VStrider.

Share this post


Link to post
Share on other sites
yes im using c++ and yes its just a ABC that does nothing by itself... i dont consider my player to be a world... but i do consider my player to be a world_update() object..

anyway, this is really pissing me off. if i step through my code, walking near an enemy that *should* be fireing his gun at me, it will get to this line

weapon.Fire();

the yellow arrow will point to this line in the debugger (MS.net) telling me this code should be executed.. however, it will never go inside this function. the line gets to this function, then skips over it, continueing on.

if i move toward the enemy that actually IS fireing at me, the same thing will happen... the red dot will reach the line of code, only right after, it will actualyl go inside this function and fire the bullet (theres breakpoints inside the function.. so i can see that its going through with the working enemy, but never going through with the ''broken'' one)..

does anyone know why this could be? why would it skip over these lines of code? everything else is fine, hes chasing me, colliding with walls, but he wont fire his gun, it just gets to that line and keeps going.. and why would one of the enemies work? i do the exact same thing to all of them and they are all created dynamically... i dunno, maybe someone spots something obvious? thanks for any help!

Share this post


Link to post
Share on other sites
quote:
Original post by jpetrie
Everything inherits from a "world" class?



Maybe it''s a solipsist kinda game.

Share this post


Link to post
Share on other sites
Hi,

can you manually step into weapon.Fire(), set a break point at this location and press F11. Where does this lead to, does it lead to your code or some assembly window, or nothing happens.

If it leads to a assembly window, or nothing happens try a full rebuild. Maybe you changed structures, classes that didn''t got rebuild. If it then still doesn''t work you probably have a memory problem you are overwriting memory somewhere in your code with the result of not getting to the code it should be going to.



Share this post


Link to post
Share on other sites
hey richy,

turns out i actually WAS getting into the functions on all the enemies. for some very weird reason an if statement is always returning false... this is an if statement inside of weapon.Fire()... for the enemy that isnt broken, when i get to weapon.Fire(), it gets to this if statement, then it executes the block of code in the statement (which is what fires the gun)... for the broken enemies, it gets to this if statement, but somehow it must return false because its skipping the block of code, and the bullet is never fired. i tried stripping down the if statement to bare bones, only checking if the target is valid. it would still only work on the one enemy, and not on the others. i even did this:

if(current_target)
{
shoot bullet
}
else current_target = player;

where current_target and player are both pointers to a Character*...

this just doesnt make sence, i mean if its not valid, i make it valid, yet someone the code is still never executed... what makes no sence is why the one enemy is working perfectly, yet the other 2 are broken.. so weird... thanks for anymore help (again these enemies are all treated exactly the same..)

ps - does anyone else get weird effects when running the debugger? like, if im stepping through code, when i return to the game, my enemies will have zoomed off somewhere, very weird, one even got into a wall somehow.. anyone experiance this? thanks for any help!!

[edited by - graveyard filla on June 9, 2004 4:19:52 AM]

Share this post


Link to post
Share on other sites
quote:
ps - does anyone else get weird effects when running the debugger? like, if im stepping through code, when i return to the game, my enemies will have zoomed off somewhere, very weird, one even got into a wall somehow.. anyone experiance this? thanks for any help!!



That''s maybe due to your timing. Suppose you have a function like player.updatePos(deltaT) with deltaT = currentTime - lastTime. Normally, this func will be called every 5 msecs or so, but if you spend a minute in the debugger, deltaT will end up at 60005, which will probably cause all sorts of weird effects in your updatePos function.

Concerning your error, i would go tracing the "currentTarget" variable and check why its NULL for all enemies except one.

Share this post


Link to post
Share on other sites
You''re most likely using a time-based updating system.

When you''re debugging the delta between the current frame will be really big ( a couple of seconds), instead of the usual ~1/60 second, and all game objects will behave badly, especially ones linked to physics.

The easy solution to this is to cap the maximum time-delta at something sensible (1/4 second usually works okay, since you''ll never be seeing 4 fps anyway).

Good luck.

Odin

Share this post


Link to post
Share on other sites
The debugger has a very useful feature called "Watch". This allows use to study the contents of a variable, including whenever it changes (obviously the pointer is being reset somewhere, or is never set in the first place).

Zorx (a Puzzle Bobble clone)
Discontinuity (an animation system for POV-Ray)

Share this post


Link to post
Share on other sites
Did it always work, or did you change code (anywhere)?

Anyway, find all the places where current_target gets a value assigned to it, is there ever an NULL assignment if so then you have found your problem! if not then i bet you have a memory problem. If weird/unexplanable stuff happens it almost always is a memory issue.

to quick check (not garanteed to work, but worth a go ), add an array to your class in front of the current_target, make it big. Now does it work correctly or are there other weird things! if so you have memory issues.

Share this post


Link to post
Share on other sites
You may have unintentionally created some sort of diamond inhertience. Basicly, its when you have the same class inherited twice. Does your code implement something like this?


class A
{};

class B : A
{};

class C : A
{};

class D : B, C
{};


--------------------------------------------------------------------------------
[C++ Reference | Java API | SDL Home Page | Lua Scripting Language | Python Scripting Language |
Chris Taylor''s Design Document (Downloadabe MS-Word Only) | Blitz Basic Homepage ]

Share this post


Link to post
Share on other sites
perhaps you've made one of the variables in your enemy or weapon class static... then it would be valid for one enemy (the last one visited when iterating) but not the others.

I don't know what your code looks like so this is a shot in the dark. But when only one object works and the others have the same functionality, my first guess is that it has something to do with a static variable since there's only one shared between all of the instantiated objects.

Good luck fixing it


[edited by - void* on June 9, 2004 11:36:05 AM]

Share this post


Link to post
Share on other sites
this bug is really weird and its starting to piss me off... my enemy has a member called Character *current_target, also the weapon itself has a *current_target too so obviously they should both have the same one at all times (hmm.. maybe use a const** for this?)... player is my global player object (its a pointer, and Player inherits from Character)..lets say i do this:

current_weapon->Set_Target(current_target);
current_weapon->Fire();

when it gets into Fire(), current_target will be null and a bullet wont be fired..

now, if i do this:

current_weapon->Set_Target(player);
current_weapon->Fire();

it fires! because of course player is definetly a valid pointer...

ok, so does anyone know how this is happening? i dont set Enemy::current_target to NULL ANYWHERE... in the Enemy constructor, copy constructor, and assignment operator, i do this:

current_target = player;

so how could this be possible? if i never set it to NULL, why is it NULL? heres how i create the objects (inside my map classes constructor)


else if(current_map[y][x]->flags & ENEMY)
{
Enemy *e = new Enemy();
e->Set_X(x*TILESIZE);
e->Set_Y(y*TILESIZE);

enemy_list.push_back(e);
World_Update::Register(e,0);

}


does anyone see anything wrong with this? i dont understand how it gets set to NULL without me telling it to, and why is it not null for ONE of the enemies? like i said, i only set current_target to = player and i do that in all the proper constructors... also, im using MS.net 2k3 and im compiling in Release mode... thanks for any help!

ps - no, there is no static members to enemy (well, i just added one, but it shouldnt effect this, and not to mention i had the problem before i added this static member)

also, im not doing any diamond inheritense. but thanks for mentioning it i will make sure not to do that.

[edited by - graveyard filla on June 10, 2004 3:27:23 AM]

[edited by - graveyard filla on June 10, 2004 3:28:22 AM]

[edited by - graveyard filla on June 10, 2004 4:44:40 AM]

Share this post


Link to post
Share on other sites
I would check that the current_target pointer is intially set for a single frame update for a single enemy. Assuming that the pointer is intially set i would then do a search across all the areas that alter this pointer, and put break points at each one to make sure they are doing what you think they are.. On top of that I would place a watch on the pointer, incase you miss any! Unfortually, as i''m sure you know, the only way to get these little gits is a thorough logical walkthrough of the code examining the areas of interest.

Matt

Share this post


Link to post
Share on other sites
well, it took 3 f'ing days, but i finnally found the little bastard .. i *think* i know what is happening, but i dont understand why . im hoping someone here could explain, its probably something simple, maybe i dont understand pointers enough, so please let me know:

i have a global pointer to a player object. this is my player. the reason hes a pointer, is because his constructor uses another global object inside it, so i just make all my global objects pointers and call new so i can give their instantiation order myself...

anyway, i have this global pointer to my player object. now, i have another global object of type Map, called map_data. then, i do this in the begining of my main:


map_data = new Map();


inside of the Map constructor, while reading in the map file current_map


if(current_map[y][x]->flags & PLAYER)
{
player = new Player();
player->Set_X(x*TILESIZE);
player->Set_Y(y*TILESIZE);

World_Update::Register(player,0);
}
else if(current_map[y][x]->flags & ENEMY)
{
Enemy *e = new Enemy();
e->Set_X(x*TILESIZE);
e->Set_Y(y*TILESIZE);


World_Update::Register(e,0);

}


basically, as im reading in each individual tile's data, if one of the flags is PLAYER, i create my player, set his position to this spot, and register him to the world.

i do the same exact thing when i find an enemy.


now, heres what happends:

my map looks something like this (E is an enemy, P is the player):

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx E xxxx
xxxx E xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxx P xxxxxxxxxxx
xxxxxxxxxxx E xxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

now, the enemy thats on the bottom of the map is the one who's working, ie, his current_target is validly pointing to the player. i read in the map from the top left corner, to the bottom right corner. so basically, it does this: (remember, inside the constructor to Enemy(), i do current_target = player; current_target is a member of Enemy and is of type Player*)

make a new enemy put him in the top right part of map
make a new enemy put him on upper left side of map
make a new player, put him in the middle
make a new enemy, put him on the bottom

inside of the constructor to Enemy(), i do this:

current_target = player;

remember, player is a a global pointer. so when the first 2 enemies are created, their current_target will = this player pointer which is pointing to garbage, then i make the player - his pointer is now valid. now, i make another enemy, this time his constructor initializes his current_target to the valid player pointer. hence, the bottom guy can shoot me, but the top guys cant.

why though? shouldnt the first 2 pointers be valid, i mean, Player *player shouldnt change, should it? maybe WHAT its pointing to will change, but when i say

current_target = player;

doesnt this mean "the address current_target stores will now = the address that player stores", when i call new, why would this change? wouldnt only the object thats stored at this address change? im just a little confused, someone please enlighten me. thanks

[edited by - graveyard filla on June 11, 2004 1:46:39 AM]

btw- its easily fixed by allocating the player before i allocate the map, and dont do any player allocating inside map - in fact this makes more sence anyway since when i load in another maps, i want to keep my player, ya know?

[edited by - graveyard filla on June 11, 2004 1:47:27 AM]

[edited by - graveyard filla on June 11, 2004 1:51:03 AM]

Share this post


Link to post
Share on other sites
I''m not sure exactly what you are doing but I''ll guess:
If you do:

// setup 1st enemy
enemy[0].target = player;

free(player);
player = malloc(sizeof(player));

initPlayer();

// setup second enemy
enemy[1].target = player;

enemy[0].target will (probably) no longer point to the player.

Either avoid deallocating the player or use handles - pointers to
pointers.

enemy[0].target = handletoplayer;

// reinit player
free(player);
player = malloc(sizeof(player));
initPlayer;

handletoplayer = player;

enemy[1].target = handletoplayer;

Share this post


Link to post
Share on other sites
thanks lucid, but could anyone explain to me why my game is doing what its doing? for those who dont want to read the post, heres a small example on what im doing:


int *some_int;
int *another_int;

another_int = some_int;

cout<< another_int // prints out memory address

some_int = new int;

cout<< another_int // prints out a DIFFERENT memory address? either way, another_int is NO LONGER VALDID?


so you see what im doing? originally another_int will point to another pointer (so they are both pointing to garbage)

then, i allocate memory for some_int. now another_int is no longer valid? i have to do another_int = some_int again? why? thanks for any help

Share this post


Link to post
Share on other sites
quote:
Original post by graveyard filla
thanks lucid, but could anyone explain to me why my game is doing what its doing? for those who dont want to read the post, heres a small example on what im doing:


int *some_int;
int *another_int;

another_int = some_int;

cout<< another_int // prints out memory address

some_int = new int;

cout<< another_int // prints out a DIFFERENT memory address? either way, another_int is NO LONGER VALDID?


so you see what im doing? originally another_int will point to another pointer (so they are both pointing to garbage)

then, i allocate memory for some_int. now another_int is no longer valid? i have to do another_int = some_int again? why? thanks for any help


Not exactly. Originally another_int will point to garbage, *not* to another pointer. another_int should never be 'valid'.

similarly:

int x,y;

x=y;
y=2;


Does x now equal 2? Same thing with pointers.

a trick though:

int *x, **y;

x=new int;
y=&x;
*x=2;
cout << **y << "\n";
*x=4;
cout << **y << "\n";

(output):
2
4

Using a pointer to a pointer, you now have something that "follows it around". Assigning a pointer to another pointer does not make a pointer to a pointer, it just *copies* the memory adress once, just like x=y *copies* the value of y into x in the first example.

[edited by - Telastyn on June 11, 2004 3:55:19 PM]

Share this post


Link to post
Share on other sites
"Impossible bugs"...

I would try:
-erase object code and compiled code, then rebuild all
-Empty your debuggers "watch" windows. That execute code, mind you.

Then, just watch the pointer''s memory adress to see when it change. Possible reasons include bad casting and out of bounds array...

Share this post


Link to post
Share on other sites

  • Advertisement