diff --git a/SimpleGame/src/CMakeLists.txt b/SimpleGame/src/CMakeLists.txt index ed3be36..567fa91 100644 --- a/SimpleGame/src/CMakeLists.txt +++ b/SimpleGame/src/CMakeLists.txt @@ -23,6 +23,7 @@ add_executable(simpleGame Source/AudioEmitter.cpp Include/AudioEmitter.hpp Source/NoteSprite.cpp Include/NoteSprite.hpp Source/NoteTile.cpp Include/NoteTile.hpp Include/NotePlaceEnum.hpp + Source/TilePattern.cpp Include/TilePattern.hpp ) target_include_directories(simpleGame PRIVATE diff --git a/SimpleGame/src/Include/AudioEmitter.hpp b/SimpleGame/src/Include/AudioEmitter.hpp index 88cacdf..e1bd695 100644 --- a/SimpleGame/src/Include/AudioEmitter.hpp +++ b/SimpleGame/src/Include/AudioEmitter.hpp @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -31,6 +33,7 @@ public: int firstNote(); int nextNote(int currentNote); int noteSecondaire(int note); - float getTime(); + float getTimeTempo() const; + float getTime() const; float timeBeforeNewGeneration{0.2f}; }; diff --git a/SimpleGame/src/Include/Game.hpp b/SimpleGame/src/Include/Game.hpp index 3a9b99d..a3b8fbf 100644 --- a/SimpleGame/src/Include/Game.hpp +++ b/SimpleGame/src/Include/Game.hpp @@ -1,3 +1,5 @@ +#pragma once + #ifndef BOOK_GAME_HPP #define BOOK_GAME_HPP diff --git a/SimpleGame/src/Include/NoteSprite.hpp b/SimpleGame/src/Include/NoteSprite.hpp index 05a1e08..252340f 100644 --- a/SimpleGame/src/Include/NoteSprite.hpp +++ b/SimpleGame/src/Include/NoteSprite.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include class NoteTile; @@ -8,6 +9,7 @@ class NoteTile; class NoteSprite { public: static sf::Texture texture; + static bool loadTexture(const std::string &filename); friend class NoteTile; private: @@ -15,5 +17,5 @@ private: float fall_speed; NoteSprite(); NoteSprite(sf::Vector2f start_pos, float fall_speed); - void update(float dtime); + void update(float dtime, sf::RenderWindow &window); }; diff --git a/SimpleGame/src/Include/NoteTile.hpp b/SimpleGame/src/Include/NoteTile.hpp index f4695b7..b2c5c65 100644 --- a/SimpleGame/src/Include/NoteTile.hpp +++ b/SimpleGame/src/Include/NoteTile.hpp @@ -1,7 +1,9 @@ #include #include +#include #include #include +#include #include #include @@ -16,21 +18,25 @@ private: NoteSprite note_sprite; // probably some tileSprite class here in the future <- - // Constructor is rivate, use create - NoteTile(float play_time, float good_interval, NotePlaceEnum place); + // Constructor is private, use create + NoteTile(float play_time, float good_interval, NotePlaceEnum place, + float current_time); // For unit testing public: // Good key press for this note, is if player press good place, within // [play_time - good_interval/2, play_time + good_interval/2] - static void create(float play_time, float good_interval, NotePlaceEnum place); + static void create(float play_time, float good_interval, NotePlaceEnum place, + float current_time); // Usefull in test, but don't use it anywhere static void clear() { existing_tiles.clear(); }; // Should be called when one of arrows key pressed, return True if it's a good // press static bool checkPress(float press_time, NotePlaceEnum key_pressed); + static void update(float dtime, sf::RenderWindow &window); + // Some getters usefull in test : float getPlayTime() const { return play_time; }; float getGoodInterval() const { return good_interval; }; diff --git a/SimpleGame/src/Include/TilePattern.hpp b/SimpleGame/src/Include/TilePattern.hpp new file mode 100644 index 0000000..70c870a --- /dev/null +++ b/SimpleGame/src/Include/TilePattern.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "AudioEmitter.hpp" +#include + +void generateTilePattern(std::vector> new_notes, + const AudioEmitter &audio_emitter); diff --git a/SimpleGame/src/Source/AudioEmitter.cpp b/SimpleGame/src/Source/AudioEmitter.cpp index f4ef50d..d88e89c 100644 --- a/SimpleGame/src/Source/AudioEmitter.cpp +++ b/SimpleGame/src/Source/AudioEmitter.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include @@ -285,7 +284,7 @@ int AudioEmitter::noteSecondaire(int note) { */ std::vector> AudioEmitter::generateMusic() { std::vector> result; - result.reserve(16 * AudioEmitter::nbr_melo_max); + result.reserve(16 * nbr_melo_max); float beatDuration = tempo / 60.f; unsigned int sampleRate = 48000; int maxsize = 400; @@ -354,9 +353,15 @@ void AudioEmitter::audioEnd() { system->release(); } -float AudioEmitter::getTime() { +float AudioEmitter::getTimeTempo() const { float beatDuration = tempo / 60.f / 8.f; unsigned long long dspClock = 0; ERRCHECK(timer->getDSPClock(&dspClock, nullptr)); return dspClock / 48000.f / beatDuration; } + +float AudioEmitter::getTime() const { + unsigned long long dspClock = 0; + ERRCHECK(timer->getDSPClock(&dspClock, nullptr)); + return dspClock / 48000.f; +} diff --git a/SimpleGame/src/Source/Game.cpp b/SimpleGame/src/Source/Game.cpp index b693450..2ec2684 100644 --- a/SimpleGame/src/Source/Game.cpp +++ b/SimpleGame/src/Source/Game.cpp @@ -1,4 +1,9 @@ #include "Game.hpp" +#include "AudioEmitter.hpp" +#include "NoteSprite.hpp" +#include "NoteTile.hpp" +#include "TilePattern.hpp" +#include #include #include #include @@ -7,41 +12,41 @@ const sf::Time Game::TimePerFrame = sf::seconds(1.f / 60.f); Game::Game() { assert(mFont.openFromFile("media/Sansation.ttf")); - // We do not need to do mStatisticsText.setFont(mFont); as mStatisticsText is - // initialized with a reference to mFont mStatisticsText.setPosition({5.f, 5.f}); mStatisticsText.setCharacterSize(10); } -void Game::run() { - sf::Clock clock; - sf::Time timeSinceLastUpdate = sf::Time::Zero; - AudioEmitter audioEmitter = AudioEmitter(); - audioEmitter.generateMusic(); - bool generated = false; - mWindow.setVerticalSyncEnabled(true); - while (mWindow.isOpen()) { - sf::Time elapsedTime = clock.restart(); - timeSinceLastUpdate += elapsedTime; - while (timeSinceLastUpdate > TimePerFrame) { - if (32.f - fmod(audioEmitter.getTime(), 32.f) < - audioEmitter.timeBeforeNewGeneration) { - if (!generated) { - audioEmitter.generateMusic(); - generated = true; - } - } else { - generated = false; - } - timeSinceLastUpdate -= TimePerFrame; +void generateTilePatternAndMusic(AudioEmitter &audio_emitter) { + generateTilePattern(audio_emitter.generateMusic(), audio_emitter); +} - processEvents(audioEmitter); - audioEmitter.audioUpdate(); - update(TimePerFrame); +bool updateAudio(AudioEmitter &audioEmitter, bool generated) { + if (32.f - fmod(audioEmitter.getTimeTempo(), 32.f) < + audioEmitter.timeBeforeNewGeneration) { + if (!generated) { + generateTilePatternAndMusic(audioEmitter); + generated = true; } + } else { + generated = false; + } + + return generated; +} + +void Game::run() { + AudioEmitter audioEmitter = AudioEmitter(); + generateTilePatternAndMusic(audioEmitter); + bool generated = false; + mWindow.setFramerateLimit(60); + while (mWindow.isOpen()) { - updateStatistics(audioEmitter); render(); + generated = updateAudio(audioEmitter, generated); + processEvents(audioEmitter); + audioEmitter.audioUpdate(); + update(TimePerFrame); + updateStatistics(audioEmitter); } } @@ -62,7 +67,8 @@ void Game::processEvents(AudioEmitter &audioEmitter) { void Game::update(const sf::Time elapsedTime) { mTarget.update(elapsedTime); } void Game::render() { - mWindow.clear(); + mWindow.clear(sf::Color::Yellow); + NoteTile::update(1.0 / 60, mWindow); mTarget.drawCurrent(mWindow); mWindow.draw(mStatisticsText); mWindow.display(); @@ -70,8 +76,8 @@ void Game::render() { void Game::updateStatistics(AudioEmitter &audioEmitter) { mStatisticsText.setString(std::format( - "Mesure = {}\nBeat = {} us", ceil(audioEmitter.getTime() / 8.f), - ceil(fmod(audioEmitter.getTime(), 8.f)))); + "Mesure = {}\nBeat = {} us", ceil(audioEmitter.getTimeTempo() / 8.f), + ceil(fmod(audioEmitter.getTimeTempo(), 8.f)))); mStatisticsUpdateTime -= sf::seconds(1.0f); mStatisticsNumFrames = 0; diff --git a/SimpleGame/src/Source/Main.cpp b/SimpleGame/src/Source/Main.cpp index e0c0f03..1c1c038 100644 --- a/SimpleGame/src/Source/Main.cpp +++ b/SimpleGame/src/Source/Main.cpp @@ -1,6 +1,13 @@ #include "Game.hpp" +#include "NoteSprite.hpp" +#include int main() { + // from out/build/src + if (!NoteSprite::loadTexture("../../../media/sprites/flower_tile.png")) { + std::cerr << "Failed to load texture!" << std::endl; + return -1; + } Game game; game.run(); } diff --git a/SimpleGame/src/Source/NoteSprite.cpp b/SimpleGame/src/Source/NoteSprite.cpp index 6a0d290..4dd8855 100644 --- a/SimpleGame/src/Source/NoteSprite.cpp +++ b/SimpleGame/src/Source/NoteSprite.cpp @@ -1,16 +1,34 @@ #include "NoteSprite.hpp" +#include +#include #include #include #include +#include +#include +#include sf::Texture NoteSprite::texture; +bool NoteSprite::loadTexture(const std::string &filename) { + return NoteSprite::texture.loadFromFile(filename); +} + NoteSprite::NoteSprite() : sprite(sf::Sprite(texture)), fall_speed(0.f) {}; NoteSprite::NoteSprite(sf::Vector2f start_pos, float fall_speed) : fall_speed(fall_speed), sprite(sf::Sprite(NoteSprite::texture)) { sprite.setPosition(start_pos); // sprite position c'est le left up corner + sprite.setColor(sf::Color::Yellow); }; -void NoteSprite::update(float dtime) { +void NoteSprite::update(float dtime, sf::RenderWindow &window) { sprite.move(sf::Vector2f(0, fall_speed * dtime)); + window.draw(sprite); + /* + printf("draw \nposition (%f, %f)\n size(%u, %u)\n", sprite.getPosition().x, + sprite.getPosition().y, sprite.getTexture().getSize().x, + sprite.getTexture().getSize().y); + + printf("texture (%u, %u)\n", NoteSprite::texture.getSize().x, + NoteSprite::texture.getSize().y);*/ }; diff --git a/SimpleGame/src/Source/NoteTile.cpp b/SimpleGame/src/Source/NoteTile.cpp index 0d39ef9..f376b1d 100644 --- a/SimpleGame/src/Source/NoteTile.cpp +++ b/SimpleGame/src/Source/NoteTile.cpp @@ -1,24 +1,29 @@ #include "NoteTile.hpp" #include "NoteSprite.hpp" #include +#include #include +const int NotePlaceXPos[3] = {200, 400, 600}; std::vector> NoteTile::existing_tiles{}; // private -NoteTile::NoteTile(float play_time, float good_interval, NotePlaceEnum place) +NoteTile::NoteTile(float play_time, float good_interval, NotePlaceEnum place, + float current_time) : play_time(play_time), good_interval(good_interval), place(place), note_sprite() { // TODO do real note_sprite init, make it fall at good speed far enough... - note_sprite.sprite.setPosition(sf::Vector2f(200, 0)); - note_sprite.fall_speed = 1; + note_sprite.fall_speed = 100; + note_sprite.sprite.setPosition( + sf::Vector2f(NotePlaceXPos[place], + 480 - note_sprite.fall_speed * (play_time - current_time))); } // public -void NoteTile::create(float play_time, float good_interval, - NotePlaceEnum place) { +void NoteTile::create(float play_time, float good_interval, NotePlaceEnum place, + float current_time) { // Can't use make_unique because constructor is private - existing_tiles.push_back( - std::unique_ptr(new NoteTile(play_time, good_interval, place))); + existing_tiles.push_back(std::unique_ptr( + new NoteTile(play_time, good_interval, place, current_time))); } bool NoteTile::checkPress(float press_time, NotePlaceEnum key_pressed) { @@ -31,3 +36,9 @@ bool NoteTile::checkPress(float press_time, NotePlaceEnum key_pressed) { } return false; } + +void NoteTile::update(float dtime, sf::RenderWindow &window) { + for (const auto ¬e_tile : NoteTile::existing_tiles) { + note_tile->note_sprite.update(dtime, window); + } +} diff --git a/SimpleGame/src/Source/RoundTarget.cpp b/SimpleGame/src/Source/RoundTarget.cpp index e475ed7..7e00841 100644 --- a/SimpleGame/src/Source/RoundTarget.cpp +++ b/SimpleGame/src/Source/RoundTarget.cpp @@ -8,6 +8,8 @@ RoundTarget::RoundTarget(const float radius, const sf::Color color, float x, } void RoundTarget::drawCurrent(sf::RenderWindow &window) const { + /*printf("sphere pos (%f, %f)\n", mShape.getPosition().x,*/ + /* mShape.getPosition().y);*/ window.draw(mShape); } diff --git a/SimpleGame/src/Source/TilePattern.cpp b/SimpleGame/src/Source/TilePattern.cpp new file mode 100644 index 0000000..abfd19d --- /dev/null +++ b/SimpleGame/src/Source/TilePattern.cpp @@ -0,0 +1,17 @@ +#include "TilePattern.hpp" +#include "AudioEmitter.hpp" +#include "NoteSprite.hpp" +#include "NoteTile.hpp" +#include +#include + +void generateTilePattern(std::vector> new_notes, + const AudioEmitter &audio_emitter) { + int i = 0; + for (auto note : new_notes) { + float start_time = note.first; + NotePlaceEnum notePlace = static_cast(i % 3); + NoteTile::create(start_time, 1.0, notePlace, audio_emitter.getTime()); + i++; + } +} diff --git a/SimpleGame/src/Test/NoteTileTest.cpp b/SimpleGame/src/Test/NoteTileTest.cpp index e9b913b..3a2a6a0 100644 --- a/SimpleGame/src/Test/NoteTileTest.cpp +++ b/SimpleGame/src/Test/NoteTileTest.cpp @@ -10,7 +10,7 @@ TEST(NoteFileTest, Yes) { EXPECT_EQ(0, 0); } TEST(NoteTileTest, CreateTile) { NoteTile::clear(); - NoteTile::create(2.0f, 0.5f, NotePlaceEnum::Right); + NoteTile::create(2.0f, 0.5f, NotePlaceEnum::Right, 0.0); EXPECT_FLOAT_EQ(NoteTile::getExistingTiles()[0]->getPlayTime(), 2.0f); EXPECT_FLOAT_EQ(NoteTile::getExistingTiles()[0]->getGoodInterval(), 0.5f); EXPECT_EQ(NoteTile::getExistingTiles()[0]->getPlace(), NotePlaceEnum::Right); @@ -21,9 +21,9 @@ TEST(NoteTileTest, CreateTile) { // est negatif est divisé par 2, voir checkPress TEST(NoteTileTest, CheckGoodPress) { NoteTile::clear(); - NoteTile::create(2.0f, 0.5f, NotePlaceEnum::Right); - NoteTile::create(3.0f, 0.5f, NotePlaceEnum::Middle); - NoteTile::create(0.5f, 0.2f, NotePlaceEnum::Left); + NoteTile::create(2.0f, 0.5f, NotePlaceEnum::Right, 0.0); + NoteTile::create(3.0f, 0.5f, NotePlaceEnum::Middle, 0.0); + NoteTile::create(0.5f, 0.2f, NotePlaceEnum::Left, 0.0); EXPECT_FALSE(NoteTile::checkPress(1.0f, NotePlaceEnum::Left)); EXPECT_FALSE(NoteTile::checkPress(0.7f, NotePlaceEnum::Left));