pygame-漂浮物

简介

同学出于好奇,在群里问了下网页中漂浮物是怎么实现的,我觉得好玩也顺手做了一个。
最终效果如下:

漂浮物

开发环境

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

构思

玩法

  • 漂浮物随机漂浮
  • 漂浮物之间会连线,距离影响线条
  • 以鼠标位中心,吸引漂浮物,但不会吸引至中心

于是某个暑假回家就全凭印象,做出了一只触手怪。。。。。

触手怪

反思

  • 漂浮物不会互相吸引
  • 被鼠标吸引的漂浮物,会在边界内自由移动(安全范围)
  • 鼠标可视为一个隐形的漂浮物,例如id = 0的碎片
  • 需要两个队列,存放点和线

制作

游戏配置

# -*-coding:utf8-*-

import pygame
import sys
import random
from pygame.locals import *
from math import *

########## 配置 #############
SCREEN_SIZE = (1920, 1080)          #分辨率
MOUSE_LINK_RADIUS = 150             #鼠标连线范围
MOUSE_SALF_RADIUS = 140             #鼠标安全范围
MOUSE_ATTRACTION = 5                #鼠标吸引力
FRAGMENT_LINK_RADIUS = 100          #碎片连线范围
FRAGMENT_SPEED = 40                 #碎片速度
FRAGMENT_MOUSE_ID = 0               #鼠标碎片ID
FRAGMENT_NUM = 100                  #碎片数量
FRAGMENT_COLOR = (135, 203, 219)    #碎片及线条颜色
  • 产生吸引力的范围应该在(MOUSE_SALF_RADIUS , MOUSE_LINK_RADIUS )之间,容错区域

向量类

class Vector():
    def __init__(self, pos):
        self.x, self.y = pos

    def __add__(self, vec):
        vec = Vector((self.x + vec.x, self.y + vec.y))
        return vec

    def __sub__(self, vec):
        vec = Vector((self.x - vec.x, self.y - vec.y))        
        return vec

    def __mul__(self, n):
        vec = Vector((self.x * n, self.y * n))
        return vec

    def get_val(self):
        return(self.x, self.y)

    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))

def rand_pos():
    return Vector((random.randint(0, SCREEN_SIZE[0]), random.randint(0, SCREEN_SIZE[1])))

def rand_vec():
    x = random.uniform(0, 1)
    while x == 0 or x == 1:
        x = random.uniform(0 ,1)

    return Vector((x, sqrt(1 - pow(x, 2))))
  • __add____sub__写起来还是比add舒服

碎片类

class Fragment:
    frag_num = 0
    def __init__(self, pos, vec, speed):
        self.pos = pos
        self.vec = vec
        self.speed = speed
        self.id = self.__class__.frag_num
        self.__class__.frag_num += 1

    def is_mouse(self):
        return True if self.id == FRAGMENT_MOUSE_ID else False

    def move(self, time):
        if self.is_mouse():
            self.pos = Vector(pygame.mouse.get_pos())
        else:
            self.pos = self.pos + Vector((self.vec.x*self.speed*time, self.vec.y*self.speed*time))
            # 碰壁反弹
            if self.pos.x <= 0 or self.pos.x >= SCREEN_SIZE[0]:
                self.vec.x = -self.vec.x
                self.pos.x = 0 if self.pos.x <= 0 else SCREEN_SIZE[0]
            if self.pos.y <= 0 or self.pos.y >= SCREEN_SIZE[1]:
                self.vec.y = -self.vec.y
                self.pos.y = 0 if self.pos.y <= 0 else SCREEN_SIZE[1]

    def check_and_link(self, other):
        link_dis = MOUSE_LINK_RADIUS if self.is_mouse() else FRAGMENT_LINK_RADIUS
        if self.pos.get_dis(other.pos) < link_dis:
            self.link(other)

    def link(self, other):
        LinePool.append((self, other))

        if self.is_mouse():
            # 鼠标吸引,让其逃不出范围
            link_dis = self.pos.get_dis(other.pos)
            if link_dis < MOUSE_LINK_RADIUS + 5 and link_dis > MOUSE_SALF_RADIUS:
                link_dir = self.pos.get_dir(other.pos)
                other.pos = (other.pos - link_dir * MOUSE_ATTRACTION)

初始化

########## 各类初始化 #############
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE, FULLSCREEN, 32)
clock = pygame.time.Clock()
FragPool = []
LinePool = []

# 造碎片
for i in range(FRAGMENT_NUM):
    FragPool.append(Fragment(rand_pos(), rand_vec(), FRAGMENT_SPEED))

画线函数

def draw_all():
    # 碎片
    for frag in FragPool:
        if frag.is_mouse(): continue
        start1, stop1 = frag.pos.get_val(), (frag.pos + Vector((1, 1))).get_val()
        start2, stop2 = (frag.pos + Vector((1, 0))).get_val(), (frag.pos + Vector((0, 1))).get_val()
        pygame.draw.line(screen, FRAGMENT_COLOR, start1, stop1)
        pygame.draw.line(screen, FRAGMENT_COLOR, start2, stop2)

    # 连线
    for link in LinePool:
        start, stop = link
        dis = start.pos.get_dis(stop.pos)
        audius = MOUSE_LINK_RADIUS if start.is_mouse() else FRAGMENT_LINK_RADIUS
        color_pro = dis / audius
        color_line = []
        for i in FRAGMENT_COLOR:
            color_line.append(i*color_pro)
        pygame.draw.line(screen, color_line, start.pos.get_val(), stop.pos.get_val())
  • 由于pygame找不到合适的画点函数,所以选择在碎片附近画一个交叉线。

游戏控制

while True:
    # 捕捉键盘鼠标,按Esc退出
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
        if event.type == KEYDOWN and event.key == K_ESCAPE:
            exit()

    # 移动碎片并连线
    time_passed = clock.tick(60)
    time_passed_second = time_passed / 1000.0
    LinePool = []
    for frag in FragPool:
        frag.move(time_passed_second)
        now_id = frag.id + 1
        while now_id < len(FragPool):
            frag.check_and_link(FragPool[now_id])
            now_id += 1

    screen.fill((255, 255, 255))
    draw_all()
    pygame.display.update()

去年做的东西了,周末想一起写上去。无奈只剩“触手怪”代码,“漂浮物”版本的找不到了,只能重新写了一个。
完整代码在这

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容