Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Cannot get sprites to draw in order  (Read 2038 times)

0 Members and 1 Guest are viewing this topic.

CannableDev

  • Newbie
  • *
  • Posts: 2
    • View Profile
    • Email
Cannot get sprites to draw in order
« on: July 17, 2018, 04:33:17 pm »
Hey All,

I'm a game dev student that is working with SFML(2.4.2) for the first time.

Context:
I'm making a simple map editor for a terrible frogger clone, that runs off of a 2D array of a class I created, where SFML is drawing a bunch of sprites to fill the screen. I've made another sprite of a crocodile that I need to layer on the top of my water sprites.

So my program is actually working fine logic wise. I have no errors or anything and the crocodile sprites are being drawn in the right location on the right tiles only and everything, but they're layered behind my first set of sprites, so normally they are invisible to the user.

I've made my other layer of sprites partially transparent to make sure of this. I've messed around with changing the draw order of my sprites among other things with no success.

Any advice on how I can get my crocodile sprite to draw over the top of my tile map? I'm open to everything (please be gentle though I only started working with SFML/c++ about 6 weeks ago I'm not too good at this yet)

If you want to take a look at the whole C++ project heres a google drive link (no viruses i promise, though google may disagree): https://drive.google.com/file/d/1ovWeXVrxQS5gxUiUWnbqWVc-DFLZZ3fn/view?usp=sharing

Code below:

int main()
{
   
   // Creating Textures
   Texture asphaltTile;
   if (!asphaltTile.loadFromFile("AsphaltTile.png")) {   }

   Texture grassTile;
   if (!grassTile.loadFromFile("GrassTile.png")) {   }

   Texture waterTile;
   if (!waterTile.loadFromFile("WaterTile.png")) { }

   Texture crocTile;
   if (!crocTile.loadFromFile("CrocTile.png")) { }

   // Colours for showing/hiding croc
   Color invisCroc(0, 0, 0, 0);
   Color visCroc(255, 255, 255, 255);

   RenderWindow window(VideoMode(1024, 576), "Legally Distinct Frogger Level Editor"); // making render window

   Grid theMap = Grid(); // declaring and constructing grid + filling with tiles

   theMap.PrintLayout(theMap);
   
   bool isLeftMouseClicked = false; // bool used for mouse clicking
   bool isRightMouseClicked = false; // bool used for mouse clicking

   // run the program as long as the window is open
   while (window.isOpen())
   {

      if (!Mouse::isButtonPressed(Mouse::Left)) { // if mouse is released allow mouse to be clicked again
         isLeftMouseClicked = false;
      }

      if (!Mouse::isButtonPressed(Mouse::Right)) { // if mouse is released allow mouse to be clicked again
         isRightMouseClicked = false;
      }

      // check all the window's events that were triggered since the last iteration of the loop
      Event event;
      while (window.pollEvent(event))
      {
         // "close requested" event: we close the window
         if (event.type == Event::Closed)
            window.close();
      }


      for (int i = 0; i < 18; i++) { // drawing sprites

         for (int j = 0; j < 32; j++) {

            Sprite newSprite; // declaring sprite to draw
            newSprite.setPosition(j * 32, i * 32);

            Sprite crocSprite; // declaring sprite to draw
            crocSprite.setPosition(j * 32, i * 32);
            

                                // Changing texture based on which tile type is selected for current tile
            switch (theMap.map[j].myType) {
            case TileType::Asphalt:
               newSprite.setTexture(asphaltTile);
               newSprite.setColor(Color(255, 255, 255, 128)); // transparent tiles for testing
               break;

            case TileType::Grass:
               newSprite.setTexture(grassTile);
               newSprite.setColor(Color(255, 255, 255, 128));
               break;

            case TileType::Water:
               newSprite.setTexture(waterTile);
               newSprite.setColor(Color(255, 255, 255, 128));
               break;

            }
                               
                                // if water tile has croc enabled, draw a croc | otherwise set sprite to be invisible
            if (theMap.map[j].hasCroc && theMap.map[j].myType == TileType::Water) {
               crocSprite.setTexture(crocTile);
               crocSprite.setColor(visCroc);
            }
            else {
               crocSprite.setColor(invisCroc);
            }

            window.draw(crocSprite);
            window.draw(newSprite);

            if (Mouse::isButtonPressed(Mouse::Left) && !isLeftMouseClicked) {
               // When the mouse is clicked, disables the mouse click with bool to prevent double clicks
               // and sets the clicked tile to the next tile type

               if (newSprite.getGlobalBounds().contains(window.mapPixelToCoords(Vector2i(event.mouseButton.x, event.mouseButton.y)))) {
                  cout << "Left Click Detected" << endl;

                                                // changing tile's type to new one when clicked
                  switch (theMap.map[j].myType) {
                  case TileType::Asphalt:
                     theMap.map[j].myType = TileType::Water;
                     break;

                  case TileType::Grass:
                     theMap.map[j].myType = TileType::Asphalt;
                     break;

                  case TileType::Water:
                     theMap.map[j].myType = TileType::Grass;
                     break;
                  }

                  isLeftMouseClicked = true;

               }

            }

            if (Mouse::isButtonPressed(Mouse::Right) && !isRightMouseClicked) {
               // When the mouse is clicked, disables the mouse click with bool to prevent double clicks
               // and sets a croc to be drawn if a water tile is clicked

               if (newSprite.getGlobalBounds().contains(window.mapPixelToCoords(Vector2i(event.mouseButton.x, event.mouseButton.y)))) {
                  cout << "Right Click Detected" << endl;

                  if (theMap.map[j].hasCroc) {

                     theMap.map[j].hasCroc = false;

                  }
                  else if (theMap.map[j].myType == TileType::Water) {

                     theMap.map[j].hasCroc = true;

                  }

                  isRightMouseClicked = true;

               }

            }

         }

      }

      window.display();

   }
   
}

 
« Last Edit: July 17, 2018, 05:30:46 pm by CannableDev »

tomvidm

  • Newbie
  • *
  • Posts: 15
    • View Profile
Re: Cannot get sprites to draw in order
« Reply #1 on: July 17, 2018, 05:17:52 pm »
In your code, you draw the crocSprite before newSprite. As far as I can see, newSprite is supposed to be the "tile" sprite. Just switch their ordering.

window.draw(crocSprite);
window.draw(newSprite);


You said you are new to SFML, so I want to give you a few handy tips.
1. You have declared bools that check if a mouse button has already been pressed, disallowing further clicks during that frame. This is a non-problem, and you should skip this bool checking completely. You already use the sf::Mouse interface, and a frame is most likely too fast for it to be possible to click twice during it.

2. Encapsulate. You already encapsulated parts of your code (Like the Grid object). However, you should continue encapsulating it, as it will make each block of code easier to read and debug. Identify parts of the code that can be written as a function. Avoid nested if-for-if-for blocks. It will make everything a lot easier for you :)

Good luck!
« Last Edit: July 17, 2018, 05:20:41 pm by tomvidm »

CannableDev

  • Newbie
  • *
  • Posts: 2
    • View Profile
    • Email
Re: Cannot get sprites to draw in order
« Reply #2 on: July 17, 2018, 05:29:53 pm »
I could have sworn I reordered that 5-6 times and tested with no difference, but it's working now so I guess I'm just an idiot.

Thanks for pointing it out.

For the bool on mouse clicking, (at least with the way I'm doing it now) I need it there because if you hold down left click over a tile it rapidly changes its texture, but I'll have another look at working around it.

As for encapsulating, I'm currently in the middle of that. Quite literally only learnt about writing between files and using headers and what not two days ago  so, still getting on top of that one.

Appreciate the help :)

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Cannot get sprites to draw in order
« Reply #3 on: July 17, 2018, 05:48:18 pm »
Glad you got the sprite ordering sorted. :)

You can (probably should) use events to do something whenever a mouse is clicked rather than wanting to know if it's currently pressed.

Also, speaking of events, you use event.mouseButton outside of the event loop so event isn't guaranteed to actually be storing a mouse button event. Remember to use event variable only inside the event loop.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*