Update location of sprite between functions - c++

Im am trying to make a clean and organized way of making sprites. The problem is that the position of the sprites are being read as zero and they are just being drawn in the top left corner.
Sprite.h
#ifndef Sprite_h
#define Sprite_h
#endif /* Sprite_h */
using namespace std;
bool show = true;
class Sprite{
public:
int Spritex;
int Spritey;
string name;
sf::Texture texture;
Sprite(string image, int x, int y){
x = Spritex;
y = Spritey;
texture.loadFromFile(image);
}
sf::Sprite getSprite() {
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setPosition(Spritex, Spritey);
return sprite;
}
void changeimage(string image);
};
void Sprite:: changeimage(string image){
texture.loadFromFile(image);
}
main.cpp
#include <iostream>
#include <SFML/Graphics.hpp>
#include "Character.h"
#include "Projectile.h"
#include "Sprite.h"
//Use std
using namespace std;
//Boolean to determine if screen will scroll
bool scroll = false;
//player that is part of Character class and computer that is part of Sprite class
Character player("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Sprites/Player.png");
Sprite computer("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Sprites/CompSprite.png", 1200, 100);
Sprite battery("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Sprites/battery4.png", 0, 0);
//boolean for whether to show weapon or not
bool showweapon;
//main loop
int main() {
int windowWidth = 5000;//width of window
int windowHeight = 5000;//height of window
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight ), "Awesome Game" );//Make the window
//Setting up the dungeon back-round
sf::Texture dungeon;
dungeon.loadFromFile("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Sprites/DungeonBack.png");
sf::Sprite backround;
backround.setTexture(dungeon);
while (window.isOpen()){
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event)){
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
window.close();
}
//Movement
if (moveChar == true){
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
player.left();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
player.right();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
player.forward();
}
if (sf:: Keyboard::isKeyPressed(sf::Keyboard::Down)){
player.backward();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift))
{
player.Highspeed();
}
else{
player.Lowspeed();
}
}
//If player intersects with comp sprite, pick up comp sprite
if (player.getSprite().getGlobalBounds().intersects(computer.getSprite().getGlobalBounds())){
show = false;
player.hascomp = true;
}
//draw and window stuff
window.clear(sf::Color(255, 255, 255));
window.draw(backround);
if (show == true){
window.draw(computer.getSprite());
}
if (show == false){
window.draw(battery.getSprite());
}
window.draw(player.getSprite());
window.display();
window.setFramerateLimit(70);
}
}
If you have a question I will do my best to answer. Everything works except the spritex and spritey are being read as 0 for some reason. Thanks for any help.

You are writing to variables x and y here, which you never read from:
Sprite(string image, int x, int y){
x = Spritex;
y = Spritey;
texture.loadFromFile(image);
}
I assume you flipped the assignments, and should write
Sprite(string image, int x, int y){
Spritex = x;
Spritey = y;
}
or
Sprite(string image, int x, int y) : Spritex(x), Spritey(y) {
texture.loadFromFile(image);
}
If you turn up your warning levels, you will be warned about things like this, and also the non-initialized member you still have (name)

Related

How do I fix attempting to reference deleted function error in C++ sfml

this is main.cpp
#include <SFML/Graphics.hpp>
#include <iostream>
#include<windows.h>
#include <string>
#include "class.cpp"
using namespace sf;
int main()
{
HWND hwnd = GetConsoleWindow();
ShowWindow(hwnd, 0);
RenderWindow window(sf::VideoMode(800, 450), "file", sf::Style::Close | sf::Style::Titlebar);
//objects
house ho;
//end objects
//inits
ho.init(10,10,10,window);
//end inits
while (window.isOpen())
{
window.clear(sf::Color::Black); //clear screan with black
sf::Event evnt;
while (window.pollEvent(evnt))
{
if (evnt.type == evnt.Closed)
{
window.close();
}
}
//draw
//end draw
window.display(); // display everything
}
return 0;
}
this is class.cpp
#include <SFML/Graphics.hpp>
class house {
private:
float rx, ry, rpop;
public:
void init(float x, float y, float pop,sf::RenderWindow window2) {
bool inittrue = false;
rx, ry, rpop = x, y, pop;
if (pop > 0) {
inittrue = true;
}
if (inittrue == true) {
sf::RectangleShape rectangle(sf::Vector2f(50.f, 40.f));
rectangle.setPosition(sf::Vector2f(x, y));
window2.draw(rectangle);
}
}
};
the error prints this
Severity Code Description Project File Line Suppression State
Error C2280 'sf::RenderWindow::RenderWindow(const sf::RenderWindow &)': attempting to reference a deleted function sfml C:\Users\Luka\Desktop\progrraming\sfml\sfml\sfml.cpp 19
thank you in advance

SFML sprite is a white square when making multiple textures

I am making a SFML framework, and when I use the function loadImage one time, the image loads correctly with all colors, but if I use it two times for another texture, there is only one sprite rendered and it's all white. I read that you don't want to delete the texture or the sprite or it will be white. But in this code I'm storing all the textures in a vector. Does any one know what is wrong in this function?
FM::Image FM::graphics::loadImage(const char* fileName) {
texturesindex++;
sf::Texture texture;
texture.loadFromFile(fileName);
textures.push_back(texture);
sf::Sprite sprite(textures[texturesindex]);
Image image;
image.sprite = sprite;
return image;
}
Here's all the code:
SFFM.cpp:
#include "SFFM.h"
#include <SFML/Graphics.hpp>
#include <vector>
#include <string>
int backgroundcolor[3] = { 0,0,0};
sf::RenderWindow Window(sf::VideoMode(800, 600), "MyGame");
std::vector<sf::Texture> textures;
int texturesindex = -1;
void FM::window::setWindowOptions(unsigned int Width, unsigned int Height, const char* Title, int FrameLimit) {
Window.setSize(sf::Vector2u(Width, Height));
Window.setFramerateLimit(FrameLimit);
Window.setTitle(Title);
}
void FM::window::setBackgroundColor(int r, int g, int b) {
backgroundcolor[0] = r;
backgroundcolor[1] = g;
backgroundcolor[2] = b;
}
FM::Image FM::graphics::loadImage(const char* fileName) {
texturesindex++;
sf::Texture texture;
texture.loadFromFile(fileName);
textures.push_back(texture);
sf::Sprite sprite(textures[texturesindex]);
Image image;
image.sprite = sprite;
return image;
}
void FM::graphics::drawImage(Image image, int x, int y, int scalex, int scaley, int rotation) {
image.sprite.setPosition(x, -y);
image.sprite.setRotation(rotation);
image.sprite.setScale(sf::Vector2f(scalex, scaley));
Window.draw(image.sprite);
}
void FM::graphics::drawImage(Image image, int x, int y, int scalex, int scaley) {
image.sprite.setPosition(x, -y);
image.sprite.setScale(sf::Vector2f(scalex, scaley));
Window.draw(image.sprite);
}
void FM::graphics::drawImage(Image image, int x, int y) {
image.sprite.setPosition(x, -y);
Window.draw(image.sprite);
}
int main()
{
FM::Start();
while (Window.isOpen())
{
sf::Event event;
while (Window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
Window.close();
else if (event.type == sf::Event::Resized)
{
Window.setView(sf::View(sf::FloatRect(0, 0, event.size.width, event.size.height)));
}
}
Window.clear(sf::Color(backgroundcolor[0], backgroundcolor[1], backgroundcolor[2]));
FM::Update();
Window.display();
}
return 0;
}
SFFM.h:
#pragma once
#include <SFML/Graphics.hpp>
namespace FM
{
void Update();
void Start();
class window {
public:
static void setWindowOptions(unsigned int Width, unsigned int Height, const char * Title, int FrameLimit);
static void setBackgroundColor(int r, int g, int b);
};
class Image {
public:
sf::Sprite sprite;
};
class graphics {
public:
static Image loadImage(const char* fileName);
static void drawImage(Image image, int x, int y, int scalex, int scaley, int rotation);
static void drawImage(Image image, int x, int y, int scalex, int scaley);
static void drawImage(Image image, int x, int y);
};
class Input {
public:
};
};
main.cpp:
#include "SFFM.h"
#include <SFML\Graphics.hpp>
FM::Image Gangster;
FM::Image Block;
int x = 0;
int y = 0;
void FM::Start() {
window::setWindowOptions(1280, 720, "Platformer", 120);
window::setBackgroundColor(0, 127, 255);
Gangster = graphics::loadImage("assets/Gangster.png");
}
void FM::Update() {
graphics::drawImage(Gangster, x, y, 5, 5);
graphics::drawImage(Block, 100, 100, 5, 5);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
y += 1;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
y -= 1;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
x += 1;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
x -= 1;
}
}
Here's a screenshot:
TL;DR Solutions, either:
Use a container other than std::vector<sf::Texture> - std::list<sf::Texture> or std::forward_list<sf::Texture>.
Store pointers to textures - std::vector<std::unique_ptr<sf::Texture>>.
Explanation
You store texture objects along with sprites referring them. This is correct because a spite just keeps a reference (a pointer) to its texture. This also implies that the texture address must remain unchanged during the sprite lifetime.
It looks like you did not take into account how std::vector push_back() works. A vector initally allocates some memory, and once there is no place to insert a new item, the vector allocates more memory and copies all inserted items and the new one there. So all the item addresses change.
In your case an item is a texture, its address is changed upon an isertion of another texture, so some sprite "looses" its texture. This usually results in white squares drawn.

How to add collision in SFML

I am working on creating pong but I have been having trouble with Collision.How can I add a pixel accurate Collision? I've created a collision when only using a main file but I can't figure it out when using header files.Can someone write out the code for Collision and add to a Collision.h and Collision.cpp for easy storage and modification.
main.cpp
#include "stdafx.h"
#include <SFML\Graphics.hpp>
#include "Paddle.h"
#include "Ball.h"
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "Pong",
sf::Style::Close| sf::Style::Resize| sf::Style::Titlebar);
Paddle paddle1;
Paddle paddle2;
Ball ball;
while (window.isOpen()) {
sf::Event evnt;
while (window.pollEvent(evnt))
{
switch (evnt.type)
{
case sf::Event::Closed:
window.close();
break;
}
}
paddle1.Update();
paddle2.Update();
ball.Update(ballDirectionX,ballDirectionY);
window.clear();
paddle1.Draw(window);
paddle2.Draw(window);
ball.Draw(window);
window.display();
}
return 0;
}
Paddle.h
#pragma once
#include <SFML\Graphics.hpp>
class Paddle
{
public:
Paddle();
~Paddle();
void Draw(sf::RenderWindow& window);
void Update();
sf::RectangleShape paddle1;
sf::RectangleShape paddle2;
private:
};
Paddle.cpp
#include "stdafx.h"
#include "Paddle.h"
Paddle::Paddle()
{
paddle1.setSize(sf::Vector2f(20.0f, 120.0f));
paddle1.setFillColor(sf::Color::Red);
paddle2.setSize(sf::Vector2f(20.0f, 120.0f));
paddle2.setFillColor(sf::Color::Green);
paddle2.setPosition(sf::Vector2f(1900.0f, 0.0f));
}
Paddle::~Paddle()
{
}
void Paddle::Draw(sf::RenderWindow& window)
{
window.draw(paddle1);
window.draw(paddle2);
}
void Paddle::Update()
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
paddle1.move(sf::Vector2f(0, -3));
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
paddle1.move(sf::Vector2f(0, 3));
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
paddle2.move(sf::Vector2f(0, -3));
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
paddle2.move(sf::Vector2f(0, 3));
}
}
Ball.h
#pragma once
#include <SFML\Graphics.hpp>
class Ball
{
public:
Ball();
~Ball();
void Draw(sf::RenderWindow& window);
void Update() {
}
sf::CircleShape ball;
private:
};
Ball.cpp
#include "stdafx.h"
#include "Ball.h"
Ball::Ball()
{
ball.setRadius(20);
ball.setPosition(sf::Vector2f(400, 540));
}
Ball::~Ball()
{
}
void Ball::Draw(sf::RenderWindow & window)
{
window.draw(ball);
}
void Ball::Update()
{
}
Since Pong is a very simple game, I suggest you to create an intersect function with a sf::CircleShape and a sf::RectangleShape as arguments, because that's how you are representing your ball and paddles respectively.
I suggest you the following implementation, but there are better ones:
bool intersects(const sf::CircleShape &c, const sf::RectangleShape &r){
sf::FloatRect fr = r.getGlobalBounds();
sf::Vector2f topLeft(fr.left, fr.top);
sf::Vector2f topRight(fr.left + fr.width, fr.top);
sf::Vector2f botLeft(fr.left, fr.top + fr.height);
sf::Vector2f botRight(fr.left + fr.width, fr.top + fr.height);
return contains(c, topLeft) ||
contains(c, topRight) ||
contains(c, botLeft) ||
contains(c, botRight);
}
This is easy, simply check if each corner of the rectangle is inside of the circle, if none of them is contained, that circle and that rectangle don't intersect.
If any of the corners are contained into the circle, they intersects.
The contains() function quite simple in fact:
bool contains(const sf::CircleShape &c, const sf::Vector2f &p){
sf::Vector2f center = c.getPosition();
float a = (p.x - center.x);
float b = (p.y - center.y);
a *= a;
b *= b;
float r = c.getRadius() * c.getRadius();
return (( a + b ) < r);
}
Is based in this question, but I've separated it in each step for better comprehension.
EDIT
Note that this method only works if rectangles are in a vertical/horizontal orientation, this is, no rotations.

How do I draw a member from a class onto a window c++

I made a character class for the player, and I want to add a player member to the class then draw the player. I am using sfml and xcode. The error I am getting is: No matching member function for call to 'draw' on the: window.draw(player); line. It looks like I need to put a sprite object into .draw() so how do I make player sprite that is part of the class and draw it onto the window? I am new to c++ and sfml so any help is very much appreciated thanks.
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;
class Character{
public:
string sprite;
int health;
int defense;
int speed;
int experience;
bool move;
int x_pos;
int y_pos;
sf::Texture texture;
//Constructor - Ran everytime a new instance of the class is created
Character(string image){
health = 100;
defense = 100;
speed = 100;
experience = 0;
x_pos = 0;
y_pos = 0;
texture.loadFromFile(image);
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, 100, 100));
sprite.setPosition(x_pos, y_pos);
}
//Destructor - Ran when the object is destroyed
~Character(){
}
//Methods
void forward();
void backward();
void left();
void right();
void attack();
};
void Character::forward(){
cout << "Go Forward";
}
void Character::backward(){
cout << "Go Backward";
}
void Character::left(){
cout << "Go Left";
}
void Character::right(){
cout << "Go Right";
}
Character player("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Player.png");
int main() {
// insert code here...
int windowWidth = 1150;
int windowHeight = 750;
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight ), "Awesome Game" );
while(window.isOpen()){
window.draw(player);
window.display();
window.setFramerateLimit(60);
}
}
You could simply add a member function that would return your player's sprite:
sf::Sprite Character::getSprite() {
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, 100, 100));
sprite.setPosition(x_pos, y_pos);
return sprite;
}
Then pass the result to window.draw:
window.draw(player.getSprite());
Alternatively, you could invert the dependency and make the player responsible for all the drawing:
void Character::draw(sf::RenderWindow& w) {
w.draw(...);
}
There are other approaches, and the choice depends largely on a lot of external factors. This should get you started, though.

Sfml pollEvent, every new image deletes the previous one

My problem is that the function don't do what I want.
This "CreateWindow" function has the main loop. In the main loop I want a fixed background and, every time I press the H button, I want to draw a Card (sprite) on the background.
What's the problem here? My function draw the cards but when I press H the previous card is deleted and the next card is drawn.
This is something about the event I think, because every time an event happens (I move the mouse, I press an other key etc) the previous card is deleted...
I'm using sfml 2.0
Here is my implementation of the Graphic class
#include "Graphic.h"
#include "SFML/Graphics.hpp"
#include <iostream>
#include <string>
#include "Card.h"
#include <string>
#include <sstream>
Graphic::Graphic(int offset)
{
this->offset = offset;
}
Graphic::~Graphic()
{
//dtor
}
int Graphic::CreateWindow(sf::RenderWindow& window, Deck &deck0)
{
sf::Vector2i screenDimensions(800, 600);
//Dimensioni della window
window.create(sf::VideoMode(screenDimensions.x, screenDimensions.y), "BlackJack", sf::Style::Titlebar | sf::Style::Close);
int index = 0;
window.setKeyRepeatEnabled(false);
//settare il background
sf::Texture bTexture;
sf::Sprite bImage;
if(!bTexture.loadFromFile("Background.png"))
std::cout << "Error" << std::endl;
bImage.setTexture(bTexture);
bImage.setScale(1.0, (float)screenDimensions.y / bTexture.getSize().y);
//MAIN LOOP----------------------
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
window.clear();
window.draw(bImage); // this is the function which draw the background
if (Event.type == sf::Event::Closed)
{
window.close();
}
if(Event.key.code == sf::Keyboard::H)
{
Card * y = deck0.dealFirst();
drawCard(window,y->graphNumber,y->getSeed(),offset);
offset = offset + 50;
}
window.display();
}
}
}
int Graphic::drawCard(sf::RenderWindow &window, int graphNumber, string seed, int offset)
{
std::ostringstream oss;
oss << graphNumber << seed << ".png";
std::string var = oss.str();
sf::Texture QHTexture;
sf::Sprite QHImage;
if(!QHTexture.loadFromFile(var))
std::cout<< "Error" <<std::endl;
QHImage.setTexture(QHTexture);
QHImage.setScale(0.5, 0.5);
QHImage.setPosition(offset + 100, 400);
window.draw(QHImage); //this is the function which draw the card's sprite
return 0;
}
Alright you shouldn't be drawing inside of your while(window.pollEvent()) loop, you should be drawing something like this:
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
{
window.close();
}
if(Event.key.code == sf::Keyboard::H)
{
Card * y = deck0.dealFirst();
drawCard(window,y->graphNumber,y->getSeed(),offset);
offset = offset + 50;
}
}
window.clear();
window.draw(bImage); // this is the function which draw the background
window.display();
}
The way you were drawing your draw call will only happen if there is an SFML event, and will only ever clear if there is an sfml event(Which is ok if you dont want it to constantly render every frame... and aren't planning any kind of animations...).
So when you hit H an sfml event was being triggers that called your draw card function, however since your card is a local variable to the function you wrote, at the end of the function it is cleared out. You need to store your cards somewhere, such as a vector or list of sf::Sprite. So an example would be:
#include "Graphic.h"
#include "SFML/Graphics.hpp"
#include <iostream>
#include <string>
#include "Card.h"
#include <string>
#include <sstream>
Graphic::Graphic(int offset)
{
this->offset = offset;
}
Graphic::~Graphic()
{
//dtor
}
int Graphic::CreateWindow(sf::RenderWindow& window, Deck &deck0)
{
sf::Vector2i screenDimensions(800, 600);
//Dimensioni della window
window.create(sf::VideoMode(screenDimensions.x, screenDimensions.y), "BlackJack", sf::Style::Titlebar | sf::Style::Close);
int index = 0;
window.setKeyRepeatEnabled(false);
//settare il background
sf::Texture bTexture;
sf::Sprite bImage;
if(!bTexture.loadFromFile("Background.png"))
std::cout << "Error" << std::endl;
bImage.setTexture(bTexture);
bImage.setScale(1.0, (float)screenDimensions.y / bTexture.getSize().y);
//MAIN LOOP----------------------
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
{
window.close();
}
if(Event.key.code == sf::Keyboard::H)
{
Card * y = deck0.dealFirst();
drawCard(window,y->graphNumber,y->getSeed(),offset);
offset = offset + 50;
}
}
window.clear();
window.draw(bImage); // this is the function which draw the background
for(int i = 0; i < cardList.size(); ++i)
{
window.draw(cardList[i]);
}
window.display();
}
}
int Graphic::drawCard(sf::RenderWindow &window, int graphNumber, string seed, int offset)
{
std::ostringstream oss;
oss << graphNumber << seed << ".png";
std::string var = oss.str();
sf::Texture QHTexture;
sf::Sprite QHImage;
if(!QHTexture.loadFromFile(var))
std::cout<< "Error" <<std::endl;
QHImage.setTexture(QHTexture);
QHImage.setScale(0.5, 0.5);
QHImage.setPosition(offset + 100, 400);
cardList.push_back(QHImage); //this adds the sprite to our list
return 0;
}