其他游戏编程研究院首页投稿(暂停使用,暂停投稿)

processing动画基础

2016-04-01  本文已影响4369人  jinglepp

写在前面

关于编程语言,江湖上曾经流转着一句话,“真正的程序员用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)
加上一些其他效果的圆周运动
上一篇下一篇

猜你喜欢

热点阅读