Advertisement
Fenny_Theo

CSC1002_4

Apr 22nd, 2020
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.00 KB | None | 0 0
  1. import turtle
  2. import time
  3. import random
  4. import math
  5.  
  6. def penInit(obj,x,y):
  7. #obj = turtle.Turtle() # 初始化
  8. obj.hideturtle() # 海龟隐藏
  9. obj.penup() # 笔全程拿起(依赖 stamp)
  10. obj.setpos(x,y) # 设置初始位置
  11. obj.speed(10) # 移动速度:最快,因为不依赖移动来刷新
  12. obj.resizemode("user") # 用户自定义,为了设置形状
  13. obj.shape("square") # 设置形状
  14. obj.shapesize(1, 1, 1) # 大小 20*20,有 1 像素的边界
  15.  
  16. def penMove(obj,dir):
  17. obj.right(obj.heading() - dir) # 转向
  18. obj.forward(20) # 向前
  19. astamp = obj.stamp() # 获取 stamp
  20. obj.left(0) # 规避 bug
  21. return astamp
  22.  
  23. direction = 0
  24. vec = list() # 存储 body stamp 的 list
  25. gesture = 0 # 存储 head 的上一个动作,初始为右
  26. eating = 0 # 记录是否在 eat,也作为计数器
  27. eatwait = 0 # eat 前的计数器
  28. headStamp = 0
  29.  
  30. def snakeMove(head,body):
  31. global direction
  32. global vec
  33. global gesture
  34. global eating
  35. global eatwait
  36. global headStamp
  37. directionGet = direction
  38. if ((directionGet == 90) and (head.ycor() > 221)): return 0
  39. if ((directionGet == 270) and (head.ycor() < -221)): return 0
  40. if ((directionGet == 180) and (head.xcor() < -221)): return 0
  41. if ((directionGet == 0) and (head.xcor() > 221)): return 0
  42. tempstamp1 = penMove(head,directionGet)
  43. tempstamp2 = penMove(body,gesture)
  44.  
  45. vec.append(tempstamp2) # 将新的 stamp 加入list
  46. if (eating > 0): # 已经碰到了食物
  47. if (eatwait > 0): # 计数器:尾巴离食物还有多少格
  48. body.clearstamp(vec.pop(0)) # 擦除尾部的 stamp
  49. eatwait -= 1
  50. else:
  51. eating -=1 # eat 的计数器。由于没有删除 stamp,蛇的长度增加了
  52. else:
  53. body.clearstamp(vec.pop(0)) # 将最旧的 stamp 移除
  54.  
  55. head.clearstamp(headStamp) # 删除旧的 head stamp
  56. headStamp = tempstamp1 # 更新 head stamp
  57. gesture = directionGet
  58.  
  59. def setRight():
  60. global direction
  61. if (direction != 180):
  62. direction = 0
  63.  
  64. def setLeft():
  65. global direction
  66. if (direction != 0):
  67. direction = 180
  68.  
  69. def setUp():
  70. global direction
  71. if (direction != 270):
  72. direction = 90
  73.  
  74. def setDown():
  75. global direction
  76. if (direction != 90):
  77. direction = 270
  78.  
  79. pausing = True # 是否暂停
  80. gameready = False # 初始化是否完成
  81.  
  82. def pauseChange(): # 空格切换暂停/继续
  83. global pausing
  84. pausing = not pausing
  85. return 0
  86.  
  87. def gameBegin(x,y): # onclick 绑定的函数
  88. global pausing
  89. global turtle
  90. global gameready
  91. if (gameready):
  92. pausing = False
  93. turtle.onclick(None)
  94.  
  95. if __name__ == "__main__":
  96.  
  97. turtle.setup(500, 500, 0, 0)
  98. turtle.title(" Snake by Kinley Lam")
  99.  
  100. # 这里的设置是为了实现点击屏幕开始游戏
  101. turtle.penup() # 笔拿起(依赖 stamp)
  102. #screenDetect.setpos(0,0) # 设置初始位置
  103. turtle.resizemode("user") # 用户自定义,为了设置形状
  104. turtle.shape("square") # 设置形状
  105. turtle.shapesize(25, 25, 1) # 大小 20*20,有 1 像素的边界
  106. turtle.color("white") # 海龟颜色
  107. turtle.onclick(gameBegin) # 绑定鼠标
  108.  
  109. words = turtle.Turtle() # 一堆说明
  110. penInit(words,-220,100)
  111. words.color("black") # 字体颜色
  112. words.write("Welcome to Kinley's version of snake...\nYou are going to use the 4 arrow keys to move the snake\naround the screen, trying to consume all the food items \nbefore the monster catches you...\n\nClick anywhere on the screen to start the game,have fun!!",False,'left',font=('Arial',12,'bold'))#字体大小调下(font=(字体名称,大小,类型))
  113.  
  114. head = turtle.Turtle()
  115. penInit(head,-20,0)
  116. head.setheading(0)
  117. head.color("red") # head 全红色
  118. headStamp = penMove(head,0)
  119.  
  120. pausePen = turtle.Turtle()
  121. penInit(pausePen,300,0)
  122.  
  123. monster = turtle.Turtle()
  124. penInit(monster,-150,-150)
  125. monster.color("purple") # 颜色紫色
  126. monsterStampStore = monster.stamp() # 存储 stamp
  127. monster.left(0)
  128. monsterStampTemp = monsterStampStore
  129.  
  130. eating = False # 是否在 eat
  131. caught = False # 是否被怪追上
  132.  
  133. # 双 timer 异步进行对于 python 单线程来说是极端现实的,唯一可行的实现方式是,使用同一个 timer,
  134. # timer 给得细一些,然后让各个 object 在不同的时间动作
  135. snakeTime = 0 # 用于 snake 的计数器
  136. snakeLevel = 80 # 计数器的 bound
  137. monsterTime = 0 # 用于 monster 的计数器
  138. monsterLevel = 20 # 用于 monster 的 bound
  139.  
  140. gameready = True # 前面的基础准备完成
  141.  
  142. while (True): # 等待单击后游戏开始,这么写是为了绕过 bug 实现暂停功能
  143. if (pausing):
  144. penMove(pausePen,0)
  145. #print("waiting")
  146. else:
  147. break
  148. turtle.title(" Snake") # 窗口标题
  149. fakeHead = head.stamp()
  150. fakeMonster = monster.stamp()
  151. words.clear() # 删掉开场说明
  152.  
  153. body = turtle.Turtle()
  154. penInit(body,-100,0)
  155. body.setheading(0)
  156. body.color("black") # body 黑色
  157. body.pencolor("blue") # body 蓝色边框
  158.  
  159. for i in range(4):
  160. astamp = penMove(body,0) # 右移同时盖章
  161. vec.append(astamp)
  162.  
  163. turtle.onkey(pauseChange, "space")
  164. turtle.onkey(setUp, "Up") # 按键响应
  165. turtle.onkey(setDown, "Down")
  166. turtle.onkey(setLeft, "Left")
  167. turtle.onkey(setRight, "Right")
  168. turtle.onkeypress(setUp, "Up")
  169. turtle.onkeypress(setDown, "Down")
  170. turtle.onkeypress(setLeft, "Left")
  171. turtle.onkeypress(setRight, "Right")
  172. turtle.listen()
  173.  
  174. foods = list() # 存放所有 food turtle 的 list
  175. food1 = turtle.Turtle() # 建立所有的 food turtle
  176. food2 = turtle.Turtle()
  177. food3 = turtle.Turtle()
  178. food4 = turtle.Turtle()
  179. food5 = turtle.Turtle()
  180. food6 = turtle.Turtle()
  181. food7 = turtle.Turtle()
  182. food8 = turtle.Turtle()
  183. food9 = turtle.Turtle()
  184. foods.append(food1) # 放入 food list
  185. foods.append(food2)
  186. foods.append(food3)
  187. foods.append(food4)
  188. foods.append(food5)
  189. foods.append(food6)
  190. foods.append(food7)
  191. foods.append(food8)
  192. foods.append(food9)
  193.  
  194. foodx = [100,80,-60,-120,20,40,-80,-180,0] # food 的 x,y 坐标
  195. foody = [140,-160,-200,20,160,-120,-140,0,100]
  196. foodExist = [0,1,2,3,4,5,6,7,8] # 有哪些食物还被剩下,编号也可用于其他 list 的定位,一举两得
  197.  
  198. for i in range(9):
  199. penInit(foods[i],foodx[i]+2,foody[i]-10)
  200. foods[i].write(i+1, False, align="center",font=("Arial", 12, "normal")) # 标注食物编号
  201.  
  202. # 各种时间戳
  203. timeBegin = time.time() # 开始时间
  204. timePaused = 0.0 # 累计暂停时间
  205. pauseCut1 = 0.0 # 用于暂停时间计算
  206. pauseCut2 = 0.0
  207. timeNow = 0.0 # 现在的时间
  208. head.clearstamp(fakeHead)
  209. monster.clearstamp(fakeMonster)
  210. while (True):
  211. if (pausing): # 绕开 bug 实现暂停
  212. penMove(pausePen,0)
  213. #print("waiting")
  214. if (pauseCut1 == 0.0): # 计算暂停时间
  215. pauseCut1 = timeNow
  216. else:
  217. pauseCut1 = pauseCut2
  218. pauseCut2 = time.time()
  219. timePaused = pauseCut2 - pauseCut1 # 累加
  220. else:
  221. snakeTime += 1 # 蛇的计数器
  222. if (eating == 0):
  223. snakeLevel = 80
  224. else:
  225. snakeLevel = 120 # 在吃,则加高 bound,拖慢蛇的速度
  226. if (snakeTime == snakeLevel): # count 到 snake 该走了
  227. snakeTime = 0
  228. snakeMove(head,body)
  229. for i in foodExist:
  230. if ((foodx[i] - head.xcor() < 1)and(foodx[i] - head.xcor() > -1)and(foody[i] - head.ycor() < 1)and(foody[i] - head.ycor() > -1)):
  231. foods[i].clear() # check 一下有没有食物被吃掉
  232. foodExist.remove(i)
  233. if (eatwait == 0):
  234. eatwait = len(vec)
  235. eating += i+1
  236. monsterTime += 1 # 怪的计数器
  237. if (monsterTime == monsterLevel): # 怪该走了
  238. # monster 的 speed 是 2
  239. temp1 = 1/math.sqrt((monster.xcor() - head.xcor())*(monster.xcor() - head.xcor()) + (monster.ycor() - head.ycor())*(monster.ycor() - head.ycor()))
  240. temp2 = random.random() + 1
  241. if (monster.xcor() != head.xcor()):
  242. monster.setx(monster.xcor() + (head.xcor() - monster.xcor())*temp1*temp2) # 新坐标
  243. if (monster.ycor() != head.ycor()):
  244. monster.sety(monster.ycor() + (head.ycor() - monster.ycor())*temp1*temp2)
  245. monsterStampTemp = monster.stamp() # 新 stamp
  246. monster.left(0)
  247. monster.clearstamp(monsterStampStore) # 擦除旧的 stamp
  248. monsterStampStore = monsterStampTemp
  249. monsterTime = 0 # 怪的计数器清零
  250. if ((monster.xcor() - head.xcor() < 20.0)and(monster.xcor() - head.xcor() > -20.0)and(monster.ycor() - head.ycor() < 20.0)and(monster.ycor() - head.ycor() > -20)):
  251. caught = True # 检测有没有捉到 head
  252. break # 游戏结束,输了
  253. if (len(foodExist) == 0): break # 食物被吃光了,赢了
  254. time.sleep(0.001) # loop delay
  255. timeNow = time.time()
  256. pauseCut1 = 0.0 # 为了让 pause 时间统计辨认是否需要累加
  257. turtle.title(" Snake: Contacted: %d Time: %d"%((9-len(foodExist)),timeNow - timeBegin - timePaused))
  258.  
  259. head.color("yellow") # head 橙色
  260. if (caught): # 判断输赢
  261. head.write("Lose", False,font=("Arial", 24, "bold"))
  262. else:
  263. head.write("Win", False,font=("Arial", 24, "bold"))
  264.  
  265. turtle.exitonclick() # 单击鼠标退出
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement