zoukankan      html  css  js  c++  java
  • 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 悠望南山

  • 相关阅读:
    Unity使Text 文字逐个出现
    Mybatis入门
    sqoop工具介绍(hdfs与关系型数据库进行数据导入导出)
    MapReduce经典入门小案例
    hdfs的java接口简单示例
    Mac环境下安装配置Hadoop伪分布式
    【转】深入理解javascript原型和闭包(完结)
    javascript面向对象一:函数
    【转】sql语句的优化分析
    【转】java调用存储过程和函数
  • 原文地址:https://www.cnblogs.com/NanShan2016/p/5572086.html
Copyright © 2011-2022 走看看