SFML community forums
Help => Graphics => Topic started by: Xeshi on March 21, 2011, 07:35:58 am
-
Hi,
sorry for my English, I use google translate to translate.
I have problem with pointer to Sprite. I use dynamic memory to create new obiekt Sprite. Unfortunately, show me the white rectangle instead of my picture. Picture is certainly ok. This is my code:
if(! iBall.LoadFromFile("obrazek.bmp") )
{
std::cout <<"Blad ladowania bitmapy pilki" <<std::endl;
}else
{
std::cout <<"Zaladowano poprawnie bitmape pilki" <<std::endl;
}
iBall.CreateMaskFromColor( sf::Color::Black, 255 );
//sf::Sprite sBall;
pBall = new sf::Sprite;
//pBall->SetColor(sf::Color::Green);
pBall->SetImage( iBall );
pBall->SetPosition(xP, yP);
pBall->SetScale(1.0f, 1.0f);
App::pApp->Draw( *pBall );
Please Help me.[/code]
-
Please always try to provide a minimal example to reproduce your problem. Whereas it already seems to be rather minimalistic, you have a call to "App::pApp" and we have to guess how your code structure looks like. ;)
Here's a minimal example you can use to test if sprites with images get displayed correctly at all:
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
int main() {
sf::RenderWindow window( sf::VideoMode( 800, 600, 16 ), "Test" );
sf::Image image;
image.LoadFromFile( "obrazek.bmp" );
sf::Sprite sprite( image );
window.Clear();
window.Draw( sprite );
window.Display();
sf::Sleep( 3.f );
return 0;
}
If that works, try to add CreateMaskFromColor() etc. (hopefully the code above is okay, it's untested)
P.S.: Google Translator does a good job nowadays. ;)
-
Please always try to provide a minimal example to reproduce your problem. Whereas it already seems to be rather minimalistic, you have a call to "App::pApp" and we have to guess how your code structure looks like. ;)
Here's a minimal example you can use to test if sprites with images get displayed correctly at all:
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
int main() {
sf::RenderWindow window( sf::VideoMode( 800, 600, 16 ), "Test" );
sf::Image image;
image.LoadFromFile( "obrazek.bmp" );
sf::Sprite sprite( image );
window.Clear();
window.Draw( sprite );
window.Display();
sf::Sleep( 3.f );
return 0;
}
If that works, try to add CreateMaskFromColor() etc. (hopefully the code above is okay, it's untested)
P.S.: Google Translator does a good job nowadays. ;)
This example works well. Only, if I use pointer to Sprite displaying error.
The code to create pointer for the window.
App::App(void)
{
pApp= new sf::RenderWindow;
pApp->Create(sf::VideoMode(800,600, 32), "okno");
//pApp->Close();
}
-
The pointer itself isn't the problem. Again I looked at your code, and there's "iBall", which seems to be put on stack. Are you sure the variable iBall is still there when you're drawing your sprite?
sf::Sprite only holds a reference to sf::Image and does not copy it. And since C++ doesn't have reference counting, you may get problems here.
-
The pointer itself isn't the problem. Again I looked at your code, and there's "iBall", which seems to be put on stack. Are you sure the variable iBall is still there when you're drawing your sprite?
sf::Sprite only holds a reference to sf::Image and does not copy it. And since C++ doesn't have reference counting, you may get problems here.
"iBall" is normaln var of class Image. It is certainly.
Do you give all the code?
-
Do you give all the code?
Would be helpful to see more than your snippets, yes.
-
Do you give all the code?
Would be helpful to see more than your snippets, yes.
App.cpp
#include "App.hpp"
#include "Ball.hpp"
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
sf::RenderWindow* App::pApp;
App::App(void)
{
pApp= new sf::RenderWindow;
pApp->Create(sf::VideoMode(800,600, 32), "okno");
//pApp->Close();
}
App::~App(void)
{
delete pApp;
std::cout<<"Wywoładno destruktor klasy App";
}
void App::ServiceEvent()
{
sf::Event Event;
while( pApp->GetEvent(Event) )
{
if( Event.Key.Code == sf::Key::Escape || Event.Type == sf::Event::Closed) { pApp->Close(); }
if( Event.Key.Code == sf::Key::Right) { /*przesun platforme w prawo */}
}
}
void App::Run()
{
Ball Ball(20.0f, 20.0f);
while( pApp->IsOpened() )
{
pApp->Display();
pApp->Clear();
App::ServiceEvent();
Ball.Update();
}
}
App.hpp
#pragma once
#include <SFML/Graphics.hpp>
class App
{
public:
App(void);
~App(void);
void ServiceEvent();
void Run();
//static float ElapsedTime;
static sf::RenderWindow *pApp; //wskaźnik na okno
};
Ball.hpp
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include "App.hpp"
class Ball
{
public:
Ball(float x, float y); //x, y pozycja poczatkowa pilki
//~Ball(void);
void Update();
private:
sf::Sprite *pBall; //wskaźnik na obiekt piłki
float x; //pozycja na osi x
float y; //pozycja na osi y
float vy; //predkosc na osi y
float vx; //predkosc na osi x
int width; //Wymiary okna
int height; //do wyswietlania
};
Ball.cpp
#include "Ball.hpp"
#include "App.hpp"
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
//Ball::~Ball(void){}
//konstruktor, zaladowanie obrazu pilki 32x32px
Ball::Ball(float xP, float yP)
{
std::cout <<"Wywołano: Konstruktor Ball" <<std::endl;
sf::Image iBall;
if(! iBall.LoadFromFile("pilka.bmp") )
{
std::cout <<"Blad ladowania bitmapy pilki" <<std::endl;
}else
{
std::cout <<"Zaladowano poprawnie bitmape pilki" <<std::endl;
}
iBall.CreateMaskFromColor( sf::Color::Black, 255 );
//sf::Sprite sBall;
pBall = new sf::Sprite;
//pBall->SetColor(sf::Color::Green);
pBall->SetImage( iBall );
pBall->SetPosition(xP, yP);
pBall->SetScale(1.0f, 1.0f);
x= xP;
y= yP;
vx= 100;
vy= 100;
width= App::pApp->GetWidth();
height= App::pApp->GetHeight();
}
//Koniec konstruktora
void Ball::Update()
{
float ElapsedTime= App::pApp->GetFrameTime();
// std::cout<<"Funkcja update wywołana" <<std::endl;
x+= vx * ElapsedTime;
y+= vy * ElapsedTime;
pBall->SetPosition(x, y);
//int width= App::pApp->GetWidth();
//int height= App::pApp->GetHeight();
if( x >= (width-32) )
{
x= width-32;
vx*= -1;
}
if( x<= 0 )
{
vx*= -1;
x=0;
}
if( y>= (height-32))
{
y= height-32;
vy*= -1;
}
if( y <= 0 )
{
vy*= -1;
y= 0;
}
App::pApp->Draw( *pBall );
}
Main.cpp
//Plik glowny pileczki :) Made by KeeL
#include <iostream>
#include <SFML/Graphics.hpp>
#include "App.hpp"
int main()
{
std::cout<<"Sterowanie strzałkami";
//App app;
App *pPoint= new App;
pPoint->Run();
//pPoint-> ~App();
return 0;
}
-
Ugh - apart from abusing pointers everywhere even when not needed - and a static renderwindow, your image file goes out of scope when leaving the Ball::Ball constructor. Thus, the image is no longer available when you're trying to draw the sprite.
Please read the documentation here:
http://www.sfml-dev.org/documentation/2.0/classsf_1_1Sprite.htm
Especially this part:
It is important to note that the sf::Sprite instance doesn't copy the image that it uses, it only keeps a reference to it. Thus, a sf::Image must not be destructed while it is used by a sf::Sprite (i.e. never write a function that uses a local sf::Image instance for creating a sprite).
-
Ugh - apart from abusing pointers everywhere even when not needed - and a static renderwindow, your image file goes out of scope when leaving the Ball::Ball constructor. Thus, the image is no longer available when you're trying to draw the sprite.
Please read the documentation here:
http://www.sfml-dev.org/documentation/2.0/classsf_1_1Sprite.htm
Especially this part:
It is important to note that the sf::Sprite instance doesn't copy the image that it uses, it only keeps a reference to it. Thus, a sf::Image must not be destructed while it is used by a sf::Sprite (i.e. never write a function that uses a local sf::Image instance for creating a sprite).
Thanks For Help.
How is the easiest way to fix?
This is my first advanced program. Just learning C++ with the library SFML.
-
The easiest way for you would most likely be to include "iBall" inside the Ball class as a member of that class, instead of declaring it inside the constructor.
And please, don't make it a pointer like everything else. ;)
Like this:
class Ball
{
/* removed for easier reading */
private:
sf::Image iBall;
};
Ball::Ball(float xP, float yP)
{
if(! iBall.LoadFromFile("pilka.bmp") )
{
/* removed for easier reading */
-
The easiest way for you would most likely be to include "iBall" inside the Ball class as a member of that class, instead of declaring it inside the constructor.
And please, don't make it a pointer like everything else. ;)
Like this:
class Ball
{
/* removed for easier reading */
private:
sf::Image iBall;
};
Ball::Ball(float xP, float yP)
{
if(! iBall.LoadFromFile("pilka.bmp") )
{
/* removed for easier reading */
So Image obiekt is to be in the class, and his statement is to be in the constructor?
I realized my mistake. By creating an image object in the constructor it was local, and after exiting the constructor was removed, so show me a white rectangle.
-
That is correct.
It's the way which means the least changes for you.
-
That is correct.
It's the way which means the least changes for you.
Sorry that such a long time, but I did not have access to a computer at the moment. After the change does not display anything to me, I have a black screen. I changed only this entry which I have said.
EDIT
I tried to use the index at all when creating a Sprite, but that does not display anything. Stowrzyłem simplest example code. Image Creation, loading the file, create a Sprite and view it using the index and, unfortunately, does not show it. By using simple variable is all about
-
show your new code if help is needed.
just comments :
int main()
{
std::cout<<"Sterowanie strzałkami";
//App app;
App *pPoint= new App;
pPoint->Run();
//pPoint-> ~App();
return 0;
}
:shock:
int main()
{
std::cout<<"Sterowanie strzałkami";
App app;
app.Run();
return 0;
}
or
int main()
{
App *app=new App;
app->Run();
delete app;
return 0;
}
are better
and you can do simple : inherit the class App from RenderWindow and the class Ball from Sprite
-
Go for the first version. Never ever use the heap when there's not a good reason to do so!
-
Go for the first version. Never ever use the heap when there's not a good reason to do so!
So how best to do it?
Do not want to tangle with the inheritance, I do not have much experience to be able to write it well.
-
So how best to do it?
Use automatic memory management whenever possible.
Type object(args);
DoSomething(object);
instead of
Type* pointer = new Type(args);
DoSomething(*pointer);
delete pointer;