Events explained

1概要

本教程是窗口事件的详细列表。它描述了它们,并说明了如何(以及如何不)使用它们。


The sf::Event type

在处理事件之前,了解sf:: event类型是什么以及如何正确使用它很重要。sf:: event是一个联合,这意味着一次只有一个成员有效(记住你的C++课程:联合的所有成员共享相同的内存空间)。有效成员是与事件类型匹配的成员,例如event。按键事件的按键。尝试读取任何其他成员将导致未定义的行为(很可能是随机或无效值)。千万不要试图使用与其类型不匹配的事件成员,这一点很重要。

sf:: event实例由sf::Window类的pollEvent(或waitEvent)函数填充。只有这两个函数才能生成有效的事件,任何尝试使用未通过成功调用pollEvent(或waitEvent)返回的sf:: event的行为都将导致上述相同的未定义行为。

需要明确的是,典型的事件循环是这样的:

sf::Event event;

// while there are pending events...
while (window.pollEvent(event))
{
    // check the type of the event...
    switch (event.type)
    {
        // window closed
        case sf::Event::Closed:
            window.close();
            break;

        // key pressed
        case sf::Event::KeyPressed:
            ...
            break;

        // we don't process other types of events
        default:
            break;
    }
}

好了,现在我们可以看到SFML支持哪些事件,它们的含义以及如何正确使用它们。


The Closed event

当用户想要通过窗口管理器提供的任何可能方法(“关闭”按钮、键盘快捷键等)关闭窗口时,会触发 sf::Event::Closed事件。此事件仅表示关闭请求,收到事件时窗口尚未关闭。

典型的代码只会调用window.close()响应此事件,实际关闭窗口。但是,您可能还需要先执行其他操作,例如保存当前应用程序状态或询问用户要执行的操作。如果您什么都不做,窗口将保持打开状态。

sf::Event联合中没有与此事件关联的成员。

if (event.type == sf::Event::Closed)
    window.close();

The Resized event

当通过用户操作或通过调用window.setSize.以编程方式调整窗口大小时,将触发sf::Event::Resized事件。设置大小。

可以使用此事件调整渲染设置:如果直接使用OpenGL,则调整视口;如果使用sfml图形,则调整当前视图。

与此事件关联的成员是event.size。它包含窗口的新大小。


The LostFocus and GainedFocus events

当窗口失去/获得焦点时,会触发sf::Event::LostFocus和sf::Event::GainedFocus事件,这在用户切换当前活动窗口时发生。当窗口失焦时,它不会接收键盘事件。

例如,如果您想在窗口处于非活动状态时暂停游戏,可以使用此事件。

sf::Event联合中没有与这些事件关联的成员。

if (event.type == sf::Event::LostFocus)
    myGame.pause();

if (event.type == sf::Event::GainedFocus)
    myGame.resume();

The TextEntered event

键入字符时会触发sf::Event::TextEntered事件。这不能与KeyPressed事件混淆:TextEntered解释用户输入并生成适当的可打印字符。例如,在法语键盘上按“^”然后按“e”将生成两个按键事件,但一个包含“ê”字符的TextEntered事件。它适用于操作系统提供的所有输入方法,即使是最具体或最复杂的输入方法。

此事件通常用于捕获文本字段中的用户输入。

与此事件关联的成员是event。文本,它包含输入字符的Unicode值。您可以将其直接放入sf::string中,也可以在确保其处于ASCII范围(0-127)后将其转换为字符。

if (event.type == sf::Event::TextEntered)
{
    if (event.text.unicode < 128)
        std::cout << "ASCII character typed: " << static_cast<char>(event.text.unicode) << std::endl;
}

请注意,由于它们是Unicode标准的一部分,因此此事件会生成一些不可打印的字符,如backspace。在大多数情况下,您需要过滤掉它们。


The KeyPressed and KeyReleased events

当按下/释放键盘键时,会触发sf::Event::KeyPressed 和sf::Event::KeyReleased事件。

如果按住一个键,将以默认操作系统延迟(即,在文本编辑器中按住字母时应用的相同延迟)生成多个按键事件。要禁用重复的按键事件,可以调用window。setKeyRepeatEnabled(错误)。另一方面,很明显,keyreased事件永远不会重复。

如果您想在按下或释放某个键时触发一次动作,例如使用空格跳转角色,或使用escape退出某个对象,则可以使用此事件。

有时,人们试图直接对按键事件做出反应,以实现平稳的运动。这样做不会产生预期的效果,因为当您按住一个键时,您只会得到几个事件(请记住,重复延迟)。要实现事件的平滑移动,必须使用一个布尔值,该布尔值在按下键时设置,在释放键时清除;然后,只要设置了布尔值,就可以移动(与事件无关)。

另一个(更容易)实现平滑移动的解决方案是使用sf::Keyboard 的实时键盘输入(请参阅专用教程)。

与这些事件关联的成员是event.key,它包含按下/释放键的代码,以及修改键(alt、control、shift、system)的当前状态。

#include <SFML/Window.hpp>
#include "iostream"
int main() {
    sf::Window window(sf::VideoMode(800, 600), "My window");
    window.setPosition(sf::Vector2i(10, 50));
    sf::Event event;
    while(window.isOpen())
    {
        while (window.pollEvent(event) ) {
            // check all the window's events that were triggered since the last iteration of the loop
            if (event.type == sf::Event::Closed)
                window.close();
            if (event.type == sf::Event::KeyPressed) {

                if (event.key.code == sf::Keyboard::Escape) {
                    std::cout << "the escape key was pressed" << std::endl;
                    std::cout << "control:" << event.key.control << std::endl;
                    std::cout << "alt:" << event.key.alt << std::endl;
                    std::cout << "shift:" << event.key.shift << std::endl;
                    std::cout << "system:" << event.key.system << std::endl;
                }
            }
        }
    }
    return 0;
}

请注意,某些键对操作系统有特殊意义,并会导致意外行为。例如,Windows上的F10键“窃取”焦点,或使用Visual Studio时启动调试器的F12键。这可能会在SFML的未来版本中得到解决。


The MouseWheelScrolled event

当鼠标滚轮向上或向下移动时,会触发sf::Event::MouseWheelScrolled事件,如果鼠标支持它,也会触发横向事件。

与此事件关联的成员是 event.mouseWheelScroll, 它包含滚轮移动的刻度数、滚轮的方向以及鼠标光标的当前位置。

if (event.type == sf::Event::MouseWheelScrolled)
{
    if (event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel)
        std::cout << "wheel type: vertical" << std::endl;
    else if (event.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel)
        std::cout << "wheel type: horizontal" << std::endl;
    else
        std::cout << "wheel type: unknown" << std::endl;
    std::cout << "wheel movement: " << event.mouseWheelScroll.delta << std::endl;
    std::cout << "mouse x: " << event.mouseWheelScroll.x << std::endl;
    std::cout << "mouse y: " << event.mouseWheelScroll.y << std::endl;
}

The MouseButtonPressed and MouseButtonReleased events

按下/释放鼠标按钮时,会触发sf::Event::MouseButtonPressed和sf::Event::MouseButtonReleased事件。

SFML支持5个鼠标按钮:左、右、中(滚轮)、额外#1和额外#2(侧按钮)。

与这些事件关联的成员是event.mouseButton。,它包含按下/释放按钮的代码,以及鼠标光标的当前位置。

if (event.type == sf::Event::MouseButtonPressed)
{
    if (event.mouseButton.button == sf::Mouse::Right)
    {
        std::cout << "the right button was pressed" << std::endl;
        std::cout << "mouse x: " << event.mouseButton.x << std::endl;
        std::cout << "mouse y: " << event.mouseButton.y << std::endl;
    }
}

The MouseMoved event

当鼠标在窗口内移动时,将触发sf::Event::MouseMoved事件。

即使窗口未聚焦,也会触发此事件。但是,只有当鼠标在窗口的内部区域内移动时才会触发,而不是在标题栏或边框上移动时。

与此事件关联的成员是event.mouseMove,它包含鼠标光标相对于窗口的当前位置。

if (event.type == sf::Event::MouseMoved)
{
    std::cout << "new mouse x: " << event.mouseMove.x << std::endl;
    std::cout << "new mouse y: " << event.mouseMove.y << std::endl;
}

The MouseEntered and MouseLeft event

当鼠标光标进入/离开窗口时,会触发sf::Event::MouseEntered和sf::Event::MouseLeft事件。

sf::Event事件联合中没有与这些事件关联的成员。

if (event.type == sf::Event::MouseEntered)
    std::cout << "the mouse cursor has entered the window" << std::endl;

if (event.type == sf::Event::MouseLeft)
    std::cout << "the mouse cursor has left the window" << std::endl;

The JoystickButtonPressed and JoystickButtonReleased events

当按下/释放操纵杆按钮时,会触发sf::Event::JoystickButtonPressed和sf::Event::JoystickButtonReleased事件。

SFML最多支持8个操纵手柄和32个按钮。

与这些事件关联的成员是event.joystickButton,它包含操纵手柄的标识符和按下/释放按钮的索引。

if (event.type == sf::Event::JoystickButtonPressed)
{
    std::cout << "joystick button pressed!" << std::endl;
    std::cout << "joystick id: " << event.joystickButton.joystickId << std::endl;
    std::cout << "button: " << event.joystickButton.button << std::endl;
}

The JoystickMoved event

操纵杆轴移动时会触发sf::Event::JoystickMoved事件。

操纵杆轴通常非常敏感,这就是为什么SFML使用检测阈值来避免用大量JoystickMoved事件垃圾发送事件循环。如果希望接收更多或更少的操纵杆移动事件,可以使用Window::setJoystickThreshold函数更改此阈值。

SFML支持8个操纵杆轴:X、Y、Z、R、U、V、POV X和POV Y。它们如何映射到操纵杆取决于其驱动程序。

与此事件关联的成员是event。joystickMove,它包含操纵杆的标识符、轴的名称及其当前位置(在[-100100]范围内)。

if (event.type == sf::Event::JoystickMoved)
{
    if (event.joystickMove.axis == sf::Joystick::X)
    {
        std::cout << "X axis moved!" << std::endl;
        std::cout << "joystick id: " << event.joystickMove.joystickId << std::endl;
        std::cout << "new position: " << event.joystickMove.position << std::endl;
    }
}

The JoystickConnected and JoystickDisconnected events

连接/断开操纵杆时,会触发sf::Event::JoystickConnected和sf::Event::JoystickDisconnected事件。

与此事件关联的成员是event.joystickConnect,它包含连接/断开的操纵手柄的标识符。

if (event.type == sf::Event::JoystickConnected)
    std::cout << "joystick connected: " << event.joystickConnect.joystickId << std::endl;

if (event.type == sf::Event::JoystickDisconnected)
    std::cout << "joystick disconnected: " << event.joystickConnect.joystickId << std::endl;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值