欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

pygame实现贪吃蛇小游戏

程序员文章站 2024-03-19 08:21:04
...

pygame实现贪吃蛇小游戏

由于这段时间实在是太聊了,没什么事做,游戏也玩腻了,所以玩起来pygame。pygame是真的容易上手,但用来做游戏也有很大的局限性,做一些小游戏还是没什么问题的。

首先,制作游戏最大的问题我认为是确定要制作的游戏的玩法,具体的细节都确定清楚之后再去实现还是很容易的。所以开发游戏最大的问题可能是需要一个好的创意,没有好的创意都没法开始。贪吃蛇相信没有人没玩过了,玩法也很简单,没吃一个方块可以使蛇的身体变长,头部碰到墙壁或者头部碰到自己身体就game over了。然后也需要一个计分板记录分数。由于只是一个简单的小游戏,不用一个具体的步骤了,就自己码代码的时候不断完善代码还是很容易完成的。

初步的版本,实现了蛇的移动和吃方块身体变长,但还没有检测导致game over 的时间。自己想到了不少事情,如可以记录游戏分数并保存到本地文件,记录最高分,但毕竟只是个小游戏,只要保证游戏的完整性就算过关了,再怎么追求完美也不过是用pygame开发的,其价值始终只在于自娱自乐。之后将这个版本完善一下就算完成了。

import pygame,sys,numpy as nu,random as ra
from pygame.sprite import Sprite,Group
class setting():
    def __init__(self,w,h):
        self.w1=0.1*w
        self.w2=0.7*w
        self.w3=0.75*w
        self.w4=0.95*w
        self.h1=0.1*h
        self.h2=0.7*h
        self.length=0.05*self.w1
        self.speed=self.length
        self.wall_length=0.1*self.length
        self.wall_color=(0,0,0)
        self.snake_color=(0,0,230)
        self.head_color=(230,0,0)
class block(Sprite):
    def __init__(self,screen,rect,test,color):
        super().__init__()
        self.screen=screen
        self.rect=rect      #pygame.Rect(0,0,10,10)
        self.test=test
        self.color=color
    def update(self):
        self.rect=self.test(self.rect)
    def draw_bullet(self):
        pygame.draw.rect(self.screen,self.color,self.rect)
class textBlock(Sprite):
    def __init__(self,screen,rect,color,text,text_color):
        super().__init__()
        self.screen=screen
        self.rect=rect      #pygame.Rect(0,0,10,10)
        self.color=color
        self.text_color=text_color
        self.font=pygame.font.SysFont(None,68)
        self.image=self.font.render(text,True,self.text_color,self.color)
        self.image_rect=self.image.get_rect()
        self.image_rect.left=rect.left-200
        self.image_rect.top=rect.top-200
    def update(self):
        pass
    def changeText(self,text):
        self.image=self.font.render(text,True,self.text_color,self.color)
    def draw_bullet(self):
        self.screen.blit(self.image,self.image_rect)
        #pygame.draw.rect(self.screen, self.color, self.rect)
def run_game():
    pygame.init()
    w,h=1200,800
    screen=pygame.display.set_mode((w,h))
    pygame.display.set_caption("pygame1")
    bg_color=(230,230,230)
    settings=setting(w,h)

    g,gg=Group(),Group()

    a = block(screen, pygame.Rect((settings.w1+settings.w2)/2, (settings.h1+settings.h2)/2,
                                  settings.length, settings.length),lambda r:r,settings.head_color)
    aa = block(screen, pygame.Rect((settings.w1 + settings.w2) / 2, (settings.h1 + settings.h2) / 2,
                                  settings.length, settings.length), lambda r: r, settings.snake_color)
    g.add(a)
    #墙壁
    wall=Group()
    w1=block(screen, pygame.Rect(settings.w1, settings.h1, settings.wall_length, settings.h2-settings.h1),
              lambda r:r,settings.wall_color)
    w2 = block(screen, pygame.Rect(settings.w1, settings.h1, settings.w2-settings.w1, settings.wall_length),
               lambda r: r,settings.wall_color)
    w3 = block(screen, pygame.Rect(settings.w2, settings.h1, settings.wall_length, settings.h2-settings.h1),
               lambda r: r,settings.wall_color)
    w4 = block(screen, pygame.Rect(settings.w1, settings.h2, settings.w2-settings.w1, settings.wall_length),
               lambda r: r,settings.wall_color)
    wall.add(w1);wall.add(w2);wall.add(w3);wall.add(w4)

    w5 = block(screen, pygame.Rect(settings.w3, settings.h1, settings.wall_length, settings.h2 - settings.h1),
               lambda r: r, settings.wall_color)
    w6 = block(screen, pygame.Rect(settings.w3, settings.h1, settings.w4 - settings.w3, settings.wall_length),
               lambda r: r, settings.wall_color)
    w7 = block(screen, pygame.Rect(settings.w4, settings.h1, settings.wall_length, settings.h2 - settings.h1),
               lambda r: r, settings.wall_color)
    w8 = block(screen, pygame.Rect(settings.w3, settings.h2, settings.w4 - settings.w3, settings.wall_length),
               lambda r: r, settings.wall_color)
    wall.add(w5)
    wall.add(w6)
    wall.add(w7)
    wall.add(w8)
    timesec = textBlock(screen, pygame.Rect(settings.w3+200, settings.h1+200, 50,50), (230, 230, 230),
                        "time:"+str(pygame.time.get_ticks()), (200, 0, 20))
    leng=1
    snakeLength = textBlock(screen, pygame.Rect(settings.w3 + 200, settings.h1 + 400, 50, 50), (230, 230, 230),
                        "length:" + str(leng), (200, 0, 20))
    start=textBlock(screen,pygame.Rect(w/2,h/2,50,50),(230,230,230),"Gluttonous Snake",(0,200,200))
    start_1 = textBlock(screen, pygame.Rect(w / 2+50, h / 2+100, 50, 50), (230, 230, 230),
                        "Start game",(200,20,20))
    start_2 = textBlock(screen, pygame.Rect(w / 2 + 50, h / 2 + 200, 50, 50), (230, 230, 230),
                        "exit", (200, 20, 20))
    block_=block(screen, pygame.Rect(w / 2-170, h / 2-85, 10, 10),
              lambda r:r,settings.wall_color)
    kw,ks,ka,kd=False,False,False,False
    start_game,exit_game,generator=False,False,False
    timeStart=0
    ls=[start_game,kw,ks,ka,kd,exit_game,timeStart,generator,leng]
    lx,ly,la=[],[],[]
    def check_event(ls,lx,ly,la):
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                sys.exit()
            elif event.type==pygame.KEYDOWN and ls[0]:
                if event.key==pygame.K_w:
                    ls[1:5]=[True,False,False,False]
                elif event.key==pygame.K_a:
                    ls[1:5]=[False,False,True,False]
                elif event.key==pygame.K_s:
                    ls[1:5]=[False,True,False,False]
                elif event.key==pygame.K_d:
                    ls[1:5]=[False,False,False,True]
            elif event.type==pygame.KEYDOWN:
                if event.key==pygame.K_SPACE :
                    if(ls[5]):
                        sys.exit()
                    else:
                        ls[0],ls[2],ls[7]=True,True,True
                        ls[6]=pygame.time.get_ticks()
                elif event.key==pygame.K_w or event.key==pygame.K_s:
                    if(ls[5]):
                        block_.rect.y-=100
                    else:
                        block_.rect.y+=100
                    ls[5]=not ls[5]
        if(ls[0]):#start game
            if(ls[7]):
                aa.rect.x,aa.rect.y=ra.randint(settings.w1+20,settings.w2-20),\
                                    ra.randint(settings.h1+20,settings.h2-20)
                ls[7]=False
            if(pygame.time.get_ticks()%30==1):
                if(ls[1] and a.rect.y>settings.h1):
                    a.rect.y-=settings.speed
                    lx.append(0)
                    ly.append(-settings.speed)
                elif(ls[2] and a.rect.y<settings.h2-settings.length):
                    a.rect.y+=settings.speed
                    lx.append(0)
                    ly.append(settings.speed)
                elif(ls[3] and a.rect.x>settings.w1):
                    a.rect.x-=settings.speed
                    lx.append(-settings.speed)
                    ly.append(0)
                elif(ls[4] and a.rect.x<settings.w2-settings.length):
                    a.rect.x+=settings.speed
                    lx.append(settings.speed)
                    ly.append(0)
                dir=-2
                for als in la:
                    als.rect.x+=lx[dir]
                    als.rect.y+=ly[dir]
                    dir-=1
            a.draw_bullet()
            g.update()
            aa.draw_bullet()
            for all in gg:
                all.draw_bullet()
            for walls in wall:
                walls.draw_bullet()
            timesec.changeText("time:"+str((pygame.time.get_ticks()-ls[6])//1000))
            timesec.draw_bullet()
            snakeLength.draw_bullet()
            if (pygame.sprite.spritecollideany(aa, g)):
                print("collide")
                ls[7]=True
                ls[8]+=1
                snakeLength.changeText("length:" + str(ls[8]))
                if(len(la)==0):
                    aaa = block(screen, pygame.Rect(a.rect.x,a.rect.y,
                                              settings.length, settings.length), lambda r: r, settings.snake_color)
                else:
                    aaa = block(screen, pygame.Rect(a.rect.x, a.rect.y,
                                                    settings.length, settings.length), lambda r: r,
                                settings.snake_color)
                for x in range(len(la)+1):
                    aaa.rect.x-=lx[-x-1]
                    aaa.rect.y-=ly[-x-1]
                gg.add(aaa)
                la.append(aaa)
        else:
            start.draw_bullet()
            start_1.draw_bullet()
            start_2.draw_bullet()
            block_.draw_bullet()
    while True:
        screen.fill(bg_color)
        check_event(ls,lx,ly,la)
        pygame.display.flip()
run_game()

最终完成版本:

import pygame,sys,numpy as nu,random as ra
from pygame.sprite import Sprite,Group
class setting():
    def __init__(self,w,h):
        self.w1=0.1*w
        self.w2=0.7*w
        self.w3=0.75*w
        self.w4=0.95*w
        self.h1=0.1*h
        self.h2=0.7*h
        self.length=0.05*self.w1
        self.speed=self.length
        self.wall_length=0.1*self.length
        self.wall_color=(0,0,0)
        self.snake_color=(0,0,230)
        self.head_color=(230,0,0)
class block(Sprite):
    def __init__(self,screen,rect,test,color):
        super().__init__()
        self.screen=screen
        self.rect=rect      #pygame.Rect(0,0,10,10)
        self.test=test
        self.color=color
    def update(self):
        self.rect=self.test(self.rect)
    def draw_bullet(self):
        pygame.draw.rect(self.screen,self.color,self.rect)
class textBlock(Sprite):
    def __init__(self,screen,rect,color,text,text_color):
        super().__init__()
        self.screen=screen
        self.rect=rect      #pygame.Rect(0,0,10,10)
        self.color=color
        self.text_color=text_color
        self.font=pygame.font.SysFont(None,68)
        self.image=self.font.render(text,True,self.text_color,self.color)
        self.image_rect=self.image.get_rect()
        self.image_rect.left=rect.left-200
        self.image_rect.top=rect.top-200
    def update(self):
        pass
    def changeText(self,text):
        self.image=self.font.render(text,True,self.text_color,self.color)
    def draw_bullet(self):
        self.screen.blit(self.image,self.image_rect)
        #pygame.draw.rect(self.screen, self.color, self.rect)
def run_game():
    pygame.init()
    w,h=1200,800
    screen=pygame.display.set_mode((w,h))
    pygame.display.set_caption("pygame1")
    bg_color=(230,230,230)
    settings=setting(w,h)

    g,gg=Group(),Group()

    a = block(screen, pygame.Rect((settings.w1+settings.w2)/2, (settings.h1+settings.h2)/2,
                                  settings.length, settings.length),lambda r:r,settings.head_color)
    aa = block(screen, pygame.Rect((settings.w1 + settings.w2) / 2, (settings.h1 + settings.h2) / 2,
                                  settings.length, settings.length), lambda r: r, settings.snake_color)
    g.add(a)
    #墙壁
    wall=Group()
    w1=block(screen, pygame.Rect(settings.w1, settings.h1, settings.wall_length, settings.h2-settings.h1),
              lambda r:r,settings.wall_color)
    w2 = block(screen, pygame.Rect(settings.w1, settings.h1, settings.w2-settings.w1, settings.wall_length),
               lambda r: r,settings.wall_color)
    w3 = block(screen, pygame.Rect(settings.w2, settings.h1, settings.wall_length, settings.h2-settings.h1),
               lambda r: r,settings.wall_color)
    w4 = block(screen, pygame.Rect(settings.w1, settings.h2, settings.w2-settings.w1, settings.wall_length),
               lambda r: r,settings.wall_color)
    wall.add(w1);wall.add(w2);wall.add(w3);wall.add(w4)

    w5 = block(screen, pygame.Rect(settings.w3, settings.h1, settings.wall_length, settings.h2 - settings.h1),
               lambda r: r, settings.wall_color)
    w6 = block(screen, pygame.Rect(settings.w3, settings.h1, settings.w4 - settings.w3, settings.wall_length),
               lambda r: r, settings.wall_color)
    w7 = block(screen, pygame.Rect(settings.w4, settings.h1, settings.wall_length, settings.h2 - settings.h1),
               lambda r: r, settings.wall_color)
    w8 = block(screen, pygame.Rect(settings.w3, settings.h2, settings.w4 - settings.w3, settings.wall_length),
               lambda r: r, settings.wall_color)
    wall.add(w5)
    wall.add(w6)
    wall.add(w7)
    wall.add(w8)
    timesec = textBlock(screen, pygame.Rect(settings.w3+200, settings.h1+200, 50,50), (230, 230, 230),
                        "time:"+str(pygame.time.get_ticks()), (200, 0, 20))
    leng=1
    snakeLength = textBlock(screen, pygame.Rect(settings.w3 + 200, settings.h1 + 400, 50, 50), (230, 230, 230),
                        "length:" + str(leng), (200, 0, 20))
    start=textBlock(screen,pygame.Rect(w/2,h/2,50,50),(230,230,230),"Gluttonous Snake",(0,200,200))
    start_1 = textBlock(screen, pygame.Rect(w / 2+50, h / 2+100, 50, 50), (230, 230, 230),
                        "Start game",(200,20,20))
    start_2 = textBlock(screen, pygame.Rect(w / 2 + 50, h / 2 + 200, 50, 50), (230, 230, 230),
                        "exit", (200, 20, 20))
    block_=block(screen, pygame.Rect(w / 2-170, h / 2-85, 10, 10),
              lambda r:r,settings.wall_color)
    kw,ks,ka,kd=False,False,False,False
    start_game,exit_game,generator,gameOver=False,False,False,False
    timeStart=0
    ls=[start_game,kw,ks,ka,kd,exit_game,timeStart,generator,leng,gameOver]
    lx,ly=[],[]
    def check_event(ls,lx,ly,gg):
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                sys.exit()
            elif event.type==pygame.KEYDOWN and ls[0] and not ls[9]:
                if event.key==pygame.K_w:
                    ls[1:5]=[True,False,False,False]
                elif event.key==pygame.K_a:
                    ls[1:5]=[False,False,True,False]
                elif event.key==pygame.K_s:
                    ls[1:5]=[False,True,False,False]
                elif event.key==pygame.K_d:
                    ls[1:5]=[False,False,False,True]
            elif event.type==pygame.KEYDOWN and not ls[9]:
                if event.key==pygame.K_SPACE :
                    if(ls[5]):
                        sys.exit()
                    else:
                        ls[0],ls[2],ls[7]=True,True,True
                        ls[6]=pygame.time.get_ticks()
                elif event.key==pygame.K_w or event.key==pygame.K_s:
                    if(ls[5]):
                        block_.rect.y-=100
                    else:
                        block_.rect.y+=100
                    ls[5]=not ls[5]
            elif event.type==pygame.KEYDOWN:
                if event.key==pygame.K_SPACE :
                    if(ls[5]):
                        sys.exit()
                    else:
                        ls[0],ls[2],ls[7],ls[9],ls[8]=True,True,True,False,1
                        la ,lx,ly= [],[],[]
                        snakeLength.changeText("length:" + str(ls[8]))
                        gg.empty()
                        ls[6]=pygame.time.get_ticks()
                        a.rect.x,a.rect.y=(settings.w1+settings.w2)/2, (settings.h1+settings.h2)/2
                elif event.key==pygame.K_w or event.key==pygame.K_s:
                    if(ls[5]):
                        block_.rect.y-=100
                    else:
                        block_.rect.y+=100
                    ls[5]=not ls[5]
        if(ls[0] and not ls[9]):#start game
            if(ls[7]):
                aa.rect.x,aa.rect.y=ra.randint(settings.w1+20,settings.w2-20),\
                                    ra.randint(settings.h1+20,settings.h2-20)
                ls[7]=False
            if(pygame.time.get_ticks()%30==1):
                if(ls[1] and a.rect.y>=settings.h1):
                    a.rect.y-=settings.speed
                    lx.append(0)
                    ly.append(-settings.speed)
                elif(ls[2] and a.rect.y<=settings.h2-settings.length):
                    a.rect.y+=settings.speed
                    lx.append(0)
                    ly.append(settings.speed)
                elif(ls[3] and a.rect.x>=settings.w1):
                    a.rect.x-=settings.speed
                    lx.append(-settings.speed)
                    ly.append(0)
                elif(ls[4] and a.rect.x<=settings.w2-settings.length):
                    a.rect.x+=settings.speed
                    lx.append(settings.speed)
                    ly.append(0)
                dir=-2
                for als in gg:
                    als.rect.x+=lx[dir]
                    als.rect.y+=ly[dir]
                    dir-=1
            a.draw_bullet()
            g.update()
            aa.draw_bullet()
            for all in gg:
                all.draw_bullet()
            for walls in wall:
                walls.draw_bullet()
            timesec.changeText("time:"+str((pygame.time.get_ticks()-ls[6])//1000))
            timesec.draw_bullet()
            snakeLength.draw_bullet()
            if (pygame.sprite.spritecollideany(aa, g)):
                print("collide")
                ls[7]=True
                ls[8]+=1
                snakeLength.changeText("length:" + str(ls[8]))
                aaa = block(screen, pygame.Rect(a.rect.x, a.rect.y,
                                                    settings.length, settings.length), lambda r: r,
                                settings.snake_color)
                for x in range(len(gg)+1):
                    aaa.rect.x-=lx[-x-1]
                    aaa.rect.y-=ly[-x-1]
                gg.add(aaa)
            if pygame.sprite.spritecollideany(a,wall) or pygame.sprite.spritecollideany(a,gg):
                ls[9],ls[1],ls[2],ls[3],ls[4]=True,False,False,False,False
                print("game over")
            if a.rect.x==settings.w1-settings.length or a.rect.x==settings.w2 \
                or a.rect.y==settings.h1-settings.length or a.rect.y==settings.h2:
                ls[9], ls[1], ls[2], ls[3], ls[4] = True, False, False, False, False
                print("game over")
        else:
            if ls[9]:
                start.changeText("again or exit")
                start_1.changeText("again")
            start.draw_bullet()
            start_1.draw_bullet()
            start_2.draw_bullet()
            block_.draw_bullet()
    while True:
        screen.fill(bg_color)
        check_event(ls,lx,ly,gg)
        pygame.display.flip()
run_game()

pygame实现贪吃蛇小游戏

虽然可能还有不足之处,但玩起来感觉还不错。