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

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.

Related

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

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))
{
}

C++ - Blocks don't move and my array does not work

I'm trying to make a game using C++ in SFML for the first time.
Want : 6 blocks fall from random top to bottom.
Result : 1 block stay at the top.
How should I fix in this code?
#include <SFML/Graphics.hpp>
#include <vector>
#include <time.h>
using namespace sf;
using namespace std;
struct Position{
int x;
int y;
};
int main()
{
srand(time(NULL));
RenderWindow window(VideoMode(600, 480), "AVOID BLOCKS");
window.setFramerateLimit(60);
Texture t1, t2;
t1.loadFromFile("images/block.png");
t2.loadFromFile("images/cha2.png");
Sprite block(t1), cha2(t2);
Position blockPos;
blockPos.y = 0 + t1.getSize().y;
cha2.setPosition(300, 400);
float blockSpeed = 4;
const int size = 6;
vector<Sprite> blocks(6);
int n = 0;
auto bsize = t1.getSize();
for (int i = 0; i < 6; i++) {
blocks[n].setTexture(t1);
blocks[n].setPosition(rand()%10*bsize.x, 0);
n++;
}
while (window.isOpen())
{
Event e;
while (window.pollEvent(e)) {
if (e.type == Event::Closed)
window.close();
}
auto cha2_pos = cha2.getPosition();
if (Keyboard::isKeyPressed(Keyboard::Left)) {
if (cha2.getPosition().x < 0)
continue;
cha2.move(-5.0, 0.0);
}
if (Keyboard::isKeyPressed(Keyboard::Right)) {
if (cha2.getPosition().x > 600)
continue;
cha2.move(5.0, 0.0);
}
if (blockPos.y >= 480) {
blockPos.y = 0 + t1.getSize().y;
blockSpeed = blockSpeed + 0.2;
}
else
blockPos.y += blockSpeed;
for (int i = 0; i < blocks.size(); i++) {
if (FloatRect(cha2_pos.x + 3, cha2_pos.y + 3, 10, 10).
intersects(blocks[i].getGlobalBounds())) {
window.close();
}
}
window.clear();
window.draw(block);
window.draw(cha2);
window.display();
}
return 0;
}
The character at the bottom moves well.
I have no idea why block doesn't move and there's only one.
I think there's something wrong in the part starts "const int size".
Your program have two main problems. First of all, you don't draw all the blocks in the vector but you draw only the particular block you have made. This is why you see only one block on screen and not all the blocks you have create. The solution for this is:
for(auto& blk : blocks)
window.draw(blk);
The second problem affects the movement of the blocks. You have create a struct Position but you never associated with the blocks. So after you increase blockPos.y, you must move the blocks at that new blockPos.y. Explicit:
for(auto& blk : blocks)
blk.setPosition(blockPos.x, blockPos.y);
In this way you will have the problem that every block will be in the exact same position with the others because the blockPos variable is common for all blocks. A good idea is to make a class Block so which block to have his own position and movement. An example to what I say is:
class Block {
private:
Sprite block;
Position blockPos;
public:
Block(Texture& texture, int x, int y)
{
block.setTexture(texture);
blockPos.y = y;
blockPos.x = x; // save this value because you will need it
// every time you move the block
}
void setBlockPosition(float y)
{
blockPos.y = y;
}
Vector2<float> getBlockPosition()
{
return Vector2f(blockPos.x, blockPos.y);
}
void blockMovement(int y)
{
blockPos.y += y;
block.setPosition(blockPos.x, blockPos.y);
}
Sprite getSprite()
{
return block;
}
void Draw(RenderWindow& window)
{
window.draw(block);
}
};
After that I declare a vector with the new dynamic objects:
vector<Block*> blocks(6);
for(unsigned int i = 0; i < blocks.size(); i++)
{
blocks[i] = new Block(t1, rand()%10*t1.getSize().x ,0 - t1.getSize().y);
}
I change your if statements also:
for(unsigned int i = 0; i < blocks.size(); i++) //check for which block in the vector
{
if (blocks[i]->getBlockPosition().y >= 480) {
blocks[i]->setBlockPosition(0 - 200);
blockSpeed = blockSpeed + 0.2;
}
else {
blocks[i]->blockMovement(blockSpeed);
}
}
for (unsigned int i = 0; i < blocks.size(); i++) {
if (FloatRect(cha2_pos.x + 3, cha2_pos.y + 3, 10, 10)
.intersects(blocks[i]->getSprite().getGlobalBounds())) {
window.close();
}
}
Don't forget at the end to delete the objects because they was allocate dynamically:
for(unsigned int i = 0; i < blocks.size(); i++)
delete blocks[i];
return 0;

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;
}