Fate

pygame实现贪吃蛇和2048

Markdown

很久没有更新博客啦,今天端午节放假,正好有时间更新下博客,把前两个星期完成的软工作业写成一篇博客好了(大雾).

pygame

  • pygame 网上有一篇非常完整教程,大家有兴趣的可以去学习一个,做一点2D游戏也是很有趣的.

  • 为了完成软工作业,我和同学一人做了两个pygame的小游戏,他做了Flappy Brids俄罗斯方块,我做了2048贪吃蛇.所以在这里我只介绍我自己写的两个游戏.另外两个游戏,可以去这个博客,不知道会不会更新..

  • github地址,大家如果觉得好的话,希望能够点个star呀.

贪吃蛇

  • 这是一款非常老的游戏了,我选这个的原因是因为刚刚接触pygame,所以做一个容易一点的游戏,后来做完2048之后想做一个连连看的,懒癌发作就没写了.

  • 游戏界面
    Markdown

  • 游戏的主循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    def runGame():
    #游戏主循环
    startx = random.randint(5, CELLWIDTH - 6)
    starty = random.randint(5,CELLHEIGHT - 6)
    #最开始蛇长度为 3
    snake = [
    {'x':startx,'y': starty},
    {'x': startx - 1, 'y': starty},
    {'x': startx - 2, 'y': starty}
    ]
    #最开始的方向
    direction = RIGHT
    #生成苹果位置
    apple = appleLocation()
    #循环一次的时间
    TIME = 0.1
    #蛇的长度作为一个标志,如果这个标志变化了,那么TIME也就变化,控制游戏难度
    laststate = len(snake)
    while True:
    SCREEN.blit(BACKGROUND_PICTURE,(0,0))
    #draw_grid()
    #蛇死亡后返回
    if snakeDie(snake):
    return
    lastdirection = direction #记录前一个方向,防止出现BUG
    #事件循环
    for event in pygame.event.get():
    if event.type==QUIT:
    exit()
    elif event.type == KEYDOWN:
    key = event.key
    if lastdirection != RIGHT:
    if (key ==K_a or key==K_LEFT) and direction!=RIGHT: #往左
    direction = LEFT
    if lastdirection != LEFT:
    if (key ==K_d or key==K_RIGHT) and direction!=LEFT: #往右
    direction = RIGHT
    if lastdirection != DOWN:
    if (key ==K_a or key==K_UP) and direction!=DOWN: #往上
    direction = UP
    if lastdirection != UP:
    if (key ==K_s or key==K_DOWN) and direction!=UP: #往下
    direction = DOWN
    if key==K_ESCAPE:
    exit()
    #吃到了苹果,生成新苹果,否则,删除蛇的尾巴
    if snake[HEAD]['x']== apple['x'] and snake[HEAD]['y'] == apple['y']:
    apple = appleLocation()
    else:
    del snake[-1] #删除掉蛇的尾巴
    #新的头
    new_head = {'x':snake[HEAD]['x']+direction[0],'y':snake[HEAD]['y']+direction[1]}
    snake.insert(0,new_head)
    #绘制蛇,苹果,分数
    draw_snake(snake)
    draw_apple(apple)
    draw_score(10*(len(snake)-3))
    #绘制鼠标
    (x,y) = pygame.mouse.get_pos()
    SCREEN.blit(MOUSEIMAGE,(x-MOUSEIMAGE.get_width()/2,y-MOUSEIMAGE.get_height()/2))
    #刷新屏幕
    pygame.display.update()
    FPSCLOCK.tick(FPS)
    #蛇的当前长度为蛇的当前状态
    nowstate = len(snake)
    #状态变化
    if laststate!=nowstate:
    TIME-=0.005
    laststate = nowstate
    #确保循环时间合理性
    if TIME<0: TIME = 0
    time.sleep(TIME)
  • 注释都已经写得清楚了,解释一下为啥要设置一个lastdirection:在玩的过程中,发现在快速按键的情况下蛇会莫名死亡,后来发现是由于前一步的设置了游戏难度,每次都等待了0.1s,当在这0.1s的等待时间内,如果触发了多个事件,就有可能出BUG,比如我这次的方向是向RIGHT,在等待的0.1s内进来了两个时间UP,LEFT,等到下一次进入事件循环时,我们的当前状态就会从RIGHT变成UP,然后又变成了LEFT,于是蛇的方向就相反了;解决方案是设置一个lastdirection状态,每次都需判断这次的方向不能与lastdirection方向相反.

2048

  • 这个游戏其实我大二的时候就用JAVA实现过了,现在又用pygame写一遍,逻辑是差不多.高三的时候一直觉得这个游戏很好玩的.

  • 主页面

Markdown

  • 这个游戏主要是弄清方块怎么移动的,就很容易实现了.每次移动的过程中,运算时通过三重循环迭代进行实现的,比如UP的操作,引发的事件就是:

    1
    2
    3
    For y: 1->3
    For x: 0->3
    For y1: y->0
  • 每一行都受其下面所有行的影响,而这一行又会影响其上面的每一行,所以通过三重循环模拟递推过程,可以实现移动操作。

  • 移动的实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    def moveKey(e):
    '''
    判定键盘事件
    '''
    global SCORE,TIMES #引用全局变量,如果要修改全局变量的值必须这么弄,不然SCORE会被认为是局部变量
    flag = False #标志整个图是否发生了变化,如果发生了变化就调用 create()
    # 触发了向上的操作
    if e.key == K_UP or e.key == K_w:
    for y in range(1,SIZE):
    for x in range(0,SIZE):
    if array[x][y] == 0: continue
    dispos = -1 # 标记位置 ,如果这个dispos一直为-1 ,那么证明y以上的所有位置都不会被y代替的位置,否则y1的位置将被y位置的元素代替
    for y1 in range(y-1,-1,-1):
    if array[x][y1]!=0:
    if array[x][y] == array[x][y1]:
    flag = True
    dispos = -1
    SCORE += 2*array[x][y1]
    array[x][y1]*=2
    array[x][y] = 0
    TIMES+=1 #空位增加了
    break #直接退出循环,该层已经不可能再往上走了
    else:
    dispos = y1
    #不为-1的情况
    if dispos is not -1:
    flag = True
    array[x][dispos] = array[x][y]
    array[x][y] = 0
    #触发了向下的操作
    if e.key == K_DOWN or e.key == K_s:
    for y in range(SIZE-1,-1,-1):
    for x in range(0,4):
    if array[x][y] == 0: continue
    dispos = -1
    for y1 in range(y+1,SIZE):
    if array[x][y1]!=0:
    if array[x][y] == array[x][y1]:
    flag = True
    dispos = -1
    SCORE += 2*array[x][y1]
    array[x][y1]*=2
    array[x][y] = 0
    TIMES+=1 #空位增加了
    break #直接退出循环,该层已经不可能再往上走了
    else:
    dispos = y1
    if dispos is not -1:
    flag = True
    array[x][dispos] = array[x][y]
    array[x][y] = 0
    #触发了向左的操作
    if e.key == K_a or e.key == K_LEFT:
    for y in range(0,SIZE):
    for x in range(1,SIZE):
    if array[x][y] == 0:continue
    dispos = -1
    for x1 in range(x-1,-1,-1):
    if array[x1][y] !=0:
    if array[x1][y]== array[x][y]:
    flag = True
    dispos = -1
    SCORE += 2*array[x1][y]
    array[x1][y]*=2
    array[x][y] = 0
    TIMES+=1
    break
    else:
    dispos = x1
    if dispos is not -1:
    flag = True
    array[dispos][y] = array[x][y]
    array[x][y] = 0
    #触发了向右的操作
    if e.key == K_d or e.key == K_RIGHT:
    for y in range(0,SIZE):
    for x in range(SIZE-1,-1,-1):
    if array[x][y] == 0:continue
    dispos = -1
    for x1 in range(x+1,SIZE):
    if array[x1][y] !=0:
    if array[x1][y]== array[x][y]:
    flag = True
    dispos = -1
    SCORE += 2*array[x1][y]
    array[x1][y]*=2
    array[x][y] = 0
    TIMES+=1
    break
    else:
    dispos = x1
    if dispos is not -1:
    flag = True
    array[dispos][y] = array[x][y]
    array[x][y] = 0
    if flag:
    #创造新数字方块
    create()
  • 每次调用create函数生成4(0.25的概率)或者2(0.75的概率)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def create():
    '''
    在空方块处产生新的数字
    '''
    flag = False # 直到某个空位置产生一个新的数 flag 才变成 0
    if TIMES>0:
    while not flag:
    x = random.randint(0,3)
    y = random.randint(0,3)
    #print x,y
    if array[x][y] == 0:
    if random.randint(0,3) == 0: #1/4的几率生成 4
    array[x][y] = 4
    else:
    array[x][y] = 2
    flag = True

后记

  • 估计更新完这一篇又要拖更了,珍惜每一次假期和学习的机会呀,大学多学点东西,工作起来可能更加没时间学东西了
  • 本游戏的github地址

热评文章