Mirrage/Heat Shimmer/Kagerou Effect Displayable
Posted: Thu Mar 26, 2015 9:09 pm
Scanline code flagrantly stolen adapted from Human Bolt Diary's Perspective Displayable.
The following will take a displayable and show a screen consisting of that displayable with animated "heat haze" style mirage. It accomplishes this by slicing the image into horizontal lines, and then stretching and offsetting this lines by an oscillating amount, that shifts in phase as time passes
I originally developed it for providing the illusion of a heavily magnified view of a far away object on the horizon, but see it as more useful for anything requiring a heat shimmer, great for fiery ovens, searing deserts, scorching alien stars, and the occasional steamy onsen or noxious smog. Those indulging in stumbling intoxication may also find the effect appropriate.
it could also conceivably be used at low amplitudes in combination with a raster scanline texture to give the illusion of an retro tv/computer monitor
The magnitude of offset and stretch can be manipulated with the "amplitude" variable.
The frequency of the wave is determined by the inverse of the "wavelength" variable
The cycle time is determined by the number of slices and shown timebase. As this is a resource intensive process, please don't expect this to be a rapid animation
The following will take a displayable and show a screen consisting of that displayable with animated "heat haze" style mirage. It accomplishes this by slicing the image into horizontal lines, and then stretching and offsetting this lines by an oscillating amount, that shifts in phase as time passes
I originally developed it for providing the illusion of a heavily magnified view of a far away object on the horizon, but see it as more useful for anything requiring a heat shimmer, great for fiery ovens, searing deserts, scorching alien stars, and the occasional steamy onsen or noxious smog. Those indulging in stumbling intoxication may also find the effect appropriate.
it could also conceivably be used at low amplitudes in combination with a raster scanline texture to give the illusion of an retro tv/computer monitor
The magnitude of offset and stretch can be manipulated with the "amplitude" variable.
The frequency of the wave is determined by the inverse of the "wavelength" variable
The cycle time is determined by the number of slices and shown timebase. As this is a resource intensive process, please don't expect this to be a rapid animation
Code: Select all
init python:
import math
import pygame
######################################## Mirage Heat Shimmer Distortion Effect #####################################
test_image = Image("example.jpg") # Whatever image we're distorting
class Mirage(renpy.Displayable):
def __init__(self,image):
super(renpy.Displayable,self).__init__()
self.start_image = image
self.W2 = config.screen_width/2
self.H2 = config.screen_height/2
self.amplitude = 0.02
self.wavelength = 10
# Stretch each scanline horizontally, oscillating from +amplitude to -amplitude across specified wavelength
# Shift oscillation over time by st
def render(self,width,height,st,at):
render = renpy.Render(0, 0)
self.img = self.start_image
self.img = self.makeScanlines(self.img)
h = 1.0
for scanline in self.img:
zoom_factor = 1.0-self.amplitude
# math.sin(x) returns the sine of x radians
self.t = Transform(scanline, xzoom=(1/zoom_factor)+(math.sin(h/self.wavelength + st)*self.amplitude), yzoom=(1.01))
h +=1.0
child_render = renpy.render(self.t, 0, 0, st, at)
cW,cH = child_render.get_size()
#final ammount subtracted from h sets y placement
render.blit(child_render, ((self.W2)-(cW/2),h - 0))
renpy.redraw(self, 0.1)
return render
# Cut image into scanlines
def makeScanlines(self, base_image):
cut = []
child_render = renpy.render(base_image, config.screen_width, config.screen_height, 0, 0)
width = int(child_render.get_size()[0]) #Prevents get_size from returning a float
height = int(child_render.get_size()[1])
cut = [Transform(base_image, crop=(0,i,width,1)) for i in range(height)]
return cut
init:
define Distortion = Mirage(test_image)
image before = test_image
# Screen drawn onto
screen after:
add Distortion
# The game starts here.
label start:
show before
"before"
show screen after
"after"
return