1

Model、View、Controllerのアイデアに大まかに基づいて、ゲームの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);
}
4

1 に答える 1

2

モデルにはとメソッドclass menuが必要です。add_view(menuview *v)update()

menu_renderer次に、ウィジェットの更新を派生ビュー(または)に委任できますcli_menu_renderer

コントローラーは、コントローラーが実行される(またはコマンドを実行する)ときにモデルを(メンバーとして)知る必要があり、モデルをセッター(のようにm_menu_model->set_selected(item, state))で更新する必要があり、モデルはセッターを呼び出しますupdate()

コントローラーmenu_controllerには更新メソッドがあり、if (menuview->toggle_select()) m_menu_model->toggle_selected();(すべてのメニュービューで実装する必要がある)入力を要求してセッターを呼び出すこともできますが、それはビューとコントローラーの柔軟性のない結合です(MVCをコマンドパターンで確認して詳細を確認できます)高度な組み合わせ)。

位置には、int m_x、m_y、m_w、m_hなどのメンバー変数を設定できます。ただし、これらのメンバーはGUIを備えたビューに固有であるため、派生ビューのみがそれらを必要とします。

次に、これらの値を使用してマウスの位置と比較し、次のようなMouseOver検出メソッドを使用できます。

// 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();
}
于 2012-08-21T18:22:08.130 に答える