This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
I've been looking through ATL and Transform() documentation, and I haven't seen anything regarding a perspective manipulation on an image and/or displayable. Is there a sort of Matrix Transform I'm not aware of, or is this feature not available at all?
Your wish has come true! (Kinda, not really)Asceai wrote:I wish.
My math skills are not nearly strong enough to seriously attempt this, but reading articles on the SNES Mode 7 put crazy ideas in my head.
The following displayable uses crop to make scanlines and a xzoom to fake out the perspective effect. As is, it's probably too inefficient/resource intensive for anything more complex than a tiny demo, but here we go:
Keyboard left and right keys to rotate, up key to activate/deactivate the effect. Make test_image whatever displayable you want to use.
Code: Select all
init python: test_image = Image("img_00.png") #Whatever image we're distorting class Perspective(renpy.Displayable): def __init__(self,image): super(renpy.Displayable,self).__init__() self.start_image = image self.W2 = config.screen_width * 0.5 self.H2 = config.screen_height * 0.5 self.active = False self.dir = 0 #Rotation amount def render(self,width,height,st,at): render = renpy.Render(0, 0) #Rotate the image before cutting it into scanlines and displaying it self.img = Transform(self.start_image, xanchor=0.5,yanchor=0.5,rotate=self.dir) self.img = self.makeScanlines(self.img) h = 1.0 ay = self.H2 for scanline in self.img: if self.active == False: zoom_factor = 1 else: zoom_factor = 100.0 / ay self.t = Transform(scanline, xzoom=(1/zoom_factor)) h +=1.0 ay +=1.0 child_render = renpy.render(self.t, 0, 0, st, at) cW,cH = child_render.get_size() render.blit(child_render, ((self.W2)-(cW/2),(self.H2)+h)) return render #Keyboard Events def event(self, ev, x, y, st): import pygame if ev.type == pygame.KEYDOWN: if ev.key == pygame.K_LEFT: if self.dir >= 360: self.dir = 0 else: self.dir += 3 renpy.redraw(self, 0) if ev.key == pygame.K_RIGHT: if self.dir <= -360: self.dir = 0 else: self.dir -= 3 renpy.redraw(self, 0) if ev.key == pygame.K_UP: if self.active == False: self.active = True else: self.active = False renpy.redraw(self, 0) #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()) #Prevents get_size from returning a float height = int(child_render.get_size()) cut = [Transform(base_image, crop=(0,i,width,1)) for i in range(height)] return cut #Screen drawn onto screen test: add Perspective(test_image): xanchor 0.5 yanchor 0.5 # The game starts here. label start: call screen test return
- Eileen-Class Veteran
- Posts: 1258
- Joined: Fri Sep 21, 2007 7:13 am
- Projects: a battle engine
Should img_00.png have a minimum or maximum size compared to the screen?
It was meant to be used for small images, around 100x100. Testing with a 1000x1000 image, you'll have to alter the y value of the blit to get it on screen. Of course, using a large image will cause some pretty intense slowdown, even on a small window resolution.
The most important thing to note is that while the code above will give a reasonably distorted image, the math isn't actually correct, it's not stretching at the correct amounts per scanline.