Visuel notes
This commit is contained in:
parent
e2fb0d911a
commit
05f8b11dec
14 changed files with 137 additions and 50 deletions
|
@ -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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <fmod.hpp>
|
||||
#include <fmod_errors.h>
|
||||
#include <memory>
|
||||
|
@ -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};
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef BOOK_GAME_HPP
|
||||
#define BOOK_GAME_HPP
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include <SFML/Graphics/Sprite.hpp>
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include <NotePlaceEnum.hpp>
|
||||
#include <NoteSprite.hpp>
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include <SFML/Graphics/StencilMode.hpp>
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
#include <SFML/Window/Window.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
@ -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; };
|
||||
|
|
7
SimpleGame/src/Include/TilePattern.hpp
Normal file
7
SimpleGame/src/Include/TilePattern.hpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "AudioEmitter.hpp"
|
||||
#include <vector>
|
||||
|
||||
void generateTilePattern(std::vector<std::pair<float, int>> new_notes,
|
||||
const AudioEmitter &audio_emitter);
|
|
@ -2,7 +2,6 @@
|
|||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
@ -285,7 +284,7 @@ int AudioEmitter::noteSecondaire(int note) {
|
|||
*/
|
||||
std::vector<std::pair<float, int>> AudioEmitter::generateMusic() {
|
||||
std::vector<std::pair<float, int>> 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;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
#include "Game.hpp"
|
||||
#include "AudioEmitter.hpp"
|
||||
#include "NoteSprite.hpp"
|
||||
#include "NoteTile.hpp"
|
||||
#include "TilePattern.hpp"
|
||||
#include <SFML/Graphics/Color.hpp>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
|
@ -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;
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
#include "Game.hpp"
|
||||
#include "NoteSprite.hpp"
|
||||
#include <iostream>
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -1,16 +1,34 @@
|
|||
#include "NoteSprite.hpp"
|
||||
#include <SFML/Graphics/Color.hpp>
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include <SFML/Graphics/Sprite.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
#include <SFML/Window/Window.hpp>
|
||||
#include <bits/types/cookie_io_functions_t.h>
|
||||
#include <cstdio>
|
||||
|
||||
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);*/
|
||||
};
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
#include "NoteTile.hpp"
|
||||
#include "NoteSprite.hpp"
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
#include <SFML/Window/Window.hpp>
|
||||
#include <memory>
|
||||
|
||||
const int NotePlaceXPos[3] = {200, 400, 600};
|
||||
std::vector<std::unique_ptr<NoteTile>> 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<NoteTile>(new NoteTile(play_time, good_interval, place)));
|
||||
existing_tiles.push_back(std::unique_ptr<NoteTile>(
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
17
SimpleGame/src/Source/TilePattern.cpp
Normal file
17
SimpleGame/src/Source/TilePattern.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include "TilePattern.hpp"
|
||||
#include "AudioEmitter.hpp"
|
||||
#include "NoteSprite.hpp"
|
||||
#include "NoteTile.hpp"
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
void generateTilePattern(std::vector<std::pair<float, int>> new_notes,
|
||||
const AudioEmitter &audio_emitter) {
|
||||
int i = 0;
|
||||
for (auto note : new_notes) {
|
||||
float start_time = note.first;
|
||||
NotePlaceEnum notePlace = static_cast<NotePlaceEnum>(i % 3);
|
||||
NoteTile::create(start_time, 1.0, notePlace, audio_emitter.getTime());
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue