Jump to content

Photo

No Name Yet -- CD'awgs Non-ZC Temporary Dev Log

C++

  • Please log in to reply
101 replies to this topic

#31 Anarchy_Balsac

Anarchy_Balsac

    Quest Builder

  • Members

Posted 11 October 2015 - 10:34 PM

Having the spawn function inside of doodad is asking for trouble.  It may or may not be causing the position problem, but is there a reason that you need it to be within doodad?  Or can you make do with it being external?  External is better if you can do that.  It could be what's causing the problem, but even if it's not, it can easily cause others.  You're basically having objects spawn themselves, when it is much better to have something else spawn them.



#32 C-Dawg

C-Dawg

    Magus

  • Members

Posted 11 October 2015 - 10:39 PM

How so?  I mean, I call it "Spawn," but what really is going on is I have a generic "Init" function in GameObject.h and I wanted a way to initalize with additional data for specific kinds of gameobjects (enemies, items, doodads, etc).  So Spawn is like "Init Plus."  The GameObjectManager actually creates the new Doodad, then it calls the Spawn() function so that Doodad arranges itself.  Since different Doodads will do different things, each will have its own peculiar way of arranging its affairs when it is given a "Spawn" function.  Seems like I'd put that method in each type of GameObject, yes?

 

EDIT: Fixed another issue; since GetX was returning a float, my trace prints were screwed up.  Fixed that, and they look OK.  But it's not spawning where it should be.  Hm..


Edited by C-Dawg, 11 October 2015 - 10:43 PM.


#33 Anarchy_Balsac

Anarchy_Balsac

    Quest Builder

  • Members

Posted 11 October 2015 - 10:49 PM

How so?  I mean, I call it "Spawn," but what really is going on is I have a generic "Init" function in GameObject.h and I wanted a way to initalize with additional data for specific kinds of gameobjects (enemies, items, doodads, etc).  So Spawn is like "Init Plus."  The GameObjectManager actually creates the new Doodad, then it calls the Spawn() function so that Doodad arranges itself.  Since different Doodads will do different things, each will have its own peculiar way of arranging its affairs when it is given a "Spawn" function.  Seems like I'd put that method in each type of GameObject, yes?

 

EDIT: Fixed another issue; since GetX was returning a float, my trace prints were screwed up.  Fixed that, and they look OK.  But it's not spawning where it should be.  Hm..

 

Ah, but THAT'S the problem right there.  They are ALREADY spawned at 0,0 before the spawn function is called.  Try modifying velX and velY for a single frame, THAT should adjust their position to where you need them.



#34 C-Dawg

C-Dawg

    Magus

  • Members

Posted 11 October 2015 - 10:51 PM

But... there's no frame in between being instantiated and the call to Spawn().  The GameObjectManager does both in the same few lines of code...



#35 Anarchy_Balsac

Anarchy_Balsac

    Quest Builder

  • Members

Posted 11 October 2015 - 11:03 PM

But... there's no frame in between being instantiated and the call to Spawn().  The GameObjectManager does both in the same few lines of code...

 

Frame, microsecond, whatever terminology you wish to use.  Just have something that reads in the position, and modifies velX and velY accordingly until it reaches said position.

 

If their moving, velX and velY should be working, so I figure this is an easy workaround.  Of course, you'll have to store the speeds in temporary variables and add in a boolean flag for this to work, but it should go something like this:

if (doodad.positioning == false)
{
  if (doodad.getPositionX() < x)
  {
    velX = 512;
  }
  else if (doodad.getPositionX() > x)
  {
    velX = -512;
  }
  else
  {
    velX = 0;
  }
  if (doodad.getPositionY() < y)
  {
    velY = 512;
  }
  else if (doodad.getPositionY() > y)
  {
    velY = -512;
  }
  else
  {
    velY = 0;
  }
  if ((doodad.getPositionX() == x) && (doodad.getPositionY() == y))
  {
    doodad.positioning = true;
    velX = trueXSpeed;
    velY = trueYSpeed;
  }
}


#36 C-Dawg

C-Dawg

    Magus

  • Members

Posted 11 October 2015 - 11:04 PM

How is that different from just setting X and Y directly initially?



#37 Anarchy_Balsac

Anarchy_Balsac

    Quest Builder

  • Members

Posted 11 October 2015 - 11:08 PM

How is that different from just setting X and Y directly initially?

 

Well, since the x and y you're setting aren't working as intended, but velX and velY are, I say the workaround is worth trying, it's what I'd do.  If it still doesn't work, then you've got an even more serious problem than it seems.



#38 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 11 October 2015 - 11:17 PM

You fixed the int/float thing, but it's still wrong immediately after setting it? Could there be a shadowing issue, perhaps? I don't see where, but you're setting x and tracing GameObject::x, so maybe. You could try checking the address of both x and GameObject::x and make sure they're the same.

Side note:
        setup_bitmap = al_create_bitmap(64,64);
        al_set_target_bitmap(setup_bitmap);
        al_clear_to_color(al_map_rgb(255, 0, 255));
        setup_bitmap = al_load_bitmap("MarsFloatingPlatform.png");
That's a memory leak. There's no need to create a bitmap before loading the image.

#39 C-Dawg

C-Dawg

    Magus

  • Members

Posted 11 October 2015 - 11:33 PM

If I use the al_create_bitmap and then assign the setup_bitmap to something else, does it leave the original creation behind?



#40 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 11 October 2015 - 11:46 PM

Yes, it does. The bitmap is heap allocated (i.e. al_create_bitmap() uses malloc() internally), so you have to explicitly delete it. Once you lose the pointer, there's no way to do that. In this case, you should be able to use al_get_target_bitmap() to get it back, but I don't expect you're doing that.
It's possible Allegro keeps a list and will clean up automatically, but you still wouldn't want to leave unused objects lying around.

#41 Gleeok

Gleeok

    It's dangerous to dough alone, bake this.

  • Members
  • Real Name:Pillsbury
  • Location:Magical Land of Dough

Posted 12 October 2015 - 12:29 AM

It's worse than a memory leak because the gpu might have to start paging texture memory, or whatever they do.

        setup_bitmap = al_create_bitmap(64,64);
        al_set_target_bitmap(setup_bitmap);
        al_clear_to_color(al_map_rgb(255, 0, 255));
        setup_bitmap = al_load_bitmap("MarsFloatingPlatform.png");

Should just be:

        setup_bitmap = al_load_bitmap("MarsFloatingPlatform.png");
        assert(setup_bitmap);
This is actually a double leak. If you fix the first leak, then months from now you'll soon realize it still leaks!
You might even want to just throw together a function that loads bitmaps.

ALLEGRO_BITMAP* LoadBitmap(const char* filename)
{
        if(already loaded somewhere)
            return existing_bitmap;

        ALLEGRO_BITMAP* bitmap = al_load_bitmap(filename);
        assert(bitmap);

        return bitmap;
}
Also, usually velocity is a float when a position is a float. Sort of strange they are not.

Set a breakpoint right before you setup your doodad, then press F11 to step through the code one line at a time. Bring up the 'this' object in the watch list and you can debug where things are going wrong.

#42 C-Dawg

C-Dawg

    Magus

  • Members

Posted 12 October 2015 - 02:40 PM

Got it all worked out.  Problem was more with the logic of the moving pattern than anything else; my use of %f instead of %d was pointing me the ass-wrong direction.

 

I have velX and velY as floats because integer math appears to be useless for smooth movement.  Also, I discovered you want to have velX and velY actually just be speed, and then move in a direction defined by dirX and dirY.  Basically, THIS gives me movement I want:

 

x =+ velX * dirX;

y =+ velY * dirY;

// Friction

velX = velX/2;

 

Whereas THIS gives me different movement depending on whether I'm going left or right
 

x =+ velX;  // assuming negative velX for left

y =+ velY;  // assuming negative velY for up

// Friction

velX = velX/2;

 

It was really freaking weird.  I assume C++ does something strange with division of negatives or something, but whatever.

 

I also removed the al_new_bitmap calls that were not necessary.  But, Gleeok, when you say it's a double-leak... what do you mean?  I always use the destructor function to clean up the sprite's loaded .png file when Im done using it; is that what you're talking about?


Edited by C-Dawg, 12 October 2015 - 02:42 PM.


#43 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 12 October 2015 - 03:03 PM

Probably an integer truncation thing. That can be tricky sometimes.
int x=5, y=5;
x+=1.5; // x==6
y-=1.5; // y==3

As for %f/%d in printf(), perhaps you already know this, but I'll explain just in case. Normally, different numeric types are more or less interchangeable because of implicit casting. If you pass an int to a function that takes a float, the compiler will insert the code to convert it. That's not the case with variadic functions, because their arguments aren't explicitly typed. The compiler has no way of knowing what to cast to, so arguments are passed in exactly as you give them. So if you give printf() an int for %f, it will interpret the value incorrectly, and the number it prints will be basically meaningless.

#44 Gleeok

Gleeok

    It's dangerous to dough alone, bake this.

  • Members
  • Real Name:Pillsbury
  • Location:Magical Land of Dough

Posted 12 October 2015 - 06:47 PM

I'd still recommend stepping through the debugger for the 'the next bug' though. Eventually you're going to get a real nasty bug (will always happen at least once) and you'll need the practice! :P

x =+ velX * dirX;
y =+ velY * dirY;


Do you mean:

x += velX * dirX;
y += velY * dirY;
?


I also removed the al_new_bitmap calls that were not necessary.&nbsp; But, Gleeok, when you say it's a double-leak... what do you mean?&nbsp; I always use the destructor function to clean up the sprite's loaded .png file when Im done using it; is that what you're talking about?


That's actually a good question. The answer is something every game programmer should know, but sadly does not.

Every time you re-load a resource, such as a bitmap, that is already loaded in memory, I'd say that qualifies as a severe memory bug. Also, what you'll find out eventually anyway is that you can just throw these sprites into a spritesheet and suddenly you will have very few bitmaps to load compared to having hundreds or thousands of them; I'll just cut to the end and tell you that the performance increase of avoiding needless state changes for every draw call on a gpu is at least a factor of 10x!

#45 C-Dawg

C-Dawg

    Magus

  • Members

Posted 12 October 2015 - 10:31 PM

Ah, so you're saying instead of making a new bitmap pointer for every game object -- every enemy and item grabs a .png from memory when it loads up -- just do what ZeldaClassic does and have a single spritesheet where EVERYTHING goes draw a small section of it to the screen when it needs to, huh?  That does sound faster, but it also sounds tricky; every object in the game will need access to that single bitmap object!  I dunno how to accomplish that.

 

 

 

As for %f/%d in printf(), perhaps you already know this, but I'll explain just in case. Normally, different numeric types are more or less interchangeable because of implicit casting. If you pass an int to a function that takes a float, the compiler will insert the code to convert it. That's not the case with variadic functions, because their arguments aren't explicitly typed. The compiler has no way of knowing what to cast to, so arguments are passed in exactly as you give them. So if you give printf() an int for %f, it will interpret the value incorrectly, and the number it prints will be basically meaningless.

 

 

You may safely assume I don't know much of anything yet!  I figure I need to be screwing around with the basic engine for a least six months / year before I have enough accumulated knowledge under my belt to actually start making the game in earnest.

 

So I got the moving platforms working.... kinda.  I have trouble with the player falling through them sometimes and falling off when it changes direction from downward movement to upwards movement always.  But, that's just logic issues to noodle through.  Will work on it more tomorrow.  Once I get the items squared away, I'll look into that spritesheet idea.  Assuming I can learn how to make a "global spritesheet" or whatever that all objects can see.

 

I think, initially, I won't make spritesheets as a single file because I like the freedom of making each enemy / item / whatever it's own .png for animations.  But I could make an object that holds and deploys all sprites rather than making new bmp objects in every GameObject that gets born, so that should still work out okay.


Edited by C-Dawg, 12 October 2015 - 10:36 PM.




Also tagged with one or more of these keywords: C++

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users