processing动画基础

写在前面

关于编程语言,江湖上曾经流转着一句话,“真正的程序员用C++”。好吧,可不论怎么说我也不想为了成为了一个真正的程序员跳进C++这个大坑。家里翻了大半本之后闲置的C++ Primer,我实在是不知道什么时候能有勇气翻完。完全没什么动力啊,翻完了它短时间内我也不知道能干啥。--!

这里可以引出processing了。这个语言把常用的图形相关的操作都抽象封装好了,你只需要简单的调用它们就行了。size(320,240)就可以建立一个320x240大小的画布,现在想在画布上画一个点,调用point(60,80),就可以在(60,80)的位置画一个点了。想画一条线只需调用line(0,0,width,height),就可以画一条从左上角到右下角的线。width和height就是画布的宽和高的尺寸,processing会自动把它转换成实际的画布尺寸。

看看它的官网介绍吧。processing就是设计出来用来学习视觉艺术和可视化编程用的,用它的大都是些搞艺术的或者业余爱好者们。正因为如此,它被设计的非常简单和易学,上手它真的不需要多长时间。有编程基础的,特别是有学过java的,可能都不需要几分钟就能上手了--它默认使用的就是个简化版的java,所以它也是跨平台的,不管你用的是windows,mac os 还是linux,都能用。

另外,processing最大的优点是它还是免费的。你可以点这里选择No Donation免费下载到它。当然了,你也可以根据你的能力选择其他的选项给予捐助。

图形基础

首先要说明的是processing支持android mode,java mode,python mode...等等好几个模式,我选择的是python 。不是为了什么高尚的理由,只是因为我懒,想少敲几个括号少写几个分号而已。顺便安利一下:python也是挺简单方便的,貌似我也没看几天教程。反正我不是高手,有时候自己太笨了那就用笨一点的方法呗,能够解决问题就行了。

主界面
安装Python Mode for Processing

不啰嗦了,不论我们要画什么,都得有个地方去画吧。
所以,第一句得从一块画布开始:

size(320,240)

这是建立一个320像素宽,240像素高的画布的命令。
Ctrl+R,然后就可以看到相应大小的画布了。

你当然可以改成你想要的大小,如size(800,600)

有了画布,点、线、面走起:

1.从一个点开始:

size(320,240)
point(160,120)

320x240px的画布,在(160,120)的位置画了一个小黑点。


点1

不太明显是吧,没事,我们可以加上这两句:

size(320,240)
background(255)
strokeWeight(10)
point(160,120)

background(255)表示把背景色改成白色。这里顺便提一下,background()一个参数时取值范围是[0,255],表示从0(黑色)到255(白色)的灰度值。
这个说到颜色动画的时候再说,具体的参数可以查看:background()
上面好像忘了说坐标系了,直接画张图吧:

坐标系

官方的坐标系介绍配图:

coordinates2D3D.png

角度与弧度,不想画图了,截张《Getting Started with Processing》书里的吧:

角度与弧度

2.processing里有一些常用的系统变量,像width,height,mouseX,mouseY...具体的可以查文档
像上面的例子在画布中间画个小点,可以改成:

size(320,240)
background(255)
strokeWeight(10)
point(width/2,height/2)

执行效果是一样的,但是不论你在size()把画布改成多少,这个点都可以画在画布中间,如图:

Paste_Image.png

另外值得一提的两个特殊方法是setup()和draw():
*setup()在processing执行时被执行一次,可以用来初始化一些指令。
*draw()在processing重绘画布时由processing自动调用。

好了,关于processing的有时间再补充吧。标题写的动画基础,结果写了半天我还没有让它动起来。再拖下去有坑的危险。就让我从这个点开始动起来吧。

动画基础

1.匀速运动

1.1 直线运动
首先考虑的简单一些的匀速运动,让点沿x轴从左运动到右,假定x轴上的速度是vx,代码如下:

x, y, vx = 0, 120, 2

def setup():
    size(320, 240)
    strokeWeight(10)
    background(255)

def draw():
    global x, y, vx
    x += vx
    background(255)
    point(x, y)

OK,点动起来了,从左边(0,120)的位置开始,每一帧点都向右移动vx(代码中设定为2px)的距离,然后从画布右边消失了,并且黄鹤一去不复返...OTL


jdfw.gif

没事,我们可以加上一个检测语句,如果点从右边移动出了画布(x>width),我们就让它回到起点(x=0)好了.(弹性和碰撞我们后面再说)

# vx是点在x轴上的速度

def setup():
    global x, y, vx
    x, y = 0, height / 2
    vx=2
    size(320, 240)
    strokeWeight(10)
    background(255)

def draw():
    global x, y, vx
    x += vx
    if x > width:
        x = 0
    background(255)
    point(x, y)

这样,小球超出范围就会从起点重新开始了。

jdfw2.gif

同理y轴上的运动可以增加一个vy,下面的例子点在x,y两个轴上都有速度:

# x,y是点的坐标(x,y)
# vx,vy是点在x轴和y轴上的速度

def setup():
    global x, y, vx, vy
    x, y, vx, vy = 0, 0, 2, 2
    size(240, 240)
    strokeWeight(10)
    background(255)

def draw():
    global x, y, vx, vy
    x += vx
    y += vy
    if x > width:
        x = 0
    if y > height:
        y = 0
    background(255)
    point(x, y)
jdfw3.gif

可以看到圆点的实际速度v是两个轴上的的速度vx和vy的向量和。如图:

Paste_Image.png

也就是根据实际运动速度值v和任意方向a,我们同样可以算出来圆点在x轴上和y轴上的速度vx,vy。
很明显:
vx=v*cos(a)
vy=v*sin(a)
现在可以以速度v往任意方向a运动了:

# 点坐标(x,y),速度v,方向a

def setup():
    global x, y, v, a
    x, y, v, a = width / 2, height / 2, 2, radians(10)
    size(320, 240)
    strokeWeight(10)
    background(255)

def draw():
    global x, y, v, a
    vx = v * cos(a)
    vy = v * sin(a)
    x += vx
    y += vy
    # x,y超出范围返回起始位置
    if x < 0 or x > width:
        x = width / 2
        y = height / 2
    if y < 0 or y > height:
        x = width / 2
        y = height / 2
    background(255)
    point(x, y)


这里要注意一下cos()和sin()的参数是弧度值,如果给的是角度,可以使用radians()转换成弧度。
另外,参见之前的角度与弧度的图,processing的值是顺时针增加的,不是逆时针。


jdfw4.gif

这个例子里的vx,vy其实是固定值,可以放到setup()里计算一次就够了,不用在draw()里每次计算。没错,这个例子里确实可以这样改,这样写的原因是还有接下来的圆周运动呢。
哎,不知不觉码字码到好晚了。头一次用Markdown,还不太熟悉,圆周就留着和变速运动一起慢慢写吧。

1.2 圆周运动
接着来写圆周运动吧。
为了看起来方便,用AI画了张示意图:

Paste_Image.png

这个例子如上图:(x0,y0)为圆心,半径为r,起始角度为start_a,速度为v。那么很显然,点的坐标(x,y)应该是:

a=start_a
x=x0+rcos(a)
y=y0+r
sin(a)

现在要让点绕圆心(x0,y0)作以恒定速度v作圆周运动,很明显只需要知道一个变量角速度va。这个v是线速度且值恒定,那么每帧这个角度a的变化值va(也就是角速度)也很简单算出来:以线速度和以角速度分别算出来的转一圈的时间t应该是相等的:

t=TWO_PI*r/v=TWO_PI/va

得到:

va=v/r

ok,现在足够完成圆周运动的动画了:

def setup():
    global x0, y0, v, r, a
    # 以点x0,y0为圆心,v是线速度,r是圆半径
    x0, y0, v, r = width / 2, height / 2, 3, 30
    # start_a是起始角度,单位是度
    start_a = 30
    a = radians(start_a)
    size(320, 240)
    strokeWeight(10)
    background(255)

def draw():
    global x0, y0, v, a, r
    va = float(v) / r
    x = x0 + r * cos(a)
    y = y0 + r * sin(a)
    a += va
    background(255)
    point(x, y)
圆周运动

可以在圆心加个十字线更明显一些:

def setup():
    global x0, y0, v, r, a
    # 以点x0,y0为圆心,v是线速度,r是圆半径
    x0, y0, v, r = width / 2, height / 2, 3, 30
    # start_a是起始角度,单位是度
    start_a = 30
    a = radians(start_a)
    size(320, 240)
    strokeWeight(10)
    background(255)
    frameRate(24)

frm=0

def draw():
    global x0, y0, v, a, r
    va = float(v) / r
    x = x0 + r * cos(a)
    y = y0 + r * sin(a)
    a += va
    background(255)
    point(x, y)
    
    # 在圆心画一个十字线
    strokeWeight(1)
    line(width / 2 - 5, height / 2, width / 2 + 5, height / 2)
    line(width / 2, height / 2 - 5, width / 2, height / 2 + 5)
    strokeWeight(10)
标示圆心的圆周运动

这些基本的运动是基础,你可以在基础之上加上一些自己的想法。试着改动一下初始参数,或者干脆加上自己想要的效果:比如改变颜色、透明度或大小,或者弄成阵列。比如可以试着让圆慢慢消失,代码如下:

def setup():
    global x0, y0, v, r, a
    # 以点x0,y0为圆心,v是线速度,r是圆半径
    x0, y0, v, r = width / 2, height / 2, 10, 30
    # start_a是起始角度,单位是度
    start_a = 30
    a = radians(start_a)
    size(320, 240)
    strokeWeight(10)
    background(255)
    frameRate(24)


def draw():
    global x0, y0, v, a, r
    va = float(v) / r
    x = x0 + r * cos(a)
    y = y0 + r * sin(a)
    a += va
    # background(255)
    fill(0x33ffffff)
    noStroke()
    rect(0,0,width,height)
    stroke(0,0,0)
    strokeWeight(10)
    point(x, y)
加上一些其他效果的圆周运动
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容