python pygame 编写贪吃蛇

python pygame 编写贪吃蛇


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

player1 wasd ,player2 up left down right,esc退出当前场景 space 暂停。


# 效果

在这里插入图片描述

一、main.py

启动页

1 background

​ 背景

2 player

​ 蛇头

​ speed 速度 每格20

2.1 init

​ 初始化,随机位置,记录方向用于定时移动,记录蛇头上一个位置,用于判断 不能反向移动,key_status 移动方式 True wasd False 上下左右

2.2 update

​ 接收键盘输入,修改当前方向 ,并校验方向+当前位置不等于上一个位置

2.3 go

​ 移动 每250秒执行一次,检查是否出边界

2.4check

​ 检查是否出边界

3 foodSprite

​ 食物精灵

3.1 init

​ 食物,初始化随机位置

4 bodySprite

​ 蛇身精灵

4.1 init

​ 初始化位置

4.2 update

​ 移动

5 game

​ 游戏主函数

5.1 init

​ 初始化背景,玩家,存入精灵组中,创建蛇身精灵组,食物精灵组,创建玩家移动事件每250毫秒,生成食物事件1500毫秒,创建得分

5.2 plant_line

​ 背景显示方格,调试用,不用可以关掉

5.3 show_text

​ 显示字体 得分

5.4 place_sprites

​ 绘制精灵组里的精灵,食物、背景、玩家、蛇身

5.5 check_sprites

​ 碰撞检测,蛇头和蛇身、蛇头和食物,玩家和玩家

5.6 key_listener

​ 键盘监听 wasd、上下左右 esc退出 空格暂停

5.7 run

​ 循环绘制执行 限制120帧

6 buttonSprite

​ 按钮精灵,主界面使用

7 show_text

​ 绘制字体通用方法

8 Menu

​ 主界面

8.1 init

​ 菜单页面初始化,初始化两个按钮 1个玩家 2个玩家

8.2 run

​ 循环函数,选择完以后调用game方法

#coding=utf-8
from numpy import floor

try:
    import sys
    import random
    import math
    import os
    import getopt
    import pygame as pygame
    from socket import *
    from pygame.locals import *
except ImportError as err:
    print("couldn't load module. %s" % (err))
    sys.exit(2)

class background(pygame.sprite.Sprite):
    def __init__(self,size):
        super().__init__()
        self.surf = pygame.Surface(size)
        self.surf = self.surf.convert()
        self.surf.fill((125, 125, 125))
        self.rect = self.surf.get_rect()

class player(pygame.sprite.Sprite):

    speed = 20

    def __init__(self,size, key_status=True):
        super().__init__()
        self.background_size = size
        self.surf = pygame.Surface((20,20))
        self.surf = self.surf.convert()
        self.surf.fill((139,0,139))
        self.rect = self.surf.get_rect(center=(int(floor(random.randint(0,self.background_size[0]/20)) * 20-10),int(floor(random.randint(0,self.background_size[1]/20))) * 20-10))
        self.direction = 0, -self.speed
        self.last_pos = (0,0)
        self.key_status = key_status

    def update(self, key, flag=False):
        direction = self.direction
        if self.key_status:
            if key == K_UP:
                self.direction = (0, -self.speed)
                # self.rect.move_ip(0, -self.speed)
            elif key == K_DOWN:
                self.direction = (0, self.speed)
                # self.rect.move_ip(0, self.speed)
            elif key == K_LEFT:
                self.direction = (-self.speed, 0)
                # self.rect.move_ip(-self.speed, 0)
            elif key == K_RIGHT:
                self.direction = (self.speed, 0)
        else:
            if key == K_w:
                self.direction = (0, -self.speed)
                # self.rect.move_ip(0, -self.speed)
            elif key == K_s:
                self.direction = (0, self.speed)
                # self.rect.move_ip(0, self.speed)
            elif key == K_a:
                self.direction = (-self.speed, 0)
                # self.rect.move_ip(-self.speed, 0)
            elif key == K_d:
                self.direction = (self.speed, 0)
            # self.rect.move_ip(self.speed, 0)
        if flag:
            x, y = self.rect.center
            lx, ly = self.last_pos
            dx,dy = self.direction
            if (x + dx) == lx and (y+dy)==ly:
                #上一个位置
                self.direction = direction
        self.check()

    def go(self):
        self.last_pos = self.rect.center
        self.rect.move_ip(self.direction)
        self.check()

    def check(self):
        # 限定player在屏幕中
        if self.rect.left < 0:
            self.rect.left = 0
        elif self.rect.right > self.background_size[0]:
            self.rect.right = self.background_size[0]
        if self.rect.top <= 0:
            self.rect.top = 0
        elif self.rect.bottom >= self.background_size[1]:
            self.rect.bottom = self.background_size[1]

class foodSprite(pygame.sprite.Sprite):
    def __init__(self,size):
        super().__init__()
        self.background_size = size
        self.surf = pygame.Surface((20, 20))
        self.surf = self.surf.convert()
        self.surf.fill((255,182,193))
        self.rect = self.surf.get_rect(center=(int(floor(random.randint(0,self.background_size[0]/20)) * 20-10),int(floor(random.randint(0,self.background_size[1]/20))) * 20-10))

class bodySprite(pygame.sprite.Sprite):
    def __init__(self,pos):
        super(bodySprite, self).__init__()
        self.surf = pygame.Surface((20,20))
        self.surf = self.surf.convert()
        self.surf.fill((0,0,0))
        self.rect = self.surf.get_rect(center=pos)
        self.direction = ()

    def update(self, direction):
        self.direction = direction
        self.rect.move_ip(direction)

class game():
    def __init__(self,num="1"):
        pygame.init()
        self.screen = pygame.display.set_mode((640, 480))
        pygame.display.set_caption('贪吃蛇')
        self.num = num
        #是否显示线
        self.plant_flag = True

        #初始化背景
        self.background = background(self.screen.get_size())
        self.screen.blit(self.background.surf,self.background.rect)

        self.player = player(self.screen.get_size(),True)
        self.all_sprites = pygame.sprite.Group()
        self.all_sprites.add(self.background)
        self.all_sprites.add(self.player)
        self.players = pygame.sprite.Group()
        self.players.add(self.player)
        self.player2 = player(self.screen.get_size(),False)
        #用户
        if num == "2":
            self.all_sprites.add(self.player2)
            self.players.add(self.player2)

        self.foods_sprites = pygame.sprite.Group()

        self.bodys_sprites = pygame.sprite.Group()
        self.bodys_sprites2 = pygame.sprite.Group()

        self.ADDENEMY = pygame.USEREVENT + 1  # 事件本质上就是整数常量。比 USEREVENT 小的数值已经对应内置事件,因此任何自定义事件都必须比 USEREVENT 大)
        pygame.time.set_timer(self.ADDENEMY, 250)  # 每隔 250 毫秒(四分之一秒) 触发

        self.GEN_FOOD = pygame.USEREVENT + 2  # 事件本质上就是整数常量。比 USEREVENT 小的数值已经对应内置事件,因此任何自定义事件都必须比 USEREVENT 大)
        pygame.time.set_timer(self.GEN_FOOD, 1500)  # 每隔 250 毫秒(四分之一秒) 触发

        self.score = 0 #得分
        self.score2 = 0  # 得分
    """
    调试用
    """
    def plant_line(self, space=20):
        color = (0,0,0)
        w,h = self.screen.get_size()
        ws,hs = w//space , h//space
        for i in range(hs):
            pygame.draw.line(self.screen, color, (0, 20*i), (640, 20*i), 1)
        for i in range(ws):
            pygame.draw.line(self.screen, color, (20*i, 0), (20*i, 480), 1)

    #显示字体
    def show_text(self, font_size=40, font_bold=True, font_italic=False):
        cur_font = pygame.font.SysFont("华文宋体", font_size)
        cur_font.set_bold(font_bold)
        cur_font.set_italic(font_italic)
        text_message = cur_font.render("Score: "+str(self.score), 12, (220,20,60))
        self.screen.blit(text_message, (460,20))
        if self.num == "2":
            text_message2 = cur_font.render("Score: " + str(self.score2), 12, (220, 20, 60))
            self.screen.blit(text_message2, (40, 20))

    def place_sprites(self):
        for sprite in self.all_sprites:
            self.screen.blit(sprite.surf, sprite.rect)

        for sprite in self.foods_sprites:
            self.screen.blit(sprite.surf, sprite.rect)

        for sprite in self.bodys_sprites:
            self.screen.blit(sprite.surf, sprite.rect)

        for sprite in self.bodys_sprites2:
            self.screen.blit(sprite.surf, sprite.rect)

    #碰撞检测
    def check_sprites(self):
        collide_list = pygame.sprite.spritecollide(self.player, self.bodys_sprites, False)
        if len(collide_list) > 0:
            print('碰到自己身体了,分数清零 重新开始')
            self.bodys_sprites = pygame.sprite.Group()
            self.score = 0

        collide_list = pygame.sprite.spritecollide(self.player, self.foods_sprites, False)
        for c in collide_list:
            print("撞上了")
            self.foods_sprites.remove(c)
            self.score += 1
            body = bodySprite(self.player.last_pos)
            self.bodys_sprites.add(body)

        collide_list = pygame.sprite.spritecollide(self.player2, self.bodys_sprites2, False)
        if len(collide_list) > 0:
            print('碰到自己身体了,分数清零 重新开始')
            self.bodys_sprites2 = pygame.sprite.Group()
            self.score2 = 0

        collide_list = pygame.sprite.spritecollide(self.player2, self.foods_sprites, False)
        for c in collide_list:
            print("撞上了")
            self.foods_sprites.remove(c)
            self.score2 += 1
            body = bodySprite(self.player2.last_pos)
            self.bodys_sprites2.add(body)

        collide = pygame.sprite.collide_rect(self.player2, self.player)
        if collide:
            print("撞上了")
            self.bodys_sprites2 = pygame.sprite.Group()
            self.score2 = 0
            self.bodys_sprites = pygame.sprite.Group()
            self.score = 0

    #键盘监听
    def key_listener(self):
        for event in pygame.event.get():
            if event.type == QUIT:
                return True
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    return True
                elif event.key == K_SPACE:
                    paused = True
                    while paused:
                        for event in pygame.event.get():
                            if event.type == QUIT:
                                pygame.quit()
                                return
                            elif event.type == KEYDOWN:
                                if event.key == K_SPACE:
                                    paused = False
                                elif event.key == K_ESCAPE:
                                    return True
                else:
                    self.player.update(event.key, flag=True if len(self.bodys_sprites) > 0 else False)
                    self.player2.update(event.key, flag=True if len(self.bodys_sprites2) > 0 else False)
            elif event.type == self.ADDENEMY:  # 自定义事件
                self.player.go()
                self.player2.go()
                body_pos = None
                for i, sprite in enumerate(self.bodys_sprites):
                    if i == 0:
                        body_pos = sprite.rect.center
                        sprite.rect.center = self.player.last_pos
                    else:
                        a = sprite.rect.center
                        sprite.rect.center = body_pos
                        body_pos = a
                    pygame.display.flip()
                for i, sprite in enumerate(self.bodys_sprites2):
                    if i == 0:
                        body_pos = sprite.rect.center
                        sprite.rect.center = self.player2.last_pos
                    else:
                        a = sprite.rect.center
                        sprite.rect.center = body_pos
                        body_pos = a
                    pygame.display.flip()
            elif event.type == self.GEN_FOOD:  # 自定义事件
                f = foodSprite(self.screen.get_size())
                self.foods_sprites.add(f)

    def run(self):
        clock = pygame.time.Clock()
        while True:
            #键盘监听
            flag = self.key_listener()
            if flag:
                return
            #放置精灵组
            self.place_sprites()
            # 显示得分
            self.show_text()
            #碰撞检测
            self.check_sprites()

            #是否显示调试图
            if self.plant_flag:
                self.plant_line()

            pygame.display.flip()
            clock.tick(120)

class buttonSprite(pygame.sprite.Sprite):
    def __init__(self, name, pos):
        super(buttonSprite, self).__init__()
        self.name = name
        self.surf = pygame.Surface((180,150))
        self.surf = self.surf.convert()
        self.surf.fill((225, 225, 225))
        self.rect = self.surf.get_rect(center=pos)

    #显示字体

def show_text(screen, text,pos,color, font_size=40, font_bold=True, font_italic=False):
    cur_font = pygame.font.SysFont("华文宋体", font_size)
    cur_font.set_bold(font_bold)
    cur_font.set_italic(font_italic)
    text_message = cur_font.render(text, 12, color)
    screen.blit(text_message, pos)

class Menu():
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((640, 480))
        pygame.display.set_caption('贪吃蛇')
        # 初始化背景
        self.background = background(self.screen.get_size())
        self.screen.blit(self.background.surf, self.background.rect)

        one_player_button = buttonSprite("1",(220,160))
        two_player_button = buttonSprite("2",(410, 160))


        self.all_sprite = pygame.sprite.Group()
        self.all_sprite.add(one_player_button)
        self.all_sprite.add(two_player_button)

    def run(self):
        clock = pygame.time.Clock()
        while True:
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    return
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if event.button == 1:
                        for s in self.all_sprite:
                            if s.rect.collidepoint(event.pos):
                                game(s.name).run()
            self.screen.blit(self.background.surf,self.background.rect)
            for sprite in self.all_sprite:
                self.screen.blit(sprite.surf,sprite.rect)
            show_text(self.screen, "1个玩家", (140, 140), (220, 20, 60))
            show_text(self.screen, "2个玩家", (330, 140), (220, 20, 60))
            pygame.display.flip()
            clock.tick(30)

if __name__ == '__main__':
    # game().run()
    Menu().run()

总结

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,以下是一个基于Python贪吃小游戏的代码示例: ```python import pygame import random # 设置游戏界面尺寸 SCREEN_WIDTH = 480 SCREEN_HEIGHT = 480 # 贪吃身体大小 BLOCK_SIZE = 20 # 初始化pygame模块 pygame.init() # 创建游戏界面对象 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 设置游戏标题 pygame.display.set_caption('贪吃') # 定义颜色对象 color_red = pygame.Color(255, 0, 0) color_green = pygame.Color(0, 255, 0) color_blue = pygame.Color(0, 0, 255) color_white = pygame.Color(255, 255, 255) color_black = pygame.Color(0, 0, 0) # 定义游戏时钟对象 clock = pygame.time.Clock() # 定义贪吃初始位置和长度 snake_position = [100, 100] snake_body = [[100, 100], [80, 100], [60, 100]] # 定义食物初始位置 food_position = [random.randrange(1, (SCREEN_WIDTH//BLOCK_SIZE))*BLOCK_SIZE, random.randrange(1, (SCREEN_HEIGHT//BLOCK_SIZE))*BLOCK_SIZE] # 定义初始方向 direction = 'RIGHT' change_direction = direction # 画出贪吃和食物 def draw_score(score): score_font = pygame.font.SysFont(None, 25) score_surface = score_font.render('Score: {0}'.format(score), True, color_white) screen.blit(score_surface, (10, 10)) def draw_snake(snake_body): for position in snake_body: pygame.draw.rect(screen, color_green, pygame.Rect(position[0], position[1], BLOCK_SIZE, BLOCK_SIZE)) def draw_food(food_position): pygame.draw.rect(screen, color_red, pygame.Rect(food_position[0], food_position[1], BLOCK_SIZE, BLOCK_SIZE)) # 游戏主循环 score = 0 while True: # 处理游戏事件 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit(0) elif event.type == pygame.KEYDOWN: if event.key == pygame.K_RIGHT: change_direction = 'RIGHT' elif event.key == pygame.K_LEFT: change_direction = 'LEFT' elif event.key == pygame.K_UP: change_direction = 'UP' elif event.key == pygame.K_DOWN: change_direction = 'DOWN' elif event.key == pygame.K_ESCAPE: pygame.event.post(pygame.event.Event(pygame.QUIT)) # 判断是否更改方向 if change_direction == 'RIGHT' and direction != 'LEFT': direction = 'RIGHT' elif change_direction == 'LEFT' and direction != 'RIGHT': direction = 'LEFT' elif change_direction == 'UP' and direction != 'DOWN': direction = 'UP' elif change_direction == 'DOWN' and direction != 'UP': direction = 'DOWN' # 移动贪吃的身体 if direction == 'RIGHT': snake_position[0] += BLOCK_SIZE elif direction == 'LEFT': snake_position[0] -= BLOCK_SIZE elif direction == 'UP': snake_position[1] -= BLOCK_SIZE elif direction == 'DOWN': snake_position[1] += BLOCK_SIZE # 判断贪吃是否吃到食物 if snake_position == food_position: food_position = [random.randrange(1, (SCREEN_WIDTH//BLOCK_SIZE))*BLOCK_SIZE, random.randrange(1, (SCREEN_HEIGHT//BLOCK_SIZE))*BLOCK_SIZE] score += 10 else: snake_body.pop() # 更新贪吃身体的位置 snake_body.insert(0, list(snake_position)) # 绘制游戏界面 screen.fill(color_black) draw_score(score) draw_snake(snake_body) draw_food(food_position) pygame.display.update() # 判断游戏是否结束 if snake_position[0] < 0 or snake_position[0] > SCREEN_WIDTH-BLOCK_SIZE or \ snake_position[1] < 0 or snake_position[1] > SCREEN_HEIGHT-BLOCK_SIZE: pygame.quit() exit(0) for block in snake_body[1:]: if snake_position == block: pygame.quit() exit(0) # 设置游戏帧数并更新 clock.tick(15) ``` 希望能帮到您! 如需更详细的说明,请与我交流。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

matianlongg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值