概述
Canvas组件是App Inventor 2中实现2D绘图和游戏的核心组件。它支持:
- 基本图形绘制(线、圆、矩形)
- 图片精灵(ImageSprite)动画
- 触摸/拖拽交互
- 碰撞检测
- 定时动画
Canvas组件核心属性
| 属性 | 说明 |
|---|---|
| Width/Height | 画布尺寸 |
| BackgroundColor | 背景颜色 |
| BackgroundImage | 背景图片 |
| PaintColor | 画笔颜色 |
| LineWidth | 线条宽度 |
| FontSize | 文字大小 |
核心事件
| 事件 | 参数 | 说明 |
|---|---|---|
| Touched(x, y) | 触摸坐标 | 点击画布 |
| Dragged(x, y, prevX, prevY) | 拖拽坐标 | 拖拽画布 |
| Flung(x, y, speed, heading) | 速度方向 | 快速滑动 |
基本图形绘制
绘制线条
当 Canvas1.拖动(被拖动, 起点X, 起点Y, 当前X, 当前Y, 上一X, 上一Y)
如果 被拖动
调用 Canvas1.画线(上一X, 上一Y, 当前X, 当前Y)
绘制圆形
当 Canvas1.触摸(触摸, X, Y)
调用 Canvas1.画圆(X, Y, 20, true) ' x, y, 半径, 填充
绘制矩形
当 Canvas1.触摸(触摸, X, Y)
调用 Canvas1.画矩形(X - 25, Y - 25, X + 25, Y + 25, 颜色)
绘制文字
当 Canvas1.触摸(触摸, X, Y)
调用 Canvas1.画文字(X, Y, "Hello!", Canvas1.画笔颜色)
ImageSprite(图片精灵)
ImageSprite是Canvas上的可移动图片对象,是实现游戏角色的基础。
核心属性
| 属性 | 说明 |
|---|---|
| Picture | 精灵图片 |
| X, Y | 位置坐标 |
| Heading | 移动方向(0-360°,0=向上) |
| Speed | 移动速度 |
| Interval | 移动间隔(毫秒) |
| Rotates | 是否跟随方向旋转 |
| Visible | 是否可见 |
| Z | 层级(越大越前面) |
基本动画
当 Screen1.初始化
设 ImageSprite1.图片 = "character.png"
设 ImageSprite1.X = 100
设 ImageSprite1.Y = 100
设 ImageSprite1.方向 = 90 ' 向右
设 ImageSprite1.速度 = 5
设 ImageSprite1.间隔 = 50 ' 50ms移动一次
设 ImageSprite1.启用 = true
方向控制(键盘/按钮)
当 按钮_上.被点击
设 ImageSprite1.方向 = 0 ' 向上
当 按钮_下.被点击
设 ImageSprite1.方向 = 180 ' 向下
当 按钮_左.被点击
设 ImageSprite1.方向 = 270 ' 向左
当 按钮_右.被点击
设 ImageSprite1.方向 = 90 ' 向右
碰撞检测
当 ImageSprite1.碰撞(其他组件)
如果 其他组件 = ImageSprite2
' 两个精灵碰撞了
设 ImageSprite1.启用 = false
调用 通知.显示信息("碰撞!", "游戏结束")
到达边缘
当 ImageSprite1.到达边缘()
' 反弹
设 ImageSprite1.方向 = ImageSprite1.方向 + 180
如果 ImageSprite1.方向 > 360
设 ImageSprite1.方向 = ImageSprite1.方向 - 360
实战案例:地球围绕太阳旋转
设 角度 = 0
设 太阳X = 200
设 太阳Y = 200
设 轨道半径 = 100
当 Screen1.初始化
' 画太阳
调用 Canvas1.画圆(太阳X, 太阳Y, 30, 黄色)
' 画轨道
设 Clock1.计时器间隔 = 50
设 Clock1.启用计时器 = true
当 Clock1.计时
角度 = 角度 + 3
如果 角度 > 360
角度 = 0
' 计算地球位置(圆周运动)
设 地球X = 太阳X + 轨道半径 * 数学.余弦(角度 * 数学.PI / 180)
设 地球Y = 太阳Y + 轨道半径 * 数学.正弦(角度 * 数学.PI / 180)
' 重绘(清除后重画)
调用 Canvas1.清除()
调用 Canvas1.画圆(太阳X, 太阳Y, 30, 黄色) ' 太阳
调用 Canvas1.画圆(地球X, 地球Y, 12, 蓝色) ' 地球
实战案例:翻翻乐(记忆配对游戏)
功能需求
- 4x4的卡片网格(8对)
- 点击翻开卡片
- 配对成功保持翻开,失败翻回
- 计分和计时
界面设计
- Canvas(填满屏幕)
- Clock(计时用)
- 标签_分数、标签_时间
积木块代码
设 卡片数据 = ["🍎","🍌","🍊","🍇","🍉","🍓","🥝","🍑"]
设 卡片数据 = 合并列表(卡片数据, 卡片数据) ' 16张(8对)
设 卡片数据 = 随机打乱(卡片数据)
设 网格列数 = 4
设 网格行数 = 4
设 卡片宽度 = 0
设 卡片高度 = 0
设 卡片状态 = 创建空列表 ' true=翻开, false=未翻
设 第一次选择 = -1
设 第二次选择 = -1
设 等待中 = false
设 分数 = 0
当 Screen1.初始化
设 卡片宽度 = Canvas1.宽度 / 网格列数
设 卡片高度 = Canvas1.高度 / 网格行数
' 初始化卡片状态
设 i = 1
当 i ≤ 16
设 卡片状态 = 添加列表项(卡片状态, false)
设 i = i + 1
绘制卡片()
设 Clock1.计时器间隔 = 1000
设 Clock1.启用计时器 = true
定义 绘制卡片()
调用 Canvas1.清除()
设 i = 0
当 i < 16
设 行 = 数学.向下取整(i / 网格列数)
设 列 = i 模 网格列数
设 X = 列 * 卡片宽度 + 5
设 Y = 行 * 卡片高度 + 5
如果 列表第(i+1)项(卡片状态) = true
' 已翻开 - 显示内容
调用 Canvas1.画矩形(X, Y, X + 卡片宽度 - 10, Y + 卡片高度 - 10, 白色)
调用 Canvas1.画文字(X + 卡片宽度/2 - 10, Y + 卡片高度/2, 列表第(i+1)项(卡片数据), 黑色)
否则
' 未翻开 - 显示背面
调用 Canvas1.画矩形(X, Y, X + 卡片宽度 - 10, Y + 卡片高度 - 10, 蓝色)
设 i = i + 1
当 Canvas1.触摸(触摸, X, Y)
如果 非 等待中
设 列 = 数学.向下取整(X / 卡片宽度)
设 行 = 数学.向下取整(Y / 卡片高度)
设 索引 = 行 * 网格列数 + 列 + 1
如果 索引 ≥ 1 且 索引 ≤ 16
如果 列表第索引项(卡片状态) = false
' 翻开卡片
调用 替换列表项(卡片状态, 索引, true)
如果 第一次选择 = -1
设 第一次选择 = 索引
否则
设 第二次选择 = 索引
' 检查配对
如果 列表第第一次选择项(卡片数据) = 列表第第二次选择项(卡片数据)
' 配对成功
设 分数 = 分数 + 10
标签_分数.文本 = "分数:" & 分数
设 第一次选择 = -1
设 第二次选择 = -1
否则
' 配对失败,等1秒后翻回
设 等待中 = true
设 Clock_翻回.启用 = true
绘制卡片()
Canvas绘图方法汇总
| 方法 | 参数 | 说明 |
|---|---|---|
| DrawLine | x1, y1, x2, y2 | 画线 |
| DrawCircle | x, y, r, fill | 画圆 |
| DrawRect | left, top, right, bottom | 画矩形 |
| DrawText | x, y, text, color | 画文字 |
| DrawTextAtAngle | x, y, text, angle | 旋转文字 |
| DrawImage | image, x, y, w, h | 画图片 |
| Clear | — | 清除画布 |
| Save | — | 保存为图片 |
| GetBackgroundPixelColor | x, y | 获取像素颜色 |
常见问题
Q1: 闪烁问题怎么解决?
Canvas频繁重绘会闪烁。解决方案:
- 使用双缓冲(先画完再显示)
- 减少重绘频率
- 使用Sprite而不是Canvas绘图
Q2: 精灵图片背景透明?
使用PNG格式的图片,去掉背景色。App Inventor的ImageSprite支持PNG透明通道。
Q3: 如何实现虚拟摇杆?
Canvas + Dragged事件实现虚拟摇杆:
设 摇杆中心X = 100
设 摇杆中心Y = Canvas1.高度 - 100
设 摇杆半径 = 50
当 Canvas1.拖动(被拖动, 起X, 起Y, 当X, 当Y, 上X, 上Y)
设 距离 = 数学.平方根((当X-摇杆中心X)^2 + (当Y-摇杆中心Y)^2)
如果 距离 ≤ 摇杆半径
' 更新摇杆位置
设 摇杆X = 当X
设 摇杆Y = 当Y
否则
' 限制在范围内
设 角度 = 数学.反正切2(当Y - 摇杆中心Y, 当X - 摇杆中心X)
设 摇杆X = 摇杆中心X + 摇杆半径 * 数学.余弦(角度)
设 摇杆Y = 摇杆中心Y + 摇杆半径 * 数学.正弦(角度)
' 设置精灵方向
设 ImageSprite1.方向 = 数学.反正切2(-(当Y - 摇杆中心Y), 当X - 摇杆中心X) * 180 / 数学.PI
总结
| 功能 | 方案 |
|---|---|
| 自由绘画 | Canvas + Dragged |
| 游戏角色 | ImageSprite |
| 碰撞检测 | ImageSprite.Collided |
| 圆周运动 | 三角函数计算坐标 |
| 卡片游戏 | Canvas重绘 |
| 虚拟摇杆 | Canvas + 拖拽 |
版权声明:MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权,本文档由 ai2claw 🐝 整理。
扫码添加客服咨询