001-Paint_FreePythonGames项目代码详解(每行都有注释!!!)
一 turtle库
https://www.cnblogs.com/chen0307/articles/9645138.html
https://www.cnblogs.com/nier2b/p/10793235.html
1 基本概念:Turtle库是Python语言中一个很流行的绘制图像的函数库,
2 原理:想象一个小乌龟,在一个横轴为x、纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行的路径上绘制了图形。
3 常用命令:
turtle库包含100多个功能函数,主要包括窗体函数、画笔状态函数和画笔运动函数三类
- 画布:画布就是turtle为我们展开用于绘图区域,我们可以设置它的大小和初始位置。
- 设置画布大小: turtle.screensize(canvwidth, canvheight, bg),参数分别为画布的宽(单位像素), 高, 背景颜色。
- 设置画布初始位置:turtle.setup(width, height, startx, starty),参数:width, height: 输入宽和高为整数时, 表示像素; 为小数时, 表示占据电脑屏幕的比例,(startx, starty): 这一坐标表示矩形窗口左上角顶点的位置, 如果为空,则窗口位于屏幕中心。
- 画笔:
- 画笔的状态:坐标原点(位置),面朝x轴正方向(方向), turtle绘图中,就是使用位置方向描述小乌龟(画笔)的状态。
- 画笔的属性
- turtle.pensize():设置画笔的宽度
- turtle.pencolor():没有参数传入,返回当前画笔颜色,传入参数设置画笔颜色,可以是字符串如"green", "red",也可以是RGB 3元组。
- turtle.speed(speed):设置画笔移动速度,画笔绘制的速度范围[0,10]整数,数字越大越快。
- 绘图命令
- 画笔运动命令
- 画笔控制命令
- 全局控制命令
- 其他命令
4 库的导入https://www.jianshu.com/p/b502c89132dd
- import turtle
- 则对turtle库中函数调用采用turtle.<函数名>( )形式
-
import turtle turtle.circle(200)
- from turtle import *
- 则对turtle库中函数调用采用<函数名>( )形式,不再使用turtle.作为前导
-
1 from turtle import * 2 circle(200)
- 或者仅导入所使用的函数
-
1 from turtle import circle 2 circle(200)
- import turtle as t
- 保留字as将turtle库给予别名t, 则对turtle库中函数调用采用更简洁的t.<函数名>( )形式
-
1 import turtle as t 2 t.circle(200)
5 相关函数
(1)turtle.circle()函数
- 功能:根据半径radius绘制extent角度的弧形
- 语法:turtle.circle(radius, extent=None)
- 参数:正正左顺,负负右逆
- radius :弧形半径(当radius值为正数时,圆心在当前位置/小海龟左侧;当radius值为负数时,圆心在当前位置/小海龟右侧。)
- extent :弧形角度。当无该参数或参数为None时,绘制整个圆形。(当extent值为正数时,顺小海龟当前方向绘制;当extent值为负数时,逆小海龟当前方向绘制。)
(2)使用屏幕事件相关函数
1) listen()函数
- 语法:turtle.listen(xdummy=None, ydummy=None)
- 功能:设置焦点到 TurtleScreen (以便接收按键事件)。使用两个 Dummy 参数以便能够传递
listen()
给 onclick 方法。
2) onkey()函数
- 语法:turtle.onkey(fun,key)
- 参数:
- fun -- 一个无参数的函数或
None
- key -- 一个字符串: 键 (例如 "a") 或键标 (例如 "space")
- fun -- 一个无参数的函数或
- 功能:绑定 fun 指定的函数到按键释放事件。如果 fun 值为
None
,则移除事件绑定。注: 为了能够注册按键事件,TurtleScreen 必须得到焦点。(参见 methodlisten()
方法。)
3) onscreenclink()函数
- 语法:turtle.onclick(fun,btn=1,add=None)
参数:
- fun -- 一个函数,调用时将传入两个参数表示在画布上点击的坐标。
- btn -- 鼠标按钮编号,默认值为 1 (鼠标左键)
- add --
True
或False
-- 如为True
则将添加一个新绑定,否则将取代先前的绑定
- 功能:绑定 fun 指定的函数到鼠标点击屏幕事件。如果 fun 值为
None
,则移除现有的绑定。
二 代码内容
1 """Paint, for drawing shapes. 2 3 Exercises 4 5 1. Add a color. 6 2. Complete circle. 7 3. Complete rectangle. 8 4. Complete triangle. 9 5. Add width parameter. 10 11 """ 12 13 from turtle import * # 导入turtle库 14 from freegames import vector # 引入向量,用来定义坐标 15 16 def line(start, end): # 定义一个画一条线的函数,参数类型只能是向量 17 "Draw line from start to end." 18 penup() # 画笔提起操作 19 goto(start.x, start.y) # 将画笔移动到起点坐标为(x,y)的位置 20 pendown() # 画笔放下操作 21 goto(end.x, end.y) # 将画笔移动到终点坐标为(x,y)的位置 22 23 def square(start, end): # 定义一个画正方形的函数,参数类型只能是向量 24 "Draw square from start to end." 25 up() # 画笔提起操作 26 goto(start.x, start.y) # 将画笔移动到起点坐标为(x,y)的位置 27 down() # 画笔放下操作 28 begin_fill() # 准备开始填充图形 29 30 for count in range(4): # 循环4次,用于画矩形 31 forward(end.x - start.x) # 向当前画笔方向移动一段距离,该距离是第二次点击鼠标所在位置的横坐标减去第一次点击鼠标所在位置的横坐标 32 left(90) # 调整画笔方向:逆时针移动90° 33 34 end_fill() # 填充图形结束 35 36 def paint_circle(start, end): # 画圆,半径为正(负),表示圆心在画笔的左边(右边)画圆 37 "Draw circle from start to end." 38 up() # 画笔提起操作 39 goto(start.x,start.y) # 将画笔移动到起点坐标为(x,y)的位置 40 down() # 画笔放下操作 41 begin_fill() # 准备开始填充图形 42 fillcolor("pink") # 将填充颜色设置为粉色 43 radius = end.x - start.x # 圆的半径是第二次点击屏幕所在位置的横坐标减去第一次点击屏幕所在位置的横坐标 44 circle(radius) # radius为正,逆时针画一个半径为radius的圆;radius为负,顺时针画一个半径为radius的圆 45 end_fill() # 填充图形结束 46 # pass # TODO # 内容需要自己补充 47 48 def rectangle(start, end): # 画矩形 49 "Draw rectangle from start to end." 50 up() # 画笔提起操作 51 goto(start.x,start.y) # 将画笔移动到起点坐标为(x,y)的位置 52 down() # 画笔放下操作 53 begin_fill() # 准备开始填充图形 54 55 fillcolor("purple") # 将填充颜色设置为紫色 56 for count in range(2): # 循环2次,用于画矩形 57 forward(end.x-start.x) # 向当前画笔方向移动一段距离 58 left(90) # 调整画笔方向:逆时针移动90° 59 forward(end.y-start.y) # 向当前画笔方向移动一段距离 60 left(90) # 调整画笔方向:逆时针移动90° 61 62 end_fill() 63 # pass # TODO 64 65 def triangle(start, end): # 画三角形 66 "Draw triangle from start to end." 67 up() # 画笔提起操作 68 goto(start.x,start.y) # 将画笔移动到起点坐标为(x,y)的位置 69 down() # 画笔放下操作 70 begin_fill() # 准备开始填充图形 71 72 fillcolor("blue") # 将填充颜色设置为蓝色 73 for count in range(3): # 循环3次,用于画正三角形 74 forward(end.x-start.x) # 向当前画笔方向移动一段距离,该距离是第二次点击鼠标所在位置的横坐标减去第一次点击鼠标所在位置的横坐标 75 left(120) # 调整画笔方向:逆时针移动120° 76 77 end_fill() # 填充图形结束 78 #pass # TODO 79 80 def tap(x, y): # 用来存储鼠标的初始位置或者要画的图形 81 "Store starting point or draw shape." 82 start = state['start'] 83 84 if start is None: 85 state['start'] = vector(x, y) # 将字典中'start'初始化为一个向量 86 else: 87 shape = state['shape'] # 将字典中'shape'的值赋给shape变量 88 end = vector(x, y) # 定义画图结束位置的向量 89 shape(start, end) # 调用shape变量对应的函数绘制图形 90 state['start'] = None # 将start字典的'start'元素值重置为None 91 92 def store(key, value): # 用来接收键盘输入的数据 93 "Store value in state at key." 94 state[key] = value # 通过更改state列表的key的值来控制画笔的颜色和画出的图形 95 96 state = {'start': None, 'shape': rectangle}# 定义一个字典类型state变量用来告诉程序要绘制什么图形 97 setup(500, 500, 500,0) # 设置画布初始位置 98 onscreenclick(tap) # 绑定tap函数到鼠标点击屏幕事件,即鼠标点击一次屏幕调用一次tap函数 99 # 可能这句代码的意思是每次在画布上敲击鼠标,都调用一次tap函数; 100 # 第一次敲击鼠标调用tap函数后,将画笔的起点位置状态由None改变为一个向量vector(x, y) 101 # 第二次敲击鼠标调用tap函数后,在tap函数内部调用shape值对应的函数进行画图 102 103 listen() # 设置焦点到 TurtleScreen (以便接收按键事件) 104 onkey(undo, 'u') # 撤销上一个turtle动作 105 onkey(lambda: color('black'), 'K') # 在画图过程中,第一次点击鼠标后,输入大写字母'K'可将画笔的颜色设置为黑色 106 onkey(lambda: color('white'), 'W') # 在画图过程中,第一次点击鼠标后,输入大写字母'W'可将画笔的颜色设置为白色 107 onkey(lambda: color('green'), 'G') # 在画图过程中,第一次点击鼠标后,输入大写字母'G'可将画笔的颜色设置为绿色 108 onkey(lambda: color('blue'), 'B') # 在画图过程中,第一次点击鼠标后,输入大写字母'B'可将画笔的颜色设置为蓝色 109 onkey(lambda: color('red'), 'R') # 在画图过程中,第一次点击鼠标后,输入大写字母'R'可将画笔的颜色设置为红色 110 onkey(lambda: store('shape', line), 'l') # 在画图过程中,第一次点击鼠标后,输入小写字母'l'可将画出的图形设置为直线 111 onkey(lambda: store('shape', square), 's') # 在画图过程中,第一次点击鼠标后,输入小写字母's'可将画出的图形设置为正方形 112 onkey(lambda: store('shape', paint_circle), 'c') # 在画图过程中,第一次点击鼠标后,输入小写字母'c'可将画出的图形设置为圆 113 onkey(lambda: store('shape', rectangle), 'r') # 在画图过程中,第一次点击鼠标后,输入小写字母'r'可将画出的图形设置为矩形 114 onkey(lambda: store('shape', triangle), 't') # 在画图过程中,第一次点击鼠标后,输入小写字母't'可将画出的图形设置为三角形 115 116 done() # 必须是乌龟图形程序中的最后一个语句。
花了三天,大概5个小时左右吧,搞懂了代码,本来写了三个博客,发现有完整代码的那个博客没人看,所以把三个博客合在一起了。