06-主菜单与角色选择界面
1 主菜单界面
我们首先在MenuScene中删掉之前测试的代码
这时候我们需要思考要将摄像机定义在哪里
- 一种是定义在场景内部,但这导致在不同场景之间共享摄像机数据比较麻烦
- 另一种是像资源一样作为全局变量,但这终究是一种杂乱且不太优雅的设计。我们一层层封装的目的就是尽可能的减少全局变量的使用。
我们的实现方法是在调用on_draw时将摄像机作为参数传递进来。
我们首先来到Scene类中,在on_draw添加摄像机作为参数
virtual void on_draw( const Camera& camera ) { }
同时,对Scene的子类进行同样的修改。以及SceneManager也需要修改。
之后我们来到main.cpp中定义main_camera
Camera main_camera;
在主循环的渲染阶段将摄像机对象传递给场景管理器
scene_manager.on_draw(main_camera);
这样看虽然摄像机已经被创建,但是还是没有避免使用全局变量,main_camera现在还是全局变量。
但是不用着急,当我们使用GameObject对整个游戏大一统时,设计将变得更加优雅。
现在回到MenuScene::on_draw()中,我们使用put_image显示背景图片
putimage(0, 0, &img_menu_background);
运行程序,我们可以看到主菜单背景图铺满整个游戏窗口

之后,我们为主菜单添加背景音乐,在MenuScene::on_enter()中添加
void on_enter() {
mciSendString(_T("play bgm_menu repeat from 0"), NULL, 0, NULL);
}
void on_input(const ExMessage& msg) {
if(msg.message == WM_KEYUP)
{
mciSendString(_T("play ui_confirm from 0"), NULL, 0, NULL);
scene_manager.switch_to(SceneManager::SceneType::Selector);
}
}
2 角色选择界面
我们在SelectorScene中引入将要用到的资源
extern IMAGE img_VS; // VS 艺术字图片
extern IMAGE img_1P; // 1P 文本图片
extern IMAGE img_2P; // 2P 文本图片
extern IMAGE img_1P_desc; // 1P 键位描述图片
extern IMAGE img_2P_desc; // 2P 键位描述图片
extern IMAGE img_gravestone_left; // 朝向左的墓碑图片
extern IMAGE img_gravestone_right; // 朝向右的墓碑图片
extern IMAGE img_selector_tip; // 选角界面提示信息文本图片
extern IMAGE img_selector_background; // 选角界面背景图
extern IMAGE img_1P_selector_btn_idle_left; // 1P 向左选择按钮默认状态图片
extern IMAGE img_1P_selector_btn_idle_right; // 1P 向右选择按钮默认状态图片
extern IMAGE img_1P_selector_btn_down_left; // 1P 向左选择按钮按下状态图片
extern IMAGE img_1P_selector_btn_down_right; // 1P 向右选择按钮按下状态图片
extern IMAGE img_2P_selector_btn_idle_left; // 2P 向左选择按钮默认状态图片
extern IMAGE img_2P_selector_btn_idle_right; // 2P 向右选择按钮默认状态图片
extern IMAGE img_2P_selector_btn_down_left; // 2P 向左选择按钮按下状态图片
extern IMAGE img_2P_selector_btn_down_right; // 2P 向右选择按钮按下状态图片
extern IMAGE img_peashooter_selector_background_left; // 选角界面朝向左的豌豆射手背景图片
extern IMAGE img_peashooter_selector_background_right; // 选角界面朝向右的豌豆射手背景图片
extern IMAGE img_sunflower_selector_background_left; // 选角界面朝向左的龙日葵背景图片
extern IMAGE img_sunflower_selector_background_right; // 选角界面朝向右的龙日葵背景图片
extern Atlas atlas_peashooter_idle_left; // 豌豆射手朝向左的默认动画图集
extern Atlas atlas_peashooter_idle_right; // 豌豆射手朝向右的默认动画图集
extern Atlas atlas_sunflower_idle_left; // 龙日葵朝向左的默认动画图集
extern Atlas atlas_sunflower_idle_right; // 龙日葵朝向右的默认动画图集
extern IMAGE img_avatar_peashooter; // 豌豆射手头像图片
extern IMAGE img_avatar_sunflower; // 龙日葵头像图片
vscode多行同时编辑
按住alt 滑动鼠标可以多选行进行修改
也可以尝试shift alt 按住并滑动鼠标
private:
POINT pos_img_VS = { 0 }; // VS 艺术字图片位置
POINT pos_img_tip = { 0 }; // 提示信息文本图片位置
POINT pos_img_1P = { 0 }; // 1P 文本图片位置
POINT pos_img_2P = { 0 }; // 2P 文本图片位置
POINT pos_img_1P_desc = { 0 }; // 1P 键位描述图片位置
POINT pos_img_2P_desc = { 0 }; // 2P 键位描述图片位置
POINT pos_img_1P_name = { 0 }; // 1P 角色姓名文本位置
POINT pos_img_2P_name = { 0 }; // 2P 角色姓名文本位置
POINT pos_animation_1P = { 0 }; // 1P 角色动画位置
POINT pos_animation_2P = { 0 }; // 2P 角色动画位置
POINT pos_img_1P_gravestone = { 0 }; // 1P 墓碑图片位置
POINT pos_img_2P_gravestone = { 0 }; // 2P 墓碑图片位置
POINT pos_1P_selector_btn_left = { 0 }; // 1P 向左切换按钮位置
POINT pos_1P_selector_btn_right = { 0 }; // 1P 向右切换按钮位置
POINT pos_2P_selector_btn_left = { 0 }; // 2P 向左切换按钮位置
POINT pos_2P_selector_btn_right = { 0 }; // 2P 向右切换按钮位置
Animation animation_peashooter; //豌豆射手动画
Animation animation_sunflower; //龙日葵动画
在on_enter中进行初始化
animation_peashooter.set_atlas(&atlas_peashooter_idle_right);
animation_sunflower.set_atlas(&atlas_sunflower_idle_right);
animation_peashooter.set_interval(100);
animation_sunflower.set_interval(100);
之后我们使用下面的代码来定义各种位置
static const int OFFSET_X = 50;
pos_img_VS.x = (getwidth() - img_VS.getwidth()) / 2;
pos_img_VS.y = (getheight() - img_VS.getheight()) / 2;
pos_img_tip.x = (getwidth() - img_selector_tip.getwidth()) / 2;
pos_img_tip.y = getheight() - 125;
pos_img_1P.x = (getwidth() / 2 - img_1P.getwidth()) / 2 - OFFSET_X;
pos_img_1P.y = 35;
pos_img_2P.x = getwidth() / 2 + (getwidth() / 2 - img_2P.getwidth()) / 2 + OFFSET_X;
pos_img_2P.y = pos_img_1P.y;
pos_img_1P_desc.x = (getwidth() / 2 - img_1P_desc.getwidth()) / 2 - OFFSET_X;
pos_img_1P_desc.y = getheight() - 150;
pos_img_2P_desc.x = getwidth() / 2 + (getwidth() / 2 - img_2P_desc.getwidth()) / 2 + OFFSET_X;
pos_img_2P_desc.y = pos_img_1P_desc.y;
pos_img_1P_gravestone.x = (getwidth() / 2 - img_gravestone_right.getwidth()) / 2 - OFFSET_X;
pos_img_1P_gravestone.y = pos_img_1P.y + img_1P.getheight() + 35;
pos_img_2P_gravestone.x = getwidth() / 2 + (getwidth() / 2 - img_gravestone_left.getwidth()) / 2 + OFFSET_X;
pos_img_2P_gravestone.y = pos_img_1P_gravestone.y;
pos_animation_1P.x = (getwidth() / 2 - atlas_peashooter_idle_right.get_image(0)->getwidth()) / 2 - OFFSET_X;
pos_animation_1P.y = pos_img_1P_gravestone.y + 80;
pos_animation_2P.x = getwidth() / 2 + (getwidth() / 2 - atlas_peashooter_idle_right.get_image(0)->getwidth()) / 2 + OFFSET_X;
pos_animation_2P.y = pos_animation_1P.y;
pos_img_1P_name.y = pos_animation_1P.y + 155;
pos_img_2P_name.y = pos_img_1P_name.y;
pos_1P_selector_btn_left.x = pos_img_1P_gravestone.x - img_1P_selector_btn_idle_left.getwidth();
pos_1P_selector_btn_left.y = pos_img_1P_gravestone.y + (img_gravestone_right.getheight() - img_1P_selector_btn_idle_left.getheight()) / 2;
pos_1P_selector_btn_right.x = pos_img_1P_gravestone.x + img_gravestone_right.getwidth();
pos_1P_selector_btn_right.y = pos_1P_selector_btn_left.y;
pos_2P_selector_btn_left.x = pos_img_2P_gravestone.x - img_2P_selector_btn_idle_left.getwidth();
pos_2P_selector_btn_left.y = pos_1P_selector_btn_left.y;
pos_2P_selector_btn_right.x = pos_img_2P_gravestone.x + img_gravestone_left.getwidth();
pos_2P_selector_btn_right.y = pos_1P_selector_btn_left.y;
d对于游戏界面中各类元素的位置,如果有一套用来描述居中、外边距等的框架,实现起来就更加顺手。但是布局框架是一个深坑,目前项目阶段只有这一小部分场景内容设计界面,所以我们暂时不进行讨论。
在EasyX中我们可以使用getwidth()和getheight()来获取当前窗口的宽高
putimage(0, 0, &img_selector_background);
putimage_alpha(pos_img_VS.x, pos_img_VS.y, &img_VS);
putimage_alpha(pos_img_1P.x, pos_img_1P.y, &img_1P);
putimage_alpha(pos_img_2P.x, pos_img_2P.y, &img_2P);
putimage_alpha(pos_img_1P_gravestone.x, pos_img_1P_gravestone.y, &img_gravestone_right);
putimage_alpha(pos_img_2P_gravestone.x, pos_img_2P_gravestone.y, &img_gravestone_left);
putimage_alpha(pos_img_1P_desc.x, pos_img_1P_desc.y, &img_1P_desc);
putimage_alpha(pos_img_2P_desc.x, pos_img_2P_desc.y, &img_2P_desc);
putimage_alpha(pos_img_tip.x, pos_img_tip.y, &img_selector_tip);

这样选择界面的静态元素就都实现了。
评论
如果你已登录 GitHub,就可以直接在这里评论。