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
Related
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'm new to c++ so I'm a bit confused on this one. I'm trying to have the player spawn, then when the user presses "C", the player switches with a car. What's happening currently is the player is initially spawning in the correct location, then the car is spawning where the player initially spawned, not where it currently is. However, since I'm using the function getPosition(), I would assume it would spawn in the current position of the player.
Player.h:
#pragma once
#include <SFML\Graphics.hpp>
#include <string>
class player {
public:
sf::Texture normalTexture;
sf::Sprite normalSprite;
sf::Texture carTexture;
sf::Sprite carSprite;
sf::Texture springTexture;
sf::Sprite springSprite;
sf::Texture rocketTexture;
sf::Sprite rocketSprite;
sf::IntRect normalRect[1];
sf::IntRect carRect[1];
sf::IntRect springRect[1];
sf::IntRect rocketRect[1];
bool rocket=false;
bool car=false;
bool spring=false;
bool normal=false;
player();
player(sf::Vector2f position, std::string normalFileLoc, std::string carFileLoc, std::string springFileLoc, std::string rocketFileLoc);
void update();
};
Player.cpp:
#include "Player.h"
player::player() : player::player(sf::Vector2f(100, 0), "player.jpg", "car.png", "spring.png", "rocket.png") {
}
player::player(sf::Vector2f position, std::string normalFileLoc, std::string
carFileLoc, std::string springFileLoc, std::string rocketFileLoc)
{
normalTexture.loadFromFile(normalFileLoc);
normalRect[0] = sf::IntRect(0, 0, 64, 128);
normalSprite.setTexture(normalTexture);
normalSprite.setTextureRect(normalRect[0]);
normalSprite.setOrigin(0,0);
normalSprite.setScale(1, 1);
normalSprite.setPosition(position.x, position.y);
carTexture.loadFromFile(carFileLoc);
carRect[0] = sf::IntRect(0, 0, 64, 64);
carSprite.setTexture(carTexture);
carSprite.setTextureRect(carRect[0]);
carSprite.setOrigin(0, -64);
carSprite.setScale(1, 1);
carSprite.setPosition(normalSprite.getPosition().x, normalSprite.getPosition().y);
}
Main.cpp I know it looks gross, I plan on making it look nicer later:
#include <SFML/Graphics.hpp>
#include <SFML\Graphics\Rect.hpp>
#include "player.h"
int main()
{
sf::RenderWindow window(sf::VideoMode(750, 750), "SFML Works!");
player thePlayer;
const float gravity = .001;
int groundheight = 500;
sf::Vector2f velocity(sf::Vector2f(0, 0));
thePlayer.normal = true;
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 (thePlayer.car && event.key.code == sf::Keyboard::C)
{
thePlayer.car = false;
thePlayer.spring = false;
thePlayer.rocket = false;
thePlayer.normal = true;
break;
}
if (thePlayer.spring && event.key.code == sf::Keyboard::S)
{
thePlayer.car = false;
thePlayer.spring = false;
thePlayer.rocket = false;
thePlayer.normal = true;
break;
}
if (thePlayer.rocket && event.key.code == sf::Keyboard::R)
{
thePlayer.car = false;
thePlayer.spring = false;
thePlayer.rocket = false;
thePlayer.normal = true;
break;
}
if (event.key.code == sf::Keyboard::C)
{
thePlayer.car = true;
thePlayer.spring = false;
thePlayer.rocket = false;
thePlayer.normal = false;
break;
}
if (event.key.code == sf::Keyboard::R)
{
thePlayer.car = false;
thePlayer.spring = false;
thePlayer.rocket = true;
thePlayer.normal = false;
break;
}
if (event.key.code == sf::Keyboard::S)
{
thePlayer.car = false;
thePlayer.spring = true;
thePlayer.rocket = false;
thePlayer.normal = false;
break;
}
}
}
if (thePlayer.normal)
{
velocity.x = 0;
thePlayer.normalSprite.move(velocity.x, velocity.y);
if (thePlayer.normalSprite.getPosition().y < groundheight)
{
velocity.y += gravity;
}
else
{
thePlayer.normalSprite.setPosition(thePlayer.normalSprite.getPosition().x, groundheight);
velocity.y = 0;
}
}
if (thePlayer.car)
{
thePlayer.carSprite.move(velocity.x, velocity.y);
if (thePlayer.carSprite.getPosition().y < groundheight)
{
velocity.y += gravity;
}
else
{
thePlayer.carSprite.setPosition(thePlayer.carSprite.getPosition().x, groundheight);
velocity.y = 0;
}
}
window.clear();
if (thePlayer.normal)
{
window.draw(thePlayer.normalSprite);
}
if (thePlayer.car)
{
window.draw(thePlayer.carSprite);
}
window.display();
}
}
Thanks so much!
Before drawing the car you should adjust its position to your player position :
if (thePlayer.car)
{
thePlayer.carSprite.setPosition(thePlayer.normalSprite.getPosition());
window.draw(thePlayer.carSprite);
}
But as ractiv said, you should organize your code differently. I suggest you to learn more about c++ "good pratices" before trying to do this kind of games.
We miss the main function to know exactly what happens when the car spawns but I think that you initialize the car in the Player constructor and does not move it when the player presses 'C'.
You should have something like that :
if(event.key.code == sf::Keyboard::C) {
player.spawnCar();
}
and in your spawnCar() function :
carSprite.setPosition(normalSprite.getPosition());
EDIT
As I said in my comment, you should use getters and setters to access to your attributes. According to your current main.cpp, you should have this :
if (event.key.code == sf::Keyboard::C)
{
thePlayer.car = true;
thePlayer.spring = false;
thePlayer.rocket = false;
thePlayer.normal = false;
carSprite.setPosition(normalSprite.getPosition());
break;
}
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.
I've been lurking around these forums from time to time when I needed help throughout my university programming classes, but recently I've been having trouble, and couldn't find the answer anywhere.
I started learning to program games for a bigger project of mine through:
http://www.gamefromscratch.com/page/Game-From-Scratch-CPP-Edition-Part-3.aspx
When i compile my code, I get
1>------ Build started: Project: PANG, Configuration: Debug Win32 ------
1> Game.cpp
1>MainMenu.obj : error LNK2001: unresolved external symbol "public: static class sf::RenderStates const sf::RenderStates::Default" (?Default#RenderStates#sf##2V12#B)
1>SplashScreen.obj : error LNK2001: unresolved external symbol "public: static class sf::RenderStates const sf::RenderStates::Default" (?Default#RenderStates#sf##2V12#B)
1>G:\My Documents\Visual Studio 2012\Projects\PANG\Debug\PANG.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
The thing I do not get is that I DO define SplashScreen and MainMenu in my Game.cpp...
Game.h
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
class Game
{
public:
static void Start();
static sf::RenderWindow& GetWindow();
private:
static bool isExiting();
static void GameLoop();
static void ShowSplashScreen();
static void ShowMenu();
enum GameState { Uninitialized, ShowingSplash, Paused, ShowingMenu, Playing, Exiting };
static GameState _gameState;
static sf::RenderWindow _mainWindow;
};
Game.cpp
#include "stdafx.h"
#include "Game.h"
#include "MainMenu.h"
#include "SplashScreen.h"
void Game::Start(void)
{
if(_gameState != Uninitialized)
return;
_mainWindow.create(sf::VideoMode(1024,768,32),"Pang!");
_gameState= Game::ShowingSplash;
while(!isExiting())
{
GameLoop();
}
_mainWindow.close();
}
bool Game::isExiting()
{
if(_gameState == Game::Exiting)
return true;
else
return false;
}
sf::RenderWindow& Game::GetWindow()
{
return _mainWindow;
}
void Game::GameLoop()
{
switch(_gameState)
{
case Game::ShowingMenu:
{
ShowMenu();
break;
}
case Game::ShowingSplash:
{
ShowSplashScreen();
break;
}
case Game::Playing:
{
sf::Event currentEvent;
while(_mainWindow.pollEvent(currentEvent))
{
_mainWindow.clear(sf::Color(0,0,0));
_mainWindow.display();
if(currentEvent.type == sf::Event::Closed)
{
_gameState = Game::Exiting;
}
if(currentEvent.type == sf::Event::KeyPressed)
{
// if(currentEvent.key.code == sf::Key::Escape) ShowMenu();
}
}
break;
}
}
}
void Game::ShowSplashScreen()
{
SplashScreen splashScreen;
splashScreen.Show(_mainWindow);
_gameState = Game::ShowingMenu;
}
void Game::ShowMenu()
{
MainMenu mainMenu;
MainMenu::MenuResult result = mainMenu.Show(_mainWindow);
switch(result)
{
case MainMenu::Exit:
_gameState = Game::Exiting;
break;
case MainMenu::Play:
_gameState = Game::Playing;
break;
}
}
Game::GameState Game::_gameState = Uninitialized;
sf::RenderWindow Game::_mainWindow;
SplashScreen.cpp
#include "StdAfx.h"
#include "SplashScreen.h"
void SplashScreen::Show(sf::RenderWindow & renderWindow)
{
sf::Texture texture;
if(texture.loadFromFile("images/SplashScreen.png") != true)
{
return;
}
sf::Sprite sprite(texture);
renderWindow.draw(sprite);
renderWindow.display();
sf::Event event;
while(true)
{
while(renderWindow.pollEvent(event))
{
if(event.type == sf::Event::EventType::KeyPressed
|| event.type == sf::Event::EventType::MouseButtonPressed
|| event.type == sf::Event::EventType::Closed)
{
return;
}
}
}
}
SplashScreen.h
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
class SplashScreen
{
public:
void Show(sf::RenderWindow& window);
};
MainMenu.cpp
#include "stdafx.h"
#include "MainMenu.h"
MainMenu::MenuResult MainMenu::Show(sf::RenderWindow& window)
{
sf::Texture texture;
texture.loadFromFile("images/MainMenu.png");
sf::Sprite sprite(texture);
MenuItem playButton;
playButton.rect.top = 145;
playButton.rect.height = 380;
playButton.rect.left = 0;
playButton.rect.width = 1023;
playButton.action = Play;
MenuItem exitButton;
exitButton.rect.top = 383;
exitButton.rect.left = 0;
exitButton.rect.width = 1023;
exitButton.rect.height = 560;
exitButton.action = Exit;
_menuItems.push_back(playButton);
_menuItems.push_back(exitButton);
window.draw(sprite);
window.display();
return GetMenuResponse(window);
}
MainMenu::MenuResult MainMenu::HandleClick(int x,int y)
{
std::list<MenuItem>::iterator it;
for (it = _menuItems.begin(); it != _menuItems.end(); it++)
{
sf::Rect<int>menuItemRect = (*it).rect;
if( x > menuItemRect.left
&& x < menuItemRect.left + menuItemRect.width
&& y > menuItemRect.top
&& y < menuItemRect.height + menuItemRect.top)
{
return (*it).action;
}
}
return Nothing;
}
MainMenu::MenuResult MainMenu::GetMenuResponse(sf::RenderWindow& window)
{
sf::Event menuEvent;
while(true)
{
while(window.pollEvent(menuEvent))
{
if(menuEvent.type == sf::Event::MouseButtonPressed)
{
return HandleClick(menuEvent.mouseButton.x,menuEvent.mouseButton.y);
}
if (menuEvent.type == sf::Event:: Closed)
{
return Exit;
}
}
}
}
MainMenu.h
#pragma once
#include "SFML/Window.hpp"
#include "SFML/Graphics.hpp"
#include <list>
class MainMenu
{
public:
enum MenuResult {Nothing, Exit, Play};
struct MenuItem
{
public:
sf::Rect<int> rect;
MenuResult action;
};
MenuResult Show(sf::RenderWindow & window);
private:
MenuResult GetMenuResponse(sf::RenderWindow& window);
MenuResult HandleClick(int x, int y);
std::list<MenuItem> _menuItems;
};
Any help would be greatly appreciated, Thank You !
I have found the solution. I removed SFML_STATIC from the preprocessor in properties and it worked ! thanks Adriano for the help !
So I am making a 2D platformer using SDL. I have experience in C/C++, but I haven't really written anything with it in the past 8 months. I'm using SDL to render my graphics, and I get an entirely blank screen, and I can't really seem to figure out why. Can anybody help me figure out why this isn't rendering?
EDIT: I added the extra code that was missing.
Map.cpp
#include "Map.h"
int map[10][10] = { {0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
};
Map::Map()
: g( Graphics() )
{
grassTile = SDL_LoadBMP("grass.bmp");
}
Map::~Map()
{
}
void Map::renderMap()
{
for (int y = 0; y < 10; y++)
{
for (int x = 0; x < 10; x++)
{
int newPos = map[y][x];
if (newPos == 0)
{
g.drawImage(x * 32, y * 32, grassTile);
}
}
}
}
Graphics.cpp
#include "Graphics.h"
#include <iostream>
#include <SDL.h>
#include <Windows.h>
using namespace std;
Graphics::Graphics()
: count( 0 )
{
}
Graphics::~Graphics()
{
}
int Graphics::getWidth(int i)
{
return this->width = i;
}
int Graphics::getHeight(int i)
{
return this->height = i;
}
void Graphics::initScreen(int width,int height, char* title)
{
if (!SDL_Init(SDL_INIT_EVERYTHING) == 1)
{
cout << "SDL is running" << endl;
}
SDL_WM_SetCaption(title,NULL);
screen = SDL_SetVideoMode(width,height,8,NULL);
getWidth(width);
getHeight(height);
}
void Graphics::beginFrame()
{
SDL_FillRect(screen,NULL,0x000000);
}
void Graphics::repaint()
{
SDL_Flip(screen);
}
void Graphics::loadImage(char* location, SDL_Surface* sur)
{
sur = SDL_LoadBMP(location);
}
void Graphics::renderTileMap(SDL_Surface* sur, int width, int height, int amountX, int amountY)
{
for (int y = 0; y < amountY; y++)
{
for (int x = 0; x < amountX; x++)
{
drawImage(x * width, y * height, sur);
}
}
}
void Graphics::pixel(int x,int y, int r,int g, int b)
{
if (screen != NULL)
{
if (screen->pixels != NULL)
{
Uint8* pixels = (Uint8*)screen->pixels;
Uint8* indevidualPixel = pixels + (y * screen->pitch) + x;
*indevidualPixel = SDL_MapRGB(screen->format,r,g,b);
}
}
}
void Graphics::drawImage(int x,int y, SDL_Surface* sur)
{
SDL_Rect rect;
rect.x = x;
rect.y = y;
SDL_BlitSurface(sur,NULL,screen,&rect);
}
Main.cpp>
#include <SDL.h>
#include <cstdio>
#include "Graphics.h"
#include "Keyboard.h"
#include "Game.h"
SDL_Event event;
bool running = true;
Game game = Game();
int main(int argc, char* argv[])
{
game.k = Keyboard();
game.g.initScreen(900,500, "theDevCorner's SDL Tutorials!!!");
while (running)
{
SDL_PollEvent(&event);
if (event.type == SDL_QUIT)
{
running = false;
}
if (event.type == SDL_KEYUP)
{
SDLKey keyReleased = event.key.keysym.sym;
if (keyReleased == SDLK_RIGHT)
{
game.k.right = false;
}
if (keyReleased == SDLK_LEFT)
{
game.k.left = false;
}
if (keyReleased == SDLK_DOWN)
{
game.k.down = false;
}
if (keyReleased == SDLK_UP)
{
game.k.up = false;
}
}
if (event.type == SDL_KEYDOWN)
{
SDLKey keyPressed = event.key.keysym.sym;
if (keyPressed == SDLK_RIGHT)
{
game.k.right = true;
}
if (keyPressed == SDLK_LEFT)
{
game.k.left = true;
}
if (keyPressed == SDLK_DOWN)
{
game.k.down = true;
}
if (keyPressed == SDLK_UP)
{
game.k.up = true;
}
}
game.g.beginFrame();
game.render();
game.g.repaint();
}
return 0;
};
Game.cpp
#include "Game.h"
Game::Game()
: g(Graphics()),
x( 0 ),
y( 0 ),
m( Map() )
{
image = SDL_LoadBMP("grass.bmp");
}
Game::~Game()
{
}
void Game::keyLogic()
{
if (k.right)
{
x += 5;
}
if (k.left)
{
x -= 5;
}
if (k.down)
{
y += 5;
}
if (k.up)
{
y -= 5;
}
}
void Game::update()
{
if (count < 10)
{
count++;
}
if (count == 10)
{
keyLogic();
count = 0;
}
}
void Game::render()
{
update();
m.renderMap();
}
You have two instances of Graphics, one in Game and one in Map. You call Graphics::initScreen on the one in the Game instance game, but later you try to render in the Graphics instance of the Map instance game.m, where the SDL surface screen is uninitialized. Specifically game.render(); calls game.m.renderMap();, which calls game.m.g.drawImage(...).
Decide for one location of the Graphics instance or use references.