App Inventor 2 Canvas绘图教程 - 游戏精灵与动画实现

« 返回首页

概述

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 🐝 整理。

文档反馈