美文网首页
pygame-躲鱼鱼

pygame-躲鱼鱼

作者: 烧鸡胤 | 来源:发表于2018-08-18 17:40 被阅读0次

    简介

    去年还在游戏公司时候,没事用pygame做的小玩意,整理下来做个留念。
    效果如下Gif图:


    躲鱼鱼.gif

    开发环境

    • windows10
    • pygame1.9.4
    • python3.6
    • 下载python配置好环境变量,命令行执行pip install pygame

    构思

    玩法

    • 玩家控制蚯蚓(鼠标),躲避小鱼。
    • 小鱼在靠近蚯蚓时越发警惕,游速减慢。
    • 蚯蚓触碰小鱼(进入攻击范围)时就游戏结束,计时停止。

    资源

    • 图片:背景 蚯蚓 鱼
    • 音乐:玩家脑补

    模块

    • 向量(鱼的翻转)
    • 鱼(鱼的运动)
    • pygame(键鼠事件,帧数,打印)

    制作

    1. 代码

    游戏配置

    import pygame
    import time
    import random
    from pygame.locals import *
    from sys import exit
    from math import *
    
    ########## 配置 #############
    SCREEN_SIZE = (1920, 1080)      #分辨率
    FISH_ATK_DIS = 40               #鱼的攻击范围
    WORM_IMG_FILE = "worm.png"      #蚯蚓图
    SEA_IMG_FILE = "sea.jpg"        #背景图
    FISH_IMG_FILE = ["fish_move_0.png", "fish_move_1.png", "fish_move_2.png"]   #鱼图片
    FISH_BIRTH_POINT = ((0, 0), (SCREEN_SIZE[0], 0), (0, SCREEN_SIZE[1]), (SCREEN_SIZE))    # 出生点
    FISH_NUM_MAX = 100              #鱼条数
    FISH_BORN_TIME = 0.3            #鱼产生间隔
    FISH_SPEED = 180                #鱼速度
    FISH_HIT_RADIUS = 45            #鱼碰撞半径
    FRAMES_DELAY_MAX = 16           #鱼动画延迟帧数
    

    向量类

    class Vector():
        def __init__(self, pos):
            self.x, self.y = pos
    
        def add(self, vec):
            self.x += vec.x
            self.y += vec.y
    
        def dec(self, vec):
            self.x -= vec.x
            self.y -= vec.y
    
        def mul(self, n):
            self.x *= n
            self.y *= n
    
        def get_len(self):
            return sqrt(pow(self.x, 2) + pow(self.y, 2))
    
        def get_dir(self, vec):
            dist = self.get_dis(vec)
            if dist == 0: return 0
            return  Vector(((vec.x-self.x)/dist, (vec.y-self.y)/dist))
    
        def get_dis(self, vec):
            return sqrt(pow(vec.x-self.x, 2) + pow(vec.y-self.y, 2))
    
    • get_len:取长度
    • get_dir:方向
    • get_dis:取距离

    class Fish():
        fish_num = 0
        def __init__(self, vec, radius=FISH_HIT_RADIUS):
            self.pos = Vector(vec)
            self.speed = 0
            self.angle = 0              #用来画图旋转角度
            self.hit_radius = radius    #碰撞半径
            self.frames_delay = 0         #用于帧播放
            self.fish_now_frames = 1
            self.tail_dir = 1
    
        def get_pos(self):
            return Vector(self.pos)
    
        def move(self, worm_vec, time):
            pos = self.pos
    
            # 撞到兄弟了,弹开
            for fish in fish_pool:
                if self is not fish and self.is_hit(fish):
                    dis = pos.get_dis(fish.pos)
                    self.speed = (FISH_SPEED * dis / 10)
                    m_dir = pos.get_dir(fish.pos)
                    fish.pos.add(Vector((m_dir.x*self.speed*time, m_dir.y*self.speed*time)))
                    pos.dec(Vector((m_dir.x*self.speed*time, m_dir.y*self.speed*time)))
                    return
    
            dis = pos.get_dis(worm_vec)
            self.speed = (FISH_SPEED * dis / 100)
            m_dir = pos.get_dir(worm_vec)
            pos.add(Vector((m_dir.x*self.speed*time, m_dir.y*self.speed*time)))
            self.rotate(worm_vec)
    
        def rotate(self, vec):
            fish_dir = self.pos.get_dir(vec)
            fish_cos = acos(fish_dir.x/fish_dir.get_len())
            if fish_dir.y > 0: fish_cos = -fish_cos
            self.angle = fish_cos/pi*180 - 90
    
        def blit(self, surface=None):
            scn = screen
            frames_delay, fish_now_frames, tail_dir = self.frames_delay, self.fish_now_frames, self.tail_dir
            if surface is not None: #图片打印区域
                scn = surface
    
            if fish_now_frames+tail_dir < 0 or fish_now_frames+tail_dir >= len(FISH_IMG_FILE):   #设置尾巴方向
                self.tail_dir = -tail_dir
    
            if frames_delay >= FRAMES_DELAY_MAX:    #设置鱼图片
                self.frames_delay %= FRAMES_DELAY_MAX
                self.fish_now_frames += tail_dir
            self.frames_delay += 1
    
            fish_rotated = pygame.transform.rotate(fish_img[fish_now_frames], self.angle)   #旋转
            f_draw_pos = (self.pos.x-fish_img_size[0]/2, self.pos.y-fish_img_size[1]/2)
            scn.blit(fish_rotated, f_draw_pos)
    
        def get_dis(self, fish):
            return self.pos.get_dis(fish.pos)
    
        def is_hit(self, fish):
            if self.get_dis(fish) < self.hit_radius:
                return True
            return False
    
        @classmethod
        def fish_born(cls):
            fish_pool.append(Fish(FISH_BIRTH_POINT[random.randint(0,3)]))
            Fish.fish_num += 1
    
    • move:往蚯蚓移动
    • rotate:调整鱼头方向
    • blit: 打印图片
    • is_hit: 撞鱼了
    • fish_born:产鱼(随机出现在地图四个角落),直接丢进fish_pool队列。

    初始化

    ########## 各类初始化 #############
    pygame.init()
    screen = pygame.display.set_mode(SCREEN_SIZE, FULLSCREEN, 32)   # 屏幕尺寸 全屏
    mfont = pygame.font.Font(None, 32)                              # ttf文件位置及字体大小
    pygame.mouse.set_visible(False)                                 # 关闭光标显示
    
    # 载入鱼、蚯蚓、背景图片
    fish_img = []
    for i in range(3):
        fish_img.append(pygame.image.load(FISH_IMG_FILE[i]).convert_alpha())
    worm_img = pygame.image.load(WORM_IMG_FILE).convert_alpha()
    sea_img = pygame.transform.scale(pygame.image.load(SEA_IMG_FILE).convert_alpha(), SCREEN_SIZE)
    fish_img_size = fish_img[0].get_size()
    worm_img_size = worm_img.get_size()
    fish_born_stamp = 0
    
    # 时钟
    clock = pygame.time.Clock()
    alive_time_stamp = time.time()
    
    
    # 简陋鱼池(放鱼的)
    fish_pool = []
    

    游戏控制

    # 打印所有图片
    def draw_all():
        font_size = mfont.size('')
        w_pos = (mouse_v.x-worm_img_size[0]/2, mouse_v.y-worm_img_size[1]/2)
    
        screen.blit(sea_img, (0, 0))
        screen.blit(worm_img, w_pos)
        for i in fish_pool:
            i.blit()
        text = mfont.render(u"%.2f" % float(time.time()-alive_time_stamp), True, (0, 125, 0))
        screen.blit(text, ((SCREEN_SIZE[0])/2, SCREEN_SIZE[1]/2))
    
    while True:
        # 捕捉键盘鼠标,按Esc退出
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            if event.type == KEYDOWN and event.key == K_ESCAPE:
                exit()
    
        # 造鱼
        if Fish.fish_num < FISH_NUM_MAX and fish_born_stamp < time.time()-FISH_BORN_TIME:
            fish_born_stamp = time.time()
            Fish.fish_born()
    
        # 按照60fps的速度刷新鱼,否则会因电脑差异影响游速
        time_passed = clock.tick(60)
        time_passed_second = time_passed / 1000.0
        mouse_v = Vector(pygame.mouse.get_pos())
        is_over = False
        for fish in fish_pool:
            fish.move(mouse_v, time_passed_second)
            if fish.pos.get_dis(mouse_v) <= FISH_ATK_DIS:
                is_over = True
                alive_time_stamp = time.time() - alive_time_stamp
        if is_over: break;
    
        draw_all()
        pygame.display.update()
    
    while True:
        # 捕捉键盘,按Esc退出
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            if event.type == KEYDOWN and event.key == K_ESCAPE:
                exit()
                    
        # 打印成绩
        screen.fill((0, 0, 0))
        text = mfont.render(u"%.2f" % alive_time_stamp, True, (0, 125, 0))
        screen.blit(text, ((SCREEN_SIZE[0])/2, SCREEN_SIZE[1]/2))
        pygame.display.update()                                      
    

    2. 图片

    蚯蚓 随便挑一个,PS自己抠的~~略略略

    PS抠出左中右三个动作
    图片均源自百度

    文件放在github

    相关文章

      网友评论

          本文标题:pygame-躲鱼鱼

          本文链接:https://www.haomeiwen.com/subject/aeufiftx.html