资讯专栏INFORMATION COLUMN

PyGame贪吃蛇的实现

elisa.yang / 3089人阅读

摘要:最近帮人做了个贪吃蛇的游戏交作业用,很简单,界面如下开始界面游戏中界面是不是很简单朴素。代码在这里赋值,而不是在事件的循环中赋值,避免按键太快

最近帮人做了个贪吃蛇的游戏(交作业用),很简单,界面如下:
开始界面:

游戏中界面:

是不是很简单、朴素。(欢迎大家访问GitHub)


游戏是基于PyGame框架制作的,程序核心逻辑如下:

游戏界面分辨率是640*480,蛇和食物都是由1个或多个20*20像素的正方形块儿(为了方便,下文用点表示20*20像素的正方形块儿)组成,这样共有32*24个点,使用pygame.draw.rect来绘制每一个点;

初始化时蛇的长度是3,食物是1个点,蛇初始的移动的方向是右,用一个数组代表蛇,数组的每个元素是蛇每个点的坐标,因此数组的第一个坐标是蛇尾,最后一个坐标是蛇头;

游戏开始后,根据蛇的当前移动方向,将蛇运动方向的前方的那个点append到蛇数组的末位,再把蛇尾去掉,蛇的坐标数组就相当于往前挪了一位;

如果蛇吃到了食物,即蛇头的坐标等于食物的坐标,那么在第2点中蛇尾就不用去掉,就产生了蛇长度增加的效果;食物被吃掉后,随机在空的位置(不能与蛇的身体重合)再生成一个;

通过PyGameevent监控按键,改变蛇的方向,例如当蛇向右时,下一次改变方向只能向上或者向下;

当蛇撞上自身或墙壁,游戏结束,蛇头装上自身,那么蛇坐标数组里就有和舌头坐标重复的数据,撞上墙壁则是蛇头坐标超过了边界,都很好判断;

其他细节:做了个开始的欢迎界面;食物的颜色随机生成;吃到实物的时候有声音提示等。


代码:

#!/usr/bin/env python  
# -*- coding:utf-8 -*- 

""" 
@version: v1.0 
@author: Harp
@contact: liutao25@baidu.com 
@software: PyCharm 
@file: MySnake.py 
@time: 2018/1/15 0015 23:40 
"""


import pygame
from os import path
from sys import exit
from time import sleep
from random import choice
from itertools import product
from pygame.locals import QUIT, KEYDOWN


def direction_check(moving_direction, change_direction):
    directions = [["up", "down"], ["left", "right"]]
    if moving_direction in directions[0] and change_direction in directions[1]:
        return change_direction
    elif moving_direction in directions[1] and change_direction in directions[0]:
        return change_direction
    return moving_direction


class Snake:

    colors = list(product([0, 64, 128, 192, 255], repeat=3))[1:-1]

    def __init__(self):
        self.map = {(x, y): 0 for x in range(32) for y in range(24)}
        self.body = [[100, 100], [120, 100], [140, 100]]
        self.head = [140, 100]
        self.food = []
        self.food_color = []
        self.moving_direction = "right"
        self.speed = 4
        self.generate_food()
        self.game_started = False

    def check_game_status(self):
        if self.body.count(self.head) > 1:
            return True
        if self.head[0] < 0 or self.head[0] > 620 or self.head[1] < 0 or self.head[1] > 460:
            return True
        return False

    def move_head(self):
        moves = {
            "right": (20, 0),
            "up": (0, -20),
            "down": (0, 20),
            "left": (-20, 0)
        }
        step = moves[self.moving_direction]
        self.head[0] += step[0]
        self.head[1] += step[1]

    def generate_food(self):
        self.speed = len(self.body) // 16 if len(self.body) // 16 > 4 else self.speed
        for seg in self.body:
            x, y = seg
            self.map[x//20, y//20] = 1
        empty_pos = [pos for pos in self.map.keys() if not self.map[pos]]
        result = choice(empty_pos)
        self.food_color = list(choice(self.colors))
        self.food = [result[0]*20, result[1]*20]


def main():
    key_direction_dict = {
        119: "up",  # W
        115: "down",  # S
        97: "left",  # A
        100: "right",  # D
        273: "up",  # UP
        274: "down",  # DOWN
        276: "left",  # LEFT
        275: "right",  # RIGHT
    }

    fps_clock = pygame.time.Clock()
    pygame.init()
    pygame.mixer.init()
    snake = Snake()
    sound = False
    if path.exists("eat.wav"):
        sound_wav = pygame.mixer.Sound("eat.wav")
        sound = True
    title_font = pygame.font.SysFont("arial", 32)
    welcome_words = title_font.render("Welcome to My Snake", True, (0, 0, 0), (255, 255, 255))
    tips_font = pygame.font.SysFont("arial", 24)
    start_game_words = tips_font.render("Click to Start Game", True, (0, 0, 0), (255, 255, 255))
    close_game_words = tips_font.render("Press ESC to Close", True, (0, 0, 0), (255, 255, 255))
    gameover_words = title_font.render("GAME OVER", True, (205, 92, 92), (255, 255, 255))
    win_words = title_font.render("THE SNAKE IS LONG ENOUGH AND YOU WIN!", True, (0, 0, 205), (255, 255, 255))
    screen = pygame.display.set_mode((640, 480), 0, 32)
    pygame.display.set_caption("My Snake")
    new_direction = snake.moving_direction
    while 1:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            elif event.type == KEYDOWN:
                if event.key == 27:
                    exit()
                if snake.game_started and event.key in key_direction_dict:
                    direction = key_direction_dict[event.key]
                    new_direction = direction_check(snake.moving_direction, direction)
            elif (not snake.game_started) and event.type == pygame.MOUSEBUTTONDOWN:
                x, y = pygame.mouse.get_pos()
                if 213 <= x <= 422 and 304 <= y <= 342:
                    snake.game_started = True
        screen.fill((255, 255, 255))
        if snake.game_started:
            snake.moving_direction = new_direction  # 在这里赋值,而不是在event事件的循环中赋值,避免按键太快
            snake.move_head()
            snake.body.append(snake.head[:])
            if snake.head == snake.food:
                if sound:
                    sound_wav.play()
                snake.generate_food()
            else:
                snake.body.pop(0)
            for seg in snake.body:
                pygame.draw.rect(screen, [0, 0, 0], [seg[0], seg[1], 20, 20], 0)
            pygame.draw.rect(screen, snake.food_color, [snake.food[0], snake.food[1], 20, 20], 0)
            if snake.check_game_status():
                screen.blit(gameover_words, (241, 310))
                pygame.display.update()
                snake = Snake()
                new_direction = snake.moving_direction
                sleep(3)
            elif len(snake.body) == 512:
                screen.blit(win_words, (33, 210))
                pygame.display.update()
                snake = Snake()
                new_direction = snake.moving_direction
                sleep(3)
        else:
            screen.blit(welcome_words, (188, 100))
            screen.blit(start_game_words, (236, 310))
            screen.blit(close_game_words, (233, 350))
        pygame.display.update()
        fps_clock.tick(snake.speed)


if __name__ == "__main__":
    main()

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44568.html

相关文章

  • python完成简单的贪吃蛇小游戏附编号

      此篇文章主要是详细介绍了python完成简单的贪吃蛇小游戏附编号,文章内容紧扣主题进行详尽的基本介绍,具有很强的参考意义,需用的朋友可以学习一下  序言:  不知道有没有同学们和我一样,最开始触碰程序编程的动机就是为了做一个游戏打?  接下来要跟大家分享是指一个pygame所写的贪食蛇手机游戏:  贪食蛇这一个手机游戏在编程设计里的熟客,由于:  简易,最基本游戏情节你只需要蛇和食物2个就可以...

    89542767 评论0 收藏0
  • 小白成长日记:写个贪吃

    摘要:贪吃蛇并不是通过操作来完成移动的,而是通过记录贪吃蛇的路径来将身体渲染出来。目前没有内置的操作符判断对象的内容是否相同。 还是用的vue,本来以为不合适,但想法错了。贪吃蛇并不是通过操作dom来完成移动的,而是通过记录贪吃蛇的路径来将身体渲染出来。 一般移动元素,我们都是变动它的css达到目的,但我在写贪吃蛇的时候发现这样很难以实现,参考了网上的资源,发现大部分人是通过记录贪吃蛇的路径...

    archieyang 评论0 收藏0
  • 在手机或电脑浏览器上玩贪吃

    摘要:贪吃蛇源代码地址在手机浏览器上的显示效果贪吃蛇的基本框架首先确定蛇的移动区域,由一组标签构成,给予一个宽高,就组成了蛇的活动区域。以最小宽度为基准贪吃蛇的框架补全在里添加要创建个来作为贪吃蛇的活动场所。 贪吃蛇 源代码地址:https://github.com/jiaoshibo/... 在手机浏览器上的显示效果 showImg(https://segmentfault.com/img...

    Big_fat_cat 评论0 收藏0
  • 在手机或电脑浏览器上玩贪吃

    摘要:贪吃蛇源代码地址在手机浏览器上的显示效果贪吃蛇的基本框架首先确定蛇的移动区域,由一组标签构成,给予一个宽高,就组成了蛇的活动区域。以最小宽度为基准贪吃蛇的框架补全在里添加要创建个来作为贪吃蛇的活动场所。 贪吃蛇 源代码地址:https://github.com/jiaoshibo/... 在手机浏览器上的显示效果 showImg(https://segmentfault.com/img...

    zhangfaliang 评论0 收藏0
  • 不小心用js重做了一遍贪吃

    摘要:基于这个核心重新实现了一次贪吃蛇游戏,并且完善了游戏的关卡设计,效果如下效果预览详细思路分析 贪吃蛇游戏想必没人会感到陌生,这个游戏的js版本在网上也是一搜一大把,今天我要介绍的仍然是如何用js做一个贪吃蛇游戏,但在关键一步,蛇的运动的实现上略有不同。 贪吃蛇的js版本通常用连续的方块元素来实现蛇身,蛇的运动处理一般是这样的,让蛇头向运动方向偏移一格,其后的元素依次移向前一个元素的位置...

    kidsamong 评论0 收藏0

发表评论

0条评论

elisa.yang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<