From 7c572e5e14ba7801c5e888dec79951e51a120b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horv=C3=A1th=20Kata?= <horka23@cortex.itk.ppke.hu> Date: Sat, 10 May 2025 23:40:26 +0200 Subject: [PATCH] menu+bemeneti mezok a jatekosok neveinek --- app.hpp | 2 +- button.cpp | 2 +- gamelogic.cpp | 12 +---- main.cpp | 144 +++++++++++++++++++++++++++++++++++++++---------- statictext.cpp | 89 ++++++++++++++++++++++++++++++ statictext.hpp | 19 +++++++ textbox.cpp | 111 ++++++++++++++++++++++++++++++++++++++ textbox.hpp | 29 ++++++++++ textedit.cpp | 28 ++++++++++ textedit.hpp | 16 ++++++ 10 files changed, 410 insertions(+), 42 deletions(-) create mode 100644 statictext.cpp create mode 100644 statictext.hpp create mode 100644 textbox.cpp create mode 100644 textbox.hpp create mode 100644 textedit.cpp create mode 100644 textedit.hpp diff --git a/app.hpp b/app.hpp index 4081938..3d960ea 100644 --- a/app.hpp +++ b/app.hpp @@ -19,7 +19,7 @@ public: virtual ~App(); void registerWidget(Widget* widget); - void event_loop(); + virtual void event_loop(); virtual void action(const std::string& id) = 0; // Add these to avoid incomplete type issues diff --git a/button.cpp b/button.cpp index bf04277..83c7b2f 100644 --- a/button.cpp +++ b/button.cpp @@ -20,7 +20,7 @@ void Button::draw(){ } int text_x=_x+(_size_x-gout.twidth(_text))/2; - int text_y =_y+(_size_y-gout.cascent()-gout.cdescent())/2+gout.cascent(); + int text_y =_y+(_size_y-gout.cascent()-gout.cdescent())/2; gout << move_to(text_x, text_y) << color(0,0,0) << text(_text); } diff --git a/gamelogic.cpp b/gamelogic.cpp index 834f423..071808a 100644 --- a/gamelogic.cpp +++ b/gamelogic.cpp @@ -16,17 +16,7 @@ void GameLogic::reset() { _winner=EMPTY; _last_move_row=-1; _last_move_col=-1; - /*int _board[GameLogic::ROWS][GameLogic::COLS]; - for (int i = 0; i < GameLogic::ROWS; ++i) { - for (int j = 0; j < GameLogic::COLS; ++j) { - _board[i][j] = GameLogic::EMPTY; - } - } - _current_player = PLAYER1; - gameover = false; - _winner = EMPTY; - _last_move_row = -1; - _last_move_col = -1;*/ + } diff --git a/main.cpp b/main.cpp index 9170ce0..d1a4e39 100644 --- a/main.cpp +++ b/main.cpp @@ -3,6 +3,7 @@ #include "gamelogic.hpp" #include "cell.hpp" #include "button.hpp" +#include "textbox.hpp" #include <vector> #include <iostream> @@ -12,12 +13,82 @@ using namespace genv; class Amoba: public App{ private: - GameLogic _game; - vector<vector<Cell*>> _cells; - vector<Widget*> _widgets; + enum Mode {MENU, GAME}; + Mode current_mode; + std::string player1_name, player2_name; + + Textbox* name1_input; + Textbox* name2_input; Button* start_button; - Button* restart_button; + std::vector<Widget*> menu_widgets; + + + std::vector<std::vector<Cell*>> _cells; + std::vector<Widget*> game_widgets; + GameLogic _game; bool game_started; + Button* restart_button; + + + + + void createMenu() { + name1_input = new Textbox(this, 190, 300, 200, 40); + menu_widgets.push_back(name1_input); + registerWidget(name1_input); + + name2_input = new Textbox(this, 410, 300, 200, 40); + menu_widgets.push_back(name2_input); + registerWidget(name2_input); + + start_button = new Button(this, 350, 360, 100, 40, "START"); + menu_widgets.push_back(start_button); + registerWidget(start_button); + } + + + + void handleMenu(){ + if(start_button->isSelected() && !name1_input->getText().empty()){ + player1_name=name1_input->getText(); + player2_name=name2_input->getText(); + current_mode=GAME; + start_button->setSelected(false); + game_started=true; + } + else{ + start_button->setSelected(false); + } + + } + + + + + + void handleMouseEvent(const genv::event& ev){ + _focused_widget = nullptr; + std::vector<Widget*>* active_widgets; + + if (current_mode==MENU){ + active_widgets=&menu_widgets; + } else { + active_widgets=&game_widgets; + } + + for (Widget* w:*active_widgets){ + if (w->is_selected(ev.pos_x, ev.pos_y)){ + _focused_widget=w; + break; + } + } + + if (_focused_widget) { + _focused_widget->handle_event(ev); + } +} + + @@ -48,6 +119,7 @@ private: } }); rowcells.push_back(cell); + game_widgets.push_back(cell); } _cells.push_back(rowcells); @@ -61,22 +133,13 @@ private: const int button_width=100; const int button_height=40; - - - - start_button=new Button(this, _width-3*button_width+10, 50, button_width, button_height, "START"); - _widgets.push_back(start_button); restart_button=new Button(this, _width-4*button_width, 50, button_width, button_height, "RESTART"); + game_widgets.push_back(restart_button); _widgets.push_back(restart_button); } - - - - - void handleColumnclick(int col){ if(game_started && !_game.GameOver()){ if(_game.makeMove(col)){ @@ -91,17 +154,16 @@ private: } - void checkButtons(){ - if(start_button && start_button->isSelected()){ + /*if(start_button && start_button->isSelected()){ game_started=true; start_button->setSelected(false); - } + }*/ if(restart_button && restart_button->isSelected()){ _game.reset(); - game_started=false; + game_started=true; //generateCells(); updateBoard(); restart_button->setSelected(false); @@ -135,7 +197,8 @@ private: public: - Amoba(int w, int h): App(w, h), game_started(false){ + Amoba(int w, int h): App(w, h), game_started(false), current_mode(MENU){ + createMenu(); generateCells(); createButtons(); updateBoard(); @@ -143,19 +206,22 @@ public: ~Amoba(){ - for(int i=0; i<_cells.size(); i++){ - for(int j=0; j<_cells[i].size(); j++){ - delete _cells[i][j]; - } - + for (Widget* widget : menu_widgets) { + delete widget; + } + for (Widget* widget : game_widgets) { + delete widget; + } + for (std::vector<Cell*>& row : _cells) { + for (Cell* cell : row) { + delete cell; } + } _cells.clear(); - delete start_button; - delete restart_button; } - void action(const std::string& id) override { + void action(const std::string& id) override { if (id == "enter" || id == "space") { _game.reset(); updateBoard(); @@ -164,7 +230,7 @@ public: - void event_loop(){ + void event_loop() override{ gout.open(_width, _height); gin.timer(20); event ev; @@ -172,7 +238,14 @@ public: while(gin>>ev){ if(ev.type==ev_mouse){ handleMouseEvent(ev); - checkButtons(); + if(current_mode==MENU){ + handleMenu(); + } + else if(current_mode==GAME){ + checkButtons(); + } + + // checkButtons(); } else if(ev.type==ev_key){ if(_focused_widget){ @@ -186,6 +259,19 @@ public: } + void drawAllWidgets() { + if(current_mode==MENU){ + for(Widget* widget:menu_widgets){ + widget->draw(); + } + } + else if(current_mode==GAME){ + for(Widget* widget : game_widgets){ + widget->draw(); + } + } + gout << genv::refresh; + } }; diff --git a/statictext.cpp b/statictext.cpp new file mode 100644 index 0000000..2ada044 --- /dev/null +++ b/statictext.cpp @@ -0,0 +1,89 @@ +#include "statictext.hpp" +#include "graphics.hpp" +using namespace genv; + +StaticText::StaticText(int x, int y, int sx, int sy, const std::string& s) + : Widget(x, y, sx, sy), _text(s), _cursor_pos(0), _show_cursor(false), _editable(false) {} + +void StaticText::draw() { + gout << move_to(_x, _y) << color(255, 255, 255) << box(_size_x, _size_y); + gout.load_font("LiberationMono-Regular.ttf", 15); + + gout << move_to(_x+2 + 2, _y+10) << color(0, 0, 0); + + std::string visible_text = _text; + int text_width = gout.twidth(visible_text); + + while (text_width > _size_x - 4 && !visible_text.empty()) { + visible_text.pop_back(); + text_width = gout.twidth(visible_text); + } + + gout << text(visible_text); + + + if (_editable && _show_cursor) { + std::string before_cursor = _text.substr(0, _cursor_pos); + int cursor_x = _x + 2 + gout.twidth(before_cursor); + + + if (cursor_x < _x + _size_x - 2) { + gout << move_to(cursor_x+2, _y + _size_y/4) << color(0, 0, 0) + << line(0, gout.cascent() + gout.cdescent()); + } + } +} + +void StaticText::handle(event ev) { + if (ev.type == ev_mouse && ev.button == btn_left) { + + _editable = is_selected(ev.pos_x, ev.pos_y); + _show_cursor = _editable; + + if (_editable) { + + int click_x = ev.pos_x - _x - 2; + std::string temp; + _cursor_pos = 0; + + for (size_t i = 0; i < _text.length(); i++) { + temp += _text[i]; + if (gout.twidth(temp) > click_x) { + break; + } + _cursor_pos = i + 1; + } + } + } + + if (!_editable) return; + + if (ev.type == ev_key) { + _show_cursor = true; + + if (ev.keycode == key_left && _cursor_pos > 0) { + _cursor_pos--; + } else if (ev.keycode == key_right && _cursor_pos < _text.length()) { + _cursor_pos++; + } else if (ev.keycode == key_backspace && _cursor_pos > 0) { + _text.erase(_cursor_pos - 1, 1); + _cursor_pos--; + } else if (ev.keycode == key_delete && _cursor_pos < _text.length()) { + _text.erase(_cursor_pos, 1); + } else if (ev.keycode >= 32 && ev.keycode < 256) { + std::string temp_text = _text; + temp_text.insert(_cursor_pos, 1, ev.keycode); + if (gout.twidth(temp_text) <= _size_x - 4) { + _text.insert(_cursor_pos, 1, ev.keycode); + _cursor_pos++; + } + } else if (ev.keyutf8 != "") { + std::string temp_text = _text; + temp_text.insert(_cursor_pos, ev.keyutf8); + if (gout.twidth(temp_text) <= _size_x - 4) { + _text.insert(_cursor_pos, ev.keyutf8); + _cursor_pos += ev.keyutf8.length(); + } + } + } +} diff --git a/statictext.hpp b/statictext.hpp new file mode 100644 index 0000000..db2cb3f --- /dev/null +++ b/statictext.hpp @@ -0,0 +1,19 @@ +#ifndef STATICTEXT_HPP +#define STATICTEXT_HPP + +#include "widgets.hpp" +#include <string> + +class StaticText : public Widget { +protected: + std::string _text; + size_t _cursor_pos; + bool _show_cursor; + bool _editable; +public: + StaticText(int x, int y, int sx, int sy, const std::string& s); + virtual void draw() override; + virtual void handle(genv::event ev) override; +}; + +#endif diff --git a/textbox.cpp b/textbox.cpp new file mode 100644 index 0000000..c52adf6 --- /dev/null +++ b/textbox.cpp @@ -0,0 +1,111 @@ +#include "textbox.hpp" +#include "graphics.hpp" + +using namespace genv; + +Textbox::Textbox(App* parent, int x, int y, int sx, int sy): Widget(parent, x, y, sx, sy), _text(""), _cursor_pos(0), _show_cursor(false), _editable(false){} + + +void Textbox::draw(){ + gout << move_to(_x, _y) << color(50, 50, 50) << box(_size_x, _size_y); + gout.load_font("LiberationSans-Regular.ttf", 15); + + gout << move_to(_x+2 + 2, _y+15) << color(255, 255, 255); + + + + std::string visible_text = _text; + int text_width = gout.twidth(visible_text); + + while (text_width > _size_x - 4 && !visible_text.empty()) { + visible_text.pop_back(); + text_width = gout.twidth(visible_text); + } + + gout << text(visible_text); + + + if (_editable && _show_cursor) { + std::string before_cursor = _text.substr(0, _cursor_pos); + int cursor_x = _x + 2 + gout.twidth(before_cursor); + + + if (cursor_x < _x + _size_x - 2) { + gout << move_to(cursor_x+2, _y + _size_y/4) << color(0, 0, 0) + << line(0, gout.cascent() + gout.cdescent()); + } + } + + + + /*gout << move_to(_x, _y) << color(220, 220, 220) << box(_size_x, _size_y); + + if (_active){ + gout << move_to(_x, _y) << color(200, 200, 200) << line(_size_x, 0) + << line(0, _size_y) << line(-_size_x, 0) << line(0, -_size_y); + */ + } + + //gout << move_to(_x+5, _y+_size_y/2+gout.cascent()/2) << color(255, 255, 255) << text(_text); + + + +void Textbox::handle_event(event ev){ + if (ev.type==ev_mouse && ev.button==btn_left) { + _editable=is_selected(ev.pos_x, ev.pos_y); + _show_cursor=_editable; + } + if (!_editable) {return;} + if (_editable){ + + int click_x=ev.pos_x-_x - 2; + std::string temp; + _cursor_pos=0; + + for (int i=0; i<_text.length(); i++){ + temp+=_text[i]; + if (gout.twidth(temp)>click_x){ + break; + } + _cursor_pos=i+1; + } + } + + + + + if (ev.type==ev_key){ + _show_cursor=true; + + if (ev.keycode==key_left && _cursor_pos>0){ + _cursor_pos--; + } + else if (ev.keycode==key_right && _cursor_pos<_text.length()){ + _cursor_pos++; + } + else if (ev.keycode==key_backspace &&_cursor_pos>0){ + _text.erase(_cursor_pos - 1, 1); + _cursor_pos--; + } + else if (ev.keycode==key_delete && _cursor_pos<_text.length()){ + _text.erase(_cursor_pos, 1); + + } + else if (ev.keycode>=32 && ev.keycode<256){ + std::string temp_text=_text; + temp_text.insert(_cursor_pos, 1, ev.keycode); + if (gout.twidth(temp_text)<=_size_x-4){ + _text.insert(_cursor_pos, 1, ev.keycode); + _cursor_pos++; + } + } else if (ev.keyutf8!=""){ + std::string temp_text=_text; + temp_text.insert(_cursor_pos, ev.keyutf8); + if (gout.twidth(temp_text)<=_size_x-4) { + _text.insert(_cursor_pos, ev.keyutf8); + _cursor_pos+=ev.keyutf8.length(); + _cursor_pos++; + } + } + } +} diff --git a/textbox.hpp b/textbox.hpp new file mode 100644 index 0000000..4a82d3f --- /dev/null +++ b/textbox.hpp @@ -0,0 +1,29 @@ +#ifndef TEXTBOX_HPP_INCLUDED +#define TEXTBOX_HPP_INCLUDED + + +#include "graphics.hpp" +#include "widgets.hpp" +#include "app.hpp" +#include <string> + + +class Textbox: public Widget{ +private: + std::string _text; + size_t _cursor_pos; + bool _show_cursor; + bool _editable; + +public: + Textbox(App* parent, int x, int y, int sx, int sy); + void draw() override; + void handle_event(genv::event ev) override; + + std::string getText() const {return _text;} + void setText(std::string newtext){_text=newtext;} + +}; + + +#endif // TEXTBOX_HPP_INCLUDED diff --git a/textedit.cpp b/textedit.cpp new file mode 100644 index 0000000..e9ef1af --- /dev/null +++ b/textedit.cpp @@ -0,0 +1,28 @@ +#include "textedit.hpp" + +TextEdit::TextEdit(int x, int y, int sx, int sy, std::string s) + : Widget(x,y,sx,sy), _text(s) +{} + +using namespace genv; + +void TextEdit::draw() +{ + gout.load_font("LiberationMono-BoldItalic.ttf", 20); + gout <<move_to(_x, _y) << color(255,255,255) << box(_size_x, _size_y) << color(0, 0, 0) << move_to(_x+5, _y+5) << text(_text); +} + +void TextEdit::handle(event ev) +{ + if(ev.type == ev_key) + { + if(ev.keycode==key_backspace) + { + _text=_text.substr(0,_text.size()-1); + } + else + { + _text+=ev.keyutf8; + } + } +} diff --git a/textedit.hpp b/textedit.hpp new file mode 100644 index 0000000..cd1ad64 --- /dev/null +++ b/textedit.hpp @@ -0,0 +1,16 @@ +#ifndef TEXTEDIT_HPP +#define TEXTEDIT_HPP + +#include "widgets.hpp" + +class TextEdit : public Widget +{ +protected: + std::string _text; +public: + TextEdit(int, int, int, int, std::string); + virtual void draw() override; + virtual void handle(genv::event) override; +}; + +#endif // TEXTEDIT_HPP -- GitLab