My Sprites are not drawing even though there is no error? - c++

Here is my code.I just dont know why my sprites are not drawing. I used the window.draw() function in the nested for loop for 2d array of sprites but it is not drawing it.Just look at my nested loop for 2d array of sprites named Board. Help will be appreciated.
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
#include <stdlib.h>
#include<time.h>
#include<cstdlib>
using namespace std;
using namespace sf;
int main()
{
Music music;
music.openFromFile("mainmusic.wav");
music.play();
bool drawRed = true;
bool deletePlay = false;
//Creating window for game
sf::RenderWindow window(sf::VideoMode(1280, 720), "SFML", sf::Style::Close | Style::Titlebar);
//creating rect of exact sem size as window to use it for a bg
sf::RectangleShape player(sf::Vector2f(1280.0f, 720.0f));
//creating a texture for starting background
sf::Texture bg_texture;
bg_texture.loadFromFile("candy_crushbg.jpg");
player.setTexture(&bg_texture);
//creating texture for play button
Texture play;
play.loadFromFile("cstartbtn.png");
//creating sprite for play button texture
Sprite start;
start.setTexture(play);
start.setPosition(Vector2f(530, 490));
start.setScale(Vector2f(0.2f, 0.2f));
start.setOrigin(Vector2f(265, 245));
//creating texture for playing background
Texture startbg;
startbg.loadFromFile("start_bg.jpg");
int k, lower = 1, upper = 5, x = 400, y = 100;
Texture RCandy, BCandy, OCandy, GCandy, YCandy;
RCandy.loadFromFile("red_candy.png");
BCandy.loadFromFile("blue_candy.png");
OCandy.loadFromFile("orange_candy.png");
GCandy.loadFromFile("green_candy.png");
YCandy.loadFromFile("yellow_candy.png");
Sprite Board[8][8];
srand(time(0));
int i, j, random;
//loop for opening window
while(window.isOpen()) {
//creating event for game functions
sf::Event evnt;
Event play;
//calling event in a loop
while (window.pollEvent(evnt)) {
switch (evnt.type) {
//event for when we click close button
case sf::Event::Closed:
window.close();
break;
//event when mouse is clicked on PLAY button
case Event::MouseButtonPressed:
//getting global boundaries of play button
sf::Vector2f Mousepos = window.mapPixelToCoords(sf::Mouse::getPosition(window));
switch(evnt.key.code) {
case Mouse :: Left:
//checking if mouse click is in the boundary of play button
if (start.getGlobalBounds().contains(Mousepos)) {
cout << "Sprite Clicked\n";
//deleting play button
deletePlay = true;
window.clear();
player.setTexture(&startbg);
`
for (i = 0; i < 8; i++) {
x = 400;
for (j = 0; j < 8; j++) {
random = rand() % ((upper - lower) + lower) + 1;
cout << random << " ";
x = x + 50;
if (random == 1) {
Board[i][j].setTexture(RCandy);
Board[i][j].setPosition(x, y);
Board[i][j].setScale(Vector2f(0.2f, 0.2f));
}
else if (random == 2) {
Board[i][j].setTexture(OCandy);
Board[i][j].setPosition(x, y);
Board[i][j].setScale(Vector2f(0.2f, 0.2f));
}
else if (random == 3) {
Board[i][j].setTexture(YCandy);
Board[i][j].setPosition(x, y);
Board[i][j].setScale(Vector2f(0.2f, 0.2f));
}
else if (random == 4) {
Board[i][j].setTexture(GCandy);
Board[i][j].setPosition(x, y);
Board[i][j].setScale(Vector2f(0.2f, 0.2f));
}
else if (random == 5) {
Board[i][j].setTexture(BCandy);
Board[i][j].setPosition(x, y);
Board[i][j].setScale(Vector2f(0.2f, 0.2f));
}
window.draw(Board[i][j]);
window.display();`
}
cout << endl;
y = y + 50;
}
}
}
break;
}
}
window.draw(player);
if (!deletePlay) {
window.draw(start);
}
window.display();
}
}

You must draw your board outside of the event loop.
Right now, your board is displayed only once (When you click on the left button of your mouse). You should write something like that after the 'window.clear();':
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
window.draw(Board[i][j]);
Also, you must use 'window.display();' only once and at the end of the game loop.
If your want to draw the board as long as your the left button of your mouse is pressed, you can use:
if(sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
}

Related

Why are the rectangles/bars not swapping with each other?

I am writing a bubble sort visualizer. But I can't seem to figure out how to swap the rectangles/bars.
#include<iostream>
#include<SFML/Graphics.hpp>
#include<cstdlib>
#include<ctime>
#include<chrono>
#include<thread>
int main()
{
srand(time(NULL));
sf::RenderWindow window(sf::VideoMode(798, 400), "Yoo", sf::Style::Default);
sf::RectangleShape *rec=new sf::RectangleShape[133];
for (int i = 0; i < 133; i++)
{
int num = rand() % 400;
rec[i].setFillColor(sf::Color::Red);
rec[i].setSize(sf::Vector2f(4.0f, static_cast<float>(num)));
rec[i].setPosition(sf::Vector2f(static_cast<float>(i * 6), 400-num));
}
sf::Event ev;
while (window.isOpen())
{
int i = rand() % 133;
int j = rand() % 133;
while (window.pollEvent(ev))
{
if (ev.type == sf::Event::Closed())
{
window.close();
}
}
window.clear(sf::Color::White);
rec[i].setFillColor(sf::Color::Blue);
rec[j].setFillColor(sf::Color::Green);
sf::Vector2f tmp = rec[i].getPosition();
sf::Vector2f size = rec[i].getSize();
rec[i].setPosition(rec[j].getPosition());
rec[i].setSize(rec[j].getSize());
rec[j].setSize(size);
rec[j].setPosition(tmp);
for (int i = 0; i < 133; i++)
{
window.draw(rec[i]);
}
rec[i].setFillColor(sf::Color::Red);
rec[j].setFillColor(sf::Color::Red);
window.display();
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
}
delete[] rec;
}
what is wrong with this code? I have tried normal swapping using std::swap to swap the rectangle array. It didn't work. So, I thought I should swap the position and size. It is not working either. But as shown in this picture, I can see the colors Blue and Green are interchanging correctly.
I tested your program. Your goal is to draw a green bar and a blue bar and swap them?
When you draw your rectangle, you swap them before displaying the window. So you don't see them swap. If you want, you have to draw your rectangles and display your window before swapping them.
window.clear(sf::Color::White);
rec[i].setFillColor(sf::Color::Blue);
rec[j].setFillColor(sf::Color::Green);
for (int i = 0; i < 133; i++)
{
window.draw(rec[i]);
}
window.display(); // display them before swap.
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
window.clear(sf::Color::White);
sf::Vector2f tmp = rec[i].getPosition();
sf::Vector2f size = rec[i].getSize();
rec[i].setPosition(rec[j].getPosition());
rec[i].setSize(rec[j].getSize());
rec[j].setSize(size);
rec[j].setPosition(tmp);
for (int i = 0; i < 133; i++)
{
window.draw(rec[i]);
}
rec[i].setFillColor(sf::Color::Red);
rec[j].setFillColor(sf::Color::Red);
window.display(); // display them again
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
something like this.

Random shape and movement generation not drawing shape

I have been working on a simple C++ and SFML program recently, but have gotten stuck. Basically I want to do two things:
I want to generate a number of circles with random coordinates
I want to make those circles move randomly around the screen
I figured using a vector for the circles would be best so that I can use am int to determine the number of shapes.
The coordinates are generating correctly, but the shape is not drawing to the screen!
Here is my code:
#include "SFML/Graphics.hpp"
#include <stdlib.h>
#include <iostream>
int main()
{
srand(time(NULL));
const int WINDOW_X = 800;
const int WINDOW_Y = 480;
sf::RenderWindow window(sf::VideoMode(WINDOW_X, WINDOW_Y), "Epidemic Simulation", sf::Style::Close | sf::Style::Titlebar);
int numPeople = 2;
float size = 5;
int status = 0;
//Declare CircleShape
std::vector<sf::CircleShape> person(size);
//Change color depending on status
for (int i = 0; i < numPeople; i++)
{
if (status == 0)
person[i].setFillColor(sf::Color::Green);
else if (status == 1)
person[i].setFillColor(sf::Color::Red);
else if (status == 2)
person[i].setFillColor(sf::Color::Black);
else
{
std::cout << ("Error: Incorrect color value");
person[i].setFillColor(sf::Color::Green);
}
}
//Generate random coordinates for each circle
for (int i = 0; i < numPeople; i++)
{
int xPos = rand() % WINDOW_X - (size * 2);
int yPos = rand() % WINDOW_Y - (size * 2);
if (xPos < (size * 2))
xPos = 0;
if (yPos < (size * 2))
yPos = 0;
std::cout << ("X position: ") << xPos << (", Y position: ") << yPos << "\n";
}
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear(sf::Color::White);
//Draw circle
for (int i = 0; i < numPeople; i++)
window.draw(person[i]);
window.display();
}
return 0;
}
Any idea why the shape is not drawing? And how would I get the shape to move in a random direction?
It seems you just have to make a few changes.
The main ones (from the output of the diff command) are:
> // Give the circles definite radius value and segment count:
> for (int i = 0; i < numPeople; i++)
> {
> person[i].setRadius(size);
> person[i].setPointCount(100);
> }
and also:
// Generate random coordinates for each circle:
for (int i = 0; i < numPeople; i++)
{
int xPos = rand() % WINDOW_X - (size * 2);
int yPos = rand() % WINDOW_Y - (size * 2);
... <clip> ...
person[i].setPosition(xPos, yPos);
}
Side note:
The srand() and rand() functions are part of a legacy C API. They are not meant to be used in new C++ code. It is recommended to #include the <random> header and use the C++11 API. See paper for details: n3551.pdf.

How do you access each shape/object individually in SFML for C++

I'am looking for a way to make multiple clickable rectangle shapes appear on the users screen using SFML.
The code that i wrote only works for the last initialized shape and changes the color for all of the squares.
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace std;
int main()
{
sf::RenderWindow window(sf::VideoMode(1280, 720), "warships");
sf::RectangleShape shape(sf::Vector2f(50, 50));
shape.setFillColor(sf::Color::Green);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear(sf::Color::Black);
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 10; ++j)
{
int x,y;
y = 50 + 65 * i;
x = 260 + 80 * j;
shape.setPosition(x,y);
window.draw(shape);
}
}
if (shape.getGlobalBounds().contains(window.mapPixelToCoords(sf::Mouse::getPosition(window))) and event.type == sf::Event::MouseButtonPressed )
shape.setFillColor(sf::Color::Yellow);
window.display();
}
return 0;
}
As suggested in the comments, you create only one RectangleShape and then change it's position. Probably better idea would be to create array of shapes with predefined positions at the begining of your code like this:
std::vector<sf::RectangleShape> shapes;
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 10; ++j)
{
int x,y;
y = 50 + 65 * i;
x = 260 + 80 * j;
shapes.push_back(sf::RectangleShape(sf::Vector(x, y)));
shapes.back().setFillColor(sf::Color::Green);
}
}
then in your drawing loop just simply
window.clear(sf::Color::Black);
for (auto& shape : shapes)
{
if (shape.getGlobalBounds().contains(window.mapPixelToCoords(sf::Mouse::getPosition(window))) and event.type == sf::Event::MouseButtonPressed )
shape.setFillColor(sf::Color::Yellow);
window.draw(shape);
}
window.display();

SFML draw many sprites

So I need to draw one sprite like 5 times, moving another sprite some pixels forward, so they don't stack. My for loop didn't work and now I have no idea how to do this. I also created a class Hero, because I need to draw it's sprite only 1 time. When I run the program, it displays only 1 tower on nothing.
int main() {
sf::RenderWindow screen(sf::VideoMode(700, 580), "SFML Demo");
sf::Event event;
int posX = 0, posY = 0;
Image TileSet;
TileSet.loadFromFile("Town.png");
Hero My_Hero("Orc.png");
Texture TowerTexture;
TowerTexture.loadFromImage(TileSet);
Sprite Tower;
Tower.setTexture(TowerTexture);
Tower.setPosition(0, 0);
Tower.setTextureRect(IntRect(383, 96, 145, 280));
while (screen.isOpen()) {
while (screen.pollEvent(event)) {
if (event.type == sf::Event::EventType::Closed)
screen.close();
}
screen.clear();
for (int i = 0; i < 4; ++i) {
screen.draw(Tower);
posX += 40;
Tower.setPosition(posX, posY);
}
My_Hero.MoveHero();
screen.draw(My_Hero.getSprite());
screen.display();
}
}
Your problem come from posX.
You should set back posX to zero every frame.
Something like:
posX = 0;
for (int i = 0; i < 4; ++i) {
screen.draw(Tower);
posX += 40;
Tower.setPosition(posX, posY);
}

Trying to make a ball bounce across the render window

I am trying to make a ball bounce across the render window using SFML. I am trying to make the ball appear in a new random location each time as well. I cannot make the ball go infinitely though. When ever I play it and it spawns a new location it does not bounce off the render window though. I don't know how to make it do this.
#include <iostream>
#include <SFML/Graphics.hpp>
#include <stdlib.h>
#include <time.h>
using namespace std;
using namespace sf;
int main()
{
RenderWindow window(sf::VideoMode(1500, 800), "Bouncing Circle");
window.setFramerateLimit(60);
srand(time(NULL));
int randx = rand() % 1500 + 1;
int randy = rand() % 800 + 1;
int x;
int y;
int distance = 1500 - randx;
int distance2 = 800 - randy;
int BREAK = 1;
sf::CircleShape MyCircle(50);
MyCircle.setPosition(randx, randy);
MyCircle.setFillColor(sf::Color(500, 0, 0));
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event))
;
{
if (event.type == sf::Event::Closed)
window.close();
}
x = randx;
y = randy;
for (int ii = 0; ii < distance and ii < distance2; ii++) {
x++;
y++;
MyCircle.setPosition(x, y);
window.draw(MyCircle);
window.display();
window.clear();
if (x == distance and y == distance2) {
for (int aa = 0; aa <= 650; aa++) {
MyCircle.setPosition(x, y);
////////////////////////////
// The code past this mark is from a different thing I tried. It is probably useless[
////////////////////////////
x++;
y--;
window.draw(MyCircle);
window.display();
window.clear();
if (aa == 650) {
for (int pp = 0; pp <= 92; pp++) {
MyCircle.setPosition(x, y);
x++;
y++;
window.draw(MyCircle);
window.display();
window.clear();
if (pp == 92) {
for (int n = 0; n <= 570; n++) {
MyCircle.setPosition(x, y);
x--;
y++;
window.draw(MyCircle);
window.display();
window.clear();
}
////////////////////////////
// ]
////////////////////////////
}
}
}
}
}
}
}
return 0;
}