我如何在pygame中从一种颜色淡入另一种颜色?我要慢慢将圆圈的颜色从绿色变为蓝色,从紫色变为粉红色,再由红色变为橙色,再从黄色变为绿色。我该怎么做?目前,我正在使用
def colour():
switcher = {
0: 0x2FD596,
1: 0x2FC3D5,
2: 0x2F6BD5,
3: 0x432FD5,
4: 0x702FD5,
5: 0xBC2FD5,
6: 0xD52F91,
7: 0xD52F43,
8: 0xD57F2F,
9: 0xD5D52F,
10: 0x64D52F,
11: 0x2FD557,
}
return switcher.get(round((datetime.datetime.now() - starting_time).total_seconds()%11))
但是在颜色之间确实有很大的跨度,而且看上去笨拙。
答案 0 :(得分:4)
关键是要简单地计算每个步骤中每个通道(a,r,g和b)的更改量。 Pygame的import React from 'react';
import ReactDOM from 'react-dom';
import HouseFull from '../HouseFull';
import {shallow} from 'enzyme';
test('check HouseFull Render', () => {
const div = document.createElement('div');
ReactDOM.render(<HouseFull />, div);
});
it('Check for prop = true', () => {
const wrapper = shallow(<HouseFull hasSeat={true}/>);
expect(wrapper.text().toLowerCase()).toEqual('vacant');
});
it('Check for prop = false', () => {
const wrapper = shallow(<HouseFull hasSeat={false}/>);
expect(wrapper.text().toLowerCase()).toEqual('housefull');
//expect(wrapper.contains(<div>HouseFull</div>)).toEqual(true);
});
类非常方便,因为它允许在每个通道上进行迭代,并且输入灵活,因此您可以更改例如在下面的示例中,从Color
到'blue'
,它将仍然运行。
这是一个简单的示例:
0x2FD596
如果您不想依赖于帧速率,而是使用基于时间的方法,则可以将代码更改为:
import pygame
import itertools
pygame.init()
screen = pygame.display.set_mode((800, 600))
colors = itertools.cycle(['green', 'blue', 'purple', 'pink', 'red', 'orange'])
clock = pygame.time.Clock()
base_color = next(colors)
next_color = next(colors)
current_color = base_color
FPS = 60
change_every_x_seconds = 3.
number_of_steps = change_every_x_seconds * FPS
step = 1
font = pygame.font.SysFont('Arial', 50)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
text = font.render('fading {a} to {b}'.format(a=base_color, b=next_color), True, pygame.color.Color('black'))
step += 1
if step < number_of_steps:
# (y-x)/number_of_steps calculates the amount of change per step required to
# fade one channel of the old color to the new color
# We multiply it with the current step counter
current_color = [x + (((y-x)/number_of_steps)*step) for x, y in zip(pygame.color.Color(base_color), pygame.color.Color(next_color))]
else:
step = 1
base_color = next_color
next_color = next(colors)
screen.fill(pygame.color.Color('white'))
pygame.draw.circle(screen, current_color, screen.get_rect().center, 100)
screen.blit(text, (230, 100))
pygame.display.update()
clock.tick(FPS)
答案 1 :(得分:3)
您可以将所有颜色从一种颜色转换为另一种颜色,方法是将其转换为int,增加数字,然后将其转换回十六进制。然后循环,直到达到下一个值,如下所示:
value1 = 0xff00ff
value2 = 0xffffff
increment = 1 # amount to decrease or increase the hex value by
while value1 != value2:
if value1 > value2:
if int(value1)-increment < int(value2): # failsafe if the increment is greater than 1 and it skips being the value
value1 = value2
else:
value1 = hex(int(value1)-increment)
else:
if int(value1)+increment > int(value2):
value1 = value2
else:
value1 = hex(int(value1)+increment)
code_to_change_colour(value1)
有关此实现的更优雅的实现,请参见Prune的编辑。请注意,code_to_change_colour(value1)
应该更改为,但是您要在程序中更改颜色。增量将使您更改跳过的颜色数。显然,此代码需要以易于使用的方式进行编辑:例如类似def fade(value1, value2)
的函数。
通过@Prune编辑-因为代码在注释中无法正常工作。
请注意,您编写的大部分内容都是“仅”循环控制。您已经知道了起始值和终止值以及固定的增量。这建议使用for
循环而不是while
。考虑一下:
value1 = int(0xff00ff)
value2 = int(0xffffff)
increment = 1 if value1 < value2 else -1
for current in range(value1, value2, increment):
code_to_change_colour(hex(value1))
value1 = value2
答案 2 :(得分:2)
如果您只想计算颜色(不使用任何表面),则可以执行以下操作:
首先,您需要确定溶解所需的时间。您还需要存储原始和最终颜色。最后,计算混合。我将为此创建一个类:
import pygame
import time
class color_blend:
def __init__(self, start_color, end_color, duration=1000):
self.start_color = pygame.Color(start_color.r, start_color.g, start_color.b)
self.current_color = pygame.Color(start_color.r, start_color.g, start_color.b)
self.end_color = end_color
self.duration = float(duration)
self.start_time = color_blend.millis()
# Return current time in ms
@staticmethod
def millis():
return (int)(round(time.time() * 1000))
# Blend any 2 colors
# 0 <= amount <= 1 (0 is all initial_color, 1 is all final_color)
@staticmethod
def blend_colors(initial_color, final_color, amount):
# Calc how much to add or subtract from start color
r_diff = (final_color.r - initial_color.r) * amount
g_diff = (final_color.g - initial_color.g) * amount
b_diff = (final_color.b - initial_color.b) * amount
# Create and return new color
return pygame.Color((int)(round(initial_color.r + r_diff)),
(int)(round(initial_color.g + g_diff)),
(int)(round(initial_color.b + b_diff)))
def get_next_color(self):
# Elapsed time in ms
elapsed_ms = color_blend.millis() - self.start_time
# Calculate percentage done (0 <= pcnt_done <= 1)
pcnt_done = min(1.0, elapsed_ms / self.duration)
# Store new color
self.current_color = color_blend.blend_colors(self.start_color, self.end_color, pcnt_done)
return self.current_color
def is_finished(self):
return self.current_color == self.end_color
# Blend red to green in .3 seconds
c = color_blend(pygame.Color(255, 0, 0), pygame.Color(0, 255, 0), 300)
while not c.is_finished():
print(c.get_next_color())
您可以轻松地对此进行修改以进行非线性混合。例如,在blend_colors
中:amount = math.sin(amount * math.pi)
(我不是Pygame专家-可能已经有内置功能了。)
答案 3 :(得分:1)
在新颜色的背景上,将前景色设置为旧颜色。使用set_alpha()
执行淡入淡出。一旦您完全采用了新颜色,就可以使该表面成为前景,并为您的第三种颜色创建新背景。根据需要重复。
This question和其他对“ fade”和set_alpha()
的引用应该可以使您完成工作。
就足以让您动起来吗?
答案 4 :(得分:1)
我犹豫要发布答案,因为我想出了与Sloth几乎相同的答案,但我只想提及linear interpolation(简称lerp
,在英文中也称为mix
OpenGL / GLSL)。它通常用于两种颜色之间的混合,但是不幸的是pygame的Color
类没有lerp方法,因此您必须定义自己的lerp
函数并使用列表推导来内插RGBA值。
这是Wikipedia移植到Python的lerp
函数(t
是权重,必须在0到1之间):
def lerp(v0, v1, t):
return (1 - t) * v0 + t * v1
现在,您可以通过列表理解来掌握两种颜色的RGBA值。
color = [lerp(v0, v1, t) for v0, v1 in zip(color1, color2)]
例如:
>>> [lerp(v0, v1, .5) for v0, v1 in zip((0, 0, 0), (255, 255, 255))]
[127.5, 127.5, 127.5]
>>> [lerp(v0, v1, .25) for v0, v1 in zip((0, 0, 0), (255, 255, 255))]
[63.75, 63.75, 63.75]
如果不需要Alpha通道,还可以使用pygame的Vector3类,该类具有lerp
方法来设置颜色,那么您只需要编写:{{1} }。
color = color1.lerp(color2, t)
答案 5 :(得分:0)
不久前我遇到了类似的问题,我走了一条疯狂的路线,学习一些微积分来做到这一点 R = X,G = Y,B = Z
然后编写了一个程序来计算R0和R1(X0和X1)等之间的差。
#Nick Poling
#Fade Test V2
import random
#import mpmath
#import sympy
import time
import pygame
import shelve
import sys
from pygame.locals import *
#Always Initialize
pygame.init()
#sympy contains function line_3d?
#top level?
#formated string?
#Change Name Displayed in Corner
MY_FONT = 'freesansbold.ttf'
FONTSIZE_1 = 20
pygame.display.set_caption('Fade Test V2')
GAME_NAME = pygame.font.Font(MY_FONT, FONTSIZE_1)
#Boards
GAME_SCREEN_WIDTH = 900
GAME_SCREEN_HEIGHT = 600
Main_Game_Loop = 1
def get_close_out():
#Save_Game = get_Save_Game()
pygame.quit()
sys.exit()
def get_Save_Game():
#Save
global Main_Game_Loop
global GAME_SCREEN_COLOR
global GAME_SCREEN_WIDTH
global GAME_SCREEN_HEIGHT
saveGameShelfFile = shelve.open('Fade Test V1')
saveGameShelfFile['GAME_SCREEN_WIDTH'] = GAME_SCREEN_WIDTH
saveGameShelfFile['GAME_SCREEN_HEIGHT'] = GAME_SCREEN_HEIGHT
def get_Load_Game():
global Main_Game_Loop
global GAME_SCREEN_COLOR
global GAME_SCREEN_WIDTH
global GAME_SCREEN_HEIGHT
try:
#Load
saveGameShelfFile = shelve.open('Fade Test V1')
GAME_SCREEN_WIDTH = saveGameShelfFile['GAME_SCREEN_WIDTH']
GAME_SCREEN_HEIGHT = saveGameShelfFile['GAME_SCREEN_HEIGHT']
except:
#Save
#Save_Game = get_Save_Game()
#Load
saveGameShelfFile = shelve.open('Fade Test V1')
GAME_SCREEN_WIDTH = saveGameShelfFile['GAME_SCREEN_WIDTH']
GAME_SCREEN_HEIGHT = saveGameShelfFile['GAME_SCREEN_HEIGHT']
GAME_SCREEN = pygame.display.set_mode((GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT),pygame.RESIZABLE)
#By putting the GAME_SCREEN here you can make the resize doable with the press of a button
#Does need to be un "#" to work when press "L"
def get_Colors():
#Colors
global BLACK
global WHITE
BLACK = [0, 0, 0]
WHITE = [255,255,255]
def get_Main_Game():
global Main_Game_Loop
global GAME_SCREEN_COLOR
global GAME_SCREEN_WIDTH
global GAME_SCREEN_HEIGHT
global BLACK
global WHITE
global Point_1
global Point_2
global Vector_1
global Vector_2
Colors = get_Colors()
GAME_SCREEN_COLOR = BLACK
#Load_Game = get_Load_Game()
GAME_SCREEN = pygame.display.set_mode((GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT),pygame.RESIZABLE)
while Main_Game_Loop == 1:
GAME_SCREEN.fill(GAME_SCREEN_COLOR)
Equation_Of_Lines_in_3D_Space = get_Equation_Of_Lines_in_3D_Space()
for t in range(0,255):
XYZ_1 = [Point_1[0] + (Vector_1[0] * t), Point_1[1] + (Vector_1[1] * t), Point_1[2] + (Vector_1[2] * t)]
XYZ_2 = [Point_2[0] + (Vector_2[0] * t), Point_2[1] + (Vector_2[1] * t), Point_2[2] + (Vector_2[2] * t)]
GAME_SCREEN_COLOR = XYZ_1
GAME_SCREEN.fill(GAME_SCREEN_COLOR)
ticks = pygame.time.delay(5)
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
close_out = get_close_out()
elif event.type == pygame.VIDEORESIZE:
# There's some code to add back window content here.
surface = pygame.display.set_mode((event.w, event.h),pygame.RESIZABLE)
GAME_SCREEN_HEIGHT = event.h
GAME_SCREEN_WIDTH = event.w
pygame.display.update()
def get_Equation_Of_Lines_in_3D_Space():
global Point_1
global Point_2
global BLACK
global WHITE
global Vector_1
global Vector_2
global LCM_X1
global LCM_X2
global LCM_Y1
global LCM_Y2
global LCM_Z1
global LCM_Z2
Point_1 = BLACK
Point_2 = WHITE
Vector_1 = []
Vector_2 = []
LCM_X1 = []
LCM_X2 = []
LCM_Y1 = []
LCM_Y2 = []
LCM_Z1 = []
LCM_Z2 = []
for i in range(0,3):
#
Delta_XYZ_1 = Point_2[i] - Point_1[i]
Vector_1.append(Delta_XYZ_1)
Delta_XYZ_2 = Point_1[i] - Point_2[i]
Vector_2.append(Delta_XYZ_2)
factors = get_factors()
def get_factors():
global num_1
global num_2
global Vector_1
global Vector_2
global LCM_XYZ_1
global LCM_XYZ_2
for i in range(1,7):
if i == 1:
num_1 = Vector_1[0]
num_2 = 1
elif i == 2:
num_1 = Vector_2[0]
num_2 = 2
elif i == 3:
num_1 = Vector_1[1]
num_2 = 3
elif i == 4:
num_1 = Vector_2[1]
num_2 = 4
elif i == 5:
num_1 = Vector_1[2]
num_2 = 5
elif i == 6:
num_1 = Vector_2[2]
num_2 = 6
get_largest_and_lowest_common_factors(num_1)
get_LCM_XYZ()
Vector_1[0] = Vector_1[0] / LCM_XYZ_1[0]
Vector_1[1] = Vector_1[1] / LCM_XYZ_1[0]
Vector_1[2] = Vector_1[2] / LCM_XYZ_1[0]
#
Vector_2[0] = Vector_2[0] / LCM_XYZ_2[0]
Vector_2[1] = Vector_2[1] / LCM_XYZ_2[0]
Vector_2[2] = Vector_2[2] / LCM_XYZ_2[0]
def get_largest_and_lowest_common_factors(x):
global num_1
global num_2
global Vector_1
global Vector_2
global LCM_X1
global LCM_X2
global LCM_Y1
global LCM_Y2
global LCM_Z1
global LCM_Z2
#This function takes a number and puts its factor into a list
for i in range(1, x + 1) or range(-x, x - 1, -1):
try:
if x % i == 0:
if num_1 == Vector_1[0] and num_2 == 1:
LCM_X1.append(i)
elif num_1 == Vector_1[1] and num_2 == 3:
LCM_Y1.append(i)
elif num_1 == Vector_1[2] and num_2 == 5:
LCM_Z1.append(i)
elif num_1 == Vector_2[0] and num_2 == 2:
LCM_X2.append(i)
elif num_1 == Vector_2[1] and num_2 == 4:
LCM_Y2.append(i)
elif num_1 == Vector_2[2] and num_2 == 6:
LCM_Z2.append(i)
except ZeroDivisionError:
return 0
def get_LCM_XYZ():
global LCM_X1
global LCM_Y1
global LCM_Z1
global LCM_X2
global LCM_Y2
global LCM_Z2
global LCM_XYZ_1
global LCM_XYZ_2
#If 1 is 0
check_1 = 0
check_2 = 0
check_3 = 0
for i in range(0,3):
if i == 0:
if LCM_X1 == [] and LCM_X2 == []:
check_1 = 1
elif i == 1:
if LCM_Y1 == [] and LCM_Y2 == []:
check_2 = 2
elif i == 2:
if LCM_Z1 == [] and LCM_Z2 == []:
check_3 = 3
F_check = check_1 + check_2 + check_3
if F_check == 1:
LCM_X1.extend(LCM_Y1)
LCM_X2.extend(LCM_Y2)
elif F_check == 2:
LCM_Y1.extend(LCM_X1)
LCM_Y2.extend(LCM_X2)
elif F_check == 3:
if check_2 == 0:
LCM_Z1.extend(LCM_Y1)
LCM_Z2.extend(LCM_Y2)
elif check_2 != 0:
LCM_X1.extend(LCM_Z1)
LCM_X2.extend(LCM_Z2)
LCM_Y1.extend(LCM_Z1)
LCM_Y2.extend(LCM_Z2)
elif F_check == 4:
LCM_X1.extend(LCM_Y1)
LCM_X2.extend(LCM_Y2)
LCM_Z1.extend(LCM_Y1)
LCM_Z2.extend(LCM_Y2)
elif F_check == 5:
LCM_Y1.extend(LCM_X1)
LCM_Y2.extend(LCM_X2)
LCM_Z1.extend(LCM_X1)
LCM_Z2.extend(LCM_X2)
elif F_check == 6:
LCM_X1.append(1)
LCM_X2.append(1)
LCM_Y1.append(1)
LCM_Y2.append(1)
LCM_Z1.append(1)
LCM_Z2.append(1)
LCM_X1 = set(LCM_X1)
LCM_Y1 = set(LCM_Y1)
LCM_Z1 = set(LCM_Z1)
LCM_X2 = set(LCM_X2)
LCM_Y2 = set(LCM_Y2)
LCM_Z2 = set(LCM_Z2)
LCM_XYZ_1 = list(set.intersection(LCM_X1,LCM_Y1,LCM_Z1))
LCM_XYZ_2 = list(set.intersection(LCM_X2,LCM_Y2,LCM_Z2))
LCM_XYZ_1.sort(reverse = True)
LCM_XYZ_2.sort(reverse = True)
Main_Game = get_Main_Game()
答案 6 :(得分:0)
Pygame 提供 pygame.Color
对象。该对象可以从各种参数(例如 RGBA 颜色通道、十六进制数字、字符串等)构造颜色。
它还提供了方便的方法 lerp
,可以插入 2 种颜色:
返回一个颜色,它是自身和 RGBA 空间中给定颜色之间的线性插值
使用 pygame.Color
对象和 lerp
方法从颜色列表中插入颜色:
def lerp_color(colors, value):
fract, index = math.modf(value)
color1 = pygame.Color(colors[int(index) % len(colors)])
color2 = pygame.Color(colors[int(index + 1) % len(colors)])
return color1.lerp(color2, fract)
插值值必须随时间变化。使用 pygame.time.get_ticks
以毫秒为单位获取当前时间:
colors = ["green", "blue", "purple", "pink", "red", "orange", "yellow"]
value = (pygame.time.get_ticks() - start_time) / 1000
current_color = lerp_color(colors, value)
最小示例:
import pygame, math
def lerp_color(colors, value):
fract, index = math.modf(value)
color1 = pygame.Color(colors[int(index) % len(colors)])
color2 = pygame.Color(colors[int(index + 1) % len(colors)])
return color1.lerp(color2, fract)
pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
start_time = pygame.time.get_ticks()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
start_time = pygame.time.get_ticks()
colors = ["green", "blue", "purple", "pink", "red", "orange", "yellow"]
value = (pygame.time.get_ticks() - start_time) / 1000
current_color = lerp_color(colors, value)
window.fill((255, 255, 255))
pygame.draw.circle(window, current_color, window.get_rect().center, 100)
pygame.display.flip()
pygame.quit()
exit()