OOP游戏菜单系统开发概念
OOP Game Menu System Development Conceptualising
我正试图为游戏编写一个OO菜单系统,大致基于模型、视图和控制器的思想。到目前为止,在我的应用程序中,我已经将视图命名为"渲染器",模型没有后缀。我创建了一个通用菜单类,它存储菜单的项目,即menu_item对象,还有一个菜单渲染器类,它为每个项目创建渲染器并渲染它们。问题是,我不确定将数据存储在哪里,也不确定每个项目应该在屏幕上的位置的逻辑,以及如何检查它是否被悬停在上面等等。我最初的想法是在每个菜单项上存储和设置一个选定的属性,不同的视图可以对其进行不同的渲染,但即便如此,我该如何定位组成按钮的图形元素呢?
到目前为止,代码摘录如下:(更多代码请访问https://gist.github.com/3422226)
/**
* Abstract menu model
*
* Menus have many items and have properties such as a title
*/
class menu {
protected:
std::string _title;
std::vector<menu_item*> _items;
public:
std::string get_title();
void set_title(std::string);
std::vector<menu_item*> get_items();
};
class menu_controller: public controller {
private:
menu* _menu;
public:
menu_controller(menu*);
virtual void update();
};
class menu_item {
protected:
std::string _title;
public:
menu_item(std::string title);
virtual ~menu_item();
std::string get_title();
};
class menu_renderer: public renderer {
private:
menu* _menu;
bitmap _background_bitmap;
static font _title_font;
std::map<menu_item*, menu_item_renderer*> _item_renderers;
public:
menu_renderer(menu*);
virtual void render();
};
font menu_renderer::_title_font = NULL;
menu_renderer::menu_renderer(menu* menu) {
_menu = menu;
_background_bitmap = ::load_bitmap("blackjack_menu_bg.jpg");
if (!_title_font)
_title_font = ::load_font("maven_pro_regular.ttf",48);
}
void menu_renderer::render() {
::draw_bitmap(_background_bitmap, 0, 0);
/* Draw the menu title */
const char* title = _menu->get_title().c_str();
int title_width = ::text_width(_title_font, title);
::draw_text(title, color_white, _title_font, screen_width() - title_width - 20, 20);
/* Render each menu item */
std::vector<menu_item*> items = _menu->get_items();
for (std::vector<menu_item*>::iterator it = items.begin(); it != items.end(); ++it) {
menu_item* item = *it;
if (!_item_renderers.count(item))
_item_renderers[item] = new menu_item_renderer(item, it - items.begin());
_item_renderers[item]->render();
}
}
class menu_item_renderer: public renderer {
private:
unsigned _order;
menu_item* _item;
static font _title_font;
public:
menu_item_renderer(menu_item*, unsigned);
virtual ~menu_item_renderer();
virtual void render();
};
font menu_item_renderer::_title_font = NULL;
menu_item_renderer::menu_item_renderer(menu_item* item, unsigned order) {
_item = item;
_order = order;
if (!_title_font)
_title_font = ::load_font("maven_pro_regular.ttf",24);
}
menu_item_renderer::~menu_item_renderer() {
// TODO Auto-generated destructor stub
}
void menu_item_renderer::render() {
const char* title = _item->get_title().c_str();
int title_width = ::text_width(_title_font, title);
unsigned y = 44 * _order + 20;
::fill_rectangle(color_red, 20, y, title_width + 40, 34);
::draw_text(title, color_white, _title_font, 30, y + 5);
}
您的模型class menu
需要add_view(menuview *v)
和update()
方法。
然后,您可以将小部件的更新委托给派生视图(menu_renderer
或cli_menu_renderer
)。
当控制器运行(或执行命令)并且必须使用Setter(如m_menu_model->set_selected(item, state)
)更新模型并且模型在Setter上调用update()
时,控制器需要知道模型(作为成员)。
你的控制器menu_controller
有一个更新方法,你也可以要求输入,比如if (menuview->toggle_select()) m_menu_model->toggle_selected();
(所有菜单视图都必须实现)并调用setter,但这是视图和控制器的不灵活耦合(你可以用命令模式检查MVC以获得更高级的组合)。
对于"位置",可以设置成员变量,如int m_x、m_y、m_w、m_h。但是这些成员是特定于具有GUI的视图的,因此只有派生的视图需要它们。
然后,您可以使用这些值与鼠标位置进行比较,并使用鼠标悬停检测方法,如下所示:
// View menu_item
bool menu_item::over()
{
if (::mouse_x > m_x
&& ::mouse_x < m_x + m_w
&& ::mouse_y > m_y
&& ::mouse_y < m_y + m_h) {
return true;
}
return false;
}
// update on gui menu item
bool menu_item::update()
{
if (over()) {
m_over = true;
}
else {
m_over = false;
}
// onclick for the idea
if ((::mouse_b & 1) && m_over) {
// here you could invoke a callback or fire event
m_selected = 1;
} else {
m_selected = 0;
}
return m_selected;
}
// update the command line interface menu item
bool cli_menu_item::update()
{
if ((::enterKeyPressed & 1) && m_selected) {
// here you could invoke a callback or fire event
m_selected = 1;
} else {
m_selected = 0;
}
return m_selected;
}
void menu_item_renderer::render() {
// update widgets
_item->update();
// ...
}
// Model
void menu::add_view(menuview *v) {
m_view=v;
}
void menu::update() {
if (m_view) m_view->update();
}
bool menu::set_selected(int item, int state) {
m_item[index]=state;
update();
}
- C++,系统无法执行指定的程序
- 在UNIX系统中使用DIR查找文件的字节大小
- 错误处理.将系统错误代码映射到泛型
- 当系统的卷被修改时,如何修改WASAPI环回捕获卷
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- 在C++游戏中与库存系统作斗争
- 文件系统:复制功能的速度秘诀是什么
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 如何用RISC-V GD32VF103CBT6开发板卸载精确的ADC过采样
- 在gtest.中使用fff.h模拟系统API
- 如何制作无限制照明系统
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 如何传递多个 std::文件系统选项?
- 我正在开发服务器,ip作为参数传递不起作用
- 遍历顺序由 std::文件系统directory_iterator给出
- 为什么开发人员将C / C ++用于嵌入式系统,而不是像Python这样的高级语言与C相比?
- 应用程序在非开发系统上崩溃
- OOP游戏菜单系统开发概念
- 使用C++开发与Linux系统相关的程序
- 如何正确地开发概率系统