We (school) are developping a game in C++ with SFML. The game is a fight game, where we need to play little sounds when the player gets hit for exemple.
I'm attempting to play a sf::Sound in a loop. I know we should not call the play() method of sf::Sound in a loop, but as the SFML apps all run in while loops, I have no other choices. Or at least, I don't know any other way to do it.
I tried to use a sound manager, I read multiple posts about it but I found nothing working.
Here is a sample code :
#include <SFML/Audio.hpp>
#include <vector>
#include <iostream>
int main() {
int FPS = 60;
// sf::Music music;
// if(!music.openFromFile("resources/audio/fight_theme.ogg")) {
// std::cout << "Music was not found" << std::endl;
// }
// music.setVolume(10.f);
// music.play();
// Create the main window
sf::VideoMode desktopMode = sf::VideoMode::getDesktopMode();
sf::RenderWindow app(
sf::VideoMode(
desktopMode.width,
desktopMode.height,
desktopMode.bitsPerPixel),
"SkyddaForStackOverflow",
sf::Style::Fullscreen
);
app.setFramerateLimit(FPS);
//Main loop
while (app.isOpen()) {
/*In the actual code, we have two player instances.
When the user press S or keyDown button, we call the attack function.
In the function, we deal the damages to the ennemy, then we call playSound
to play the hitting sound
Please note this is a sample code to help understanding the case.
In the actual code, everything is delegated to the Player class, to a SoundLoader (which is basically playSound() here)
The problem is, even with delegation, even if the playSound method is not situated in the main loop,
it is called in the main loop so the location of the code does not make any difference : it won't play since it won't
be called outside of a loop as we do for the background music (see commented code after main() {..., the background music
works fine.*/
if(player.attack(ennemy)) {
playSound();
}
}
return EXIT_SUCCESS;
}
void playSound() {
sf::SoundBuffer buffer;
if(!buffer.loadFromFile(path)) {
std::cout << "Sound was not found at " << path << std::endl;
}
sf::Sound sound(buffer);
sound.play();
}
Don't hesitate if you have additionnal questions.
Thanks !
The issue is not with "being called outside the loop"; the issue is that your sf::Sound object is destroyed at the end of the playSound function!
First, define two global (or class-) variables:
std::map<std::string, sf::SoundBuffer> buffers;
std::map<std::string, sf::Sound> sounds;
You can now define playSound as follows:
void playSound(std::string path) {
if (auto it = sounds.find(path); it == sounds.end()) {
bool ok = buffers[path].loadFromFile(path);
// do something if ok is false
sounds[path] = sf::Sound{buffers[path]};
}
sounds[path].play();
}
This will keep your sf::Sound objects (and associated sf::SoundBuffers) alive. The first call will load the file from disk, the subsequent calls will just restart the existing sound.
Note that this code is slightly suboptimal in favor of understandability: it looks up sounds[path] twice. As an exercise to you, get rid of the second lookup by reusing it in the play call.
Related
Hello i'm newbie in C++ specially on STL,
I need to create a function with an infinite loop to calculate and process big data (such as Genetic Algorithm), but i also need keep Ui responsive and update it within (after each round) that infinite loop and start/stop operation manually.
something like this:
bool working = false;
void do_process()
{
while(working)
{
// do some stuff
}
}
void btnStart()
{
working = true;
do_process();
}
void btnEnd()
{
working = false;
}
would you please guide me to a proper solution without any 3rdparty lib, thanks.
and apologies for terrible English.
The code below should get you started. But be careful, implementing a multi-threading application is generally a hard problem also for experienced users. Lot of knowledge is required about memory access synchronization and deadlock analysis. Consider the example below is really essential. For instance, in btnStart and btnStop you should check if a thread is already running. Checking the global bool working may require synchronization. Similarly, checking for null pointer may require synchronization. Bottom line, it is way more complicate than it may seem.
#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include <memory>
bool working = false;
std::unique_ptr<std::thread> t;
void do_process()
{
while(working)
{
std::cout << "Hi. I am a secondary thread and I am running.\n";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void btnStart()
{
working = true;
t.reset(new std::thread(do_process)); // start the thread
}
void btnEnd()
{
working = false; // inform the thread of termination
t->join(); // wait for thread termination
t.reset(NULL);
}
int main()
{
std::cout << "Hi, I am the main thread.\n";
std::cout << "I'll now launch another thread and sleep for a while\n";
btnStart();
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
btnEnd();
std::cout << "What happened while I was slepping?\n";
return 0;
}
I am fairly new also to c++ but i have something that might help.
when i want to run something like an update to my code or to run something external without cramming my original project with code, i like to use ShellExecute to run another c++ program or external program. To use ShellExecute you need #include<windows.h>
For example if i want to update my program, i use #include<fstream>, #include<windows.h>, and #include<string> to check for a value in a file called 'updatereq.txt' (i make it my self). And in my program i run ifstream to check in the file if there is a '1'. If the if statement detects '1' it does this:
void Update(string filename)
{
ShellExecute(NULL,"open",filename.c_str(),NULL,NULL,SW_SHOWNORMAL)
}
This will run with:
HWND set as NULL, Operation set as: "open", File set as string:filenameconstant, Parameters set as NULL, Directory set as NULL(will run in the Directory of originally launching, usually at the main file), and Mode set as SW_SHOWNORMAL which will run it infront of you normally. This is also SW_SHOWMINIMIZED and SW_SHOWMAXIMIZED
Hope this helps!
PS: Remember to mention the file / program name that you are going to run when calling this function
So my use case is the following: I have a handful of functions and fields defined inside a namespace. One of these functions will initialize the fields, then run another function inside a call to std::async. The function called should run indefinitely until flagged to stop, most commonly from outside of its own thread. The basic code looks something like this
namespace Game
{
void Create() {
Initialize();
auto returned = std::async(RunGameLoop, std::ref(FLAGS));
}
}
Now, the way I have attempted to implement this is by initializing these flags in the namespace:
namespace Game
{
namespace // This is used because the fields and functions here should be for internal use only
{
bool stopped = false;
}
}
Inside the RunGameLoop function the basic structure is set up like this
namespace Game
{
namespace // This is used because the fields and functions here should be for internal use only
{
void RunGameLoop()
{
while (!stopped)
{
// ... do stuff
}
}
}
}
But seemingly due to how async works, if I change the value of stopped from anywhere other than inside the RunGameLoop function, the RunGameLoop function does not see any change. Presumably when creating the async function call, C++ simply copies all values in scope at the time of construction, passing them by value instead of reference.
My question is: How do I make this change noticeable inside the async function loop? Or even better: Is there a better way to communicate simple global flags like this with an async function in C++? I have experimented with using std::ref, passing pointers, and passing an entire map of flags by reference, but seemingly no changes made outside of the RunGameLoop function will be noticeable inside the RunGameLoop function.
Edit: I've managed to replicate the issue in a minimal example, this program will run indefinitely, and indeed never reach the second std::cout statement, counterintuitively. The std::async call does, in fact, not seem to run the function asynchronously at all, which is a bit harsher than what I experienced in my own project. I acknowledge I might be misunderstanding how std::async is supposed to be used, but it seems like this code should work to me.
Edit 2: I bungled my prior example, so I fixed it. Unfortunately now it seems to behave as expected, unlike my actual project:
#include <iostream>
#include <future>
namespace test
{
namespace
{
std::atomic<bool> testbool = false;
std::future<void> returned;
void queryTestBool()
{
while (!testbool)
{
}
std::cout << "EXITED THREAD: " << std::boolalpha << testbool << std::endl;
}
}
void Initialize()
{
testbool = false;
}
void Delete()
{
testbool = !testbool;
returned.get();
}
void Create()
{
Initialize();
returned = std::async(queryTestBool);
}
}
int main()
{
using namespace test;
std::cout << std::boolalpha << testbool << std::endl;
Create();
Delete();
std::cout << std::boolalpha << testbool << std::endl;
}
This program outputs
false
EXITED THREAD: true
true
meaning that not only does the Delete function successfully change the value of testbool, but that change is noticed in the asynchronous while loop. This last part is what isn't happening in my own project for some reason, even when I use std::atomic. I will investigate further.
So I feel massively stupid. After struggling with this for weeks, implementing all sorts of stuff, I finally discovered that the place my test called the Delete() function was being skipped because of a failed assertion that I didn't expect to make the test exit before running the rest... Mystery solved
I have a question which is quite general, but I hope someone will be able to at least point me in the right direction.
I created my project a I was building it only in Debug mode with /MDd flag.
But it started to have perfomance issues, so I wanted to try it in Release mode to see, how it goes.
Problem is, that when I use /MD or /MT flag and Release mode my application instantly crashes.
So I tried to find out why. It works fine in Debug. I've tried some code changes, but nothing helped. So I decided to make my app just start and comment out rest of my code. But it was still crashing. Even when my code was unused. It didn't crash only, when I completly removed those unused parts of code.
I think it's something with variable inicialization/declaration, but I'm not quite sure what I should look for.
Could someone suggest me what can cause application to crash even if it's just Declaration/Inicialization and is not even used in RunTime?
I hope you can somehow understand what is my problem.
Thanks for any suggestions!
EDIT: Code which crashes, when unused code is in project, but does not crash when i remove unused code.
#include "core/oxygine.h"
#include "Stage.h"
#include "DebugActor.h"
//#include "Galatex.h"
using namespace oxygine;
//called each frame
int mainloop()
{
//galatex_update();
//update our stage
//update all actors. Actor::update would be called also for all children
getStage()->update();
if (core::beginRendering())
{
Color clearColor(32, 32, 32, 255);
Rect viewport(Point(0, 0), core::getDisplaySize());
//render all actors. Actor::render would be called also for all children
getStage()->render(clearColor, viewport);
core::swapDisplayBuffers();
}
//update internal components
//all input events would be passed to Stage::instance.handleEvent
//if done is true then User requests quit from app.
bool done = core::update();
return done ? 1 : 0;
}
//it is application entry point
void run()
{
ObjectBase::__startTracingLeaks();
//initialize Oxygine's internal stuff
core::init_desc desc;
#if OXYGINE_SDL || OXYGINE_EMSCRIPTEN
//we could setup initial window size on SDL builds
desc.w = 1800;
desc.h = 1000;
//marmalade settings could be changed from emulator's menu
#endif
//galatex_preinit();
core::init(&desc);
//create Stage. Stage is a root node
Stage::instance = new Stage(true);
Point size = core::getDisplaySize();
getStage()->setSize(size);
//DebugActor is a helper actor node. It shows FPS, memory usage and other useful stuff
DebugActor::show();
//initialize this example stuff. see example.cpp
//galatex_init();
#ifdef EMSCRIPTEN
/*
if you build for Emscripten mainloop would be called automatically outside.
see emscripten_set_main_loop below
*/
return;
#endif
//here is main game loop
while (1)
{
int done = mainloop();
if (done)
break;
}
//user wants to leave application...
//lets dump all created objects into log
//all created and not freed resources would be displayed
ObjectBase::dumpCreatedObjects();
//lets cleanup everything right now and call ObjectBase::dumpObjects() again
//we need to free all allocated resources and delete all created actors
//all actors/sprites are smart pointer objects and actually you don't need it remove them by hands
//but now we want delete it by hands
//check example.cpp
//galatex_destroy();
//renderer.cleanup();
/**releases all internal components and Stage*/
core::release();
//dump list should be empty now
//we deleted everything and could be sure that there aren't any memory leaks
ObjectBase::dumpCreatedObjects();
ObjectBase::__stopTracingLeaks();
//end
}
#ifdef __S3E__
int main(int argc, char* argv[])
{
run();
return 0;
}
#endif
#ifdef OXYGINE_SDL
#include "SDL_main.h"
extern "C"
{
int main(int argc, char* argv[])
{
run();
return 0;
}
};
#endif
#ifdef EMSCRIPTEN
#include <emscripten.h>
void one() { mainloop(); }
int main(int argc, char* argv[])
{
run();
emscripten_set_main_loop(one, 0, 0);
return 0;
}
#endif
So I'll write it here for possibly other newbies like me which would find themselves in similar sutiation.
My problem was in Initialization of static and other variables which were "outside of function". For example:
MyObject object = new MyObject(); //This was the reason, why it was crashing, just had to move
// initialization of such variables to function which was called with object creation.
void MyClass::myFunction(){
object->doSomething();
}
So when program started inicialization of those variables caused crash of program.
Note: It seems like it was problem with objects, cause variables like Integers or such were just fine.
Well, I'm not totally sure why this is allowed in Debug mode, but crashes Release mode right after start, maybe someone could answer under this comment and explain this behavior, I'm just begginer and I'm doing lot of bad stuff, but I'm trying and that's good, right? :D
I hope i didn't waste too much of your time guys and maybe this post will be useful to someone in future.
I'm building a small game.
One of the input options is to restart the game. The only way I could think of doing this was to call the main function from within the main function
int main(int argc, char argv[]) {
...
if (input == "restart") {
main(argc, argv);
}
Is this bad form? Will it even work?
No, the C++ standard disallows calling main manually.
To cite the standard (C++11: 3.6.1 Main Function)
The function main shall not be used within a program. The linkage
(3.5) of main is implementation-defined.
A program that defines main as deleted or that declares main to be inline, static, or constexpr is ill-
formed. The name main is not otherwise reserved.
You can't call main() recursively. That's actually undefined behavior.
Use a loop instead:
int main() {
bool restart = false;
do {
// Do stuff ...
// Set restart according some condition inside of the loop
if(condition == true) {
restart = true;
} // (or simplyfied restart = condtion;)
} while(restart);
}
Do not do this. From http://en.cppreference.com/w/cpp/language/main_function
The main function has several special properties:
1) It cannot be used anywhere in the program
a) in particular, it cannot be called recursively
Since recursively calling main is impossible in C++ and would not really solve the problem, here's my 2 cents on how to deal with the problem:
Basically, any large program is a loop that might look like this:
int main()
{
bool quit = false;
//Initialise and aquire resources...
while (!quit)
{
//Run game and set quit if user wants to quit...
}
//free resources, should be automatic when RAII is adhered.
}
Your game should already look something like this, since any program that is not a loop will immidiately quit and won't be much of a game. Just change the structure to this:
int main()
{
bool quit = false;
bool restart = false;
while (!quit)
{
Restart = false;
//Initialise and aquire resources...
while (!quit && !restart)
{
//Run game and update quit and restart according to user input.
}
//free resources, should be automatic when RAII is adhered.
}
}
you can use GOTO but this is not a good way of programming in general. As the guys mentioned to use booleans or loops to check the current state or any other way instead of goto because it causes sometimes problems in the compiler. However it is still available in C and not C++ (AFAIK)
If in addition to reloading internal resources, you also need to reload external things like a libraries that the game links to you can do this by re-launching the game in a thread, detaching the thread and then shutting down.
I use this in a game I've made where I have automatic updates, to start the new updated executable and libraries.
int main() {
//initialize the game
bool restart=false, quit=false;
while (!quit) {
//Main loop of the game
}
if (restart) {
#ifdef _WIN32
std::thread relaunch([](){ system("start SpeedBlocks.exe"); });
#elif __APPLE__
std::thread relaunch([](){
std::string cmd = "open " + resourcePath() + "../../../SpeedBlocks.app";
system(cmd.c_str());
});
#else
std::thread relaunch([](){ system("./SpeedBlocks"); });
#endif
relaunch.detach();
}
return 0;
}
A bit of a hack, but it gets the job done. The #ifdefs just make it use the correct launch cmd for Windows/Max/Linux.
I'm making a program that can update the states of objects whilst rendering.
So my first approach was the obvious draw and update in the main while loop, but this problem limited the update state part to the speed of rendering (the computer speed) so this wasn't a good approach.
So I tried to think about the problem and came up with a solution that making a detached thread whose purpose is to update the game. Here is my code of this:
//DEFAULT
#include <iostream>
#include <chrono>
#include <thread>
//SFML
#include <SFML/Graphics.hpp>
void sleep_fnc(bool*);
void update_game(bool*/*, Some objects...*/);
#define cycles_per_milisecond 1000/30
int main() {
bool flag = true;
sf::RenderWindow window(sf::VideoMode(680, 480), "I work!");
std::thread (sleep_fnc, &flag).detach();
std::thread(update_game, &flag/*, Some objects...*/).detach();
if (window.isOpen()) {
window.clear();
//DRAW STUFF HERE
window.display();
}
return 0;
}
void sleep_fnc(bool *flag_ptr) {
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(cycles_per_milisecond));
*flag_ptr = true;
}
}
void update_game(bool *flag_ptr/*, Some objects...*/) {
while (true) {
if (*flag_ptr) {
//Do update stuff
*flag_ptr = false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
After I fiddled around with this code someone else realized that this wasn't such a good solution (thanks to you whomever pointed it out). The reason for this is if one object is being modified by the update loop WHILE the render loop is in its cycle something undefined would probably be the outcome, so I went back and started thinking again.
After thinking I came up with a solution that every class could inherit some universal class that had a boolean whether the object was being used by the draw loop or update loop, if it was in use, one of the loops would wait until the boolean flag indicated that it was ready for use again. It would probably be best if the update loop wasn't the one to wait.
Then it finally hit me that drawing the objects would be useless if they hadn't been updated. I believe that using a timer to test execution time and using that is unreliable, and there must be some other way than limiting the frame rate.
Would this prove that a frame rate higher than the update-rate is useless and is there some other approach that doesn't involve testing the execution time of last cycle and using that?