有很多 Python 新手留言问:“Python 入门很久了,但项目经验很少,有没有什么项目,可以让自己实践一下呢?”
这是个很普遍的问题,今天呢就给大家分享五个适合新手练手的趣味游戏项目
准备工作:安装Python
python版本:3.5.4
pygame版本:1.9.3(pip安装即可)
效果
部分源码
'''游戏初始化'''def initGame():# 初始化pygame, 设置展示窗口pygame.init()pygame.mixer.init()screen = pygame.display.set_mode(cfg.SCREENSIZE)pygame.display.set_caption('Bunnies and Badgers —— 微信公众号: Charles的皮卡丘')# 加载必要的游戏素材game_images = {}for key, value in cfg.IMAGE_PATHS.items():game_images[key] = pygame.image.load(value)game_sounds = {}for key, value in cfg.SOUNDS_PATHS.items():if key != 'moonlight':game_sounds[key] = pygame.mixer.Sound(value)return screen, game_images, game_sounds'''主函数'''def main():# 初始化screen, game_images, game_sounds = initGame()# 播放背景音乐pygame.mixer.music.load(cfg.SOUNDS_PATHS['moonlight'])pygame.mixer.music.play(-1, 0.0)# 字体加载font = pygame.font.Font(None, 24)# 定义兔子bunny = BunnySprite(image=game_images.get('rabbit'), position=(100, 100))# 跟踪玩家的精度变量, 记录了射出的箭头数和被击中的獾的数量.acc_record = [0., 0.]# 生命值healthvalue = 194# 弓箭arrow_sprites_group = pygame.sprite.Group()# 獾badguy_sprites_group = pygame.sprite.Group()badguy = BadguySprite(game_images.get('badguy'), position=(640, 100))badguy_sprites_group.add(badguy)# 定义了一个定时器, 使得游戏里经过一段时间后就新建一支獾badtimer = 100badtimer1 = 0# 游戏主循环, running变量会跟踪游戏是否结束, exitcode变量会跟踪玩家是否胜利.running, exitcode = True, Falseclock = pygame.time.Clock()while running:# --在给屏幕画任何东西之前用黑色进行填充screen.fill(0)# --添加的风景也需要画在屏幕上for x in range(cfg.SCREENSIZE[0]//game_images['grass'].get_width()+1):for y in range(cfg.SCREENSIZE[1]//game_images['grass'].get_height()+1):screen.blit(game_images['grass'], (x*100, y*100))for i in range(4): screen.blit(game_images['castle'], (0, 30+105*i))# --倒计时信息countdown_text = font.render(str((90000-pygame.time.get_ticks())//60000)+":"+str((90000-pygame.time.get_ticks())//1000%60).zfill(2), True, (0, 0, 0))countdown_rect = countdown_text.get_rect()countdown_rect.topright = [635, 5]screen.blit(countdown_text, countdown_rect)# --按键检测# ----退出与射击for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.MOUSEBUTTONDOWN:game_sounds['shoot'].play()acc_record[1] += 1mouse_pos = pygame.mouse.get_pos()angle = math.atan2(mouse_pos[1]-(bunny.rotated_position[1]+32), mouse_pos[0]-(bunny.rotated_position[0]+26))arrow = ArrowSprite(game_images.get('arrow'), (angle, bunny.rotated_position[0]+32, bunny.rotated_position[1]+26))arrow_sprites_group.add(arrow)# ----移动兔子key_pressed = pygame.key.get_pressed()if key_pressed[pygame.K_w]:bunny.move(cfg.SCREENSIZE, 'up')elif key_pressed[pygame.K_s]:bunny.move(cfg.SCREENSIZE, 'down')elif key_pressed[pygame.K_a]:bunny.move(cfg.SCREENSIZE, 'left')elif key_pressed[pygame.K_d]:bunny.move(cfg.SCREENSIZE, 'right')# --更新弓箭for arrow in arrow_sprites_group:if arrow.update(cfg.SCREENSIZE):arrow_sprites_group.remove(arrow)# --更新獾if badtimer == 0:badguy = BadguySprite(game_images.get('badguy'), position=(640, random.randint(50, 430)))badguy_sprites_group.add(badguy)badtimer = 100 - (badtimer1 * 2)badtimer1 = 20 if badtimer1>=20 else badtimer1+2badtimer -= 1for badguy in badguy_sprites_group:if badguy.update():game_sounds['hit'].play()healthvalue -= random.randint(4, 8)badguy_sprites_group.remove(badguy)# --碰撞检测for arrow in arrow_sprites_group:for badguy in badguy_sprites_group:if pygame.sprite.collide_mask(arrow, badguy):game_sounds['enemy'].play()arrow_sprites_group.remove(arrow)badguy_sprites_group.remove(badguy)acc_record[0] += 1# --画出弓箭arrow_sprites_group.draw(screen)# --画出獾badguy_sprites_group.draw(screen)# --画出兔子bunny.draw(screen, pygame.mouse.get_pos())# --画出城堡健康值, 首先画了一个全红色的生命值条, 然后根据城堡的生命值往生命条里面添加绿色.screen.blit(game_images.get('healthbar'), (5, 5))for i in range(healthvalue):screen.blit(game_images.get('health'), (i+8, 8))# --判断游戏是否结束if pygame.time.get_ticks() >= 90000:running, exitcode = False, Trueif healthvalue <= 0:running, exitcode = False, False# --更新屏幕pygame.display.flip()clock.tick(cfg.FPS)# 计算准确率accuracy = acc_record[0] / acc_record[1] * 100 if acc_record[1] > 0 else 0accuracy = '%.2f' % accuracyshowEndGameInterface(screen, exitcode, accuracy, game_images)
Python版本:3.6.4
相关模块:
cocos2d模块;
pyaudio模块;
以及一些Python自带的模块。
相信很多人对八音符这款游戏并不陌生吧,其核心玩法是利用声音控制一个带辫子的小黑球不断前进,大概是长这样子的吧:
游戏主要使用了cocos2d模块和pyaudio模块,前者用于搭建游戏框架,后者用于获得麦克风的声音。
部分源码'''定义声控游戏类'''class VCGame(cocos.layer.ColorLayer):def __init__(self):super(VCGame, self).__init__(255, 255, 255, 255, 800, 600)# frames_per_bufferself.num_samples = 1000# 声控条self.vbar = Sprite(cfg.BLOCK_IMAGE_PATH)self.vbar.position = 20, 450self.vbar.scale_y = 0.1self.vbar.image_anchor = 0, 0self.add(self.vbar)# 皮卡丘self.pikachu = Pikachu(cfg.PIKACHU_IMAGE_PATH)self.add(self.pikachu)# 地面self.floor = cocos.cocosnode.CocosNode()self.add(self.floor)position = 0, 100for i in range(120):b = Block(cfg.BLOCK_IMAGE_PATH, position)self.floor.add(b)position = b.x + b.width, b.height# 声音输入audio = PyAudio()self.stream = audio.open(format=paInt16, channels=1, rate=int(audio.get_device_info_by_index(0)['defaultSampleRate']), input=True, frames_per_buffer=self.num_samples)# 屏幕更新self.schedule(self.update)'''碰撞检测'''def collide(self):diffx = self.pikachu.x - self.floor.xfor b in self.floor.get_children():if (b.x <= diffx + self.pikachu.width * 0.8) and (diffx + self.pikachu.width * 0.2 <= b.x + b.width):if self.pikachu.y < b.height:self.pikachu.land(b.height)break'''定义游戏规则'''def update(self, dt):# 获取每帧的音量audio_data = self.stream.read(self.num_samples)k = max(struct.unpack('1000h', audio_data))self.vbar.scale_x = k / 10000.0if k > 3000:self.floor.x -= min((k / 20.0), 150) * dt# 皮卡丘跳跃if k > 8000:self.pikachu.jump((k - 8000) / 1000.0)# 碰撞检测self.collide()'''重置'''def reset(self):self.floor.x = 0'''run'''if __name__ == '__main__':cocos.director.director.init(caption="Pikachu Go Go Go")cocos.director.director.run(cocos.scene.Scene(VCGame()))
游戏简介:
将图像分为m×n个矩形块,并将图像右下角的矩形块替换为空白块后,将这些矩形块随机摆放成原图像的形状。游戏目标为通过移动非空白块将随机摆放获得的图像恢复成原图像的模样,且规定移动操作仅存在于非空白块移动到空白块。
例如下图所示:
部分源码
while True:game_board, blank_cell_idx = CreateBoard(num_rows, num_cols, num_cells)if not isGameOver(game_board, size):break# 游戏主循环is_running = Truewhile is_running:# --事件捕获for event in pygame.event.get():# ----退出游戏if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):pygame.quit()sys.exit()# ----键盘操作elif event.type == pygame.KEYDOWN:if event.key == pygame.K_LEFT or event.key == ord('a'):blank_cell_idx = moveL(game_board, blank_cell_idx, num_cols)elif event.key == pygame.K_RIGHT or event.key == ord('d'):blank_cell_idx = moveR(game_board, blank_cell_idx, num_cols)elif event.key == pygame.K_UP or event.key == ord('w'):blank_cell_idx = moveU(game_board, blank_cell_idx, num_rows, num_cols)elif event.key == pygame.K_DOWN or event.key == ord('s'):blank_cell_idx = moveD(game_board, blank_cell_idx, num_cols)# ----鼠标操作elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:x, y = pygame.mouse.get_pos()x_pos = x // cell_widthy_pos = y // cell_heightidx = x_pos + y_pos * num_colsif idx == blank_cell_idx-1:blank_cell_idx = moveR(game_board, blank_cell_idx, num_cols)elif idx == blank_cell_idx+1:blank_cell_idx = moveL(game_board, blank_cell_idx, num_cols)elif idx == blank_cell_idx+num_cols:blank_cell_idx = moveU(game_board, blank_cell_idx, num_rows, num_cols)elif idx == blank_cell_idx-num_cols:blank_cell_idx = moveD(game_board, blank_cell_idx, num_cols)# --判断游戏是否结束if isGameOver(game_board, size):game_board[blank_cell_idx] = num_cells - 1is_running = False# --更新屏幕screen.fill(cfg.BACKGROUNDCOLOR)for i in range(num_cells):if game_board[i] == -1:continuex_pos = i // num_colsy_pos = i % num_colsrect = pygame.Rect(y_pos*cell_width, x_pos*cell_height, cell_width, cell_height)img_area = pygame.Rect((game_board[i]%num_cols)*cell_width, (game_board[i]//num_cols)*cell_height, cell_width, cell_height)screen.blit(game_img_used, rect, img_area)for i in range(num_cols+1):pygame.draw.line(screen, cfg.BLACK, (i*cell_width, 0), (i*cell_width, game_img_used_rect.height))for i in range(num_rows+1):pygame.draw.line(screen, cfg.BLACK, (0, i*cell_height), (game_img_used_rect.width, i*cell_height))pygame.display.update()clock.tick(cfg.FPS)
游戏规则:
玩家通过“AD”键或者“←→”操控前进中的滑雪者,努力避开路上的树,尽量捡到路上的小旗。
如果碰到树,则得分减50,如果捡到小旗子,则得分加10。
效果
部分源码
'''游戏主循环'''while True:# --事件捕获for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.KEYDOWN:if event.key == pygame.K_LEFT or event.key == pygame.K_a:speed = skier.turn(-1)elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:speed = skier.turn(1)'''--更新当前游戏帧的数据'''skier.move()distance += speed[1]if distance >= 640 and obstaclesflag == 0:obstaclesflag = 1obstacles0 = createObstacles(20, 29)obstacles = AddObstacles(obstacles0, obstacles1)if distance >= 1280 and obstaclesflag == 1:obstaclesflag = 0distance -= 1280for obstacle in obstacles0:obstacle.location[1] = obstacle.location[1] - 1280obstacles1 = createObstacles(10, 19)obstacles = AddObstacles(obstacles0, obstacles1)for obstacle in obstacles:obstacle.move(distance)'''--碰撞检测'''hitted_obstacles = pygame.sprite.spritecollide(skier, obstacles, False)if hitted_obstacles:if hitted_obstacles[0].attribute == "tree" and not hitted_obstacles[0].passed:score -= 50skier.setFall()updateFrame(screen, obstacles, skier, score)pygame.time.delay(1000)skier.setForward()speed = [0, 6]hitted_obstacles[0].passed = Trueelif hitted_obstacles[0].attribute == "flag" and not hitted_obstacles[0].passed:score += 10obstacles.remove(hitted_obstacles[0])'''--更新屏幕'''updateFrame(screen, obstacles, skier, score)clock.tick(cfg.FPS)
游戏规则:
游戏有单人和双人两种模式,己方大本营被破或者己方坦克被歼灭则游戏失败,成功通过所有关卡则游戏胜利。另外,玩家可以通过射击特定的坦克使地图上随机出现一个道具,若己方坦克捡到该道具,则触发一个事件,例如坦克能力的增强。
效果图
部分源码
'''主函数'''def main(cfg):# 游戏初始化pygame.init()pygame.mixer.init()screen = pygame.display.set_mode((cfg.WIDTH, cfg.HEIGHT))pygame.display.set_caption(cfg.TITLE)# 加载游戏素材sounds = {}for key, value in cfg.AUDIO_PATHS.items():sounds[key] = pygame.mixer.Sound(value)sounds[key].set_volume(1)# 开始界面is_dual_mode = gameStartInterface(screen, cfg)# 关卡数levelfilepaths = [os.path.join(cfg.LEVELFILEDIR, filename) for filename in sorted(os.listdir(cfg.LEVELFILEDIR))]# 主循环for idx, levelfilepath in enumerate(levelfilepaths):switchLevelIterface(screen, cfg, idx+1)game_level = GameLevel(idx+1, levelfilepath, sounds, is_dual_mode, cfg)is_win = game_level.start(screen)if not is_win: breakis_quit_game = gameEndIterface(screen, cfg, is_win)return is_quit_game'''run'''if __name__ == '__main__':while True:is_quit_game = main(cfg)if is_quit_game:break
以上这五款游戏都是我在学习的过程中完成的,我们可以发现 Python 是一种非常实用的编程语言,他可以开发游戏以外,还可以适用于开发各种类型和规模的应用程序。此外,Python 配置的程序包对于开发者来说价值巨大,能够极大地简化开发过程。
如果有正在跟我一样的自学的朋友,需要我本篇的代码或者其他的Python学习资料可以私信我(转发此文私信发我“经典游戏”)
最后,我想说的是,Python 的应用潜力无限,你唯一缺少的就是找准适当的创意。