簡介
同學出于好奇,在群里問了下網(wǎng)頁中漂浮物是怎么實現(xiàn)的俺叭,我覺得好玩也順手做了一個绪抛。
最終效果如下:
開發(fā)環(huán)境
- windows10
- pygame1.9.4
- python3.6
- 下載python配置好環(huán)境變量饥追,命令行執(zhí)行
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 #碎片數(shù)量
FRAGMENT_COLOR = (135, 203, 219) #碎片及線條顏色
- 產(chǎn)生吸引力的范圍應該在(MOUSE_SALF_RADIUS 化焕, MOUSE_LINK_RADIUS )之間,容錯區(qū)域
向量類
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))
畫線函數(shù)
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找不到合適的畫點函數(shù),所以選擇在碎片附近畫一個交叉線键兜。
游戲控制
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()
去年做的東西了,周末想一起寫上去普气。無奈只拭瞻蹋“觸手怪”代碼,“漂浮物”版本的找不到了现诀,只能重新寫了一個夷磕。
完整代碼在這