• IIPP迷你项目(三)“Stopwatch: The Game”


    0 本周项目说明

    这一次博客是Coursera的IIPP课程第三周迷你项目的实现,基础要求是做一个秒表,能start能stop能reset,更高的要求是在此秒表的基础上完成两个小游戏,但是鉴于第二个小游戏牵扯到“按下键盘的某一个键则frame会立即反应”,而这一步怎么实现课程还没讲,所以本次博客暂且先不实现这个小游戏,单纯实现靠button控制的秒表,以及第一个小游戏。

    1 canvas简介

    为了方便后续过程中我自己的查阅,我将canvas整理如下。本文内容除过参考Coursera的视频之外,还有simpleguics2pygame — canvas,但是个人感觉这个说明文档写得不够好,不如CodeSculptor中带的那个清晰,但是Google不是被墙了么无法方便地登入CodeSculptor,所以只能结合视频和这个文档来写程序了。

    Joe老师在视频中打开的CodeSculptor的canvas说明书界面如下,我感觉真是一目了然……

    简单来说就是canvas这个类所提供的成员函数能够完成以下功能:

    (1)写字(canvas.draw_text);

    (2)画直线(canvas.draw_line);

    (3)画折线(canvas.draw_polyline);

    (4)画闭合多边形(canvas.draw_polygon);

    (5)画圆(canvas.draw_circle);

    (6)载入外部图像(canvas.draw_image)。

    而具体每个成员函数里面填写什么样的参数,就得查阅 simpleguics2pygame — canvas 了,虽然这个文档怎么用这些函数说的不清不楚,但是查个参数还是可以的。

    这里我给出一段用于实验的代码,里面包含了上述canvas类中所有成员函数(除了canvas.draw_image),为了方便显示各成员函数的效果,我用不同颜色对这些形状予以绘制。

     1 import SimpleGUICS2Pygame.simpleguics2pygame as simplegui
     2 
     3 ### event handler ### 
     4 def draw(canvas):
     5     canvas.draw_text("Hello!",[100,100],24,"Red") # 文本
     6     canvas.draw_line([3,3],[20,40],3,"White") # 直线
     7     canvas.draw_polyline([(50,80),(60,10),(40,44)],3,"Green") # 折线
     8     canvas.draw_polygon([(80,80),(110,120),(120,160)],3,"Blue") # 闭合图形
     9     canvas.draw_circle([60,60],40,3,"Yellow") # 画圆
    10     
    11 ### create a frame ###
    12 frame = simplegui.create_frame("Stopwatch: the game",200,200) # 200*200为画布大小
    13 
    14 ### register event handlers ###
    15 frame.set_draw_handler(draw)
    16 
    17 ### start frame ###
    18 frame.start()

    其基本过程大致描述如下:在启动frame的一刻,画布也随之启动,于是与画布相挂钩的回调函数draw()将被调用。在draw()函数中设定画什么,在画布上也就相应显示什么。最终画布上的显示如下:

    至于canvas.draw_image,目测是后面的迷你项目会讲到的,这里我还暂时不知道怎么使用它载入图像,先放着不管。

    2 timers简介

    timer是本次小项目中关键环节之二,时间的变化正是由它产生的。

    具体的用法还是看Scott老师打开的CodeSculptor说明书吧:

    可以发现创建timer的时候需要给出两个参数,一个是时间间隔——也就是每隔多长时间调用一次回调函数timer_handler;另一个则是等待被调用的回调函数。

    同时,如果要使用timer,除过创建它之外还需要开启它,方法是在启动frame之前先启动timer,即timer.start()。这里有点像单片机里的定时计数器,需要开启定时器才能运作,否则定时器是不工作的,就像开关被关掉了一样。

    下面我给出在canva上不断更新当前秒数的代码:

     1 import SimpleGUICS2Pygame.simpleguics2pygame as simplegui
     2 
     3 ### global variable ###
     4 message = "0"
     5 interval = 1000
     6 
     7 ### event handler ### 
     8 def draw(canvas): # canva的回调函数
     9     canvas.draw_text( message,[100,100],24,"Red")
    10     
    11 def tick(): # timer的回调函数
    12     global message
    13     num = int(message)
    14     num += 1
    15     message = str(num)
    16     
    17 ### create a frame ###
    18 frame = simplegui.create_frame("Stopwatch: the game",200,200) # 200*200为画布大小
    19 
    20 ### register event handlers ###
    21 frame.set_draw_handler(draw)
    22 timer = simplegui.create_timer(interval,tick)
    23 
    24 ### start frame ###
    25 timer.start()
    26 frame.start()

    大概意思就是说每隔interval(1秒钟)时长,就会调用一次timer的回调函数tick。回调函数tick负责改变message的值,然后画布就可以利用其超快自我刷新机制自动更新了。

    到此为止一个秒表的雏形就打得差不多了,下面要做的工作就是进一步细化,以及加上“开始”“停止”以及“复位”按钮。

    3 普通秒表

    这一次的秒表只能实现“按start开启”“按stop暂停”以及“按reset复位”的功能,不添加游戏。

    其基本思想就是把A:BC.D中的A、B、C、D当成四个int变量来处理,然后再转成字符串进行拼接,拼接结果就是message。这点似乎和Joe老师提示的不同,不过我觉得这样比较省事。

    然后那三个按钮所对应的回调函数start、stop、reset各司其职,往里面填写功能就行了。

    代码如下:

     1 import SimpleGUICS2Pygame.simpleguics2pygame as simplegui
     2 
     3 ### global variable ###
     4 message = "0:00.0"
     5 interval = 100
     6 A = 0
     7 B = 0
     8 C = 0
     9 D = 0
    10 
    11 ### helper function ###
    12 def format():
    13     global A,B,C,D
    14     global message
    15     message = str(A) + ":" + str(B) + str(C)+ "." + str(D)
    16 
    17 ### event handler ### 
    18 def draw(canvas): # canva 的回调函数
    19     canvas.draw_text( message,[60,100],30,"White")
    20     
    21 def tick(): # timer 的回调函数
    22     global A,B,C,D
    23     if D < 9:
    24         D += 1
    25     else:
    26         D = 0
    27         if C < 9:
    28             C += 1
    29         else:
    30             C = 0
    31             if B < 5:
    32                 B += 1
    33             else:
    34                 B = 0
    35                 if A < 9:
    36                     A += 1
    37                 else:
    38                     A = 0
    39     format()
    40 
    41 def start():
    42     timer.start()
    43 
    44 def stop():
    45     timer.stop()
    46 
    47 def reset():
    48     global message
    49     timer.stop()
    50     message = "0:00.0"
    51         
    52 ### create a frame ###
    53 frame = simplegui.create_frame("Stopwatch: the game",200,200) # 200*200为画布大小
    54 
    55 ### register event handlers ###
    56 frame.set_draw_handler(draw)
    57 timer = simplegui.create_timer(interval,tick)
    58 frame.add_button("start", start, width=100)
    59 frame.add_button("stop", stop, width=100)
    60 frame.add_button("reset", reset, width=100)
    61 
    62 ### start frame ###
    63 frame.start()

    4 能玩stop游戏的秒表

    首先对于这个游戏进行一些必要说明:

    (1)这里的秒表是精确到秒的小数点后一位的,也就是D。D每个100毫秒增加1,游戏的规则就是如果说我们刚好在D=0的时候点下了stop键,则分数+1。鉴于此,在画图板右上角设定了红色的“stop/chance”,其中stop记录“成功在D=0时按下stop的次数”,而chance记录“不论成功失败,我总共点了多少次stop”。

    (2)同时还规定,在秒表停止(暂停或复位)的时候,再点stop是不进入累计的,因此根据这一点需要设定一个全局变量timer_on,如果定时器是开着的则为True,是关着的则为False,规定在timer_on变量为False的时候不论是stop还是chance都不进行累计。

    (3)每一次timer.start()之后,立刻把timer_on置为True,每一次timer.stop()之后,立刻把timer_on置为False。这就是为什么在stop按钮的回调函数中要先写“判断stop/chance”的代码,然后再timer.stop(),因为判断的时候务必得保证定时器是跑着的。

    该程序的代码如下所示:

     1 import SimpleGUICS2Pygame.simpleguics2pygame as simplegui
     2 
     3 ### global variable ###
     4 message = "0:00.0"
     5 game_chance = 0
     6 game_stop = 0
     7 timer_on = False
     8 interval = 100
     9 A = 0
    10 B = 0
    11 C = 0
    12 D = 0
    13 
    14 ### helper function ###
    15 def format():
    16     global A,B,C,D
    17     global message
    18     message = str(A) + ":" + str(B) + str(C)+ "." + str(D)
    19 
    20 ### event handler ### 
    21 def draw(canvas): # canva 的回调函数
    22     global game_stop,game_chance
    23     game = str(game_stop) + "/" + str(game_chance)
    24     canvas.draw_text( message, [60,100], 30, "White")
    25     canvas.draw_text( game, [150,30], 30, "Red")
    26     
    27 def tick(): # timer 的回调函数
    28     global A,B,C,D
    29     if D < 9:
    30         D += 1
    31     else:
    32         D = 0
    33         if C < 9:
    34             C += 1
    35         else:
    36             C = 0
    37             if B < 5:
    38                 B += 1
    39             else:
    40                 B = 0
    41                 if A < 9:
    42                     A += 1
    43                 else:
    44                     A = 0
    45     format()
    46 
    47 def start():
    48     global timer_on    
    49     timer.start()
    50     timer_on = True
    51 
    52 def stop():
    53     global timer_on
    54     global game_chance,game_stop
    55     global D
    56     if (timer_on == True):
    57         game_chance += 1
    58         if (D == 0):
    59             game_stop += 1
    60     timer.stop()
    61     timer_on = False
    62 
    63 def reset():
    64     global timer_on
    65     global game_chance,game_stop
    66     global message
    67     timer.stop()
    68     timer_on = False
    69     message = "0:00.0"
    70     game_chance = 0
    71     game_stop = 0
    72     
    73         
    74 ### create a frame ###
    75 frame = simplegui.create_frame("Stopwatch: the game",200,200) # 200*200为画布大小
    76 
    77 ### register event handlers ###
    78 frame.set_draw_handler(draw)
    79 timer = simplegui.create_timer(interval,tick)
    80 frame.add_button("start", start, width=100)
    81 frame.add_button("stop", stop, width=100)
    82 frame.add_button("reset", reset, width=100)
    83 
    84 ### start frame ###
    85 frame.start()

    最终的界面如下:

    这是五次里有两次成功点中整秒数(即D=0)时所得的结果。

    2016.6.9

    by 悠望南山

  • 相关阅读:
    图像检索(image retrieval)- 11
    图像检索(image retrieval)- 10相关
    Mock.js简易教程,脱离后端独立开发,实现增删改查功能
    Azure Monitor (3) 对虚拟机磁盘设置自定义监控
    Azure Monitor (1) 概述
    Azure SQL Managed Instance (2) 备份SQL MI
    Azure Virtual Network (17) Private Link演示
    Azure Virtual Network (16) Private Link
    Azure Virtual Network (15) Service Endpoint演示
    Azure Virtual Network (14) Service Endpoint服务终结点
  • 原文地址:https://www.cnblogs.com/NanShan2016/p/5572086.html
Copyright © 2020-2023  润新知