用python画出小人发射爱心_用python代码turtle画一个坐地铁

运行效果:知乎视频​www.zhihu.com

代码:

import time, math

import turtle as t

class Human(object):

def __init__(self, x0, y0, x1=None, y1=None, v0=100, v1=100):

self.x0 = x0

self.y0 = y0

self.tx = x0

self.ty = y0

self.x1 = x0 if x1 is None else x1

self.y1 = y0 if y1 is None else y1

self.v0 = v0

self.v1 = v1

self.tv = v0

self.in_metro=False

self.need_get_on=True

self.should_remove=False

self.door_index=0

def move(self,back=False):

if self.need_get_on:

if back:

self.get_on_back()

else:

self.get_on()

else:

self.get_off()

def get_on(self):

if self.ty < -5:

self.ty+=3

elif self.ty < 0:

if self.tx

elif self.tx>self.x1:self.tx-=1

elif self.ty

self.ty+=2

elif self.ty

self.ty+=3

if self.ty>=self.y1:

self.in_metro=True

self.should_remove=True

def get_on_back(self):

if self.ty > self.y0:

self.ty-=1

else:

if self.tx > self.x0: self.tx-=1

elif self.tx

def get_off(self):

if self.ty>self.y1:

self.ty-=1

else:

self.in_metro=False

if self.tv>self.v1:

self.ty-=1

self.tv-=2

if self.tv<=self.v1:

self.should_remove=True

def draw(self):

if self.in_metro:

return

x=self.tx

y=self.ty

clr=(1-self.tv*0.01,1-self.tv*0.01,1-self.tv*0.01)

t.pencolor(clr)

goto_with_penup(x, y)

t.pensize(1)

t.begin_fill()

t.fillcolor(clr)

t.circle(4)

t.end_fill()

ty = 2

t.sety(y - ty)

t.goto(x - 6, y - ty - 2)

t.goto(x, y - ty)

t.goto(x + 6, y - ty - 2)

t.goto(x, y - ty)

ty = 6

t.sety(y - ty)

t.goto(x - 2, y - ty - 8)

t.goto(x, y - ty)

t.goto(x + 2, y - ty - 8)

t.goto(x, y - ty)

def fill_rect(w,h,c):

t.fillcolor(c)

t.begin_fill()

for i in range(2):

t.forward(w)

t.left(90)

t.forward(h)

t.left(90)

t.end_fill()

def draw_rect(w,h):

for i in range(2):

t.forward(w)

t.left(90)

t.forward(h)

t.left(90)

def setx_with_penup(tx):

t.penup()

t.setx(tx)

t.pendown()

def sety_with_penup(ty):

t.penup()

t.sety(ty)

t.pendown()

def goto_with_penup(tx,ty):

t.penup()

t.goto(tx,ty)

t.pendown()

size=60 # 车厢大小

block_num=7 # 车厢数量

human_num_str=[5,2,0,1,3,1,4] # 每节车厢的人数

# amount_human_num_str=[17,16,20,21,25,21,19] # 每节车厢的人数

amount_human_num_str=[26,25,24,24,25,24,25] # 每节车厢的人数

door_pos_arr=[0.3,1,1.7] # 一节车厢三扇门的位置

door_max_get_on_num=4

def draw_metro(x,size=40,door_open_ratio=0):

t.clear()

# t.fillcolor('white')

# t.begin_fill()

# goto_with_penup(-1000,200)

# t.goto(1000,200)

# t.goto(1000,-500)

# t.goto(-1000,-500)

# t.goto(-1000,200)

# t.end_fill()

t.pencolor('black')

t.pensize(1)

every_width=size*2

metro_h=size*0.6

goto_with_penup(x,0)

t.setx(x-every_width*0.2)

t.goto(x=x-every_width*0.1,y=metro_h)

t.setx(x)

goto_with_penup(x-every_width*0.1,metro_h*0.3)

draw_rect(metro_h*0.2,metro_h*0.4)

for a in range(0,block_num):

sety_with_penup(0)

setx_with_penup(x + a * every_width)

draw_rect(size*2,metro_h)

sety_with_penup(size*0.2)

window_w=size*0.3

window_h=size*0.25

for dx in [(door_pos_arr[0]+door_pos_arr[1])*0.5,(door_pos_arr[1]+door_pos_arr[2])*0.5]:

setx_with_penup(x + a * every_width + size*dx-window_w*0.5)

draw_rect(window_w,window_h)

sety_with_penup(0)

door_w=size*0.26

door_open_diff=0

if door_open_ratio>0:

r=door_open_ratio*0.01

door_open_diff=round(door_w*0.5*r)

for dx in door_pos_arr:

setx_with_penup(x + a * every_width + size*dx-door_w*0.5-door_open_diff)

if door_open_diff > 0: fill_rect(door_w*0.5,metro_h*0.8,'white')

draw_rect(door_w*0.5,metro_h*0.8)

setx_with_penup(x + a * every_width + size*dx+door_open_diff)

if door_open_diff > 0: fill_rect(door_w*0.5,metro_h*0.8,'white')

draw_rect(door_w*0.5,metro_h*0.8)

if door_open_diff > 0:

setx_with_penup(x + a * every_width + size*dx-door_open_diff)

fill_rect(door_open_diff*2,metro_h*0.8,'black')

sety_with_penup(size*0.25)

door_window_w=door_w*0.8

door_window_h=size*0.2

for dx in door_pos_arr:

setx_with_penup(x + a * every_width + size * dx - door_window_w * 0.5-door_open_diff)

draw_rect(door_window_w * 0.5, door_window_h)

setx_with_penup(x + a * every_width + size * dx+door_open_diff)

draw_rect(door_window_w * 0.5, door_window_h)

t.pensize(4)

for a in range(1,block_num):

sety_with_penup(0+1)

setx_with_penup(x + a*every_width+1)

t.sety(metro_h-1)

def make_human_pos(x,n,door_index,two_line=True):

arr=[]

if two_line:

for i in range(0,n,2):

human = Human(x-8,-20-20*(i//2),x1=x-4,y1=20)

human.door_index=door_index

arr.append(human)

for i in range(1,n,2):

human = Human(x+8,-20-20*(i//2),x1=x+4,y1=20)

human.door_index=door_index

arr.append(human)

else:

for i in range(0,n):

human = Human(x,-20-20*i,x1=x,y1=20)

human.door_index=door_index

arr.append(human)

return arr

def make_in_metro_human_pos(x, n,door_index):

arr=[]

for i in range(0, n):

human = Human(x, 20 * i, x1=x, y1=-10, v1=0)

human.door_index=door_index

human.in_metro=True

human.need_get_on=False

arr.append(human)

return arr

def any_get_off_human_in_door(human_arr, door_index):

for human in human_arr:

if human.door_index==door_index:

if not human.need_get_on and human.in_metro:

return True

return False

def check_no_got_on(all_human, door_got_on_num_dic):

for human in all_human:

if human.need_get_on and door_got_on_num_dic[human.door_index]>0:

return False

return True

def draw_all(all_human):

door_got_on_num_dic={}

for i in range(block_num):

door_got_on_num_dic[i*3]=door_max_get_on_num

door_got_on_num_dic[i*3+1]=door_max_get_on_num

door_got_on_num_dic[i*3+2]=door_max_get_on_num

t.screensize()

t.setup(width=1.0, height=1.0)

train_speed = 30

startx = 800

endx = -500

tempx = startx

while tempx > endx:

if tempx - endx < 500 and train_speed > 1:

if len(all_human)<20:

train_speed *= 0.9 if train_speed < 10 else 0.95

else:

train_speed *= 0.95 if train_speed > 10 else 0.98

tempx -= train_speed

if tempx < endx:

tempx = endx

t.tracer(False)

draw_metro(int(tempx), size=size)

for human in all_human: human.draw()

t.hideturtle()

t.tracer(True)

time.sleep(0)

for i in range(0, 100, 4):

t.tracer(False)

draw_metro(-500, size=size, door_open_ratio=i)

for human in all_human: human.draw()

t.hideturtle()

t.tracer(True)

time.sleep(0)

while True:

t.tracer(False)

draw_metro(int(tempx), size=size, door_open_ratio=100)

for human in all_human: human.draw()

t.hideturtle()

t.tracer(True)

time.sleep(0)

for i in range(len(all_human) - 1, -1, -1):

human = all_human[i]

if human.need_get_on:

if door_got_on_num_dic[human.door_index]>0:

if not any_get_off_human_in_door(all_human, human.door_index):

human.get_on()

if human.in_metro:

door_got_on_num_dic[human.door_index]-=1

else:

human.get_off()

if all_human[i].should_remove:

del all_human[i]

if len(all_human) == 0:

break

if check_no_got_on(all_human, door_got_on_num_dic):

for human in all_human:

if human.need_get_on:

human.y0+=20*(door_max_get_on_num//2)

break

for i in range(100, -4, -4):

t.tracer(False)

draw_metro(-500, size=size, door_open_ratio=i)

for human in all_human:

human.move(back=True)

human.draw()

t.hideturtle()

t.tracer(True)

time.sleep(0)

for x in range(len(all_human) - 1, -1, -1):

if all_human[x].should_remove:

del all_human[x]

endx = -2000

while tempx > endx:

train_speed = train_speed * 1.02

tempx -= train_speed

if tempx < endx:

tempx = endx

t.tracer(False)

draw_metro(int(tempx), size=size)

for human in all_human:

human.move(back=True)

human.draw()

t.hideturtle()

t.tracer(True)

time.sleep(0)

for x in range(len(all_human) - 1, -1, -1):

if all_human[x].should_remove:

del all_human[x]

def run(add_in_metro=None, amount_human=False):

endx = -500

num_str = amount_human_num_str if amount_human else human_num_str

all_human = []

for i in range(block_num):

n = 0 if i >= len(num_str) else int(num_str[i])

n1 = n // 3

n3 = int(math.ceil(n / 3))

n2 = n - n1 - n3

all_human += make_human_pos(endx + i * size * 2 + door_pos_arr[0] * size, n1, i * 3)

all_human += make_human_pos(endx + i * size * 2 + door_pos_arr[1] * size, n2, i * 3 + 1)

all_human += make_human_pos(endx + i * size * 2 + door_pos_arr[2] * size, n3, i * 3 + 2)

if add_in_metro:

n = 0 if i >= len(add_in_metro) else int(add_in_metro[i])

n1 = n // 3

n3 = int(math.ceil(n / 3))

n2 = n - n1 - n3

all_human += make_in_metro_human_pos(endx + i * size * 2 + door_pos_arr[0] * size, n1, i * 3)

all_human += make_in_metro_human_pos(endx + i * size * 2 + door_pos_arr[1] * size, n2, i * 3 + 1)

all_human += make_in_metro_human_pos(endx + i * size * 2 + door_pos_arr[2] * size, n3, i * 3 + 2)

while len(all_human)>0:

draw_all(all_human)

def draw_str(s):

t.screensize()

t.setup(width=1.0, height=1.0)

t.penup()

t.goto(-300,0)

t.pendown()

t.write(s, font=("Arial", 32,"bold"))

t.hideturtle()

if __name__ == '__main__':

draw_str('你希望上班坐地铁是这样的')

time.sleep(2)

run()

draw_str('再或者上班坐地铁是这样的')

time.sleep(2)

run(add_in_metro=[1,3,1,4,5,2,0])

draw_str('实际上上班坐地铁是这样的')

time.sleep(2)

run(amount_human=True,add_in_metro=[1,3,1,4,5,2,0])

draw_str('这段程序送给在外打拼的你')

time.sleep(2)

t.mainloop()

你可能感兴趣的:(用python画出小人发射爱心)