20、探索Processing中的碰撞检测与鼠标键盘交互

探索Processing中的碰撞检测与鼠标键盘交互

碰撞检测

在处理一些模拟场景时,比如多个物体在窗口中移动,会遇到物体相互重叠的问题。以多个变形虫在窗口中移动为例,为了防止它们相互重叠,需要进行碰撞检测。

由于变形虫大致呈圆形,所以可以使用圆 - 圆碰撞检测算法。该算法的原理是:对于两个圆,如果它们圆心之间的距离大于两圆半径之和,那么这两个圆没有碰撞;反之,如果圆心距离小于两圆半径之和,则两圆发生了碰撞。

# 伪代码示例,用于检测碰撞
for a in amoebas:
    for b in amoebas:
        if a is b:
            continue
        # 此处添加具体的碰撞检测和处理代码

在上述代码中,使用两层循环遍历所有变形虫对。 if a is b 语句用于避免检测一个变形虫与自身的碰撞,若 a b 是同一个实例,就跳过当前循环。

可以思考如何利用距离向量将碰撞的变形虫推开,例如添加(或减去)距离向量的一部分,使变形虫朝与碰撞对象相反的方向移动。

面向对象编程与模块化

通过面向对象编程,可以在Python中对现实世界的对象进行建模。定义一个新的类,如 Amoeba 类,并为其添加属性和方法。类就像一个对象模板,可以创建无数个实例。将相关的变量(属性)和函数(方法)组合到类中,能更有效地组织代码,这在编写大型、复杂项目时尤为有效。

同时,还可以将类和其他代码分离到不同的Python文件(模块)中,以便在项目之间共享代码,或者在同一项目的不同文件中作为可重用组件。模块可以减少主代码的行数,让我们专注于更高级的逻辑。

Processing中的向量类

Processing提供了内置的 PVector 类来处理欧几里得向量。欧几里得向量描述了既有大小又有方向的量,也可以用来存储物体的位置(以x - y坐标形式)。在模拟场景中,可以使用向量来模拟力并控制各种对象在显示窗口中的位置。

鼠标和键盘交互

在编程中,处理鼠标和键盘交互可以让程序更加生动和实用。可以将鼠标和键盘输入设备以有趣且有用的方式结合起来,例如在许多电脑游戏中,使用按键控制玩家移动,使用鼠标进行瞄准。

鼠标交互

鼠标输入可以用于执行点选操作,也可以编程实现结合鼠标移动和点击的手势动作,如拖放或平移。大多数鼠标有三个按钮:左键、右键和可点击的滚轮(兼作中键)。

Processing提供了一些系统变量来监控鼠标的状态:
- mouseX mouseY :分别表示鼠标指针在显示窗口中的水平和垂直位置。
- pmouseX pmouseY :包含上一帧的鼠标坐标。
- mousePressed :当鼠标按钮被按下时,该变量被设置为 True

下面是一个使用这些变量创建简单刮画程序的示例:

def setup():
    size(800, 400)
    frameRate(20)
    background('#000000')
    stroke('#FFFFFF')

def draw():
    circle(mouseX, mouseY, 15)

在上述代码中,每帧Processing会根据 mouseX mouseY 的值绘制一个新的白色圆圈。由于 draw() 块中没有 background() 函数,所以绘制的圆圈会一直保留,直到关闭显示窗口。

如果想要绘制连续的线条,可以将 circle() 函数替换为 line() 函数:

def draw():
    strokeWeight(15)
    line(mouseX, mouseY, pmouseX, pmouseY)

为了实现只有在按下鼠标左键时才绘制线条的功能,可以添加 if 语句:

def draw():
    strokeWeight(15)
    if mousePressed and mouseButton == LEFT:
        line(mouseX, mouseY, pmouseX, pmouseY)

为了实现彩虹色刮画效果,可以根据鼠标指针的位置设置线条的颜色:

def draw():
    colorMode(HSB, 360, 100, 100)
    h = mouseX * 360.0 / width
    s = mouseY * 100.0 / height
    b = 100
    stroke(h, s, b)
    strokeWeight(15)
    if mousePressed and mouseButton == LEFT:
        line(mouseX, mouseY, pmouseX, pmouseY)
鼠标事件

Processing提供了一系列鼠标事件函数,每次特定的鼠标事件发生时,这些函数就会执行。这些函数包括 mouseClicked() mouseDragged() mouseMoved() mousePressed() mouseReleased() mouseWheel()

下面是使用 mousePressed 变量和 mousePressed() 事件函数的对比示例:

# 使用 mousePressed 变量
def draw():
    background('#FF0000')  # 红色
    if mousePressed:
        background('#0000FF')  # 蓝色

# 使用 mousePressed() 事件函数
def draw():
    background('#FF0000')  # 红色

def mousePressed():
    background('#0000FF')  # 蓝色

在第一个示例中,只要用户按下鼠标按钮,背景颜色就会变为蓝色;在第二个示例中,每次按下鼠标按钮时,显示窗口会短暂闪烁蓝色(仅一帧),然后立即恢复为红色,因为事件函数每次事件只执行一次。

创建绘画应用

接下来,将创建一个基本的绘画应用,该应用具有一个工具调色板,用于选择颜色样本和其他选项。会使用 mousePressed() mouseReleased() mouseWheel() 函数。

准备工作
  1. 创建一个新的草图并保存为 paint_app
  2. 从指定的GitHub网页下载 Ernest.ttf 字体文件,并将其放在草图文件夹的新 data 子文件夹中。
def setup():
    size(600, 600)
    background('#004477')
    ernest = createFont('Ernest.ttf', 20)
    textFont(ernest)

swatches = ['#FF0000', '#FF9900', '#FFFF00', 
            '#00FF00', '#0099FF', '#6633FF']
brushcolor = swatches[2]
brushshape = ROUND
brushsize = 3
painting = False
paintmode = 'free'
palette = 60

在上述代码中,定义了显示窗口的大小、背景颜色、字体和一些全局变量,用于调整和监控画笔的状态。默认画笔颜色设置为黄色。

控制绘制循环

使用 loop() noLoop() 函数来控制 draw() 函数的行为。 noLoop() 函数会停止Processing持续执行 draw() 块中的代码, loop() 函数会重新激活标准的 draw() 函数行为, redraw() 函数可以用于仅执行一次 draw() 代码。

def setup():
    size(600, 600)
    background('#004477')
    ernest = createFont('Ernest.ttf', 20)
    textFont(ernest)
    noLoop()

def draw():
    print(frameCount)
    global painting, paintmode    
    if paintmode == 'free':
        if painting:
            stroke(brushcolor)
            strokeCap(brushshape)
            strokeWeight(brushsize)
            line(mouseX, mouseY, pmouseX, pmouseY)
        elif frameCount > 1:
            painting = True

def mousePressed():
    # 开始绘画
    if mouseButton == LEFT:
        loop()

def mouseReleased():
    # 停止绘画
    if mouseButton == LEFT:
        global painting
        painting = False
        noLoop()

在上述代码中,初始时 draw() 函数不循环。按下鼠标左键时, loop() 函数使 draw() 函数开始循环;释放鼠标左键时, noLoop() 函数停止循环。

添加可选颜色样本

在工具调色板中添加六个颜色样本,用户可以点击这些样本更改画笔颜色。

def draw():
    # ...之前的代码...
    # 黑色面板
    noStroke()
    fill('#000000')
    rect(0, 0, palette, height)
    # 颜色样本
    for i, swatch in enumerate(swatches):
        sx = int(i%2) * palette/2
        sy = int(i/2) * palette/2
        fill(swatch)
        square(sx, sy, palette/2)

def mousePressed():
    # ...之前的代码...
    # 样本选择
    if mouseButton == LEFT and mouseX < palette and mouseY < 90:
        global brushcolor
        brushcolor = get(mouseX, mouseY)

在上述代码中,使用 for 循环遍历 swatches 列表,绘制一个由不同颜色填充的正方形网格。当用户点击颜色样本时,使用 get() 函数获取鼠标指针下像素的颜色,并将其赋值给 brushcolor 变量。

使用鼠标滚轮调整画笔大小

mouseWheel() 事件函数用于在鼠标滚轮移动时执行代码,并可以根据滚轮的旋转方向获取正或负的值。

def draw():
    # ...之前的代码...
    # 画笔预览
    fill(brushcolor)
    if brushshape == ROUND:
        circle(palette/2, 123, brushsize)
    paintmode = 'free'

def mouseWheel(e):
    # 调整画笔大小
    global brushsize, paintmode
    paintmode = 'select'
    brushsize += e.count
    if brushsize < 3:
        brushsize = 3
    if brushsize > 45:
        brushsize = 45
    redraw()

在上述代码中,当鼠标滚轮移动时, mouseWheel() 函数会根据滚轮的旋转方向调整画笔大小,并确保画笔大小在合理范围内。同时,为了避免在调整画笔大小时绘画,将 paintmode 切换为 select

为了解决使用大画笔选择颜色样本时,颜料可能延伸到画布区域的问题,可以在 draw() 函数中添加一个 if 语句:

def draw():
    print(frameCount)
    global painting, paintmode
    if mouseX < palette:
        paintmode = 'select'
    # ...之前的代码...

通过上述步骤,就可以创建一个功能较为丰富的绘画应用,并且可以根据需要进一步扩展其功能。

下面是一个简单的流程图,展示绘画应用的主要流程:

graph TD;
    A[开始] --> B[初始化设置];
    B --> C[等待鼠标事件];
    C --> D{鼠标左键按下};
    D -- 是 --> E[开始绘画循环];
    D -- 否 --> C;
    E --> F{鼠标左键释放};
    F -- 是 --> G[停止绘画循环];
    F -- 否 --> H{鼠标滚轮滚动};
    H -- 是 --> I[调整画笔大小];
    H -- 否 --> J{鼠标点击颜色样本};
    J -- 是 --> K[更改画笔颜色];
    J -- 否 --> E;
    G --> C;

通过以上内容,我们学习了如何进行碰撞检测、使用面向对象编程和模块化、处理鼠标和键盘交互,以及创建一个基本的绘画应用。这些知识可以帮助我们开发出更加丰富和交互性强的程序。

探索Processing中的碰撞检测与鼠标键盘交互

碰撞检测的深入思考

在处理碰撞检测时,除了检测碰撞的发生,还需要考虑如何处理碰撞后的情况。对于变形虫的例子,当检测到碰撞后,可以通过向量运算来推开碰撞的变形虫。例如,可以计算两个变形虫中心之间的距离向量,然后将这个向量的一部分加到其中一个变形虫的位置上,同时从另一个变形虫的位置上减去相同的部分,从而实现推开的效果。

以下是一个简单的伪代码示例:

for a in amoebas:
    for b in amoebas:
        if a is b:
            continue
        # 计算两个变形虫中心的距离
        distance = calculate_distance(a.center, b.center)
        if distance < a.radius + b.radius:
            # 发生碰撞,计算推开向量
            push_vector = calculate_push_vector(a.center, b.center)
            # 推开变形虫
            a.position += push_vector * 0.1
            b.position -= push_vector * 0.1
鼠标和键盘交互的更多应用场景

除了前面提到的刮画程序和绘画应用,鼠标和键盘交互还可以应用于更多场景。

游戏开发

在游戏开发中,鼠标和键盘交互是非常重要的。例如,在一个射击游戏中,可以使用鼠标控制瞄准方向,使用键盘控制角色的移动。可以通过监听鼠标的点击事件来触发射击动作,监听键盘的按键事件来控制角色的前后左右移动。

def draw():
    # 绘制游戏场景
    draw_game_scene()

def mousePressed():
    if mouseButton == LEFT:
        # 触发射击动作
        shoot()

def keyPressed():
    if key == 'W':
        # 向前移动
        move_forward()
    elif key == 'S':
        # 向后移动
        move_backward()
    elif key == 'A':
        # 向左移动
        move_left()
    elif key == 'D':
        # 向右移动
        move_right()
数据可视化

在数据可视化中,鼠标和键盘交互可以让用户更方便地探索数据。例如,在一个柱状图可视化中,可以使用鼠标悬停在柱子上显示详细的数据信息,使用键盘的上下左右箭头键来切换不同的数据视图。

def draw():
    # 绘制柱状图
    draw_bar_chart()

def mouseMoved():
    for bar in bars:
        if is_mouse_over(bar):
            # 鼠标悬停在柱子上,显示详细信息
            show_details(bar)

def keyPressed():
    if key == CODED:
        if keyCode == UP:
            # 切换到上一个数据视图
            switch_view('up')
        elif keyCode == DOWN:
            # 切换到下一个数据视图
            switch_view('down')
        elif keyCode == LEFT:
            # 切换到左一个数据视图
            switch_view('left')
        elif keyCode == RIGHT:
            # 切换到右一个数据视图
            switch_view('right')
挑战与扩展
挑战 #11:添加绘画应用功能

可以为前面创建的绘画应用添加更多功能,例如添加更多的画笔形状、添加撤销和重做功能、添加保存绘画的功能等。

以下是一个添加撤销和重做功能的简单示例:

# 初始化撤销和重做栈
undo_stack = []
redo_stack = []

def draw():
    # ...之前的代码...
    if keyPressed and key == 'Z':
        if len(undo_stack) > 0:
            # 撤销操作
            redo_stack.append(current_state())
            restore_state(undo_stack.pop())
    elif keyPressed and key == 'Y':
        if len(redo_stack) > 0:
            # 重做操作
            undo_stack.append(current_state())
            restore_state(redo_stack.pop())

def mousePressed():
    # ...之前的代码...
    # 保存当前状态到撤销栈
    undo_stack.append(current_state())
    redo_stack = []
扩展:自定义鼠标指针

可以使用 cursor() 函数将鼠标指针从默认的箭头更改为其他形状。例如,将鼠标指针改为十字线:

def setup():
    size(600, 600)
    background('#004477')
    ernest = createFont('Ernest.ttf', 20)
    textFont(ernest)
    cursor(CROSS)
总结

通过本文的学习,我们掌握了多个重要的编程概念和技能。

概念/技能 描述
碰撞检测 学会使用圆 - 圆碰撞检测算法,检测物体之间的碰撞,并思考如何处理碰撞后的情况
面向对象编程与模块化 了解如何使用类来建模现实世界的对象,将相关的变量和函数组合到类中,以及如何将代码分离到不同的模块中
鼠标和键盘交互 掌握了Processing中用于监控鼠标和键盘状态的系统变量和事件函数,能够创建具有交互性的程序,如刮画程序和绘画应用
绘画应用开发 学会创建一个基本的绘画应用,包括工具调色板、颜色选择、画笔大小调整等功能,并可以根据需求进一步扩展其功能

同时,我们还探讨了鼠标和键盘交互在游戏开发和数据可视化等领域的应用,以及如何应对挑战和扩展程序功能。这些知识和技能将为我们开发更加丰富和交互性强的程序奠定坚实的基础。

下面是一个总结性的流程图,展示从学习基础概念到创建应用并进行扩展的整个过程:

graph TD;
    A[学习基础概念] --> B[碰撞检测];
    A --> C[面向对象编程与模块化];
    A --> D[鼠标和键盘交互];
    B --> E[创建绘画应用];
    C --> E;
    D --> E;
    E --> F[应用扩展];
    F --> G[添加更多功能];
    F --> H[自定义鼠标指针];
    F --> I[应用于其他领域];

希望通过本文的学习,你能够在编程的道路上更进一步,开发出更多有趣和实用的程序。

内容概要:本文介绍了一个基于冠豪猪优化算法(CPO)的无人机三维路径规划项目,利用Python实现了在复杂三维环境中为无人机规划安全、高效、低能耗飞行路径的完整解决方案。项目涵盖空间环境建模、无人机动力学约束、路径编码、多目标代价函数设计以及CPO算法的核心实现。通过体素网格建模、动态障碍物处理、路径平滑技术和多约束融合机制,系统能够在高维、密集障碍环境下快速搜索出满足飞行可行性、安全性能效最优的路径,并支持在线重规划以适应动态环境变化。文中还提供了关键模块的代码示例,包括环境建模、路径评估和CPO优化流程。; 适合人群:具备一定Python编程基础和优化算法基础知识,从事无人机、智能机器人、路径规划或智能优化算法研究的相关科研人员工程技术人员,尤其适合研究生及有一定工作经验的研发工程师。; 使用场景及目标:①应用于复杂三维环境下的无人机自主导航避障;②研究智能优化算法(如CPO)在路径规划中的实际部署性能优化;③实现多目标(路径最短、能耗最低、安全性最高)耦合条件下的工程化路径求解;④构建可扩展的智能无人系统决策框架。; 阅读建议:建议结合文中模型架构代码示例进行实践运行,重点关注目标函数设计、CPO算法改进策略约束处理机制,宜在仿真环境中测试不同场景以深入理解算法行为系统鲁棒性。
在科技快速演进的时代背景下,移动终端性能持续提升,用户对移动应用的功能需求日益增长。增强现实、虚拟现实、机器人导航、自动驾驶辅助、手势识别、物体检测距离测量等前沿技术正成为研究应用的热点。作为支撑这些技术的核心,双目视觉系统通过模仿人类双眼的成像机制,同步获取两路图像数据,并借助图像处理立体匹配算法提取场景深度信息,进而生成点云并实现三维重建。这一技术体系对提高移动终端的智能化程度及优化人机交互体验具有关键作用。 双目视觉系统需对同步采集的两路视频流进行严格的时间同步空间校正,确保图像在时空维度上精确对齐,这是后续深度计算立体匹配的基础。立体匹配旨在建立两幅图像中对应特征点的关联,通常依赖复杂且高效的计算算法以满足实时处理的要求。点云生成则是将匹配后的特征点转换为三维空间坐标集合,以表征物体的立体结构;其质量直接取决于图像处理效率匹配算法的精度。三维重建基于点云数据,运用计算机图形学方法构建物体或场景的三维模型,该技术在增强现实虚拟现实等领域尤为重要,能够为用户创造高度沉浸的交互环境。 双目视觉技术已广泛应用于多个领域:在增强现实虚拟现实中,它可提升场景的真实感沉浸感;在机器人导航自动驾驶辅助系统中,能实时感知环境并完成距离测量,为路径规划决策提供依据;在手势识别物体检测方面,可精准捕捉用户动作物体位置,推动人机交互设计智能识别系统的发展。此外,结合深度计算点云技术,双目系统在精确距离测量方面展现出显著潜力,能为多样化的应用场景提供可靠数据支持。 综上所述,双目视觉技术在图像处理、深度计算、立体匹配、点云生成及三维重建等环节均扮演着不可或缺的角色。其应用跨越多个科技前沿领域,不仅推动了移动设备智能化的发展,也为丰富交互体验提供了坚实的技术基础。随着相关算法的持续优化硬件性能的不断提升,未来双目视觉技术有望在各类智能系统中实现更广泛、更深层次的应用。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值