砚码绘图教学帮助
砚码科创 · C++ / Python / p5.js 三语绘图 · 从静态到动态 · 教学用

一三套绘图引擎总览

在砚码科创里,同一份“画图”需求可以有三套写法。它们语法不同,但绘图思路完全一致:设背景 → 选颜色 → 画图形 → (动态)每帧重画。先认清各自定位,再按需选用。

引擎学生写什么底层怎么跑擅长场景
C++GOC 图形编程标准 C++(JSCPP 解释器)浏览器 JS 解释执行静态图形、竞赛入门、坐标与几何基础
PythonPython 编程Python(Pyodide)浏览器 WASM 运行算法、数据处理,可配 turtle 绘图
p5.js动态绘图C++ 风格或Python 风格(语法壳)浏览器 canvas 实时渲染动画、鼠标键盘交互、粒子、分形
本模块的核心:动态绘图让学生用“熟悉的 C++ 或 Python 写法”写出真正跑在 p5.js 上的动画。语法是壳,能力是 p5.js——这正是 p5.js 的实际价值:画布 + 实时循环 + 交互。

二p5.js 核心概念

无论用哪套语法,最终都翻译成 p5.js。掌握这四个核心概念,就掌握了动态绘图。

1. 坐标系

画布像一张坐标纸:原点 (0,0) 在左上角,x 向右增大,y 向下增大。单位是像素。

  • 画布大小:createCanvas(宽, 高),如 createCanvas(400, 300)。
  • 常用宏:width(画布宽)、height(画布高)——写动画时用它避免写死数值。
画圆/椭圆用中心点 + 半径:circle(x, y, 直径)。画矩形用左上角 + 宽高:rect(x, y, 宽, 高)。

2. 颜色

p5.js 默认用 RGB,每个分量 0–255。可选加第 4 个参数表示透明度 alpha。

写法含义
fill(255, 0, 0)填充纯红
fill(192, 57, 43)填充朱砂红(砚码主题色)
fill(255, 100, 100, 60)填充半透明(alpha=60,颜色叠加可见)
stroke(44, 95, 138)描边靛蓝;noStroke() 关闭描边
background(220)设背景(单参数=灰度)

3. setup 与 draw:静态 vs 动态

这是 p5.js 的灵魂:

  • setup():只在开始时执行一次——建画布、设初始状态。
  • draw():每秒约 60 次循环执行——每帧重画,形成动画。
  • 只要在 draw() 里用了会变的量(frameCount、mouseX…),画面就“动”起来。
想只画一次(静态)?在 setup() 末尾写 noLoop(),draw() 只执行一次。

4. 交互:鼠标与键盘

系统变量含义
mouseX / mouseY鼠标当前位置
mouseIsPressed鼠标是否按下(true/false)
keyIsPressed是否正按着键盘
frameCount已渲染的帧数(从 0 开始,常作“时间”)

把图形坐标写成 mouseX, mouseY,图形就会跟着鼠标走。

三C++ 风格绘图

用 C++ 的语法习惯写,底层转译成 p5.js。只替换了类型关键字和函数定义,循环、分支、绘图 API 原样保留,几乎感受不到底层是 JS。

C++ 壳→ p5.js

语法对照

你写的 C++ 风格转译成 p5.js
void setup() { }function setup(){ }
void draw() { }function draw(){ }
int x = 100;let x = 100;
float y = 50.5;let y = 50.5;
for(int i=0; i<10; i++)原样保留(绘图里就是 JS 循环)
circle(x, y, r);原样保留(函数名与 p5.js 完全一致)

最小示例:一个圆

C++ 风格void setup() {
  createCanvas(400, 300);
}
void draw() {
  background(220);
  fill(192, 57, 43);
  circle(200, 150, 100);
}

动画示例:鼠标跟随 + 循环

C++ 风格void setup() {
  createCanvas(400, 300);
}
void draw() {
  background(20, 20, 30, 40);   // 半透明背景 → 留下轨迹
  for(int i = 0; i < 6; i++) {
    fill(255, i * 40, 100);
    circle(mouseX + i * 10, mouseY, 30);
  }
}
限制说明:这是教学子集,不支持指针、STL、结构体;但绘图、循环、分支、交互全部可用——正是绘图课需要的。

四Python 风格绘图

用 Python 的缩进写法,转译器按缩进补大括号,映射 def / for range / if / while。

Python 壳→ p5.js

语法对照

你写的 Python 风格转译成 p5.js
def setup():function setup(){
def draw():function draw(){
for i in range(8):for(let i=0; i<8; i+=1){
if mouseIsPressed:if(mouseIsPressed){
else: / elif x:else{ / else if(x){
# 注释// 注释
要点:Python 靠缩进区分块。转译器按缩进自动补大括号,缩进务必用统一空格(建议 4 个)。

最小示例:一个圆

Python 风格def setup():
    createCanvas(400, 300)

def draw():
    background(220)
    fill(192, 57, 43)
    circle(200, 150, 100)

动画示例:循环点阵

Python 风格def setup():
    createCanvas(400, 300)

def draw():
    background(20)
    for i in range(8):
        for j in range(6):
            fill(255, i * 30, j * 40)
            circle(40 + i * 48, 30 + j * 46, 26)

五绘图 API 速查(三语对照)

以下 API 在 C++ 风格、Python 风格、p5.js 里写法完全一致(语法壳不改变函数名)。

图形 / 功能C++ / Python 写法说明
画布createCanvas(400, 300)宽 × 高(像素)
背景background(220)也可 RGB:background(255,0,0)
填充色fill(r, g, b)可加第 4 位透明:fill(r,g,b,a)
描边色stroke(r, g, b)noStroke() 关,noFill() 关填充
描边粗细strokeWeight(n)n 为像素
圆circle(x, y, d)中心(x,y),d 为直径
椭圆ellipse(x, y, w, h)中心(x,y),宽 w 高 h
矩形rect(x, y, w, h)左上角(x,y),宽 w 高 h
直线line(x1, y1, x2, y2)两点连线
三角形triangle(x1,y1, x2,y2, x3,y3)三个顶点
点point(x, y)一个像素点
文字text("内容", x, y)先 textSize(n)、textAlign()
随机数random(最小值, 最大值)含小数的随机数
映射map(值, a1, a2, b1, b2)把值从区间[a1,a2]映射到[b1,b2]
平移translate(x, y)原点移到(x,y),便于围绕中心旋转
正弦sin(弧度)配合 frameCount 做波浪

六教学路径:从静态到动态

按台阶递进,每一步都能看到即时反馈,适合课上一次带学生“动起来”。

第 1 步静态图形 · 建立坐标感

画圆、矩形、直线;理解坐标系、RGB 颜色、setup 里加 noLoop()。一次一屏,先不追求动态。

第 2 步循环生成 · 重复的威力

用 for / range 画一排圆、点阵、棋盘格。体会“算法生成图案”。

第 3 步实时动画 · 动起来

去掉 noLoop(),用 frameCount 让图形运动、旋转、明暗变化。

第 4 步鼠标交互 · 人机对话

图形跟随 mouseX / mouseY,按 mouseIsPressed 变色。画面开始“回应”操作者。

第 5 步数学与物理 · 探究规律

用 sin / cos 做正弦波、行星轨道;map 映射数值;为 GESP / 科创选题铺路。

第 6 步创意综合 · 作品化

粒子、分形、迷你动画。结合“砚码五宝”探究流程,做成可截图存证的作品。

七经典示例(可直接在动态绘图里运行)

1. 正弦波 动态C++

C++void setup() { createCanvas(400, 300); }
void draw() {
  background(240);
  stroke(44, 95, 138); noFill();
  beginShape();
  for(int x = 0; x <= width; x += 5) {
    float y = height/2 + sin(x*0.05 + frameCount*0.05) * 60;
    vertex(x, y);
  }
  endShape();
}

2. 行星轨道 动态Python

Pythondef setup():
    createCanvas(400, 300)

def draw():
    background(10, 10, 20)
    translate(width/2, height/2)
    fill(255, 210, 120)
    circle(0, 0, 50)
    fill(120, 180, 255)
    circle(cos(frameCount * 0.05) * 90, sin(frameCount * 0.05) * 90, 18)

3. 点击变色 交互Python

Pythondef setup():
    createCanvas(400, 300)

def draw():
    background(240)
    if mouseIsPressed:
        fill(255, 100, 100)
    else:
        fill(44, 95, 138)
    circle(mouseX, mouseY, 40)

4. 粒子雨 创意C++

C++int n = 60;
float px[60], py[60];
void setup() {
  createCanvas(400, 300);
  for(int i=0; i<n; i++){ px[i]=random(0,width); py[i]=random(0,height); }
}
void draw() {
  background(20, 20, 30, 40);
  for(int i=0; i<n; i++){
    py[i] += 2; if(py[i]>height){ py[i]=0; px[i]=random(0,width); }
    fill(150, 200, 255, 160);
    circle(px[i], py[i], 4);
  }
}
提示:粒子/数组等进阶例子建议先用 C++ 风格演示(变量声明更直观);基础与动画可先用 Python 风格降低入门成本。

八常见错误排查

C++ 风格

现象原因与解决
提示“变量未定义”用了没声明的变量。先 int x=0; 再使用。
画不出图形检查是否 noFill() 且没设 fill();或 noStroke() 且图形只有描边。
页面卡死可能在 draw() 里写了死循环(如 while(1))。点“停止/重启”强制刷新,删掉死循环。

Python 风格

现象原因与解决
“语法错误:括号/缩进”缩进不一致。用统一空格(建议 4 个),别混用 Tab。
for i in range(8) 报错少写了冒号 :。每行块开头必须有冒号。
颜色没变化动画里每帧都 fill() 一次;用 frameCount 让参数变化。

通用

定位错误行:出错提示会附“约在源码第 X 行”,对照编辑器行号排查。若报错在转译后的 p5.js,点“查看 p5.js 源码”对比。
画面没“动”:确认没写 noLoop();确认 draw() 里用了会变化的量。

九课时建议(2–3 节课)

课时主题要点
第 1 节坐标系 · 静态图形setup/draw、background、fill、circle/rect;两种语法都跑一遍
第 2 节循环 + 动画for/range 生成图案;去掉 noLoop,用 frameCount 动起来
第 3 节交互 + 作品鼠标跟随、点击变色;正弦波/粒子;截图导出存证

建议结合「砚码五宝」流程:选题(砚)→ 探究(码)→ 表达(笔)→ 存证(纸),让绘图作品进入项目与证据链。