I am learning the SFML library in C++. I have been trying to implement an efficient method of organizing audio in my game by making an Audio class that contains two separate std::map for the music (sf::Music) and the sound (sf::Sound). However, when I run the program, only the music is able to play but not the sound effects. I believe the sound does load fine since it does not throw the error message. Here is my code and info. (Possibly give tips on my code as well since I am new :D )
Thanks in advance
VS2012, SFML 2.1
SFML_Snake.h (Game header file)
#pragma once
#ifndef GUARD_SFML_SNAKE
#define GUARD_SFML_SNAKE
#include "SFML/Audio.hpp"
#include "SFML/Graphics.hpp"
#include "Snake.h"
#include "Apple.h"
#include "Audio.h"
#include <iostream>
class SFML_Snake{
public:
SFML_Snake();
void run();
private:
void checkBoundary(Snake);
void checkApple(Snake&, Apple&, Audio& );
std::vector<sf::RectangleShape> loadGrid();
private:
bool processEvents();
void update(Audio&);
void render(std::vector<sf::RectangleShape>&);
public:
sf::RenderWindow window;
sf::Text textCount;
Snake snake;
Apple apple;
};
int main(){
SFML_Snake start;
start.run();
}
#endif
SFML_Snake.cpp (Game source file)
/*Import statements*/
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include "Snake.h"
#include "variables.h"
#include "Apple.h"
#include "Audio.h"
#include "SFML_Snake.h"
#include <iostream>
#include <vector>
#include <string>
#include <array>
#include <map>
#include <memory>
SFML_Snake::SFML_Snake():
window(sf::VideoMode(windowWidth, windowHeight), "SFML Application" ),
snake(Snake()), apple(Apple(0,0)), textCount(sf::Text())
{
window.setFramerateLimit(FRAMERATE);
}
void SFML_Snake::checkBoundary(Snake s){
for (int z = dots; z > 0; z--){
if ((s.x[0] == s.x[z]) && (s.y[0] == s.y[z]))
inGame = false;
}
if (s.y[0] >= windowHeight)
inGame = false;
if (s.y[0] < dotSize)
inGame = false;
if (s.x[0] >= windowWidth)
inGame = false;
if (s.x[0] < dotSize)
inGame = false;
}
void SFML_Snake::checkApple(Snake& mA, Apple& mB, Audio& audios){
if ((mA.x[0] == mB.x()) && (mA.y[0] == mB.y())){
audios.getSound("eating").play();
dots += dotInterval;
points++;
if(DEBUG)
std::cout<< points << std::endl;
textCount.setString(std::string("points: ") + std::to_string(points));
mB.locateApple();
for(int i = mA.draw().size() - 1; i >= 0; i--){
while (((mA.x[0] == mB.x()) && (mA.y[0] == mB.y()))
|| (0 == mB.x())
|| (0 == mB.y())
|| (windowWidth - dotSize/2 == mB.x())
|| (windowHeight - dotSize/2 == mB.y()))
{
mB.locateApple();
}
}
}
}
bool SFML_Snake::processEvents(){
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Escape)) {
return true;
}
snake.input();
return false;
}
void SFML_Snake::update(Audio& audios){
snake.checkReals();
snake.moveUpdate();
audios.getSound("moving").play();
checkApple(snake, apple, audios);
checkBoundary(snake);
}
void SFML_Snake::render(std::vector<sf::RectangleShape>& grid){
std::vector<sf::RectangleShape> shapearray = snake.draw();
for (int i = shapearray.size() - 1; i >= 0; i--){
window.draw(shapearray[i]);
}
window.draw(apple.draw());
for(int i = grid.size()-1; i>=0; i--){
window.draw(grid[i]);
}
window.draw(textCount);
window.display();
}
std::vector<sf::RectangleShape> SFML_Snake::loadGrid(){
std::vector<sf::RectangleShape> grid;
for(int k= dotSize/2; k<=windowHeight+dotSize/2; k+=dotSize){
sf::RectangleShape line;
line.setPosition(0, k-dotSize);
line.setSize(sf::Vector2f(windowWidth, 1));
line.setFillColor(sf::Color::Black);
if(k==dotSize/2 || k == windowHeight + dotSize/2){
line.setSize(sf::Vector2f(windowWidth, dotSize));
}
grid.push_back(line);
}
for(int i = dotSize/2; i<=windowWidth+dotSize/2; i+=dotSize){
sf::RectangleShape line;
line.setPosition(i-dotSize, 0);
line.setSize(sf::Vector2f(1, windowHeight));
line.setFillColor(sf::Color::Black);
if(i==dotSize/2 || i == windowWidth+dotSize/2){
line.setSize(sf::Vector2f(dotSize, windowHeight));
}
grid.push_back(line);
}
return grid;
}
void SFML_Snake::run(){
/*Initialize the objects*/
std::vector<sf::RectangleShape> grid = loadGrid();
if(!DEBUG)
std::cout<<"DEBUG MODE: OFF" <<std::endl;
Audio& audios = Audio();
apple.locateApple();
/*Load the audio*/
audios.getMusic("backgroundMusic").setVolume(10);
audios.getMusic("backgroundMusic").setLoop(true);
audios.getMusic("backgroundMusic").setVolume(25);
/*Load the font*/
sf::Font font;
if (!(font.loadFromFile("arial.ttf")))
if(DEBUG)
std::cout << "Error loading fonts" << std::endl;
/*Create the text*/
textCount.setFont(font);
textCount.setString(std::string("points: ") + std::to_string(points));
textCount.setColor(sf::Color::Red);
textCount.setCharacterSize(20);
textCount.setPosition(windowWidth / 2 - (textCount.getString().getSize()*(textCount.getCharacterSize() / 5)), textCount.getCharacterSize() - 10);
textCount.setStyle(sf::Text::Bold);
window.draw(textCount);
/*MAIN GAME LOOP*/
counterTick = 1;
audios.getSound("begin").play();
audios.getMusic("backgroundMusic").play();
while (inGame && !pause)
{
std::string counter = std::to_string(counterTick);
if(DEBUG)
std::cout << "Tick: " + counter << std::endl;
window.clear(sf::Color::White);
if(processEvents()){
break;
}
update(audios);
render(grid);
snake.secInput = false;
counterTick++;
}
audios.getSound("losing").play();
audios.getMusic("backgroundMusic").stop();
std::system("PAUSE");//bad practice, debuggin purposes
}
Audio.h
#pragma once
#ifndef GUARD_AUDIO_H
#define GUARD_AUDIO_H
#include "variables.h"
#include "SFML\Graphics.hpp"
#include "SFML\Audio.hpp"
#include <memory>
struct Audio{
std::map<std::string, sf::Sound> sounds;
std::map<std::string, std::unique_ptr<sf::Music>> musics;
//std::map<std::string, sf::Sound> sounds;
//std::map<std::string, sf::Music> musics;
Audio();
void Audio::addSound(sf::Sound&, sf::SoundBuffer& , const std::string&);
void Audio::addSound(sf::Sound&, const std::string&);
void Audio::addMusic(const std::string&, std::unique_ptr<sf::Music> );
sf::Sound &Audio::getSound(std::string);
sf::Music &Audio::getMusic(std::string);
void Audio::loadAudio();
};
#endif//GUARD_AUDIO_H
Audio.cpp
#include "Audio.h"
#include <iostream>
Audio::Audio(){
loadAudio();
}
void Audio::addSound(sf::Sound& s, sf::SoundBuffer& sb, const std::string &key){
s.setBuffer(sb);
sounds.insert(std::pair<std::string, sf::Sound>(key, std::move(s)));
}
void Audio::addSound(sf::Sound& s, const std::string &key){
sounds.insert(std::pair<std::string, sf::Sound>(key, s));
}
void Audio::addMusic(const std::string &key, std::unique_ptr<sf::Music> value){
musics.insert(std::pair<std::string, std::unique_ptr<sf::Music> >(key, std::move(value)));
}
sf::Sound &Audio::getSound(std::string key){
return sounds.at(key);
}
sf::Music &Audio::getMusic(std::string key){
return *musics.at(key);
}
void Audio::loadAudio(){
//sf::Music backgroundMusic;
sf::Sound s_eating;
sf::SoundBuffer sb_eating;
sf::Sound s_moving;
sf::SoundBuffer sb_moving;
sf::Sound s_losing;
sf::SoundBuffer sb_losing;
sf::Sound s_begin;
sf::SoundBuffer sb_begin;
auto backgroundMusic = std::unique_ptr<sf::Music>(new sf::Music());
if (!backgroundMusic->openFromFile("backgroundmusic.wav"))
if(DEBUG)
std::cerr << "Error opening \"backgroundmusic.wav\"" << std::endl;
if (!sb_eating.loadFromFile("eatingsfx.wav"))
if(DEBUG)
std::cerr << "Error opening \"eatingsfx.wav\"" << std::endl;
if (!sb_moving.loadFromFile("movingsfx.wav"))
if(DEBUG)
std::cerr << "Error opening \"movingsfx.wav\"" << std::endl;
if (!sb_losing.loadFromFile("losingsfx.wav"))
if(DEBUG)
std::cerr << "Error opening \"losingsfx.wav\"" << std::endl;
if (!sb_begin.loadFromFile("beginsfx.wav"))
if(DEBUG)
std::cerr << "Error opening \"beginsfx.wav\"" << std::endl;
//s_eating.setBuffer(sb_eating);
//s_moving.setBuffer(sb_moving);
//s_losing.setBuffer(sb_losing);
//s_begin.setBuffer(sb_begin);
addMusic(std::string("backgroundMusic"), std::move(backgroundMusic));
addSound(s_eating, sb_eating, std::string("eating"));
addSound(s_moving, sb_moving, std::string("moving"));
addSound(s_losing, sb_losing, std::string("losing"));
addSound(s_begin, sb_begin, std::string("begin"));
}
You basically need a sound manager, this is what I use to manager my sounds.
Header file
#pragma once
#include "SFML/Audio.hpp"
#include "Enums.h"
#include <map>
#include <vector>
#include <iostream>
class SoundLoader
{
public:
//SoundNames is an enum
SoundLoader();
~SoundLoader();
void LoadSounds();
void PlaySound(SoundNames soundName);
std::map<SoundNames, sf::SoundBuffer> Sounds;
std::vector<sf::Sound> playingSounds;
};
Source file
#include "SoundLoader.h"
SoundLoader::SoundLoader()
{
}
SoundLoader::~SoundLoader()
{
}
void SoundLoader::LoadSounds()
{
Sounds[SoundNames::sound1].loadFromFile("Assets/Sounds/sound1.wav");
}
void SoundLoader::PlaySound(SoundNames soundName)
{
if (playingSounds.size() == 0)
{
playingSounds.push_back(sf::Sound());
playingSounds.at(0).setBuffer(Sounds[soundName]);
playingSounds.at(0).play();
}
else
{
int location = -1;
for (int i = 0; i < playingSounds.size(); i++)
{
if (playingSounds.at(i).getStatus() != sf::Sound::Playing && location == -1)
{
location = i;
}
}
if (location != -1)
{
playingSounds.at(location).setBuffer(Sounds[soundName]);
playingSounds.at(location).play();
}
else
{
playingSounds.push_back(sf::Sound());
playingSounds.at(playingSounds.size()-1).setBuffer(Sounds[soundName]);
playingSounds.at(playingSounds.size() - 1).play();
}
}
}
Now you have yourself a SoundManager, you can load sounds like so and play sounds like so.
SoundLoader sl;
sl.LoadSounds();
sl.Play(SoundNames::sound1);
Hope this helps you out, if you need any more help just let me know.
The sf::SoundBuffer effectively holds the audio data you want to playback. To do so the data needs to exist as long as you're playing it. In your code however, you load the buffers in Audio::loadAudio() but as soon as you leave that function, the buffer will get destroyed and your sf::Sound object don't have any kind of data to playback.
You rather want to store the sf::SoundBuffer objects instead of the sf::Sound objects.
Related
I am writing a simple isometric game - simulator of town development. The main classes are Player class and World class. So, the problem is, that when I launching my game, all seems to be going as planned, but when I want to click "X" to close it, at the moment cursor reach place, in which red arrow points, program is being breaked this error.
It is not happening, when Player object is not created, so I think some problem in it.
Player.hpp:
#ifndef PLAYER_HEADER
#define PLAYER_HEADER
#include "Main.hpp"
#include "ToScreenF.hpp"
#include <iostream>
class Player
{
public:
sf::Vector2i MousePos;
sf::Vector2i inCell;
sf::Vector2i cellOffset;
sf::Vector2i cellSelected;
sf::Vector2f cellSelectedInWorldSpace;
sf::Image selectedTileImage;
sf::Texture selectedTileTexture;
sf::Sprite selectedTileSprite;
sf::Image CheatImage;
sf::Color color;
Player(std::string FILE);
~Player();
void Update(sf::RenderWindow* Window, sf::Vector2f TileSize, sf::Vector2f vOrigin, int WorldWidth, int WorldHeight);
};
#endif PLAYER_HEADER
Player.cpp:
#include "Player.hpp"
Player::Player(std::string FILE)
{
selectedTileImage.loadFromFile(FILE);
selectedTileImage.createMaskFromColor(sf::Color::White);
selectedTileTexture.loadFromImage(selectedTileImage);
selectedTileSprite.setTexture(selectedTileTexture);
CheatImage.loadFromFile("tileCheat.png");
}
void Player::Update(sf::RenderWindow* Window, sf::Vector2f TileSize, sf::Vector2f vOrigin, int WorldWidth, int WorldHeight)
{
MousePos = {sf::Mouse::getPosition((*Window))};
inCell = {(int)(MousePos.x / TileSize.x), (int)(MousePos.y / TileSize.y) };
cellOffset = { MousePos.x % (int)TileSize.x, MousePos.y % (int)TileSize.y };
cellSelected = {
(inCell.y - (int)vOrigin.y) + (inCell.x - (int)vOrigin.x),
(inCell.y - (int)vOrigin.y) - (inCell.x - (int)vOrigin.x)
};
color = CheatImage.getPixel(cellOffset.x, cellOffset.y);
if (color == sf::Color::Red) { cellSelected.x += -1; cellSelected.y += 0; };
if (color == sf::Color::Blue) { cellSelected.x += 0; cellSelected.y += -1; };
if (color == sf::Color::Green) { cellSelected.x += 0; cellSelected.y += 1; };
if (color == sf::Color::Yellow) { cellSelected.x += 1; cellSelected.y += 0; };
if (cellSelected.x < 0) cellSelected.x = 0;
if (cellSelected.x > (WorldWidth - 1)) cellSelected.x = 19;
if (cellSelected.y < 0) cellSelected.y = 0;
if (cellSelected.y > (WorldHeight - 1)) cellSelected.y = 19;
cellSelectedInWorldSpace = ToScreen(cellSelected.x, cellSelected.y, TileSize, vOrigin);
selectedTileSprite.setPosition(cellSelectedInWorldSpace);
Window->draw(selectedTileSprite);
std::cout << cellSelected.x << " " << cellSelected.y << std::endl;
}
ToScreenF.cpp:
#include "ToScreenF.hpp"
sf::Vector2f ToScreen(int x, int y, sf::Vector2f TileSize, sf::Vector2f vOrigin)
{
return sf::Vector2f
{
(vOrigin.x * TileSize.x) + (x - y) * (TileSize.x / 2),
(vOrigin.y * TileSize.y) + (x + y) * (TileSize.y / 2)
};
}
TApplication.hpp:
#ifndef TAPPLICATION_HEADER
#define TAPPLICATION_HEADER
#include "Main.hpp"
#include "World.hpp"
#include "Player.hpp"
namespace Application
{
class TApplication
{
protected:
sf::RenderWindow *Window;
World *GameWorld;
Player* _Player;
public:
TApplication();
~TApplication();
void Init();
void Run();
void End();
};
}
TApplication.cpp:
#include "TApplication.hpp"
namespace Application
{
TApplication::TApplication() : Window(nullptr)
{
}
TApplication:: ~TApplication()
{
}
void TApplication::Init()
{
if (Window == nullptr)
Window = new sf::RenderWindow(sf::VideoMode(1200, 800), "Town Builder Simulator");
GameWorld = new World("BasicTile.png", 100, 100);
_Player = new Player("selectedTile.png");
}
void TApplication::Run()
{
sf::Event event;
while (Window->isOpen())
{
while(Window->pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
Window->close();
}
}
Window->clear();
GameWorld->Draw(Window);
_Player->Update(Window, sf::Vector2f(40, 20), sf::Vector2f(10, 10), GameWorld->WorldWidth, GameWorld->WorldHeight);
Window->display();
}
}
void TApplication::End()
{
if (Window != nullptr)
{
delete Window;
delete GameWorld;
Window = nullptr;
}
}
}
**Main.hpp**
#ifndef MAIN_HEADER
#define MAIN_HEADER
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
#endif
Thanks in advance all who helped me, I am very grateful!)
I was working on changing sprite in my SFML project but it just doesn't want to wark. I tried everything - pointers, refrences and normal string objects. You can see in debug console i printed out this->path that containted a path to file to change but when it left the function this->path was null (empty "" string). Can you please help me? Here's the code:
Player.cpp
#include "Player.h"
#include <iostream>
Player::Player(std::string path)
{
this->path = path;
texture.loadFromFile(path);
sprite.setTexture(texture);
sprite.setPosition(500.f, 700.f);
}
void Player::update()
{
// Movement //
//if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
//sprite.move(0.f, -velocity);
//if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
//sprite.move(0.f, velocity);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
sprite.move(-velocity, 0.f);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
sprite.move(velocity, 0.f);
// Movement //
float szerokosc = sprite.getGlobalBounds().width;
float wysokosc = sprite.getGlobalBounds().height;
// Collision with screen //
// Left
if (sprite.getPosition().x < 0.f)
sprite.setPosition(0.f, sprite.getPosition().y);
// Top
if (sprite.getPosition().y < 0.f)
sprite.setPosition(sprite.getPosition().x, 0.f);
// Right
if (sprite.getPosition().x + szerokosc > 1000)
sprite.setPosition(1000 - szerokosc, sprite.getPosition().y);
// Bottom
if (sprite.getPosition().y + wysokosc > 800)
sprite.setPosition(sprite.getPosition().x, 800 - wysokosc);
// Collision with screen //
}
sf::Sprite Player::getSprite()
{
return sprite;
}
bool Player::collides(Food obj)
{
if (sprite.getGlobalBounds().intersects(obj.getSprite().getGlobalBounds()))
return true;
else
return false;
}
void Player::changeSkin(std::string path)
{
this->path = path;
std::cout << "changeSkin(): *this->path" << this->path << std::endl;
std::cout << "changeSkin(): *path" << path << std::endl;
texture.loadFromFile(path);
sprite.setTexture(texture);
}
void Player::updateSkin()
{
std::cout << "updateSkin() *this->path: " << this->path << std::endl;
std::cout << "updateSkin() *path: " << path << std::endl;
}
Player::~Player()
{
//delete texture;
//delete sprite;
}
Player.h
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <time.h>
#include "Food.h"
#include "ShopItem.h"
class Player
{
sf::Texture texture;
sf::Sprite sprite;
std::string path;
bool has_skin = false;
float velocity = 5.f;
public:
explicit Player(std::string path);
~Player();
void update();
sf::Sprite getSprite();
bool collides(Food obj);
void changeSkin(std::string path);
void updateSkin();
};
main.cpp - main() has Player::updateSkin() call
int main()
{
RenderWindow window(VideoMode(1000, 800), "Tomczyszyn Eater v0.21 BETA");
window.setFramerateLimit(60);
srand(time(nullptr));
Texture bg_text;
bg_text.loadFromFile("Assets/Textures/bg.png");
Sprite bg{ bg_text };
Player player{ "Assets/Textures/player.png" };
time_t start{};
Event event;
Intro* intro = new Intro{window};
MainMenu* menu = new MainMenu{&window};
Shop shop(&window);
Game game{player, &window};
bool intro_deleted{ false };
bool menu_deleted{ false };
bool game_started{ false };
int menuState{ 2 };
while (window.isOpen())
{
while (window.pollEvent(event))
{
if (event.type == Event::EventType::Closed)
window.close();
if (Keyboard::isKeyPressed(Keyboard::Space) && game.gameRunning() == false)
{
start = time(nullptr);
game.runGame();
}
else if (Keyboard::isKeyPressed(Keyboard::Escape) && game.gameRunning() == false)
{
menuState = 0;
}
}
window.clear();
if (game.gameRunning() == true && menuState == 1) // Main Game
{
if (game_started == false)
{
start = time(nullptr);
game_started = true;
}
if (intro_deleted == false)
{
delete intro;
intro_deleted = true;
}
if (menu_deleted == false)
{
delete menu;
menu_deleted = true;
}
window.draw(bg);
game.drawMoney();
player.update();
window.draw(player.getSprite());
// Player::updateSkin() - source of the problem
player.updateSkin();
game.update();
game.draw();
if (time(nullptr) - start == 2)
{
start = time(nullptr);
int liczba = rand() % 6 + 1;
string file_name{ "Assets/Textures/food" + to_string(liczba) + ".png" };
Food* newFood = new Food{file_name};
game.spawn(newFood);
}
game.catched();
game.fell();
}
else if (menuState == 0) // Menu
{
if (menu_deleted == true) menu = new MainMenu{ &window };
menu->draw();
menu->update(menuState);
menu_deleted = false;
}
else if (menuState == -1) // Intro
{
start = time(nullptr);
intro->play();
if (intro->intro_started() == true) menuState = 0;
}
else if (menuState == 2) // Shop
{
shop.draw();
shop.backIfClicked(menuState);
shop.checkIfBought(player, game.balance());
game.drawMoney();
}
else
{
game.drawDeathScreen();
}
window.display();
}
}
Shop.cpp - checkIfBought() has Player::changeSkin() call
void Shop::checkIfBought(Player player, int& money)
{
for (int i = 0; i < skins.size(); i++)
{
if (isClicking(skins[i].getSprite()) == true)
{
skins[i].buy(money);
player.changeSkin(skins[i].getPath()); //Plaer::changeSkin() here - source of the problem
std::cout << skins[i].getPath() << std::endl;
}
}
for (int i = 0; i < bg_skins.size(); i++)
{
if (isClicking(bg_skins[i].getSprite()) == true)
{
bg_skins[i].buy(money);
player.changeSkin(bg_skins[i].getPath()); //Plaer::changeSkin() here - source of the problem
}
}
}
Debug Console output:
changeSkin(): this->path = Assets/Textures/skin1.png
changeSkin(): path = Assets/Textures/skin1.png
Assets/Textures/skin1.png
updateSkin() this->path = Assets/Textures/player.png
updateSkin() path = Assets/Textures/player.png
Sorry if you didn't understand my english is bad. I really do need help i've spent so much time on fixing this that i just gave up.
I've been trying to make a sprite display in C++ SFML but with the use of classes. However, when I compile and run the program, nothing appears: there are no errors either.
(The only thing that happens in main is that a 'Game' object is created)
Game.h
#ifndef GAME_H
#define GAME_H
#include <SFML/Graphics.hpp>
#include "Player.h"
class Game
{
public:
Game();
private:
//Variables
sf::RenderWindow _mainWindow;
enum _gameState { Playing, Paused, Splash, Menu };
//Methods
void gameLoop();
};
#endif // GAME_H
Game.cpp
#include "Game.h"
#include "Player.h"
Game::Game() {
//Variables
_mainWindow.create(sf::VideoMode(960, 640), "Game", sf::Style::Titlebar | sf::Style::Close);
_mainWindow.setFramerateLimit(60);
//Start Game Loop
gameLoop();
}
void Game::gameLoop() {
Player player;
while(_mainWindow.isOpen()) {
sf::Event ev;
while(_mainWindow.pollEvent(ev)) {
if(ev.type == sf::Event::Closed)
_mainWindow.close();
if(ev.type == sf::Event::KeyPressed) {
if(ev.key.code == sf::Keyboard::Escape)
_mainWindow.close();
}
}
//Draw Stuff
_mainWindow.clear(sf::Color::White);
player.drawSprite(_mainWindow);
_mainWindow.display();
}
}
Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <SFML/Graphics.hpp>
#include <iostream>
class Player
{
public:
Player();
void drawSprite(sf::RenderWindow& window);
private:
bool loadSprite();
sf::Texture _playerTexture;
sf::Sprite _playerSprite;
};
#endif // PLAYER_H
Player.cpp
#include "Player.h"
#include "Game.h"
Player::Player()
{
if(!Player::loadSprite()){
return;
}
}
bool Player::loadSprite() {
sf::Texture _playerTexture;
if(!_playerTexture.loadFromFile("img/darkguy.png", sf::IntRect(32,32,32,32))) {
std::cout << "Failed to load player image" << std::endl;
return false;
} else {
sf::Sprite _playerSprite;
_playerSprite.setTexture(_playerTexture);
}
return true;
}
void Player::drawSprite(sf::RenderWindow& window) {
//sprite.setTextureRect(sf::IntRect(10, 10, 32, 32));
window.draw(_playerSprite);
std::cout << "Sprite Drawn Successfully" << std::endl;
}
You are declaring a new, local _playerSprite here:
} else {
sf::Sprite _playerSprite;
_playerSprite.setTexture(_playerTexture);
}
instead, use the existing class member:
} else {
_playerSprite.setTexture(_playerTexture);
}
You may want to drop the first line from this code as well, same issue:
bool Player::loadSprite()
{
sf::Texture _playerTexture; // <--- local redeclaration
From my memories: the texture must be a member of your class; it must exist while you are using it. In your code, _playerTexture is destroyed at the end of loadSprite(). Same problem for _playerSprite.
Edit:
You don't have to re-declare the member of your class in your methods :
bool Player::loadSprite() {
sf::Texture _playerTexture;
if(!_playerTexture.loadFromFile("img/darkguy.png", sf::IntRect(32,32,32,32))) {
std::cout << "Failed to load player image" << std::endl;
return false;
} else {
sf::Sprite _playerSprite;
_playerSprite.setTexture(_playerTexture);
}
return true;
}
Should be:
bool Player::loadSprite() {
if(!_playerTexture.loadFromFile("img/darkguy.png", sf::IntRect(32,32,32,32))) {
std::cout << "Failed to load player image" << std::endl;
return false;
} else {
_playerSprite.setTexture(_playerTexture);
}
return true;
}
(PS: Your code doesn't respect the SRP (Single Responsability Principle), Player doesn't have to display itself.)
you are drawing but not displaying the sprite for that do this
void Player::drawSprite(sf::RenderWindow& window) {
//sprite.setTextureRect(sf::IntRect(10, 10, 32, 32));
window.draw(_playerSprite);
std::cout << "Sprite Drawn Successfully" << std::endl;
//this is the display function
window.display()
}
i am creating a project using SFML. Everything worked fine up until now. I created a class called BufferHelper.cpp and then an error showed up.
I am working with:
Visual Studio Professional 2013
SFML 2.1
Windows 8.1
I have added all libaries
the 'sfml-lib.dll's for Release
and 'sfml-lib-d.dll's for Debug
Error log:
Error 1 error LNK2001: unresolved external symbol "public: class sf::SoundBuffer __thiscall BufferHelper::MergeBuffers(class sf::SoundBuffer,class sf::SoundBuffer)" (?MergeBuffers#BufferHelper##QAE?AVSoundBuffer#sf##V23#0#Z) C:\Users\Krisjanis\documents\visual studio 2013\Projects\BD_Test\BD_Test\main.obj BD_Test
Error 2 error LNK1120: 1 unresolved externals C:\Users\Krisjanis\documents\visual studio 2013\Projects\BD_Test\Release\BD_Test.exe BD_Test
Main.cpp
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
#include "BufferHelper.h"
int main()
{
sf::SoundBufferRecorder recorder;
sf::SoundBufferRecorder recorder2;
sf::SoundBuffer buffer;
sf::SoundBuffer buffer2;
sf::Sound sound;
sf::Sound sound2;
int iTrackActive = 1;
bool bTrack1Active = true;
bool bTrack2Active = false;
sf::RenderWindow window(sf::VideoMode(1200, 800), "Loopify!");
//sf::RenderWindow window(sf::VideoMode(1200, 800), "Loopify!", sf::Style::Fullscreen);
sf::Texture texture;
texture.loadFromFile("images/a.png");
BufferHelper a;
sf::SoundBuffer finalbuffer = a.MergeBuffers(buffer, buffer2);
sf::Sprite sprite;
sprite.setTexture(texture);
bool recording = false;
if (!sf::SoundBufferRecorder::isAvailable())
{
std::cout << "Recorder not available";
}
else
{
std::cout << "GO AHEAD AND RECORD";
}
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Space && !recording)
{
recording = true;
recorder.start();
}
else if (event.key.code == sf::Keyboard::Space && recording)
{
recorder.stop();
recording = false;
if (iTrackActive == 1)
{
buffer = recorder.getBuffer();
sound.setBuffer(buffer);
sound.setLoop(true);
sound.play();
}
if (iTrackActive == 2)
{
buffer2 = recorder.getBuffer();
sound2.setBuffer(buffer);
sound2.setLoop(true);
sound2.play();
}
}
else if (event.key.code == sf::Keyboard::Num1)
{
iTrackActive = 1;
}
else if (event.key.code == sf::Keyboard::Num2)
{
iTrackActive = 2;
}
}
}
window.clear();
window.draw(sprite);
window.display();
}
return 0;
}
BufferHelper.cpp
#include <SFML/System.hpp>
#include <SFML/Audio.hpp>
#include "BufferHelper.h"
#include <iostream>
#include <vector>
BufferHelper::BufferHelper()
{
}
sf::SoundBuffer MergeBuffers(sf::SoundBuffer BufferOne, sf::SoundBuffer BufferTwo)
{
int iLength;
int iShortLength;
const sf::Int16* LongerSamples;
const sf::Int16* ShorterSamples;
if (BufferOne.getSampleCount() > BufferTwo.getSampleCount())
{
LongerSamples = BufferOne.getSamples();
ShorterSamples = BufferTwo.getSamples();
iLength = BufferOne.getSampleCount();
iShortLength = BufferTwo.getSampleCount();
}
else
{
LongerSamples = BufferTwo.getSamples();
ShorterSamples = BufferOne.getSamples();
iLength = BufferTwo.getSampleCount();
iShortLength = BufferOne.getSampleCount();
}
std::vector<sf::Int16> FinalSamplesVector;
FinalSamplesVector.reserve(iLength);
for (int i = 0; i < iLength; i++)
{
if (i < iShortLength)
{
double dSampleOne = (LongerSamples[i] + 32768.) / 65535.;
double dSampleTwo = (ShorterSamples[i] + 32768.) / 65535.;
double dResult = 0;
if (dSampleOne < 0.5 && dSampleTwo < 0.5)
{
dResult = 2 * dSampleOne * dSampleTwo;
}
else
{
dResult = 2 * (dSampleOne + dSampleTwo) - 2 * dSampleOne * dSampleTwo - 1;
}
FinalSamplesVector.push_back(static_cast<sf::Int16>(dResult * 65535. - 32768.));
}
else
{
FinalSamplesVector.push_back(LongerSamples[i]);
}
}
sf::SoundBuffer FinalBuffer;
FinalBuffer.loadFromSamples(&FinalSamplesVector[0], FinalSamplesVector.size(), 2, 44100);
return FinalBuffer;
}
BufferHelper::~BufferHelper()
{
}
BufferHelper.h
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
using namespace sf;
class BufferHelper
{
public:
BufferHelper();
sf::SoundBuffer MergeBuffers(sf::SoundBuffer, sf::SoundBuffer);
~BufferHelper();
};
I will be thankful to recieve any kind of feedback.
You did not declare the body of the function MergeBuffers().
This has nothing to do with SFML, just add
sf::SoundBuffer BufferHelper::MergeBuffers(sf::SoundBuffer, sf::SoundBuffer)
{
// some code
}
in your cpp file.
Edit : I realize you mistakenly re-copied your main.cpp file code. Please show the good code for BufferHelper.cpp
I'm trying to write a small game where boxes drop down from the top of the window. But for some reason, I can't change a internal variable in the class, the y-coordinate. I don' knowif I'm missing something basic, but I can't find the bug.
Box.h
#pragma once
#include "SDL.h"
class Box
{
public:
Box();
~Box();
void setX (int a);
void setY (int a);
void setSpeed (int a);
void setSurface ();
void render(SDL_Surface *source, SDL_Window *win);
void update();
private:
int x;
int y;
int speed;
SDL_Surface *sur;
SDL_Rect rect;
};
Box.cpp
#include "Box.h"
#include "SDL_image.h"
#include <iostream>
void Box::setX(int a)
{
x = a;
}
void Box::setY (int a)
{
y = a;
}
void Box::setSpeed (int a)
{
speed = a;
}
void Box::setSurface()
{
sur = IMG_Load("C:/hello.bmp");
if (sur == NULL)
{
std::cout << IMG_GetError();
}
}
Box::Box()
{
speed = 5;
y = 0;
x = 3;
rect.x = 0;
rect.y = 0;
}
Box::~Box()
{
}
void Box::render(SDL_Surface *source, SDL_Window *win)
{
SDL_BlitSurface(sur, NULL, source, &rect);
SDL_UpdateWindowSurface(win);
}
void Box::update()
{
setY(y + speed); //I've also tried y = y + speed
rect.y = y;
}
main.cpp
#include "SDL.h"
#include "Box.h"
#include "SDL_image.h"
#include <iostream>
bool init();
void update(Box test);
void render(Box test);
SDL_Window *win;
SDL_Surface *source;
int main(int argc, char *argv[])
{
init();
bool quit = false;
SDL_Event e;
Box test;
test.setSurface();
test.render(source, win);
while (quit ==false)
{
while( SDL_PollEvent( &e ) != 0 )
{
if( e.type == SDL_QUIT )
{
quit = true;
}
}
update(test);
render(test);
}
return 0;
}
void update(Box test)
{
test.update();
}
void render(Box test)
{
test.render(source, win);
}
bool init()
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == NULL)
{
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
return 1;
}
source = SDL_GetWindowSurface(win);
return true;
}
update takes its Box argument by value, so a copy of the original Box is always made when update(test) is called. This copy is then modified, and the original is left unchanged. To fix this, make update take its argument by reference.
void update(Box& test);
void update(Box& test)
{
test.update();
}