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;
}
Related
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.
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.
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))
{
}
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;
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();