SFML community forums

Help => Graphics => Topic started by: Jimicro on January 25, 2010, 07:49:33 pm

Title: Drawing Images problem
Post by: Jimicro on January 25, 2010, 07:49:33 pm
Hello

I´m on a school projekt to do a little game. But I´m stuck. I don´t know how to draw images when they are in another file. The compiler says that Draw it´s no a function to the class. Here is the soruce for better description.

Code: [Select]
view.cpp #include <SFML/Graphics.hpp>
#include <fstream>
#include <iostream>

using namespace sf;
using namespace std;

class Map: public Sprite
{
    private:
    sf::Sprite sprite;
    char num;
    char level[12][12];
    int height;

    //Create image
   sf::Image blockImage;
   sf::Image groundImage;
   sf::Image wallImage;

    public:
    void openFile();
    void updateMap();
    void loadAllImages();
    void update();
    Map();

};


void Map::openFile()
{
    height = 0;

    //Read textfle (2D char array)
   ifstream file;
   file.open("level.txt");


   std::string line;

    while(getline(file, line))
   {
      for(int width = 0; width < 12; width++)
      {
         level[height][width] = line.at(width);
      }
      height++;
   }
   //Close file stream
   file.close();
}
void Map::loadAllImages()
{
   //Create Sprite
   Sprite blockTile(blockImage);
   Sprite groundTile(groundImage);
   Sprite wallTile(wallImage);
}

void Map::updateMap()
{

    //Scroll through level and display corresponding image of tile
      for(int y = 0; y < 12; y++)
      {
         for(int x = 0; x < 12; x++)
         {
            num = level[y][x];

            if(num == '1')
            {

               this->sprite.SetPosition(x*50, y*50);
               this->sprite.SetImage(blockImage);

            }
            else if(num == '2')
            {
               this->sprite.SetPosition(x*50, y*50);
               this->sprite.SetImage(groundImage);
            }
            else if(num == '3')
            {
                this->sprite.SetPosition(x*50, y*50);
                this->sprite.SetImage(wallImage);
            }
         }
      }
}


and the other file that contains main function.

Code: [Select]
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <fstream>
#include "view.cpp"

using namespace sf;
using namespace std;


int main()
{

    Map map;
    map.openFile();

    map.updateMap();
    //Display using SFML
    //Render Window
    sf::RenderWindow App(sf::VideoMode(640, 480), "Shoot");
    //Game loop
    while (App.IsOpened())
    {
      sf::Event Event;
      while(App.GetEvent(Event))
      {
         if(Event.Type == sf::Event::Closed)
         {
            App.Close();
         }
      }
    map.loadAllImages();


    App.Draw();
    // Clear the screen with white color
    App.Clear(sf::Color(0, 0, 255));
    //Display sprites
    App.Display();
   }
   return EXIT_SUCCESS;
   //*/
}


Hope you can help me :)
Title: Drawing Images problem
Post by: Laurent on January 25, 2010, 07:56:09 pm
Hi

Don't include a .cpp file, it's meant to be compiled and linked, not included. You must split the declaration of your class and its implementation into a header (.h) and a .cpp file.

Quote
The compiler says that Draw it´s no a function to the class

Draw wants a parameter (the object to draw). And you should call it after Clear if you want to see something ;)
Title: Drawing Images problem
Post by: Jimicro on January 25, 2010, 08:04:30 pm
Quote from: "Laurent"
Hi

Don't include a .cpp file, it's meant to be compiled and linked, not included. You must split the declaration of your class and its implementation into a header (.h) and a .cpp file.

Quote
The compiler says that Draw it´s no a function to the class

Draw wants a parameter (the object to draw). And you should call it after Clear if you want to see something ;)


okey, I will do that, but what should it be as parameter? If I remove the Draw function it will only render a blue background.

So I have no clue right now what it´s should be in the draw function.

map.Draw(&App)?
Title: Drawing Images problem
Post by: Laurent on January 25, 2010, 08:16:17 pm
Have you read the tutorials? ;)

Code: [Select]
App.Draw(map);
Title: Drawing Images problem
Post by: Jimicro on January 25, 2010, 08:19:04 pm
Quote from: "Laurent"
Have you read the tutorials? ;)

Code: [Select]
App.Draw(map);


Yes, of course. A lot of times :)

But I have tried App.Draw(map); But maybe I should check if all images loads correct.

See if I can solve the problem :)
Title: Drawing Images problem
Post by: Laurent on January 25, 2010, 08:31:11 pm
Do you have another problem when you correct this? What is it?
Title: Drawing Images problem
Post by: Jimicro on January 25, 2010, 08:39:27 pm
Quote from: "Laurent"
Do you have another problem when you correct this? What is it?


They are linked together, I want to App.Draw(groundImage); for example. Where
Code: [Select]
if(num=='1')
{
this->sprite.SetPosition(x*50, y*50);
this->sprite.SetImage(groundImage);
App.Draw();
}



But it doesn´t work.

But if I do like I did first I only get a white dot in the left upper corner. I guess thats a image that failed to load.

But how do I do to draw a Image in that case. It´s a tiled map, but it doesn´t draw any images. :(
Title: Drawing Images problem
Post by: Laurent on January 25, 2010, 08:47:59 pm
Hum, in fact there are many errors in your code ;)

Code: [Select]
void Map::loadAllImages()
{
   //Create Sprite
   Sprite blockTile(blockImage);
   Sprite groundTile(groundImage);
   Sprite wallTile(wallImage);
}

Here you just create temporary sprites using your images. These sprites will be destroyed when the function returns, so it's basically doing nothing at all. I guess you want to load your images from files?
Code: [Select]
void Map::loadAllImages()
{
   if (!blockImage.LoadFromFile("path/to/block-image") ||
       !groundImage.LoadFromFile("path/to/ground-image") ||
       !wallImage.LoadFromFile("path/to/wall-image"))
    {
        // error...
    }
}

Then you inherit from Sprite but you never use your base class. My advice would be to avoid inheriting from sf::Sprite to start. Just have a sprite as a member, and create a function to draw your map. This is what you tried to do with updateMap, all you have to do is to pass a reference to the window because you'll need it to draw something.
Code: [Select]
void Map::draw(sf::RenderWindow& window)
{

    //Scroll through level and display corresponding image of tile
      for(int y = 0; y < 12; y++)
      {
         for(int x = 0; x < 12; x++)
         {
            num = level[y][x];

            if(num == '1')
            {
               this->sprite.SetPosition(x*50, y*50);
               this->sprite.SetImage(blockImage);
            }
            else if(num == '2')
            {
               this->sprite.SetPosition(x*50, y*50);
               this->sprite.SetImage(groundImage);
            }
            else if(num == '3')
            {
                this->sprite.SetPosition(x*50, y*50);
                this->sprite.SetImage(wallImage);
            }
            window.Draw(this->sprite);
         }
      }
}

Code: [Select]
// In your main:
map.draw(App);


When everything works, I suggest that you create one sprite per tile rather than reusing a single sprite to draw them all. This is more efficient, you only need to set the position/image/etc of tiles once rather than every time you draw them.
Title: Drawing Images problem
Post by: Jimicro on January 25, 2010, 09:17:39 pm
Quote from: "Laurent"
Hum, in fact there are many errors in your code ;)

When everything works, I suggest that you create one sprite per tile rather than reusing a single sprite to draw them all. This is more efficient, you only need to set the position/image/etc of tiles once rather than every time you draw them.


Thanks a lot :) I think just like you said before it´s something wrong with the linking, it doesn´t work now to link. I put them both in a project, one is main and one is called view.cpp.

So i guess I have to check the linkings out. But I am very grateful:D I hope it vill work soon.

I have two days now to complete a lot of things.
Title: Drawing Images problem
Post by: Jimicro on January 25, 2010, 09:47:15 pm
Quote from: "Jimicro"
Quote from: "Laurent"
Hum, in fact there are many errors in your code ;)

When everything works, I suggest that you create one sprite per tile rather than reusing a single sprite to draw them all. This is more efficient, you only need to set the position/image/etc of tiles once rather than every time you draw them.


Thanks a lot :) I think just like you said before it´s something wrong with the linking, it doesn´t work now to link. I put them both in a project, one is main and one is called view.cpp.

So i guess I have to check the linkings out. But I am very grateful:D I hope it vill work soon.

I have two days now to complete a lot of things.


OMG. I don´t what to say, It works :D :D, It actually works. I´m very happy. because I´m so tired, school all day and it´s finally works.

Thank You very much :D!!!
Title: Drawing Images problem
Post by: Laurent on January 25, 2010, 09:54:57 pm
I'm glad you made it work :)
Title: Drawing Images problem
Post by: Jimicro on January 26, 2010, 03:26:29 pm
Is there anyway to compare the sprite with another image who lies in another file? like
Code: [Select]
if(character.getPosition().x <= tileSprite.GetPosition().x){
character.Move(0, 0);
}


?
Title: Drawing Images problem
Post by: Laurent on January 26, 2010, 06:36:30 pm
Sure.
Title: Drawing Images problem
Post by: Jimicro on January 26, 2010, 06:48:26 pm
Quote from: "Laurent"
Sure.


But what should I write to get the images to a class so I can compare them?

How should I do to make the sprites so I can write like I did before, so the sprite has names like wallTile.getPosition().x ? is there some way? they are like this->sprite.wallTile, and I can´t just write this->sprite(wallTile).getPosition().x

Any Ideas?
Title: Drawing Images problem
Post by: Laurent on January 26, 2010, 06:50:04 pm
Sorry, I don't understand what you want to compare.
Title: Drawing Images problem
Post by: Jimicro on January 26, 2010, 07:08:22 pm
Quote from: "Laurent"
Sorry, I don't understand what you want to compare.


Okey, I will try to explain again, I´m not so good at english :P

btw, I have 2 classes, one with character and one with tile images, and I do´t want the character to run through the wall, so I need a function to check so the character will stop if try run through the wall (image), I have done it before, but not now when they are in diffrent classes.

So I can´t just write if( character.getPosition().x <= wall.getPosition().x)

because they are in different classes. So is there any ideas?

I guess I have to do it like change  so the images is sprites with names. Like wall.getPosition for example. But I don´t now how.
Title: Drawing Images problem
Post by: Laurent on January 26, 2010, 07:59:17 pm
It will probably be easier if you show the real code (the two classes), and show in your code what you'd like to do and where ;)
Title: Drawing Images problem
Post by: Jimicro on January 26, 2010, 08:07:36 pm
Quote from: "Laurent"
It will probably be easier if you show the real code (the two classes), and show in your code what you'd like to do and where ;)


Yeah I thought so too :)
Here is the view class again.

Code: [Select]

#include <SFML/Graphics.hpp>
#include <fstream>
#include <iostream>
#include "view.hpp"

using namespace sf;
using namespace std;

void Map::openFile()
{
    height = 0;

    //Read textfle (2D char array made up of a series of integers/letters)
   ifstream file;
   file.open("level.txt");

   std::string line;

    while(getline(file, line))
   {
      for(int width = 0; width < 12; width++)
      {
         level[height][width] = line.at(width);
      }
      height++;

   }
   //Close file stream
   file.close();
}
void Map::loadAllImages()
{
   if(!blockImage.LoadFromFile("cloud.jpg")||
   !groundImage.LoadFromFile("blocks.jpg") ||
   !wallImage.LoadFromFile("wall.jpg"))
   {
       //error
   }
}

void Map::draw(sf::RenderWindow& window)
{
    //Scroll through level and display corresponding image of tile
      for(int y = 0; y < 12; y++)
      {
         for(int x = 0; x < 12; x++)
         {
            num = level[y][x];

            if(num == '1')
            {

               this->sprite.SetPosition(x*50, y*50);
               this->sprite.SetImage(blockImage);

            }
            else if(num == '2')
            {
               this->sprite.SetPosition(x*50, y*50);
               this->sprite.SetImage(groundImage);
            }
            else if(num == '3')
            {
                this->sprite.SetPosition(x*50, y*50);
                this->sprite.SetImage(wallImage);
            }
            window.Draw(this->sprite);
         }
      }
}


You see here above, this->spriteSetImage(wallImage); for example. I want so I can make them to sprite. So I can compare the image size and position with the boy´s position and size.

main:

Code: [Select]
#include "animated.hpp"
#include "view.hpp"
#include "klocka.hpp"
#include <iostream>

using namespace sftools;

enum DIRECTION {UP = 0, RIGHT = 1, DOWN = 2, LEFT = 3};

/// Load an anim, with a constant format, from a picture.
Anim AnimFromImage(const sf::Image& img, int colone_px = 0)
{
    Anim ret;
    const int width_px(50);
    for (int i = 0; i < 4; ++i)
        ret.PushFrame(Frame(img,
                            sf::IntRect(width_px * i,
                                        colone_px * 64,
                                        width_px * (1 + i),
                                        (colone_px + 1) * 68)));
    return ret;
}

/// Update the boy's anim and made his moves.
void UpdateBoy(Animated& boy, const sf::Input& input, DIRECTION& direction,
float frame_time, Anim anims[4])
{

    // Update the boy.
    boy.Update();

    // If going upward...
    if (input.IsKeyDown(sf::Key::Up))
    {
        // Don't reset the anim.
        if (direction != UP)
        {
            boy.SetAnim(anims[UP], true); // Set the new anim, and play it.
            direction = UP;
        }
        else
            boy.Play(); // In case of not currently playing.

        // Move the boy.

    }

    // leftward...
    else if (input.IsKeyDown(sf::Key::Left))
    {
        // Working the same.
        if (direction != LEFT)
        {
            boy.SetAnim(anims[LEFT], true);
            direction = LEFT;
        }
        else
        boy.Play();

        boy.Move(-200 * frame_time, 0);
    }

    // rightward...
    else if (input.IsKeyDown(sf::Key::Right))
    {
        // Working the same.
        if (direction != RIGHT)
        {
            boy.SetAnim(anims[RIGHT], true);
            direction = RIGHT;
        }
        else
            boy.Play();

        boy.Move(200 * frame_time, 0);
    }

    // Doesn't move..
    else
    boy.Stop();
}

/// Our main function.
int main(int, char**)
{
    Map map;
    klocka Klocka;
    Klocka.i = 10;
    Klocka.b = 1;
    Clock Uhr;
    Klocka.ticka();

    map.loadAllImages();
    // Our beautiful window. :)
    sf::RenderWindow window(sf::VideoMode(600, 500, 32),
    "Spel");

    // Loading a picture with four anims.
    sf::Image char_anim;
    if (!char_anim.LoadFromFile("character2.png"))
    {
        std::cerr << "Error : cannot load character.png.\n";
        return EXIT_FAILURE;
    }
    char_anim.CreateMaskFromColor(sf::Color::Black);

    // Four anims : up, down, left, right.
    Anim go[4];
    for (int i = 0; i < 4; ++i)
        go[i] = AnimFromImage(char_anim, i);

    // In 'pause' and 'loop' mode ; frame time is 0.1 s ; looking upward :
    Animated boy(go[UP], 0.1f);
    boy.SetCenter(20, 32);
    boy.SetPosition(100, 350);
    DIRECTION direction = UP;

    // Main loop.
    sf::Event event;
    bool running = true;
    while (running)
    {
        // Events loop.
        while (window.GetEvent(event))
        {
            // Here we just deal with close event.
            // Moving is handle by sf::Input.
            switch (event.Type)
            {
                case sf::Event::Closed:
                    running = false;
                    break;

                case sf::Event::KeyReleased:
                    switch (event.Key.Code)
                    {
                        case sf::Key::Escape:
                            running = false;
                            break;

                        default:
                        break;
                    }
                    break;

            default:
            break;
            }
        }
        // Clear the screen with white color
        window.Clear(sf::Color(0, 0, 0));

        if(Uhr.GetElapsedTime() > 1)
        {
            Klocka.ticka();
            Uhr.Reset();
        }

        // Make all updates.
        UpdateBoy(boy, window.GetInput(), direction,
        window.GetFrameTime(), go);
        map.openFile();

        map.draw(window);
        // Draw our strings
        window.Draw(Klocka.Hello);
        // Draw everything.
        window.Draw(boy);
        window.Display();
    }

    return EXIT_SUCCESS;
}




Here is the main.

So you see I use the anim source from wiki.

Now you see main and view, I want so the boy will detect if there is a wall. But in the UpdateBoy I can write boy.getPosition().x <= 50) just to go throug the wall. But its just a very basic thing that not will work in the end. So I want to like if(boy.getPos().x <= tile.getPosition().x)

But the images is just images.
Title: Drawing Images problem
Post by: Laurent on January 26, 2010, 08:29:02 pm
What about a function such as "map.CheckCollision(boy)" ?
Title: Drawing Images problem
Post by: Jimicro on January 26, 2010, 08:30:36 pm
Quote from: "Laurent"
What about a function such as "map.CheckCollision(boy)" ?


Yeah :) That should be nice. But where shall I write it? In the main or in view?
Title: Drawing Images problem
Post by: Jimicro on January 26, 2010, 10:06:58 pm
You can´t give me an example? I have tried all day long. But I can´t get it to work. I´m total stuck. Its just between the images and the boy where everything just not will work.

is there some way to get this to work? Everything would be so much easier I guess if it just was sprites all in just one main, but you can´t make a game without :P.

I guess I have to check collision in void UpdateBoy(), beacuse there is the movement, and there is the only function where I can change the speed.

Is there a way to implement one function of map, and all the sprites position to check with the boy? and every sprite has a individual abilty.

groundImage you should not fall down through, and the wall is you suppose not to go trough.

But I don´t know how. :(
Title: Drawing Images problem
Post by: Oz1571 on January 26, 2010, 10:18:58 pm
I recommend reading up on the basics of pointers, that should help you do what you are trying to do. Unless I'm missing something. I don't know if this is the best forum for basic programming questions, unfortunately. I'm not trying to be rude or anything, I just think you might have more luck getting help elsewhere. :)
Title: Drawing Images problem
Post by: Jimicro on January 26, 2010, 10:27:21 pm
Quote from: "Oz1571"
I recommend reading up on the basics of pointers, that should help you do what you are trying to do. Unless I'm missing something. I don't know if this is the best forum for basic programming questions, unfortunately. I'm not trying to be rude or anything, I just think you might have more luck getting help elsewhere. :)


yeah I guess so :)
Title: Drawing Images problem
Post by: Jimicro on January 28, 2010, 05:19:20 pm
I got it to work now :) But which is the best way to check collision? GetPosition maybe isn´t the best way.