User:DressyPear4/TextoAnimado
From OpenStreetMap Wiki
Jump to navigation
Jump to search
Texto animado
Criar uma janela com texto personalizado e comemorativo, pode deixar em full ou antes de tutoriais
Demonstração

Código
from javax.swing import JFrame, JPanel, Timer
from java.awt.image import BufferedImage
from java.awt import Color, Font, Dimension, BorderLayout, RenderingHints
from java.awt.event import MouseAdapter, ActionListener
import math
import random
def safeColor(r, g, b, a=255):
clamp = lambda v: max(0, min(255, int(v)))
return Color(clamp(r), clamp(g), clamp(b), clamp(a))
class FireworkParticle:
def __init__(self, x, y, vx, vy, color, life=60, gravity=0.15, fade=True):
self.x = x
self.y = y
self.vx = vx
self.vy = vy
self.max_life = float(life)
self.life = life
self.color = color
self.gravity = gravity
self.fade = fade
def animate(self):
self.x += self.vx
self.y += self.vy
self.vy += self.gravity
if self.fade:
self.life -= 1
def draw(self, g):
if self.fade and self.life <= 0: return
alpha = int(255 * (self.life / self.max_life)) if self.fade else 255
g.setColor(safeColor(self.color.getRed(), self.color.getGreen(), self.color.getBlue(), alpha))
g.fillOval(int(self.x), int(self.y), 3, 3)
class FireworksPanel(JPanel):
def __init__(self):
JPanel.__init__(self)
self.particles = []
self.textParticles = []
self.textCoords = []
self.textToDisplay = "FELIZ 2026"
self.hasExplodedText = False
self.lastW, self.lastH = 0, 0 # Para detectar redimensionamento
class ClickHandler(MouseAdapter):
def __init__(self, outer): self.outer = outer
def mousePressed(self, e): self.outer.explode(e.getX(), e.getY())
self.addMouseListener(ClickHandler(self))
def explodeText(self, w, h):
"""Recalcula o texto baseado no tamanho atual da tela"""
self.textParticles = []
self.textCoords = []
# Ajusta o tamanho da fonte proporcional à largura da tela
fontSize = int(w / 7.5)
font = Font("Serif", Font.BOLD, fontSize)
img = BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB)
g2d = img.createGraphics()
g2d.setFont(font)
metrics = g2d.getFontMetrics(font)
tx = (w - metrics.stringWidth(self.textToDisplay)) / 2
ty = (h / 2) + (metrics.getAscent() / 4)
g2d.setColor(Color.WHITE)
g2d.drawString(self.textToDisplay, int(tx), int(ty))
g2d.dispose()
baseColor = Color(255, 215, 0)
for py in range(0, h, 4):
for px in range(0, w, 4):
if (img.getRGB(px, py) >> 24) & 0xFF > 0:
self.textCoords.append((px, py))
self.textParticles.append(FireworkParticle(px, py, 0, 0, baseColor, gravity=0, fade=False))
def explode(self, x, y):
tipo = random.choice(["circle", "double_ring", "heart", "fountain"])
baseColor = safeColor(random.randint(100,255), random.randint(100,255), random.randint(100,255))
if tipo == "circle":
for i in range(60):
ang = random.uniform(0, 2 * math.pi)
spd = random.uniform(2, 6)
self.particles.append(FireworkParticle(x, y, math.cos(ang)*spd, math.sin(ang)*spd, baseColor))
elif tipo == "double_ring":
cor2 = safeColor(random.randint(100,255), 255, 255)
for i in range(40):
ang = (2 * math.pi / 40) * i
self.particles.append(FireworkParticle(x, y, math.cos(ang)*3, math.sin(ang)*3, baseColor))
self.particles.append(FireworkParticle(x, y, math.cos(ang)*6, math.sin(ang)*6, cor2))
elif tipo == "heart":
for i in range(60):
t = random.uniform(0, 2 * math.pi)
vx = 16 * math.sin(t)**3
vy = -(13 * math.cos(t) - 5 * math.cos(2*t) - 2 * math.cos(3*t) - math.cos(4*t))
self.particles.append(FireworkParticle(x, y, vx*0.25, vy*0.25, Color.RED, life=80))
elif tipo == "fountain":
cor = safeColor(200, 255, 255)
for i in range(40):
self.particles.append(FireworkParticle(x, y, random.uniform(-1.5, 1.5), random.uniform(-5, -9), cor, life=70))
def step(self):
w, h = self.getWidth(), self.getHeight()
if w <= 0 or h <= 0: return
# Se a tela mudou de tamanho ou o texto ainda não explodiu
if not self.hasExplodedText or w != self.lastW or h != self.lastH:
self.explodeText(w, h)
self.hasExplodedText = True
self.lastW, self.lastH = w, h
# Cascata infinita
if self.textCoords:
for _ in range(12):
cx, cy = random.choice(self.textCoords)
self.particles.append(FireworkParticle(cx, cy, 0, random.uniform(0.5, 1.5), Color(255,215,0, 150), life=35, gravity=0.08))
# Fogos aleatórios na tela toda
if random.random() < 0.05:
self.explode(random.randint(50, w-50), random.randint(50, h-100))
for p in self.particles[:]:
p.animate()
if p.life <= 0: self.particles.remove(p)
self.repaint()
def paintComponent(self, g):
# Background com rastro
g.setColor(Color(0, 0, 0, 50))
g.fillRect(0, 0, self.getWidth(), self.getHeight())
for p in self.textParticles: p.draw(g)
for p in self.particles: p.draw(g)
class App(object):
def __init__(self):
self.frame = JFrame("Show de Fogos 2026")
self.frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
self.frame.setLayout(BorderLayout())
self.firePanel = FireworksPanel()
self.firePanel.setPreferredSize(Dimension(800, 600))
self.frame.add(self.firePanel, BorderLayout.CENTER)
self.frame.pack()
self.frame.setLocationRelativeTo(None)
self.frame.setVisible(True)
class TimerListener(ActionListener):
def __init__(self, panel): self.panel = panel
def actionPerformed(self, e): self.panel.step()
self.timer = Timer(30, TimerListener(self.firePanel))
self.timer.start()
if __name__ in ['__main__', 'main']:
App()