Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411424 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 19, 2024, 07:26:35 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)I need an adult. SDL and C++
Pages: [1] 2
Print
Author Topic: I need an adult. SDL and C++  (Read 7973 times)
___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« on: June 19, 2008, 02:20:33 PM »

HELLO.

I am trying to learn "programming" after years of using Multimedia Fusion and other Clickteam products.

I have an issue, that I wish to address to any "uber pros" out there that maybe can help.  I only have moderate experience with C++, and I've just been trying to follow Lazy Foo tutorials for SDL. (http://lazyfoo.net/SDL_tutorials/index.php)

I have a class named "ActiveObject" (just like MMF!) and then I have this class named "Frame"  The plan was to have Frame manage a vector of ActiveObjects, and then have a bunch of classes that are children of ActiveObject, so then everything is happy and works out or something.

So, heres my current source code: the main file, active object, frame.

So when I try to add objects to the vector of Frame, and then call Frame's draw() function, nothing works.  SDL appears for a fraction of a second, then dies.  However, if I made a vector just in my main program, do push_back() with an active object that I created, and then loop through the vector calling render for each element, it works.

I tried to do some debugging but uhh ... yeah I dont know how to fix this.  Something gets incredibly screwy when I add an object to the vector of Frame, and then try to render it.  It specifically points to this line in ActiveObject, I think:

Code:
clip.x = _w * ( (_animations[_currentAnimation]._currentFrame + _animations[_currentAnimation]._startCell ) % (_sprites->w / _w) );

The _sprites->w should be the width of the file loaded in, which is 64.  I made it print out the width and height every time it renders, but when I render it with the draw function from Frame, it gives me 18 x 34 which is... not correct at all.

When I check it after just using the render() function in main though, it prints out 64 x 64, which is correct, and the program doesn't crash.  I dont really know whats going on, or if I explained it enough, but I've been trying to get this to work for awhile now and I just think that its beyond my C++ knowledge... so if there are any tips (besides "Hey why are you using C++?  You should use ___" and "Hey, why are you using SDL?  You should use ___") I would be eternally grateful.

PEACE OUT!
Logged
ColossusEntertainment
Level 1
*

Royal Leamington Spa, UK


View Profile
« Reply #1 on: June 19, 2008, 10:09:54 PM »

First of all: Hey, why are you using SDL?  You should use the Pixie Game Engine  Gentleman

But, here's the thing... you know in your constructor ActiveObject::ActiveObject method, you do:
       SDL_Surface* loadedImage = NULL;
       loadedImage = IMG_Load( filename );
       _sprites = SDL_DisplayFormatAlpha( loadedImage );                   

and in the destructor, ActiveObject::~ActiveObject, you do:
      SDL_FreeSurface(_sprites);

This means that every time an ActiveObject is created, you create a new SDL_Surface object somewhere in the memory, and you store the memory address of that object in the _sprites variable. When the object is destroyed, you tell SDL to destroy that object. This means that the memory address we are storing is no longer valid. But that's ok, because the whole ActiveObject is being destroyed, so we won't be using the _sprites variable anymore.

Now, when you add something to the frame, you do:
    void Frame::addObject(ActiveObject tempObject) {
or
    _objects.push_back(ActiveObject(filename, x, y, layer, w, h, vis, name));

In both these cases, there will be a copy made of the  ActiveObject object. When a copy is made, it doesn't call your standard constructor, but a auto-generated one which copies each variable of the class into the copy.

This means that the memory address stored in _sprites will be copied, but there won't be a copy made of the actual SDL_Surface.

So when either the original or the copy of your ActiveObject is destroyed, its destructor will destroy the SDL_Surface which BOTH ActiveObjects are holding the memory address too.

This now means that there will be an ActiveObject pointing to an invalid memory address, and when you try to use it (render) it will crash.

So, I advice that you create your objects with "new" and destroy them with "delete", so your add methods would be:
    void Frame::addObject(ActiveObject* tempObject) {
or
    _objects.push_back(new ActiveObject(filename, x, y, layer, w, h, vis, name));

so that there won't be any automatic copying of ActiveObject.
Logged
Al King
Level 1
*


Nobody expects...


View Profile
« Reply #2 on: June 19, 2008, 10:15:51 PM »

Also, as a general rule if you've got a destructor chances are you also want an explicit copy constructor. As Colossus says, though, it's a good idea to use a vector of pointers rather than objects themselves, anyway, because inheritance can screw things up with memory allocation when it comes to vectors.
« Last Edit: June 19, 2008, 10:26:06 PM by KingAl » Logged
___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« Reply #3 on: June 19, 2008, 11:16:16 PM »

So, I advice that you create your objects with "new" and destroy them with "delete", so your add methods would be:
    void Frame::addObject(ActiveObject* tempObject) {
or
    _objects.push_back(new ActiveObject(filename, x, y, layer, w, h, vis, name));

so that there won't be any automatic copying of ActiveObject.

Ah, damn, I think thats what I was trying to do, but I couldnt figure out how to do it.  Freakin' pointers and their mumbo jumbo.

Also, as a general rule if you've got a destructor chances are you also want an explicit copy constructor. As Colossus says, though, it's a good idea to use a vector of pointers rather than objects themselves, anyway, because inheritance can screw things up with memory allocation when it comes to vectors.

Yes, vector of pointers, that sounds like the best idea... argh, how do I do it.  I want to create the ActiveObjects in main and then add them... wow I am lost.  Ha haaaa.  I will continue to experiment for now.

further edit: HOLY FUCK I THINK I JUST WON.

I changed the vector in frame to this:
vector <ActiveObject*> _objects;

and changed draw() to this:
void Frame::draw() {
    for (int i=1 ; i < _layers ; i++ ) {
        for (int j=0; j < _objects.size() ; j++) {
            if (_objects[j]->getLayer() == i) {
                _objects[j]->render();
            }
        }
    }
}

And.... it works? :O
« Last Edit: June 19, 2008, 11:31:40 PM by xerus » Logged
Zaphos
Guest
« Reply #4 on: June 20, 2008, 07:14:48 AM »

Maybe you already do this, but just in case: Remember to also explicitly delete the ActiveObjects after you're done with them, now that they're not being managed directly by the vector.
Logged
cmspice
Level 1
*


View Profile
« Reply #5 on: June 20, 2008, 11:26:02 PM »

ooh, thanks for the link to lazy foo's. I think I like those tutorials better than the one I had been using.
Logged
___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« Reply #6 on: June 21, 2008, 02:38:37 PM »

Now, my engine theory is coming to life, and things seem to be working with the occasional snag that is remedied by tigIRC, however I have a question to extend to the folks of the internet.

What is the best way to go about structuring the system in which objects will move and check for collisions?  Right now, my simple movement system is similar to what I did in multimedia fusion in which 10 "game units" equals one pixel.  So if a player's speed is 10, he'll move one pixel per frame, and any overlap will carry over.  So if his speed is 15, he'll move one pixel, but then the overlap of 5 carries into the next frame so he'll actually move 2 pixels... you follow?

The issue is that I'm trying to make it so that I check for a collision on every pixel movement, so there are no wonky pass throughs.  I'm only using bounding box collision right now, as it seems pretty simple and I dont think I need anything more advanced for the time being.

Should I have a collision test function that returns a bool in the ActiveObject class, or maybe I should have it be a frame function that gets passed two active objects, and then that returns something... but then if I move an active object with a function move(), I dont know if I can access those functions from within a function!

As you can see, I'm confused.  It's difficult to find tutorials out there that are well grounded and not up in space with virtual process class application management.. classes.  :I
Logged
___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« Reply #7 on: June 23, 2008, 05:29:02 PM »

I did some work on my collision detection routine, but I'm hitting a snag that maybe someone will have some advice for.

For now, I want all of my ActiveObject classes to collide with each other, so my collide function for a MovingObject which is a sub class of ActiveObject takes in a pointer to a vector of active objects, and loops through that checking collisions.

I'm trying to make it so I move all of the objects in the game, then all of the objects check for collisions, and then they react to the collision... but this causes a problem.  I put two moving objects into the program for now, and they both move with player input.  If they become less than 1 pixel apart from each other, and one of them collides, the other will become stuck in it.

So everything is moved, then is checked for collisions, only one moving object collides with a wall or something, so when the reaction function is called for all the objects, this object gets bumped back out a pixel, and it gets placed right into the other moving object.

So basically the two of them get stuck together and are overlapping with a strip of pixels (I'm just using rectangles right now) and this is where I'm stuck.  I'm trying to figure out how I can prevent this jamming, while keeping the collision logic at the same steps for all the objects.  It seems no matter what I do results in some priority problems where the object that gets all the logic first behaves differently than the second.

So yeah, if anyone has any tips regarding something like this, shout em out. ;o
Logged
cmspice
Level 1
*


View Profile
« Reply #8 on: June 23, 2008, 10:49:59 PM »

I'm learning SDL myself and am probably less proficient than you are at the moment I should mention first.

But my idea for handling your former problem on collision is to have each rectangle bounded by a larger rectangle that is at least of size (speed)*(1 frame in seconds) larger than the object it is bounding. This way, you check for collision on this box and it'll tell you if there will be any overlapping in the next frame.
Maybe there is another way to do this? Only way I can think of. If you design it right, it shouldn't be too much programming either. (like in a platformer for example, you'd only need to do this for terrain collision because we don't really care if bullets clip you (in which case you just die))

I'm not quite sure what you're saying for the second problem. Do you mean like BOX A bounces off WALL and immediately bumps into  BOX B causing it to overlap with BOX B? Well if that's the case, you could just do what I mentioned above to check if anything is in the path where BOX B is going to be.

Hope that helps.

Good luck to both of us on our SDL endeavor.

I'm making a platformer with ROBOTS!!!!!!!
Logged
___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« Reply #9 on: June 24, 2008, 12:45:36 AM »

Okay well before I read your post, I think I solved my problem.  I think its very inefficient though...

I loop through each moving entity, first moving them in the X direction, and checking for collisions with every other collide-able object in the X direction.  Then, they react to any collisions, and are pushed back out.  Then, I loop backwards through the objects rechecking for x collisions, and then the objects react.

Rinse and repeat for the y direction.

It seems to work out okay for now, it works the way I want it to, but I dont know if its going to lag later on.
Logged
Alex May
...is probably drunk right now.
Level 10
*


hen hao wan


View Profile WWW
« Reply #10 on: June 24, 2008, 05:37:21 AM »

Collision is a bit of a nightmare and how you fix it depends on your game, really.

I've written various systems for detecting collisions, but essentially you can do it one of three ways:

1) Move things in very small increments (several per frame) until they hit something or reach the end of their movement
2) Calculate when all or any things will collide during one frame and solve for each
3) Move things the entire distance they want to move that frame and resolve collisions after they happen

For method 1, if your game is 2D and pixel based, look up Bresenham's line algorithm. I use this in my library to move things along the line of their velocity and return if they can't move any further at any point on the line. The down side to this method is you end up doing lots of collision checks for things that move very quickly.

For method 2, things get really hairy - you have to calculate all the collisions that may happen, then discard all but the earliest one, resolve that and then do the same calculation again for all objects. It's not trivial and it won't necessarily get you better results.

Most physics engines use method 1.

The other way you might do it is to use method 3, which is easy to implement (move everything, then check to see if they overlap other things) but you tend to end up with collision situations you will find hard to resolve, unless you limit your system somehow to ensure all objects move slowly or something, but then that's approaching method 1.

SO

Assuming you're using method 1, the theory for the method I outlined is that you move the object one pixel at a time in X or in Y depending on the gradient of the velocity (if it's pointing up or down you'd move in Y, left or right you'd move in X). You then keep a record of where the object is in the other axis and do appropriate checks when it moves in that axis.

Let's assume you've got an object moving generally to the right, but up (or down) a bit. This frame it will be moving from start = (20, 20) to end = (40, 30). You start with the object at (20,20), and keep a record of where it is on the Y axis (20 at the start). Then you move it over by one pixel in X until its X position is 40. Each time you move it by one pixel in X, you also move it fractionally along the Y axis. The amount you move it is calculated so that when it arrives at X = 40, the value for Y will equal 30. You can work this amount out by taking the gradient of the line (end - start). Note that you'd need to take a slightly different gradient if you're moving in Y. Also don't forget to check for divide by 0 which can often happen here.

Now every time you move the thing, you can see what its position in pixels would be by taking the integer value of the fractional Y position you've been calculating all this time. This would let you do a test against the world and any objects in it. The object would never intrude into any other objects by more than one pixel.


Anyway this is the method I use, it's calculation-heavy but completely robust. Physics engines usually move everything at once in small increments instead of one object at a time - this makes a lot more sense of course but you can still have things that are moving too fast for the game to comprehend as you're not moving everything by the same distance but moving things by an amount proportional to their speed.
« Last Edit: June 24, 2008, 05:40:49 AM by haowan » Logged

Alex May
...is probably drunk right now.
Level 10
*


hen hao wan


View Profile WWW
« Reply #11 on: June 24, 2008, 05:46:36 AM »

Now, I notice you talk about checking against every other collidable object - that's fine for now, but later on you might want to divide up your world into some kind of space, so that when you check collisions you don't have to check against everything in the world.

The easiest way to do this is the divide it all up into evenly-spaced boxes, and only check collisions with the objects in the same (or adjacent) boxes. A good way to do this is to have each collidable object in the game keep track of which box it's in, and remove itself from any boxes it used to be in.

Another way to do this is to use trees (quadtree for 2D, octree for 3D). You can look those up for yourself, as I'm not too familiar with them and have never needed to use anything but the bucket-sort I outlined above.
Logged

cmspice
Level 1
*


View Profile
« Reply #12 on: June 24, 2008, 11:05:31 AM »

Now, I notice you talk about checking against every other collidable object - that's fine for now, but later on you might want to divide up your world into some kind of space, so that when you check collisions you don't have to check against everything in the world.

The easiest way to do this is the divide it all up into evenly-spaced boxes, and only check collisions with the objects in the same (or adjacent) boxes. A good way to do this is to have each collidable object in the game keep track of which box it's in, and remove itself from any boxes it used to be in.

Another way to do this is to use trees (quadtree for 2D, octree for 3D). You can look those up for yourself, as I'm not too familiar with them and have never needed to use anything but the bucket-sort I outlined above.

sounds like it'd be a good idea for danmaku shooters :D.
Logged
cmspice
Level 1
*


View Profile
« Reply #13 on: June 24, 2008, 01:47:39 PM »

Oh, I thought I'd invade this thread with a noob question.

Is there anyway to not include all those SDL .dll files when I release my game or at the very least have them all tucked away in another folder? When you start using even the official SDL extensions, the number of DLL files just starts getting pretty ridiculous.
Logged
ColossusEntertainment
Level 1
*

Royal Leamington Spa, UK


View Profile
« Reply #14 on: June 24, 2008, 01:54:13 PM »

I'm not that familiar with SDL, only really used it for one project (this one, if anyone is curious). But maybe there's a way to use static libraries, or you could just include the source files in your own project, thus eliminating the need of DLLs...

I don't like having to bundle DLL's with my games, I much prefer the EXE to be as self-contained as possible, so I can see why you'd want to get rid of them...
Logged
mewse
Level 6
*



View Profile WWW
« Reply #15 on: June 24, 2008, 05:54:59 PM »

I'm not that familiar with SDL, only really used it for one project (this one, if anyone is curious). But maybe there's a way to use static libraries, or you could just include the source files in your own project, thus eliminating the need of DLLs...

SDL is set up to be loaded via DLLs, and its LGPL license doesn't allow you to include its source files directly in your game, unless your game is open source under a license compatible with the LGPL.  (This is so that end users can upgrade the LGPLed portion of your game, even without access to your game's source code)

A better option might be to make a subdirectory that contains your executable and the .dll files, and have a batch file or similar in the root, which actually launches the game.
Logged
mjau
Level 3
***



View Profile
« Reply #16 on: June 24, 2008, 07:07:21 PM »

SDL is set up to be loaded via DLLs, and its LGPL license doesn't allow you to include its source files directly in your game, unless your game is open source under a license compatible with the LGPL.  (This is so that end users can upgrade the LGPLed portion of your game, even without access to your game's source code)

Not exactly..  I mean, SDL is LGPL-licensed, but that doesn't actually prevent you from statically linking it, even if your game isn't GPL/LGPL or even open source at all.  Dynamically linking SDL is just usually the most convenient way to comply with the license.  Otherwise, you need to provide some other way that people can re-link the game with a different (compatible) SDL library if they wish.  (Using dlls or providing the source code of your game gets you this for free; people can just replace the dll or compile/relink.)

You could also provide object code in stead of source code, which works just as well for relinking purposes (well, assuming the object files are compatible with the new linker).  Or, you could have multiple builds of the game, one statically linked and one dynamically linked, which I think should comply too, as long as the builds are otherwise identical.  Both of these have been done before with some closed-source/commercial SDL games, so should be safe enough.

Also, you don't have to include source/object code/dynamic exe with the game itself, it's enough to provide some way for people to get it (for free).  A separate download should work.

Sticking with the dlls is less of a pain to support, though.  I'd do as mewse said Smiley

(In Linux, you can also set LD_LIBRARY_PATH to the path of a subdir with the .so files in a wrapper script or executable, or embed a relative rpath into the main executable for mostly the same effect.  Relative rpaths are relative to the current directory though, and doesn't seem to affect dlopen for some reason.)

Oh also, the above is based on what I (think I) know of the LGPL v2, which SDL is licensed under.  Haven't read the LGPL v3.  (Also IANAL blah blah etc)
Logged
Ivan
Owl Country
Level 10
*


alright, let's see what we can see


View Profile
« Reply #17 on: June 24, 2008, 07:48:56 PM »

What's wrong with dll files?
Logged

http://polycode.org/ - Free, cross-platform, open-source engine.
ColossusEntertainment
Level 1
*

Royal Leamington Spa, UK


View Profile
« Reply #18 on: June 24, 2008, 09:53:46 PM »

Ah, the licensing issues, right  Sad

Personally, I really dislike all those weird licenses that claim the software is "free", when in fact it is horribly restricted... If they want to give it away, they should give it away already, not just pretend they do.

Ok then, for an alternative (and shameless plug :D), use my game engine, which is public domain, so you can do anything you like with it (the way it should be). It's also already set up to produce a self-contained executable. Beer!

Logged
___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« Reply #19 on: June 25, 2008, 12:14:51 AM »

So, you guys program any cool variables lately?  How many lines of code did you make yesterday?

Anyway-- does anyone have any helpful hints on how to manage my actual game engine here?  I think I need a big game class, that manages some frame/level classes, and then that class controls all the entities and eventually the tilemap or the level or whatever.  I'm still trying to learn all these terms.
Logged
Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic