【Python教程】用python制作一个让人戒不掉的百变款消消乐小游戏

所需工具:

Python

聪明的大脑

勤劳的双手

 

注意:本站只提供教程,不提供任何成品+工具+软件链接,仅限用于学习和研究。

 

导语

每日游戏更新系列——今天带大家解锁消消乐小游戏!

一天深夜,我像往常一样快乐地遨游在互联网的海洋里,猝不及防地接到了一个电话。

屏幕上一个触目惊心的大字:妈。​

我一边动作迟缓地按下通话键,一边迅速反省是不是刚才发朋友圈忘记屏蔽,被她发现我又在熬夜了。

电话那头果然传来了她火急火燎的声音,但我猜中了开头,却猜不到这结局。

我妈说:“还没睡觉吧,给我解锁一下消消乐的新关卡。”

%title插图%num

我还在判断她的操作是有意试探还是虚晃一枪时,她已经开始着急了:“快点,就差最后一个人了,我在等着你啊!”

对于不想睡觉的人来说,每个辗转难眠的夜晚都是相似的,但同样清醒如鸡的我和我妈却有着各自不同的快乐源泉!

正文

其实消消乐的话主题的素材可以随意一点儿, 可以是月饼中秋版本的,动漫版本的等等等…….万物皆可。

这边准备了2组消消乐的主题:1.表情包消消乐;2.十二生肖。

%title插图%num

%title插图%num

设置拼图游戏精灵类:

  1. class gemSprite(pygame.sprite.Sprite):
  2. def __init__(self, img_path, size, position, downlen, **kwargs):
  3. pygame.sprite.Sprite.__init__(self)
  4. self.image = pygame.image.load(img_path)
  5. self.image = pygame.transform.smoothscale(self.image, size)
  6. self.rect = self.image.get_rect()
  7. self.rect.left, self.rect.top = position
  8. self.downlen = downlen
  9. self.target_x = position[0]
  10. self.target_y = position[1] + downlen
  11. self.type = img_path.split(‘/’)[-1].split(‘.’)[0]
  12. self.fixed = False
  13. self.speed_x = 10
  14. self.speed_y = 10
  15. self.direction = ‘down’

拼图上下左右移动:

  1. def move(self):
  2. if self.direction == ‘down’:
  3. self.rect.top = min(self.target_y, self.rect.top+self.speed_y)
  4. if self.target_y == self.rect.top:
  5. self.fixed = True
  6. elif self.direction == ‘up’:
  7. self.rect.top = max(self.target_y, self.rect.top-self.speed_y)
  8. if self.target_y == self.rect.top:
  9. self.fixed = True
  10. elif self.direction == ‘left’:
  11. self.rect.left = max(self.target_x, self.rect.left-self.speed_x)
  12. if self.target_x == self.rect.left:
  13. self.fixed = True
  14. elif self.direction == ‘right’:
  15. self.rect.left = min(self.target_x, self.rect.left+self.speed_x)
  16. if self.target_x == self.rect.left:
  17. self.fixed = True

定义游戏类开始游戏主循环:用python实现一个让人戒不掉的百变款消消乐

  1. class gemGame():
  2. def __init__(self, screen, sounds, font, gem_imgs, cfg, **kwargs):
  3. self.info = ‘Gemgem’
  4. self.screen = screen
  5. self.sounds = sounds
  6. self.font = font
  7. self.gem_imgs = gem_imgs
  8. self.cfg = cfg
  9. self.reset()
  10. def start(self):
  11. clock = pygame.time.Clock()
  12. # 遍历整个游戏界面更新位置
  13. overall_moving = True
  14. # 指定某些对象个体更新位置
  15. individual_moving = False
  16. # 定义一些必要的变量
  17. gem_selected_xy = None
  18. gem_selected_xy2 = None
  19. swap_again = False
  20. add_score = 0
  21. add_score_showtimes = 10
  22. time_pre = int(time.time())
  23. while True:
  24. for event in pygame.event.get():
  25. if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE):
  26. pygame.quit()
  27. sys.exit()
  28. elif event.type == pygame.MOUSEBUTTONUP:
  29. if (not overall_moving) and (not individual_moving) and (not add_score):
  30. position = pygame.mouse.get_pos()
  31. if gem_selected_xy is None:
  32. gem_selected_xy = self.checkSelected(position)
  33. else:
  34. gem_selected_xy2 = self.checkSelected(position)
  35. if gem_selected_xy2:
  36. if self.swapGem(gem_selected_xy, gem_selected_xy2):
  37. individual_moving = True
  38. swap_again = False
  39. else:
  40. gem_selected_xy = None
  41. if overall_moving:
  42. overall_moving = not self.dropGems(0, 0)
  43. # 移动一次可能可以拼出多个3连块
  44. if not overall_moving:
  45. res_match = self.isMatch()
  46. add_score = self.removeMatched(res_match)
  47. if add_score > 0:
  48. overall_moving = True
  49. if individual_moving:
  50. gem1 = self.getGemByPos(*gem_selected_xy)
  51. gem2 = self.getGemByPos(*gem_selected_xy2)
  52. gem1.move()
  53. gem2.move()
  54. if gem1.fixed and gem2.fixed:
  55. res_match = self.isMatch()
  56. if res_match[0] == 0 and not swap_again:
  57. swap_again = True
  58. self.swapGem(gem_selected_xy, gem_selected_xy2)
  59. self.sounds[‘mismatch’].play()
  60. else:
  61. add_score = self.removeMatched(res_match)
  62. overall_moving = True
  63. individual_moving = False
  64. gem_selected_xy = None
  65. gem_selected_xy2 = None
  66. self.screen.fill((135, 206, 235))
  67. self.drawGrids()
  68. self.gems_group.draw(self.screen)
  69. if gem_selected_xy:
  70. self.drawBlock(self.getGemByPos(*gem_selected_xy).rect)
  71. if add_score:
  72. if add_score_showtimes == 10:
  73. random.choice(self.sounds[‘match’]).play()
  74. self.drawAddScore(add_score)
  75. add_score_showtimes -= 1
  76. if add_score_showtimes < 1:
  77. add_score_showtimes = 10
  78. add_score = 0
  79. self.remaining_time -= (int(time.time()) – time_pre)
  80. time_pre = int(time.time())
  81. self.showRemainingTime()
  82. self.drawScore()
  83. if self.remaining_time <= 0:
  84. return self.score
  85. pygame.display.update()
  86. clock.tick(self.cfg.FPS)

既然是游戏拿肯定是有加分设置的、玩游戏要设置一个时间限制更有趣。

  1. def showRemainingTime(self):
  2. remaining_time_render = self.font.render(‘CountDown: %ss’ % str(self.remaining_time), 1, (85, 65, 0))
  3. rect = remaining_time_render.get_rect()
  4. rect.left, rect.top = (self.cfg.SCREENSIZE[0]-201, 6)
  5. self.screen.blit(remaining_time_render, rect)
  6. def drawScore(self):
  7. score_render = self.font.render(‘SCORE:’+str(self.score), 1, (85, 65, 0))
  8. rect = score_render.get_rect()
  9. rect.left, rect.top = (10, 6)
  10. self.screen.blit(score_render, rect)
  11. def drawAddScore(self, add_score):
  12. score_render = self.font.render(‘+’+str(add_score), 1, (255, 100, 100))
  13. rect = score_render.get_rect()
  14. rect.left, rect.top = (250, 250)
  15. self.screen.blit(score_render, rect)

三个图片相同即可消除:

  1. def removeMatched(self, res_match):
  2. if res_match[0] > 0:
  3. self.generateNewGems(res_match)
  4. self.score += self.reward
  5. return self.reward
  6. return 0

定义下来的图片特效:

  1. def dropGems(self, x, y):
  2. if not self.getGemByPos(x, y).fixed:
  3. self.getGemByPos(x, y).move()
  4. if x < self.cfg.NUMGRID – 1:
  5. x += 1
  6. return self.dropGems(x, y)
  7. elif y < self.cfg.NUMGRID – 1:
  8. x = 0
  9. y += 1
  10. return self.dropGems(x, y)
  11. else:
  12. return self.isFull()

拼图的位置交换:

  1. def swapGem(self, gem1_pos, gem2_pos):
  2. margin = gem1_pos[0] – gem2_pos[0] + gem1_pos[1] – gem2_pos[1]
  3. if abs(margin) != 1:
  4. return False
  5. gem1 = self.getGemByPos(*gem1_pos)
  6. gem2 = self.getGemByPos(*gem2_pos)
  7. if gem1_pos[0] – gem2_pos[0] == 1:
  8. gem1.direction = ‘left’
  9. gem2.direction = ‘right’
  10. elif gem1_pos[0] – gem2_pos[0] == -1:
  11. gem2.direction = ‘left’
  12. gem1.direction = ‘right’
  13. elif gem1_pos[1] – gem2_pos[1] == 1:
  14. gem1.direction = ‘up’
  15. gem2.direction = ‘down’
  16. elif gem1_pos[1] – gem2_pos[1] == -1:
  17. gem2.direction = ‘up’
  18. gem1.direction = ‘down’
  19. gem1.target_x = gem2.rect.left
  20. gem1.target_y = gem2.rect.top
  21. gem1.fixed = False
  22. gem2.target_x = gem1.rect.left
  23. gem2.target_y = gem1.rect.top
  24. gem2.fixed = False
  25. self.all_gems[gem2_pos[0]][gem2_pos[1]] = gem1
  26. self.all_gems[gem1_pos[0]][gem1_pos[1]] = gem2
  27. return True

​​​附游戏主程序界面:

  1. import os
  2. import sys
  3. import cfg
  4. import pygame
  5. from modules import *
  6. def main():
  7. pygame.init()
  8. screen = pygame.display.set_mode(cfg.SCREENSIZE)
  9. pygame.display.set_caption(‘消消乐小游戏’)
  10. # 加载背景音乐
  11. pygame.mixer.init()
  12. pygame.mixer.music.load(os.path.join(cfg.ROOTDIR, “resources/audios/bg.mp3”))
  13. pygame.mixer.music.set_volume(0.6)
  14. pygame.mixer.music.play(-1)
  15. # 加载音效
  16. sounds = {}
  17. sounds[‘mismatch’] = pygame.mixer.Sound(os.path.join(cfg.ROOTDIR, ‘resources/audios/badswap.wav’))
  18. sounds[‘match’] = []
  19. for i in range(6):
  20. sounds[‘match’].append(pygame.mixer.Sound(os.path.join(cfg.ROOTDIR, ‘resources/audios/match%s.wav’ % i)))
  21. # 加载字体
  22. font = pygame.font.Font(os.path.join(cfg.ROOTDIR, ‘resources/font/font.TTF’), 25)
  23. # 图片加载
  24. gem_imgs = []
  25. for i in range(1, 8):
  26. gem_imgs.append(os.path.join(cfg.ROOTDIR, ‘resources/images/gem%s.png’ % i))
  27. # 主循环
  28. game = gemGame(screen, sounds, font, gem_imgs, cfg)
  29. while True:
  30. score = game.start()
  31. flag = False
  32. # 一轮游戏结束后玩家选择重玩或者退出
  33. while True:
  34. for event in pygame.event.get():
  35. if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE):
  36. pygame.quit()
  37. sys.exit()
  38. elif event.type == pygame.KEYUP and event.key == pygame.K_r:
  39. flag = True
  40. if flag:
  41. break
  42. screen.fill((135, 206, 235))
  43. text0 = ‘Final score: %s’ % score
  44. text1 = ‘Press <R> to restart the game.’
  45. text2 = ‘Press <Esc> to quit the game.’
  46. y = 150
  47. for idx, text in enumerate([text0, text1, text2]):
  48. text_render = font.render(text, 1, (85, 65, 0))
  49. rect = text_render.get_rect()
  50. if idx == 0:
  51. rect.left, rect.top = (212, y)
  52. elif idx == 1:
  53. rect.left, rect.top = (122.5, y)
  54. else:
  55. rect.left, rect.top = (126.5, y)
  56. y += 100
  57. screen.blit(text_render, rect)
  58. pygame.display.update()
  59. game.reset()
  60. ”’run”’
  61. if __name__ == ‘__main__’:
  62. main()

效果图:

%title插图%num

​说实话这个表情包版本的找的好哇!哈哈哈 很多相似的找都找不出来~

%title插图%num

这个是真卡哇伊哈哈哈 适合家里的小朋友玩~

标签

发表评论