Python简易贪吃蛇小游戏(双人模式)



简单用py写了一个贪吃蛇游戏,有单人、双人模式,比较简单,适合初学者练手。本上每行重要的语句都有注释,做了什么事一目了然

这里介绍双人模式

一、游戏设计要点

1.游戏主体窗口(尺寸)、画布(尺寸、位置)、按钮(尺寸、位置)、文字(大小、颜色、位置)、图像、背景音乐及相关响应函数(主要是鼠标移动及点击的响应)的设计与合理排布
2.蛇与食物的类的属性设计
3.蛇位置的更新(根据键盘输入)、吃到食物加分的判定、食物的更新
4.蛇死亡的判定条件设计

二、主要模块

1.pygame
2.sys
3.random

三、用到的类

1.Snake类,定义蛇头蛇身元素的位置
2.Food类,定义食物元素的位置及单个元素的颜色

四、主要函数

1.new_food(),功能:生成一个不与蛇头位置重合的食物并返回该食物对象

def new_food(head):
    while True:

        new_food = Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255)))

        if new_food.x != head.x and new_food.y != head.y:
            break
        else:
            continue
    return new_food

2.draw_snake()、draw_food()函数,功能:绘制蛇与食物的图像,传入参数为颜色和对象:


def draw_snake(color, object):
    pygame.draw.circle(window, color, (object.x, object.y), 10)

def draw_food(food):
    pygame.draw.circle(window, food.color, (food.x, food.y), 10)

3.show_end函数,功能:显示双人模式结束时的得分界面:

def show_end():
    while True:
        window.blit(init_background, (0, 0))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit_end()

        pygame.display.set_caption("贪吃蛇大冒险")

        font = pygame.font.SysFont("simHei", 40)
        fontsurf = font.render('游戏结束! 玩家1得分: %s 玩家2得分:%s' % (score1, score2), True, black)
        window.blit(fontsurf, (150, 100))
        button("返回主菜单", 370, 300, 200, 40, blue, brightred, into_game)
        button("退出游戏", 370, 470, 200, 40, red, brightred, exit_end)
        pygame.display.update()
        clock.tick(20)

4.exit_end()函数,功能:在初始界面和游戏结束显示得分界面点击右上角的”×”时,直接退出整个游戏:


def exit_end():
    pygame.quit()
    sys.exit()

5.start_game_double()函数,功能:实现双人正常模式:

def start_game_double():

    pygame.mixer.music.play(-1)

    global score1
    global score2
    score1 = score2 = 0

    run_direction1 = "right"
    run_direction2 = "up"

    run1 = run_direction1
    run2 = run_direction2

    head1 = Snake(randint(0, 30) * 20, randint(0, 20) * 20)
    head2 = Snake(randint(0, 30) * 20, randint(0, 20) * 20)

    snake_body1 = [Snake(head1.x, head1.y + 20), Snake(head1.x, head1.y + 40)]
    snake_body2 = [Snake(head2.x, head2.y + 20), Snake(head2.x, head2.y + 40)]

    food_list = [Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255)))]
    for i in range(1,24):
        food_list.append(Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255))))

    food = Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255)))
    while True:
        window.blit(background, (0,0))

        for event in pygame.event.get():

            if event.type == pygame.QUIT:

                show_end()

            elif event.type == pygame.KEYDOWN:

                if event.key == pygame.K_UP:
                    run_direction2 = "up"

                if event.key == pygame.K_DOWN:
                    run_direction2 = "down"

                if event.key == pygame.K_LEFT:
                    run_direction2 = "left"

                if event.key == pygame.K_RIGHT:
                    run_direction2 = "right"

                if event.key == ord('w'):
                    run_direction1 = "up"

                if event.key == ord('s'):
                    run_direction1 = "down"

                if event.key == ord('a'):
                    run_direction1 = "left"

                if event.key == ord('d'):
                    run_direction1 = "right"

        for item in food_list:
            draw_food(item)

        draw_food(food)

        if len(snake_body1) != 0:
            draw_snake(black, head1)
        if len(snake_body2) != 0:
            draw_snake(black, head2)

        for item in snake_body1:
            draw_snake(blue, item)
        for item in snake_body2:
            draw_snake(green, item)

        if len(snake_body1) != 0:
            snake_body1.insert(0, Snake(head1.x, head1.y))
        if len(snake_body2) != 0:
            snake_body2.insert(0, Snake(head2.x, head2.y))

        if run1 == "up" and not run_direction1 == "down":
            run1 = run_direction1
        if run1 == "down" and not run_direction1 == "up":
            run1 = run_direction1
        if run1 == "left" and not run_direction1 == "right":
            run1 = run_direction1
        if run1 == "right" and not run_direction1 == "left":
            run1 = run_direction1
        if run2 == "up" and not run_direction2 == "down":
            run2 = run_direction2
        if run2 == "down" and not run_direction2 == "up":
            run2 = run_direction2
        if run2 == "left" and not run_direction2 == "right":
            run2 = run_direction2
        if run2 == "right" and not run_direction2 == "left":
            run2 = run_direction2

        if run1 == "up":
            head1.y -= 20
        if run1 == "down":
            head1.y += 20
        if run1 == "left":
            head1.x -= 20
        if run1 == "right":
            head1.x += 20
        if run2 == "up":
            head2.y -= 20
        if run2 == "down":
            head2.y += 20
        if run2 == "left":
            head2.x -= 20
        if run2 == "right":
            head2.x += 20

        die_flag1 = die_flag2 = False

        for body in snake_body1[1:]+snake_body2[1:]:
            if head1.x == body.x and head1.y == body.y:
                die_flag1 = True
            if head2.x == body.x and head2.y == body.y:
                die_flag2 = True
        if die_flag1 == True or head1.x < 0 or head1.x > 960 or head1.y < 0 or head1.y > 600:

            snake_body1.clear()
        if die_flag2 == True or head2.x < 0 or head2.x > 960 or head2.y < 0 or head2.y > 600:
            die_flag2 = True

            snake_body2.clear()

        if len(snake_body1) == 0 and len(snake_body2) == 0:
            show_end()

        global flag1
        global flag2
        flag1 = flag2 = 0

        for item in food_list:

            if len(snake_body1) != 0 and (head1.x == item.x and head1.y == item.y or head1.x == food.x and head1.y == food.y):
                flag1 = 1
                score1 += 1

                food_list.pop(food_list.index(item))

                food = new_food(head1)

                food_list.append(food)
                break

            elif len(snake_body2) != 0 and head2.x == item.x and head2.y == item.y or head2.x == food.x and head2.y == food.y:
                flag2 = 1
                score2 += 1

                food_list.pop(food_list.index(item))

                food = new_food(head2)

                food_list.append(food)
                break

        if len(snake_body1) != 0 and flag1 == 0:
            snake_body1.pop()

        if len(snake_body2) != 0 and flag2 == 0:
            snake_body2.pop ()
        font = pygame.font.SysFont("simHei", 25)
        mode_title1 = mode_title2 = font.render('正常模式', False, grey)
        socre_title1 = font.render('得分: %s' % score1, False, grey)
        socre_title2 = font.render('得分: %s' % score2, False, grey)
        window.blit(mode_title1, (50, 30))
        window.blit(socre_title1, (50, 65))
        window.blit(mode_title2, (800, 30))
        window.blit(socre_title2, (800, 65))

        pygame.display.update()

        clock.tick(8)

6.start_kgame_double()函数,功能:实现双人穿墙模式:

def start_kgame_double():

    pygame.mixer.music.play(-1)

    global score1
    global score2
    score1 = score2 = 0

    run_direction1 = "right"
    run_direction2 = "up"

    run1 = run_direction1
    run2 = run_direction2

    head1 = Snake(randint(0, 30) * 20, randint(0, 20) * 20)
    head2 = Snake(randint(0, 30) * 20, randint(0, 20) * 20)

    snake_body1 = [Snake(head1.x, head1.y + 20), Snake(head1.x, head1.y + 40)]
    snake_body2 = [Snake(head2.x, head2.y + 20), Snake(head2.x, head2.y + 40)]

    food_list = [Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255)))]
    for i in range(1,24):
        food_list.append(Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255))))

    food = Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255)))
    while True:
        window.blit(background, (0,0))

        for event in pygame.event.get():

            if event.type == pygame.QUIT:

                show_end()

            elif event.type == pygame.KEYDOWN:

                if event.key == pygame.K_UP:
                    run_direction2 = "up"

                if event.key == pygame.K_DOWN:
                    run_direction2 = "down"

                if event.key == pygame.K_LEFT:
                    run_direction2 = "left"

                if event.key == pygame.K_RIGHT:
                    run_direction2 = "right"

                if event.key == ord('w'):
                    run_direction1 = "up"

                if event.key == ord('s'):
                    run_direction1 = "down"

                if event.key == ord('a'):
                    run_direction1 = "left"

                if event.key == ord('d'):
                    run_direction1 = "right"

        for item in food_list:
            draw_food(item)

        draw_food(food)

        if len(snake_body1) != 0:
            draw_snake(black, head1)
        if len(snake_body2) != 0:
            draw_snake(black, head2)

        for item in snake_body1:
            draw_snake(blue, item)
        for item in snake_body2:
            draw_snake(green, item)

        if len(snake_body1) != 0:
            snake_body1.insert(0, Snake(head1.x, head1.y))
        if len(snake_body2) != 0:
            snake_body2.insert(0, Snake(head2.x, head2.y))

        if run1 == "up" and not run_direction1 == "down":
            run1 = run_direction1
        if run1 == "down" and not run_direction1 == "up":
            run1 = run_direction1
        if run1 == "left" and not run_direction1 == "right":
            run1 = run_direction1
        if run1 == "right" and not run_direction1 == "left":
            run1 = run_direction1
        if run2 == "up" and not run_direction2 == "down":
            run2 = run_direction2
        if run2 == "down" and not run_direction2 == "up":
            run2 = run_direction2
        if run2 == "left" and not run_direction2 == "right":
            run2 = run_direction2
        if run2 == "right" and not run_direction2 == "left":
            run2 = run_direction2

        if run1 == "up":
            head1.y -= 20
        if run1 == "down":
            head1.y += 20
        if run1 == "left":
            head1.x -= 20
        if run1 == "right":
            head1.x += 20
        if run2 == "up":
            head2.y -= 20
        if run2 == "down":
            head2.y += 20
        if run2 == "left":
            head2.x -= 20
        if run2 == "right":
            head2.x += 20

        if head1.x < 0:
            head1.x = 960
        if head1.x > 960:
            head1.x = 0
        if head1.y < 0:
            head1.y = 600
        if head1.y > 600:
            head1.y = 0
        if head2.x < 0:
            head2.x = 960
        if head2.x > 960:
            head2.x = 0
        if head2.y < 0:
            head2.y = 600
        if head2.y > 600:
            head2.y = 0

        die_flag1 = die_flag2 = False
        for body in snake_body1[1:]+snake_body2[1:]:
            if head1.x == body.x and head1.y == body.y:
                die_flag1 = True
            if head2.x == body.x and head2.y == body.y:
                die_flag2 = True
        if die_flag1 == True:
            snake_body1.clear()
        if die_flag2 == True:
            snake_body2.clear()

        if len(snake_body1) == 0 and len(snake_body2) == 0:
            show_end()

        global flag1
        global flag2
        flag1 = flag2 = 0

        for item in food_list:

            if len(snake_body1) != 0 and (head1.x == item.x and head1.y == item.y or head1.x == food.x and head1.y == food.y):
                flag1 = 1
                score1 += 1

                food_list.pop(food_list.index(item))

                food = new_food(head1)

                food_list.append(food)
                break

            elif len(snake_body2) != 0 and head2.x == item.x and head2.y == item.y or head2.x == food.x and head2.y == food.y:
                flag2 = 1
                score2 += 1

                food_list.pop(food_list.index(item))

                food = new_food(head2)

                food_list.append(food)
                break

        if len(snake_body1) != 0 and flag1 == 0:
            snake_body1.pop()

        if len(snake_body2) != 0 and flag2 == 0:
            snake_body2.pop ()
        font = pygame.font.SysFont("simHei", 25)
        mode_title1 = mode_title2 = font.render('穿墙模式', False, grey)
        socre_title1 = font.render('得分: %s' % score1, False, grey)
        socre_title2 = font.render('得分: %s' % score2, False, grey)
        window.blit(mode_title1, (50, 30))
        window.blit(socre_title1, (50, 65))
        window.blit(mode_title2, (800, 30))
        window.blit(socre_title2, (800, 65))

        pygame.display.update()

        clock.tick(8)

7.button()函数,功能:实现按钮样式设计和响应鼠标操作:

def button(msg, x, y, w, h, ic, ac, action=None):

    mouse = pygame.mouse.get_pos()

    click = pygame.mouse.get_pressed()
    if x + w > mouse[0] > x and y + h > mouse[1] > y:
        pygame.draw.rect(window, ac, (x, y, w, h))
        if click[0] == 1 and action != None:
            action()
    else:
        pygame.draw.rect(window, ic, (x, y, w, h))

    font = pygame.font.SysFont('simHei', 20)
    smallfont = font.render(msg, True, white)
    smallrect = smallfont.get_rect()
    smallrect.center = ((x + (w / 2)), (y + (h / 2)))
    window.blit(smallfont, smallrect)

8.into_game()函数,功能:实现游戏初始界面,选择模式:

def into_game():
    while True:
        window.blit(init_background, (0, 0))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit_end()

        font = pygame.font.SysFont("simHei", 50)

        fontsurf = font.render('欢迎来到贪吃蛇大冒险!', True, black)
        fontrect = fontsurf.get_rect()
        fontrect.center = ((480), 200)
        window.blit(fontsurf, fontrect)
        button("正常模式", 370, 370, 200, 40, blue, brightred, start_game_double)
        button("可穿墙模式", 370, 420, 200, 40, violte, brightred, start_kgame_double)
        button("退出游戏", 370, 470, 200, 40, red, brightred, exit_end)
        pygame.display.update()
        clock.tick(20)

9.主函数,功能:初始化参数设定,进入游戏

注:其中的图片、背景音乐需要自己找合适(尺寸要与窗口大小相适应)的,也可以参考我上传的资源:

欢迎各位小伙伴们fork or star哦~

Original: https://blog.csdn.net/qq_45717425/article/details/119791352
Author: Polaris_T
Title: Python简易贪吃蛇小游戏(双人模式)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/780299/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球