187 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "application.h"
 | 
						|
 | 
						|
#include <SFML/Graphics/Color.hpp>
 | 
						|
#include <SFML/Window/Event.hpp>
 | 
						|
 | 
						|
const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 60.f);
 | 
						|
 | 
						|
Application::Application() :
 | 
						|
    _game_window({1280, 720}, "Test"),
 | 
						|
    _debug(true)
 | 
						|
{
 | 
						|
    _font.loadFromFile("/usr/share/qtcreator/fonts/SourceCodePro-Regular.ttf");
 | 
						|
    _grade.setFont(_font);
 | 
						|
    _grade.setPosition(160, 160);
 | 
						|
    _grade.setFillColor(sf::Color(255, 0, 0, 0));
 | 
						|
    _grade.setCharacterSize(35);
 | 
						|
    _grade.setString("NOT INIT");
 | 
						|
}
 | 
						|
 | 
						|
void Application::run()
 | 
						|
{
 | 
						|
    std::string song_filename = "/home/naiji/METEOR.flac";
 | 
						|
 | 
						|
    _music.openFromFile(song_filename);
 | 
						|
    _music.play();
 | 
						|
    _music.setVolume(2);
 | 
						|
 | 
						|
    _game_window.display();
 | 
						|
 | 
						|
    startGameLoop();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static bool isOneFramePassed(const sf::Time& time_since_last_update)
 | 
						|
{
 | 
						|
    return time_since_last_update >= TIME_PER_FRAME;
 | 
						|
}
 | 
						|
 | 
						|
void Application::startGameLoop()
 | 
						|
{
 | 
						|
    sf::Clock timer;
 | 
						|
    sf::Time time_since_last_update = sf::Time::Zero;
 | 
						|
 | 
						|
    while (_game_window.isOpen())
 | 
						|
    {
 | 
						|
        input();
 | 
						|
 | 
						|
        time_since_last_update += timer.restart();
 | 
						|
        if (isOneFramePassed(time_since_last_update))
 | 
						|
        {
 | 
						|
            time_since_last_update -= TIME_PER_FRAME;
 | 
						|
            update();
 | 
						|
            draw();
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static sf::Text makeGradeString(const NoteGrade::Rating& rating)
 | 
						|
{
 | 
						|
    sf::Text ret;
 | 
						|
    switch (rating)
 | 
						|
    {
 | 
						|
    case (NoteGrade::Rating::BAD):
 | 
						|
        ret.setString("BAD");
 | 
						|
        ret.setFillColor(sf::Color(255, 255, 255, 255));
 | 
						|
        break;
 | 
						|
 | 
						|
    case (NoteGrade::Rating::GREAT):
 | 
						|
        ret.setString("GREAT");
 | 
						|
        ret.setFillColor(sf::Color(255, 255, 0, 255));
 | 
						|
        break;
 | 
						|
 | 
						|
    case (NoteGrade::Rating::WRONG):
 | 
						|
        ret.setString("WRONG");
 | 
						|
        ret.setFillColor(sf::Color(120, 120, 120, 255));
 | 
						|
        break;
 | 
						|
 | 
						|
    case (NoteGrade::Rating::GOOD):
 | 
						|
        ret.setString("GOOD");
 | 
						|
        ret.setFillColor(sf::Color(255, 100, 120, 255));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
void Application::input()
 | 
						|
{
 | 
						|
    sf::Event event;
 | 
						|
    while (_game_window.pollEvent(event))
 | 
						|
    {
 | 
						|
        switch (event.type)
 | 
						|
        {
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
 | 
						|
        case (sf::Event::Closed):
 | 
						|
            _game_window.close();
 | 
						|
            break;
 | 
						|
 | 
						|
        case (sf::Event::KeyPressed):
 | 
						|
            onKeyPressed(event.key.code);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static Note::Arrow keyToArrow(const sf::Keyboard::Key &key)
 | 
						|
{
 | 
						|
    switch (key)
 | 
						|
    {
 | 
						|
    case sf::Keyboard::A:
 | 
						|
    case sf::Keyboard::Left:
 | 
						|
    case sf::Keyboard::Num4:
 | 
						|
        return Note::Arrow::LEFT;
 | 
						|
 | 
						|
    case sf::Keyboard::W:
 | 
						|
    case sf::Keyboard::Up:
 | 
						|
    case sf::Keyboard::Num8:
 | 
						|
        return Note::Arrow::UP;
 | 
						|
 | 
						|
    case sf::Keyboard::D:
 | 
						|
    case sf::Keyboard::Right:
 | 
						|
    case sf::Keyboard::Num6:
 | 
						|
        return Note::Arrow::RIGHT;
 | 
						|
 | 
						|
    case sf::Keyboard::S:
 | 
						|
    case sf::Keyboard::Down:
 | 
						|
    case sf::Keyboard::Num2:
 | 
						|
        return Note::Arrow::DOWN;
 | 
						|
 | 
						|
    default:
 | 
						|
        return Note::Arrow::NONE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void Application::onKeyPressed(const sf::Keyboard::Key &key)
 | 
						|
{
 | 
						|
    if (key == sf::Keyboard::D)
 | 
						|
    {
 | 
						|
        _debug.toggle();
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    onTap(keyToArrow(key));
 | 
						|
}
 | 
						|
 | 
						|
void Application::onTap(const Note::Arrow &arrow)
 | 
						|
{
 | 
						|
    if (arrow == Note::Arrow::NONE)
 | 
						|
        return;
 | 
						|
 | 
						|
    _debug.spawnGreenPulse();
 | 
						|
 | 
						|
    const auto music_offset = _music.getPlayingOffset().asMicroseconds();
 | 
						|
    const auto note = _timeline.fetchActiveNote(music_offset);
 | 
						|
 | 
						|
    if (note)
 | 
						|
    {
 | 
						|
        const auto tap_result = note->onTap(arrow, music_offset);
 | 
						|
        _grade = makeGradeString(tap_result.rating);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void Application::update()
 | 
						|
{
 | 
						|
    const auto music_offset = _music.getPlayingOffset().asMicroseconds();
 | 
						|
 | 
						|
    _timeline.update(music_offset);
 | 
						|
    _debug.update(music_offset);
 | 
						|
 | 
						|
    if (_grade.getFillColor().a > 0)    // TODO: Encapsulate
 | 
						|
    {
 | 
						|
        const auto alpha = _grade.getFillColor().a - 20;
 | 
						|
        _grade.setFillColor(sf::Color(255, 255, 255, alpha < 0 ? 0 : alpha));
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void Application::draw()
 | 
						|
{
 | 
						|
    _game_window.clear();
 | 
						|
    _game_window.draw(_debug);
 | 
						|
    _game_window.draw(_grade);
 | 
						|
    _game_window.display();
 | 
						|
}
 |