Skip to content

Instantly share code, notes, and snippets.

@kobaltcore
Created May 21, 2020 16:20
Show Gist options
  • Save kobaltcore/2d2d913e513d25f02f4800e41fbbee8d to your computer and use it in GitHub Desktop.
Save kobaltcore/2d2d913e513d25f02f4800e41fbbee8d to your computer and use it in GitHub Desktop.
Experiments in Ren'Py heresy.
label start:
"This is the {wiggle}wiggle effect{/wiggle}."
"This is the {nearest}nearest effect{/nearest}."
"This is the {fire}fire effect{/fire}."
init python:
import math
import random
import pygame
class Appearing(renpy.Displayable):
def __init__(self, text, opaque_distance, transparent_distance, **kwargs):
super(Appearing, self).__init__(**kwargs)
self.text = Text(text)
self.opaque_distance = opaque_distance
self.transparent_distance = transparent_distance
self.alpha = 0.0
self.width = 0
self.height = 0
def render(self, width, height, st, at):
t = Transform(child=self.text, alpha=self.alpha)
child_render = renpy.render(t, width, height, st, at)
self.width, self.height = child_render.get_size()
render = renpy.Render(self.width * 0.98, self.height)
render.blit(child_render, (0, -(self.height * 0.1)))
return render
def event(self, ev, x, y, st):
distance = math.hypot(x, y - (self.height / 2))
if distance <= self.opaque_distance:
alpha = 1.0
elif distance >= self.transparent_distance:
alpha = 0.0
else:
alpha = 1.0 - 1.0 * (distance - self.opaque_distance) / (self.transparent_distance - self.opaque_distance)
if alpha != self.alpha:
self.alpha = alpha
renpy.redraw(self, 0)
return self.text.event(ev, x, y, st)
def visit(self):
return [self.text]
class Wiggle(renpy.Displayable):
def __init__(self, text, **kwargs):
super(Wiggle, self).__init__(**kwargs)
self.text = Text(text)
self.chars = [Text(char) for char in text]
self.t = 0
self.radius = 3
self.speed = -0.3
self.frequency = 5
self.spread_x = 1.5
def render(self, width, height, st, at):
width, height = self.text.size()
x0, y0 = 0, -(height * 0.15)
render = renpy.Render(width + (width * 0.15), height)
for i, char in enumerate(self.chars):
child_render = char.render(width, height, st, at)
dx = self.radius * math.cos(self.t / self.frequency + self.speed * i) * self.spread_x
dy = self.radius * math.sin(self.t / self.frequency + self.speed * i)
render.blit(child_render, (x0 + dx, y0 + dy))
x0 += child_render.get_size()[0]
self.t += 1
renpy.redraw(self, 0)
return render
def visit(self):
return self.chars
class Fire(renpy.Displayable):
def __init__(self, text, **kwargs):
super(Fire, self).__init__(**kwargs)
self.text = Text(text)
self.width, self.height = map(int, self.text.size())
"""generate palette to draw intermediate fire"""
self.fire = [[0 for _ in range(self.height)] for _ in range(self.width)]
# generate palette
self.palette = [0 for _ in range(255)]
# palette should be something from black to yellow red
self.palette[0] = pygame.Color(0, 0, 0, 255)
for index in range(1, 255):
color = pygame.Color(0, 0, 0, 255)
# original C Comments
# Hue goes from 0 to 85: red to yellow
# Saturation is always the maximum: 255
# Lightness is 0..100 for x=0..128, and 255 for x=128..255
# color = HSLtoRGB(ColorHSL(x / 3, 255, std::min(255, x * 2)));
color.hsla = (index, 100, index / 1.2, 255)
self.palette[index] = color
def render(self, width, height, st, at):
render = renpy.Render(self.width, self.height)
text_render = self.text.render(self.width, self.height, st, at)
render.blit(text_render, (0, -(self.height * 0.1)))
array2d = render.canvas().get_surface()
"""update every frame"""
# random baseline
for x in range(self.width):
self.fire[x][self.height - 9] = abs(32768 + random.randint(0, 32768)) % 256
# calculate each pixel according to neighbours
for y in range(self.height - 8):
for x in range(self.width):
# every new point depends on O Points
# N
# OOO
# O
self.fire[x][y] = \
((self.fire[(x - 1) % self.width][(y + 1) % self.height] \
+ self.fire[(x) % self.width][(y + 2) % self.height] \
+ self.fire[(x + 1) % self.width][(y + 1) % self.height] \
+ self.fire[(x) % self.width][(y + 3) % self.height]) \
* 16) / 65
# the last factor 16/65 should be slightly larger than 4
# and lesser than 5
# closer to 4 will make flames higher
array2d.set_at((x, y), self.palette[int(self.fire[x][y])])
# render.blit(text_render, (0, -(self.height * 0.1)))
renpy.redraw(self, 0)
return render
def visit(self):
return [self.text]
def wiggle_tag(tag, argument, contents):
return [(renpy.TEXT_DISPLAYABLE, Wiggle(contents[0][1]))]
config.custom_text_tags["wiggle"] = wiggle_tag
def nearest_tag(tag, argument, contents):
if "(" in argument:
argument = eval(argument)
opaque_distance, transparent_distance = argument[0], argument[1]
elif not argument:
opaque_distance, transparent_distance = 100, 200
return [(renpy.TEXT_DISPLAYABLE, Appearing(contents[0][1], opaque_distance, transparent_distance))]
config.custom_text_tags["nearest"] = nearest_tag
def fire_tag(tag, argument, contents):
return [(renpy.TEXT_DISPLAYABLE, Fire(contents[0][1]))]
config.custom_text_tags["fire"] = fire_tag
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment