Show available missions

This commit is contained in:
Jasper Blanckenburg 2022-05-20 02:47:06 +02:00
parent 6d8ada3f18
commit a904f0cdaf
5 changed files with 130 additions and 8 deletions

View File

@ -8,9 +8,6 @@
#include <memory>
#include <vector>
constexpr const char* FT_LOGO_PATH = "resources/Fasttube_Logo-white.bmp";
constexpr const char* AVENIR_FONT_PATH = "resources/Avenir-Book.ttf";
class AMI final : public View {
public:
AMI(SDL_Renderer* renderer);
@ -24,4 +21,6 @@ private:
ImageWidget ft_logo;
TextWidget choose;
ListWidget missions_widget;
std::vector<std::unique_ptr<Widget>> missions;
};

View File

@ -5,6 +5,7 @@
#include <optional>
#include <string>
#include <vector>
enum class Alignment { LEFT, RIGHT, CENTER };
struct PositionInfo {
@ -25,6 +26,10 @@ public:
virtual void set_position(int x, int y);
virtual void set_alignment(Alignment align);
int get_width();
int get_height();
const PositionInfo& get_position();
virtual void draw() = 0;
protected:
@ -68,4 +73,23 @@ protected:
std::string text;
SDL_Texture* generate_text(const std::string& text);
};
class ListWidget : public Widget {
public:
ListWidget(SDL_Renderer* renderer, int element_height,
Alignment element_alignment);
virtual ~ListWidget();
void add_element(Widget* element);
virtual void draw() override;
protected:
int element_height;
Alignment element_alignment;
std::vector<Widget*> elements;
void place_element(Widget* element, int index);
};

View File

@ -2,18 +2,49 @@
#include "defines.h"
#include "util.h"
#include "widgets.h"
#include <array>
constexpr const char* FT_LOGO_PATH = "resources/Fasttube_Logo-white.bmp";
constexpr const char* AVENIR_FONT_PATH = "resources/Avenir-Book.ttf";
constexpr int AVENIR_PTS = 20;
constexpr int FT_LOGO_HEIGHT = 40;
constexpr int GAP = 5;
constexpr int CHOOSE_Y = FT_LOGO_HEIGHT + GAP;
constexpr int MISSION_HEIGHT = 30;
constexpr std::array MISSIONS = {"ACCELERATION", "SKIDPAD", "AUTOCROSS",
"TRACKDRIVE", "EBS TEST", "INSPECTION",
"MANUAL DRIVING"};
AMI::AMI(SDL_Renderer* renderer)
: View{renderer}, avenir{util::load_font(AVENIR_FONT_PATH, 20)},
: View{renderer}, avenir{util::load_font(AVENIR_FONT_PATH, AVENIR_PTS)},
ft_logo{renderer, FT_LOGO_PATH}, choose{renderer, avenir,
"Choose a mission:"} {
ft_logo.set_height(40);
"Choose a mission:"},
missions_widget{renderer, MISSION_HEIGHT, Alignment::CENTER} {
ft_logo.set_height(FT_LOGO_HEIGHT);
ft_logo.set_position(SCREEN_WIDTH / 2, 0);
ft_logo.set_alignment(Alignment::CENTER);
widgets.push_back(&ft_logo);
choose.set_position(SCREEN_WIDTH / 2, 45);
choose.set_position(SCREEN_WIDTH / 2, CHOOSE_Y);
choose.set_alignment(Alignment::CENTER);
widgets.push_back(&choose);
int choose_height = choose.get_height();
int missions_y = CHOOSE_Y + choose_height + GAP;
int missions_height = SCREEN_HEIGHT - CHOOSE_Y - choose_height - 1;
missions_widget.set_position(0, missions_y);
missions_widget.set_width(SCREEN_WIDTH, false);
missions_widget.set_height(missions_height, false);
for (const auto mission : MISSIONS) {
missions.push_back(std::make_unique<TextWidget>(renderer, avenir, mission));
}
for (const auto& mission : missions) {
missions_widget.add_element(mission.get());
}
widgets.push_back(&missions_widget);
}
void AMI::draw() {

View File

@ -2,6 +2,7 @@
#include "AMI.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <fmt/format.h>

View File

@ -1,7 +1,9 @@
#include "widgets.h"
#include "defines.h"
#include "util.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <fmt/format.h>
@ -40,6 +42,12 @@ void Widget::set_alignment(Alignment align) {
recalculate_rect();
}
int Widget::get_width() { return rect.w; }
int Widget::get_height() { return rect.h; }
const PositionInfo& Widget::get_position() { return pos; }
void Widget::recalculate_rect() {
int x = pos.x;
int y = pos.y;
@ -129,4 +137,63 @@ SDL_Texture* TextWidget::generate_text(const std::string& text) {
"Unable to create texture from text surface: {}", SDL_GetError()));
}
return texture;
}
}
ListWidget::ListWidget(SDL_Renderer* renderer, int element_height,
Alignment element_alignment)
: Widget{renderer}, element_height{element_height},
element_alignment{element_alignment} {}
ListWidget::~ListWidget() {}
void ListWidget::add_element(Widget* element) {
int new_index = elements.size();
elements.push_back(element);
place_element(element, new_index);
}
void ListWidget::draw() {
int max_y = rect.y + rect.h;
for (size_t i = 0; i < elements.size(); i++) {
const auto& element = elements[i];
const PositionInfo& element_pos = element->get_position();
if (element_pos.y >= max_y) {
// Since the elements are sorted, we can stop the loop now.
break;
}
if (i % 2 == 1) {
SDL_SetRenderDrawColor(renderer, 0x11, 0x11, 0x11, 0xFF);
SDL_Rect fill_rect = {
.x = pos.x, .y = element_pos.y, .w = rect.w, .h = element_height};
SDL_RenderFillRect(renderer, &fill_rect);
}
element->draw();
if (i != elements.size() - 1) {
int border_y = element_pos.y + element->get_height();
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderDrawLine(renderer, rect.x, border_y, rect.x + rect.w, border_y);
}
}
}
void ListWidget::place_element(Widget* element, int index) {
int x = rect.x;
switch (element_alignment) {
case Alignment::LEFT:
break;
case Alignment::RIGHT:
x += rect.w;
break;
case Alignment::CENTER:
x += rect.w / 2;
break;
default:
throw std::runtime_error(
fmt::format("Unknown alignment: {}", (int)pos.align));
}
// Additional pixel for border
int y = rect.y + index * (element_height + 1);
element->set_position(x, y);
element->set_alignment(element_alignment);
element->set_height(element_height);
}