OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离
------ 2024-10-02 下午
code review!
文章目录
1.代码图片
运行
Mouse button 1 pressed at (100, 200)
Mouse dragged by (50, 50)
Key pressed: 65
Updating camera control
2.分析
类图:
Application -cameraControl: CameraControl* -mouseCallback: MouseCallback -keyCallback: KeyCallback +Application() +setMouseCallback(MouseCallback) +setKeyCallback(KeyCallback) +triggerMouseEvent(MouseEvent) +triggerKeyEvent(KeyEvent) +run() <<interface>> CameraControl +handleMouseEvent(MouseEvent) +handleKeyEvent(KeyEvent) +update() SimpleCameraControl -mousePressed: bool -lastX: double -lastY: double -keys: map +handleMouseEvent(MouseEvent) +handleKeyEvent(KeyEvent) +update() MouseEvent +x: int +y: int +button: int +pressed: bool KeyEvent +key: int
上面的类图展示了代码中主要类的结构和关系:
Application
类包含一个CameraControl
指针和事件回调函数指针,通过setMouseCallback
和setKeyCallback
设置事件回调。CameraControl
是一个抽象基类,定义了处理鼠标事件、键盘事件和更新的接口。SimpleCameraControl
继承自CameraControl
,实现了具体的事件处理逻辑。MouseEvent
和KeyEvent
分别表示鼠标事件和键盘事件的数据结构。
事件处理流程图:
mouseCallback keyCallback 鼠标/键盘事件 Application::triggerMouseEvent/triggerKeyEvent onMouseEvent onKeyEvent SimpleCameraControl::handleMouseEvent SimpleCameraControl::handleKeyEvent
事件处理流程如下:
- 应用程序触发鼠标或键盘事件
- 事件通过
Application::triggerMouseEvent
或Application::triggerKeyEvent
分发到对应的全局回调函数 - 回调函数
onMouseEvent
或onKeyEvent
调用SimpleCameraControl
的对应事件处理函数 SimpleCameraControl
的事件处理函数根据事件数据进行相应的处理
主程序流程图:
main 创建Application对象 设置鼠标回调为onMouseEvent 设置键盘回调为onKeyEvent 调用Application::run 模拟触发鼠标事件 模拟触发键盘事件 调用CameraControl::update
主程序的流程如下:
- 创建
Application
对象 - 设置鼠标回调函数为
onMouseEvent
- 设置键盘回调函数为
onKeyEvent
- 调用
Application::run
- 模拟触发鼠标事件
- 模拟触发键盘事件
- 调用
CameraControl::update
更新相机状态
3.UML
asciidoc
+------------------+
| CameraControl | <<abstract>>
+------------------+
| +handleMouseEvent(MouseEvent) : void |
| +handleKeyEvent(KeyEvent) : void |
| +update() : void |
+------------------+
^
|
|
+----------------------+
| SimpleCameraControl |
+----------------------+
| -mousePressed : bool |
| -lastX : double |
| -lastY : double |
| -keys : map<int, bool> |
+----------------------+
| +handleMouseEvent(MouseEvent) : void |
| +handleKeyEvent(KeyEvent) : void |
| +update() : void |
+----------------------+
+-------------------+
| Application |
+-------------------+
| -cameraControl : SimpleCameraControl*
| -mouseCallback : MouseCallback |
| -keyCallback : KeyCallback |
+-------------------+
| +setMouseCallback(MouseCallback) : void |
| +setKeyCallback(KeyCallback) : void |
| +triggerMouseEvent(MouseEvent) : void |
| +triggerKeyEvent(KeyEvent) : void |
| +run() : void |
+-------------------+
+-------------------+
| MouseEvent |
+-------------------+
| +x : int |
| +y : int |
| +button : int |
| +pressed : bool |
+-------------------+
+-----------------+
| KeyEvent |
+-----------------+
| +key : int |
+-----------------+
+--------------------+
| Global Functions |
+--------------------+
| +onMouseEvent(MouseEvent) : void |
| +onKeyEvent(KeyEvent) : void |
+--------------------+
4.代码
cpp
#include <iostream>
#include <map>
// 定义事件类型
enum class EventType {
MouseClick,
KeyPress
};
// 定义鼠标事件信息
struct MouseEvent {
int x, y;
int button;
bool pressed;
};
// 定义键盘事件信息
struct KeyEvent {
int key;
};
// 事件回调函数指针类型
using MouseCallback = void (*)(const MouseEvent&);
using KeyCallback = void (*)(const KeyEvent&);
// 抽象相机控制器基类
class CameraControl {
public:
virtual void handleMouseEvent(const MouseEvent& event) = 0;
virtual void handleKeyEvent(const KeyEvent& event) = 0;
virtual void update() = 0;
};
// 一个简单的相机控制器实现
class SimpleCameraControl : public CameraControl {
public:
void handleMouseEvent(const MouseEvent& event) override {
if (event.pressed) {
mousePressed = true;
lastX = event.x;
lastY = event.y;
std::cout << "Mouse button " << event.button << " pressed at ("
<< event.x << ", " << event.y << ")\n";
} else {
mousePressed = false;
double deltaX = event.x - lastX;
double deltaY = event.y - lastY;
std::cout << "Mouse dragged by (" << deltaX << ", " << deltaY << ")\n";
lastX = event.x;
lastY = event.y;
}
}
void handleKeyEvent(const KeyEvent& event) override {
keys[event.key] = true;
std::cout << "Key pressed: " << event.key << "\n";
}
void update() override {
std::cout << "Updating camera control\n";
}
private:
bool mousePressed = false;
double lastX = 0.0, lastY = 0.0;
std::map<int, bool> keys;
};
// 应用程序类
class Application {
public:
Application()
: cameraControl(new SimpleCameraControl()) {}
void setMouseCallback(MouseCallback callback) {
mouseCallback = callback;
}
void setKeyCallback(KeyCallback callback) {
keyCallback = callback;
}
void triggerMouseEvent(const MouseEvent& event) {
if (mouseCallback) {
mouseCallback(event);
}
}
void triggerKeyEvent(const KeyEvent& event) {
if (keyCallback) {
keyCallback(event);
}
}
void run() {
// 模拟事件触发
triggerMouseEvent(MouseEvent{100, 200, 1, true});
triggerMouseEvent(MouseEvent{150, 250, 1, false});
triggerKeyEvent(KeyEvent{65});
// 更新相机控制
cameraControl->update();
}
private:
SimpleCameraControl* cameraControl;
MouseCallback mouseCallback = nullptr;
KeyCallback keyCallback = nullptr;
};
// 全局函数
void onMouseEvent(const MouseEvent& event) {
static SimpleCameraControl control;
control.handleMouseEvent(event);
}
void onKeyEvent(const KeyEvent& event) {
static SimpleCameraControl control;
control.handleKeyEvent(event);
}
int main() {
Application app;
app.setMouseCallback(onMouseEvent);
app.setKeyCallback(onKeyEvent);
app.run();
return 0;
}