• Multiple instances of a single object?
    97 replies, posted
I'm sorry but I really don't understand what you mean there (in your other post), can you please explain?
Here's a fragment of the Bullet class from your earlier code post: [QUOTE=Samuka97;25918702] [cpp] class Bullet { public: sf::Sprite bi_p, bbi_p; // ... [/cpp] [/QUOTE] And part of Bullet's constructor: [QUOTE=Samuka97;25918702] [cpp] Bullet::Bullet (sf::Sprite* bi_p, sf::Sprite* bbi_p, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { bi_p = bi_p; bbi_p = bbi_p; // ... [/cpp] [/QUOTE] In the body of the constructor, the member variables called "bi_p" and "bbi_p" are hidden by the parameters with the same names. Those two assignment statements do nothing because both the left and the right side of the assignment both refer to the parameter. If you want to assign a parameter to a member variable of the same name, you have to either make the left side of the assignment explicitly refer to the member variable: [cpp] this->bi_p = bi_p; this->bbi_p = bbi_p; [/cpp] or use the constructor's [url=http://www.codeguru.com/forum/showthread.php?t=464084]initializer list[/url]: [cpp] Bullet::Bullet (sf::Sprite* bi_p, sf::Sprite* bbi_p, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a): // <-- Note the colon bi_p(bi_p), bbi_p(bbi_p) { // <-- The name outside the parens always refers to a member variable // ... [/cpp] Or you can just rename the variables to avoid the name clash. I use an "m_" prefix on member variables' names to avoid this type of problem. Once you do one of those things, you'll run into the second problem, which is that you can't assign an sf::Sprite* to an sf::Sprite. Judging by the "_p" suffix I'm guessing you intended the bi_p and bbi_p member variables in the Bullet class to be pointers, but they aren't, they're actual objects. Right now each of your bullets actually contains a separate pair of sprites, which seem to be default-constructed and nothing more (e.g. no images loaded into them).
Did what you said and I ran exactly into the problem you said, too. I can't really think on how to fix that, any help?
[QUOTE=Samuka97;25927218]I can't really think on how to fix that, any help?[/QUOTE] Now you're just not using your head. Remember that the intended design here is for Bullet to contain pointers to its sprites. Right now Bullet doesn't contain pointers to sprites, it contains actual sprites, and [i]that's[/i] what you need to fix. Change the member variables to be pointers and you'll have no trouble assigning them from the pointer parameters in the constructor.
[QUOTE=Wyzard;25927587]Now you're just not using your head. Remember that the intended design here is for Bullet to contain pointers to its sprites. Right now Bullet doesn't contain pointers to sprites, it contains actual sprites, and [i]that's[/i] what you need to fix. [b]Change the member variables to be pointers[/b] and you'll have no trouble assigning them from the pointer parameters in the constructor.[/QUOTE] The only possible thing I can imagine is doing [cpp] BulletSpr = &bi_p; BulletBackSpr = &bbi_p;[/cpp] and commenting out the "making of the sprite part", but that still doesn't work. [code]1>c:\users\samuka97\documents\visual studio 2008\projects\sfml_test\sfml_test\bullet.cpp(7) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'sf::Sprite **' (or there is no acceptable conversion) 1> c:\sfml-1.6\include\sfml\graphics\sprite.hpp(171): could be 'sf::Sprite &sf::Sprite::operator =(const sf::Sprite &)' 1> while trying to match the argument list '(sf::Sprite, sf::Sprite **)' 1>c:\users\samuka97\documents\visual studio 2008\projects\sfml_test\sfml_test\bullet.cpp(8) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'sf::Sprite **' (or there is no acceptable conversion) 1> c:\sfml-1.6\include\sfml\graphics\sprite.hpp(171): could be 'sf::Sprite &sf::Sprite::operator =(const sf::Sprite &)' 1> while trying to match the argument list '(sf::Sprite, sf::Sprite **)' 1>Main.cpp 1>c:\users\samuka97\documents\visual studio 2008\projects\sfml_test\sfml_test\main.cpp(22) : error C2664: 'Bullet::Bullet(sf::Sprite *,sf::Sprite *,double,double,double,double,int,int,int,int)' : cannot convert parameter 1 from 'sf::Sprite' to 'sf::Sprite *' 1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called 1>c:\users\samuka97\documents\visual studio 2008\projects\sfml_test\sfml_test\main.cpp(105) : error C2664: 'create_bullet' : cannot convert parameter 1 from 'sf::Sprite *' to 'sf::Sprite' 1> No constructor could take the source type, or constructor overload resolution was ambiguous[/code] [editline]8th November 2010[/editline] Oh my. I just changed that pecie of code to: [cpp]BulletSpr = *bi_p; BulletBackSpr = *bbi_p;[/cpp] And "Microsoft(R) Incremental Linker" crashed. What the?!
Please take a look at this piece of code again: [QUOTE=Samuka97;25918702] [cpp] class Bullet { public: sf::Sprite bi_p, bbi_p; // ... [/cpp] [/QUOTE] and tell me your thoughts on why your Bullet class has those variables.
...to be used as pointers? If I put them as anything other than sf::Sprite, it wont compile. Or am I still missing something very obvious? [editline]8th November 2010[/editline] im missing something, right?
You're right that they're meant to be used as pointers. The key fact that I'm trying to steer you toward is that, as written, they [i]aren't[/i] pointers. That's why you have compile errors in the constructor from trying to assign pointers to them. Yes, if you change them to sf::Sprite* you'll get compile errors in a few other places where you're treating them as objects, like when you pass them to the window's Draw() function. That's OK; it just means you need to add asterisks in those places to dereference the pointer.
Okay, I (think) I fixed what you mentioned, I'm now using -> instead of . but when I run my game... [IMG]http://i225.photobucket.com/albums/dd159/samuka97/darngosh.png[/IMG] :saddowns: [editline]8th November 2010[/editline] Just commented out the whole bullet-update-thing, it's not that making it crash.
If you were doing [cpp] target.draw(bbi_p); target.draw(bi_p); [/cpp] then you'd need asterisks there. If you're still making temporary copies, [cpp] sf::Sprite BulletSpr(bi_p); sf::Sprite BulletBackSpr(bbi_p); [/cpp] then the asterisks would go there instead. Wherever you need to use the sprites that the pointers point to. This isn't a matter of design, it's just syntax that you should be able to work out on your own (if you give it some thought) provided you understand how to use pointers. If you're not clear on pointers, please say so; I don't have a good sense of what you know and what you don't know so it's hard to judge which things I should focus on explaining. [editline]7th November 2010[/editline] ...looks like you [i]did[/i] work out the syntax. :-)
bullet.cpp [cpp]#include "Bullet.hpp" #include <cmath> #include <SFML/Graphics.hpp> const double pi = 3.1415; Bullet::Bullet (sf::Sprite* bi_p, sf::Sprite* bbi_p, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { *BulletSpr = *bi_p; *BulletBackSpr = *bbi_p; x = x; y = y; speed = speed; direction = direction; color_r = color_r; color_g = color_g; color_b = color_b; color_a = color_a; } Bullet::~Bullet () { } void Bullet::update(sf::RenderWindow &target) { //sf::Image BulletImage; //sf::Image BulletBackImage; //BulletImage.LoadFromFile("data/gfx/bullet1.png"); //BulletBackImage.LoadFromFile("data/gfx/bullet1_back.png"); // Create a sprite for the player image. //sf::Sprite BulletSpr(bi_p); //sf::Sprite BulletBackSpr(bbi_p); // Set up some properties for it. //BulletSpr->SetCenter(14.f, 14.f); //BulletBackSpr->SetCenter(8.f, 8.f); // Color the bullet //BulletSpr->SetColor(sf::Color(color_r, color_g, color_b, color_a)); // Calculate it's trajectory //x = x + speed * cos(direction*pi/180); //y = y - speed * sin(direction*pi/180); // Move it's sprite //BulletSpr->SetPosition(float(x), float(y)); //BulletBackSpr->SetPosition(float(x), float(y)); // And finally, draw it. //target.Draw(*BulletBackSpr); //target.Draw(*BulletSpr); }[/cpp] bullet.hpp [cpp]#ifndef BULLET_H //usually something like FILE_NAME_H #define BULLET_H #pragma once #include <SFML/Graphics.hpp> //--------------------------------------------------------------------------- class Bullet { public: double x, y, speed, direction; int color_r, color_g, color_b, color_a; sf::Sprite *BulletSpr, *BulletBackSpr; void update(sf::RenderWindow &target); Bullet (sf::Sprite* bi_p, sf::Sprite* bbi_p, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a); ~Bullet(); }; //--------------------------------------------------------------------------- #endif[/cpp] There. Just tell me what the hell is wrong because I don't see how this code could possibly go wrong.
When you have a crash like that, you need to run it in the debugger to find out which line it's crashing on. The problem might not even be anything related to the code you posted.
As soon as it loads, I get a message saying "Unhandled exception at 0x7550aae8 in SFML_Test.exe: 0xC0000005: Access violation reading location 0xcccccccc." And then a little green arrow pointing to line 48 appears. Line 48 is basically: [cpp]sf::RenderWindow App(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32), "Bullet Fusion C++ Version");[/cpp] what, it was just working when I was using arrays
Just a though but couldnt he just put the image in main and reference it in the bullet class? That way it would be 1 image but many bullets. Sorry if this is what your trying to do
I already have 1 image and 1 sprite, I just re-draw the sprite in my loop. But now I'm not caring about that, my game is crashing like for no reason whatsoever now =\ [editline]8th November 2010[/editline] gonna go to sleep, checking tomorrow night
That 0xcccccccc is the dummy value that Microsoft's compiler stores in "uninitialized" pointers (at least in debug mode, not sure about release). So something somewhere is trying to dereference a pointer that doesn't point to anything, which causes the crash. I don't see anything wrong with that line besides "WINDOW WIDTH" and "WINDOW HEIGHT" having spaces in them (I'm guessing that's a typo and the actual code has underscores). Does one of the debugger's info panels show which variable has the value 0xcccccccc? Richy, yes, that's the design we've been working toward.
pretty sure it has someting to do with this [quote]*BulletSpr = *bi_p; *BulletBackSpr = *bbi_p;[/quote] BT why are you assigning every thing to is value? [cpp]*BulletSpr = *bi_p; *BulletBackSpr = *bbi_p; x = x; y = y; speed = speed; direction = direction; color_r = color_r; color_g = color_g; color_b = color_b; color_a = color_a;[/cpp]
Also, is there a stack view that shows you which function the crash actually occurred in? It probably wasn't actually in [i]your[/i] code, it was in either the sf::RenderWindow constructor or the sf::VideoMode constructor. Knowing which one it was helps to narrow down what the cause might be. [editline]7th November 2010[/editline] [QUOTE=Richy19;25929077]pretty sure it has someting to do with this [cpp] *BulletSpr = *bi_p; *BulletBackSpr = *bbi_p; [/cpp][/QUOTE] That does look suspect, but he said he gets a green arrow on the line that constructs the RenderWindow, after seeing the "access violation" message. You may be more familiar with Visual Studio than I am -- does the green arrow indicate the line where the crash occurred, or did it restart the program and now it's just sitting on the first line of main()?
[QUOTE=Wyzard;25929041]I don't see anything wrong with that line besides "WINDOW WIDTH" and "WINDOW HEIGHT" having spaces in them (I'm guessing that's a typo and the actual code has underscores).[/QUOTE] That's actually an artifact of the forum code window. If you look to the right, there are actually up/down scroll arrows, and if you click down, you'll see the underscores. The code window is just a little too small to show them.
[QUOTE=Wyzard;25929116]You may be more familiar with Visual Studio than I am -- does the green arrow indicate the line where the crash occurred, or did it restart the program and now it's just sitting on the first line of main()?[/QUOTE] Im not extremely familiar with it, but i think it points to what made it crash, how ever that doesnt mean that the arrow is whats wrong, just that theres were it finds the error. What was the last thing you did before it gave errors? Have you tried putting in a defined size instead of Window_height/width? shouldnt matter but worth a try
[QUOTE=Richy19;25929932]how ever that doesnt mean that the arrow is whats wrong, just that theres were it finds the error.[/QUOTE] Quite true, but I'm assuming his code creates the window before it creates the bullets, which would mean the problem can't be in the bullet constructor. This assumption might not be correct though
A few hours ago, when my code compiled but didn't draw bullets, the program was running just fine. Now it crashes =\ [editline]8th November 2010[/editline] Uh. You guys said that the lines *BulletSpr etc etc were strange, so I trying editing them, but no combination let me compiler. Then I just changed it back to what it was (everything with a * before), and it compiled and now runs. But the bullets still wont draw. what??? [editline]8th November 2010[/editline] OHH WAIT. If I comment out the line: [cpp]create_bullet(&BulletSpr, &BulletBackSpr, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 2 + rand() % 2, a, 255, rand() % 255, rand() % 255, 255);[/cpp] it stops crashing, but as soon as I un-comment it, the game starts crashing again! Well, uh... so... what did I do wrong this time? [editline]8th November 2010[/editline] Found out what's crashing. It's the code inside bullet_create itself! [cpp]bool create_bullet(sf::Sprite* bi_p, sf::Sprite* bbi_p, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { Bullet temp_Bullet(bi_p, bbi_p, x, y, speed, direction, color_r, color_g, color_b, color_a); // Create a temp bullet bullets.push_back(temp_Bullet); // Add it to the list return true; // We managed to create the bullet! Yay! }[/cpp] What's wrong there?
[QUOTE=Samuka97;25935355]A few hours ago, when my code compiled but didn't draw bullets, the program was running just fine. Now it crashes =\ [editline]8th November 2010[/editline] Uh. You guys said that the lines *BulletSpr etc etc were strange, so I trying editing them, but no combination let me compiler. Then I just changed it back to what it was (everything with a * before), and it compiled and now runs. But the bullets still wont draw. what??? [editline]8th November 2010[/editline] OHH WAIT. If I comment out the line: [cpp]create_bullet(&BulletSpr, &BulletBackSpr, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 2 + rand() % 2, a, 255, rand() % 255, rand() % 255, 255);[/cpp] it stops crashing, but as soon as I un-comment it, the game starts crashing again! Well, uh... so... what did I do wrong this time? [editline]8th November 2010[/editline] Found out what's crashing. It's the code inside bullet_create itself! [cpp]bool create_bullet(sf::Sprite* bi_p, sf::Sprite* bbi_p, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { Bullet temp_Bullet(bi_p, bbi_p, x, y, speed, direction, color_r, color_g, color_b, color_a); // Create a temp bullet bullets.push_back(temp_Bullet); // Add it to the list return true; // We managed to create the bullet! Yay! }[/cpp][/QUOTE] Ah, christ. I wrote that part, didn't I? :ohdear: Edit: But I can't see what's wrong with it, was it working before?
Well, before, the game wasn't crashing but the bullets weren't being added to the list (I think)... [editline]8th November 2010[/editline] off to school, gonna read this 6 hours later
[QUOTE=Samuka97;25935355]It's the code inside bullet_create itself![/QUOTE] More likely it's in the Bullet constructor, which is called by create_bullet(). The reason the *BulletSpr=*bi_p line in the constructor looks suspicious is that it doesn't look like BulletSpr actually points to anything valid at that point in the program. If not, trying to assign to its target is undefined behavior, which often manifests as an access violation. Since your crash is an access violation with a message that indicates it's an uninitialized pointer (the 0xcccccccc), and you've determined that it's occurring in code that involves calling the constructor with this line in it, I strongly suspect this is the cause. You probably want to change those two lines to be [cpp] BulletSpr = bi_p; BulletBackSpr = bbi_p; [/cpp] since the idea is to store a copy of the pointers (still pointing to those same two sprites that are shared among all bullets), not to make copies of the sprites themselves. How well do you feel you understand pointers? Are you having trouble getting your head around the distinction between copying a pointer and copying an object? BTW, there's no point having your create_bullet() return bool when the return value is always true. May as well change it to void.
I understand what a pointer is, how it works, and why it exists, but I just don't know it's... syntax, I guess. I can't just come and say "oh, I'll define a pointer!" and do it myself. Also thanks, I didn't remember the name of the function type that didn't return anything :sweatdrop: [editline]9th November 2010[/editline] Now it doesn't crash anymore, but still no bullets being drawn. Just making sure... is this the proper thing to do? [cpp] create_bullet(&BulletSpr, &BulletBackSpr, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 2 + rand() % 2, rand() % 360, 255, rand() % 255, rand() % 255, 255); [/cpp]
[QUOTE=Samuka97;25959686]I understand what a pointer is, how it works, and why it exists, but I just don't know it's... syntax, I guess. I can't just come and say "oh, I'll define a pointer!" and do it myself.[/QUOTE] Pointer syntax is pretty simple: put '&' in front of something to get a pointer to it, and put '*' in front of a pointer to get the thing it points to. You've been doing that correctly as far as I've seen, so I don't think "syntax" is quite what you mean. Or do you find yourself doing trial and error until you get something that doesn't cause compile errors? [QUOTE=Samuka97;25959686]Just making sure... is this the proper thing to do? [cpp] create_bullet(&BulletSpr, &BulletBackSpr, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 2 + rand() % 2, rand() % 360, 255, rand() % 255, rand() % 255, 255); [/cpp][/QUOTE] I was going to say yes, but I took another look and realized we've been on a slightly wrong tack for awhile. A sprite's position is stored in the sprite itself (rather than being passed as parameters to the draw function), so if you want your bullets to appear at different positions, you should have a separate sprite for each. You need to share a single image among multiple sprites, not a single sprite among multiple bullets. That actually simplifies things, though. A sprite's constructor and setImage() function takes a [i]reference[/i] to an image, not a pointer, so it looks like you might not need to deal with pointers after all. (The sprite seems to take the address from the reference and store a pointer internally, so the use of a reference parameter is a design decision in SFML that I don't really agree with, but whatever.) With that in mind, try this out: [list] [*]Change the two sprite pointers in Bullet back to being actual sprites, not pointers. [*]Get rid of any code in main.cpp that creates sprites; you don't need it. [*]Pass the two images into Bullet's constructor as const references, instead of the Sprite* parameters that you have now, and have the constructor feed each image (parameter) to its corresponding sprite (member variable) by calling SetImage() on the latter. [/list] The result should be that you have two images, loaded once each in main.cpp, referenced by multiple sprites, each belonging to a different bullet and each holding a different position where the image should be drawn.
Will try to do that, thanks! Seems much simpler... but... [QUOTE=Wyzard;25965586]do you find yourself doing trial and error until you get something that doesn't cause compile errors?[/QUOTE] Exactly.
Well, finally got some time to try out what you said, but I'm not sure that I've done the last thing you said to do correctly. Mostly because no sprites are being drawn whatsoever :| bullet.cpp [cpp]#include "Bullet.hpp" #include <cmath> #include <SFML/Graphics.hpp> const double pi = 3.1415; Bullet::Bullet(sf::Image BulletImage2, sf::Image BulletBackImage2, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { // etc const sf::Image &BulletImage = BulletImage2; const sf::Image &BulletBackImage = BulletBackImage2; // Create a sprite for the bullet's image. sf::Sprite BulletSpr(BulletImage); sf::Sprite BulletBackSpr(BulletBackImage); // Set up some properties for it. BulletSpr.SetCenter(14.f, 14.f); BulletBackSpr.SetCenter(8.f, 8.f); // Our variables x = x; y = y; speed = speed; direction = direction; color_r = color_r; color_g = color_g; color_b = color_b; color_a = color_a; } Bullet::~Bullet () { } void Bullet::update(sf::RenderWindow &target) { // Color the bullet BulletSpr.SetColor(sf::Color(color_r, color_g, color_b, color_a)); // Calculate it's trajectory //x = x + speed * cos(direction*pi/180); //y = y - speed * sin(direction*pi/180); x = 100; y = x; // Move it's sprite BulletSpr.SetPosition(float(x), float(y)); BulletBackSpr.SetPosition(float(x), float(y)); // And finally, draw it. //target.Draw(BulletBackSpr); target.Draw(BulletSpr); }[/cpp] bullet.hpp [cpp]#ifndef BULLET_H //usually something like FILE_NAME_H #define BULLET_H #pragma once #include <SFML/Graphics.hpp> //--------------------------------------------------------------------------- class Bullet { public: double x, y, speed, direction; int color_r, color_g, color_b, color_a; sf::Image BulletImage2, BulletBackImage2; sf::Sprite BulletSpr, BulletBackSpr; void update(sf::RenderWindow &target); Bullet (sf::Image BulletImage2, sf::Image BulletBackImage2, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a); ~Bullet(); }; //--------------------------------------------------------------------------- #endif[/cpp]
Two problems, both in the Bullet constructor. The first problem is that the BulletImage2 and BulletBackImage2 parameters aren't references, which means the constructor doesn't get direct access to the images that main.cpp has, it gets [i]copies[/i] of the images. These copies are local variables within the function (as non-reference parameters always are), so they get destroyed when the constructor finishes running. In the first two lines of the constructor's body, you're creating references, but they're not references to the original images in main.cpp, they're references to the constructor's temporary copies. When you use them to initialize the sprites, the sprites end up internally holding pointers to data that's no longer valid after the constructor finishes and those temporary images are automatically destroyed. The second problem is that the BulletSpr and BulletBackSpr that you're initializing in the constructor aren't the member variables that'll be used later in update(), they're more local variables that also get destroyed when the constructor finishes running. The member variables never get initialized with images, so you don't see anything when you use them for drawing later. (The second problem inadvertently mitigates part of the first one: since the temporary images and the temporary sprites both get destroyed automatically at the end of the constructor, you're not left with sprites holding internal pointers to images that no longer exist, because the sprites no longer exist either.) A third sort-of-problem-but-not-quite is that you have a pair of images called BulletImage2 and BulletBackImage2 declared as member variables in bullet.hpp. There shouldn't be any harm in having them there, aside from wasting a little memory, but they're not used for anything and should be removed. I think you're a little confused about the distinction between local variables and member variables, so here's an example that may help: [cpp] #include <iostream> #include <string> class Foo { public: Foo(std::string const &name); std::string const &get_name() const; private: std::string m_name; }; Foo::Foo(std::string const &name) { // Store the given name into the m_name member variable m_name = name; // Create a local variable that "hides" the member variable std::string m_name(name); // Store some garbage into m_name, but it's the local one, not the member m_name = "foo"; std::cout << "In the constructor, the local m_name is: " << m_name << std::endl; } std::string const &Foo::get_name() const { // This returns a reference to the member variable; // it can't see the local variable that was created in the constructor. return m_name; } int main() { std::string world_name("world"); Foo foo(world_name); std::cout << "Hello, " << foo.get_name() << '!' << std::endl; return 0; } [/cpp] This will print "Hello, world!", not "Hello, foo!" — the assignment of "foo" to a local variable in the constructor has no effect on anything. If you comment out the assignment to the member variable on line 15, you'll get "Hello, !" instead, because then the class's stored name never gets initialized to anything, and stays at its default of the empty string. That's what you're doing with the two sprites in your Bullet constructor. This example also illustrates passing by const reference, btw. The "name" parameter in Foo's constructor provides direct (but read-only) access to the world_name variable in main().
Sorry, you need to Log In to post a reply to this thread.