Author Topic: Roof Fading script  (Read 300 times)

MetalZelda

  • Hero Member
  • *****
  • Posts: 546
    • View Profile
Roof Fading script
« on: March 26, 2018, 05:45:06 pm »
This was a script I had in mind some times ago and decided to put this to my project, this was done in 2 hours of hard debugging and getting right values in February 2018, it was revised yersteday and now use userdata rather than dynamic tiles.
This is hardly based on Project Zelda Engine's system, this time, you don't have to cut and make graphics for this, you just need to do some boring stuffs using table, programmers love tables, everyone love tables

A little resumé of what it does in glorious glitchy hypercam 4 which does not render any justice to the video
https://www.youtube.com/watch?v=9H0unEaBCwY

As you might see, this is a cool "room transition", if you have a hugeload of rooms in only 1 maps this is a cool workaround, this works excellently on inside type tilesets. I personnaly use it on Houses and Dungeons

For this script, you need :
- [Multi Events] by Christopho (http://forum.solarus-games.org/index.php/topic,784.0.html)
- Create a folder called "roof_texture" in /sprites and put all your desired roof texture in there


To use this script, you need :
- Open main.lua
- C/P this code in main.lua, remember to change path_of_the_script to the path of this script
Code: Lua
  1. local map_metatable = sol.main.get_metatable("map")
  2. require(path_of_the_script)(map_metatable)
  3.  

Let's talk real deal will ya

Code: Lua
  1. --[[
  2.   Fadable rooms
  3.   Made by MetalZelda
  4.   Inspired by: Project Zelda Engine
  5.   Feb.2018 - Rev Mar.2018
  6.   Version 1.6
  7.  
  8.   REQUIRED:
  9.  
  10.   - [Multi Events] by Christopho
  11.     (http://forum.solarus-games.org/index.php/topic,784.0.html)
  12.  
  13.   Simulate multiple rooms by hiding one using a table
  14.  
  15.   {
  16.     texture = {
  17.          src = "texture_path",
  18.          opacity = 0 - 255,
  19.         }
  20.     x = x position of the roof
  21.     y = y position of the roof
  22.     width = horizontal lenght of the roof
  23.     height = vertical lenght of the roof
  24.     color = {r, g, b} (color of the roof)
  25.   }
  26.  
  27.   color can be omnitted if using a texture
  28.   texture can be omnitted if using a color preset
  29.  
  30.   You can combine both by using a semi-transparent texture and apply a color, the color will be drawn bellow
  31.  
  32.   Trigger zone is defined by the script bellow
  33.   Usually: rooms.under = (x >= rooms.x - 9 and x <= rooms.x + rooms.width + 9) and (y >= rooms.y - 6 and y <= rooms.y + rooms.height + 23)
  34. ]]
  35.  
  36. return function(map)
  37.   -- This is the incrementation value, 8 is faster enough
  38.   local opacity_increment = 8
  39.  
  40.   map:register_event("on_started", function(map)
  41.     -- If nothing exists on the rooms table means that there are nothing to display, the scripts stops here.
  42.     if map.fade_rooms == nil then
  43.           return
  44.         end
  45.        
  46.         -- Store additionnal data on the roof table such as surface, color and opacity (default = 255) that can be automatically set by the script
  47.         for num, rooms in ipairs(map.fade_rooms) do
  48.           rooms.surface = sol.surface.create(rooms.width, rooms.height)
  49.          
  50.           if rooms.color then
  51.             rooms.surface:fill_color(rooms.color)
  52.           end
  53.          
  54.           if rooms.texture then
  55.             local texture_surface = sol.surface.create("roof_texture/" .. rooms.texture.src .. ".png")
  56.             local texture_width, texture_height = texture_surface:get_size()
  57.                
  58.                 if rooms.texture.opacity then
  59.               texture_surface:set_opacity(rooms.texture.opacity)
  60.                 end
  61.                
  62.                 -- Get the total pixels to cover
  63.                 local total = ((rooms.width * rooms.height) /  (texture_width * texture_height))
  64.                
  65.                 local x = 0
  66.                 local y = 0
  67.                  
  68.                 for i = 1, total do
  69.                   -- Draw the texture on the right place
  70.                   texture_surface:draw(rooms.surface, x, y)
  71.                  
  72.                   -- Increment next value
  73.                   x = x + texture_width
  74.                  
  75.                   if x >= rooms.width then
  76.                     x = 0
  77.                     y = y + texture_height
  78.                   end
  79.                 end        
  80.           end
  81.          
  82.           rooms.opacity = 255
  83.         end
  84.   end)
  85.  
  86.  
  87.   map:register_event("on_draw", function(map, dst_surface)
  88.     -- To avoid errors, if there is nothing to draw, abort.
  89.     if map.fade_rooms == nil then
  90.           return
  91.         end
  92.        
  93.     for _, rooms in ipairs(map.fade_rooms) do
  94.           local cam_x, cam_y = map:get_camera():get_position()
  95.           rooms.surface:draw(dst_surface, rooms.x - cam_x, rooms.y - cam_y)
  96.          
  97.           local opacity = rooms.opacity
  98.          
  99.           -- Get player position, current layer is not a necessary parameter.
  100.           local x, y = map:get_hero():get_position()
  101.          
  102.           -- Define the rule of being under a roof for any roof.
  103.           rooms.under = (x >= rooms.x - 9 and x <= rooms.x + rooms.width + 9) and (y >= rooms.y - 6 and y <= rooms.y + rooms.height + 23)
  104.          
  105.           -- Define opacity variation for roof
  106.           if rooms.under or rooms.force_under then
  107.             rooms.opacity = rooms.opacity > (opacity_increment - 1) and rooms.opacity - opacity_increment or 0
  108.           else
  109.             rooms.opacity = rooms.opacity < (255 - opacity_increment) and rooms.opacity + opacity_increment or 255
  110.           end
  111.          
  112.           -- Don't need to update any opacity if the game is paused.
  113.           if map:get_game():is_paused() then
  114.             rooms.opacity = opacity
  115.           end
  116.                  
  117.           rooms.surface:set_opacity(rooms.opacity)
  118.         end
  119.   end)
  120.  
  121.   function map:dim_room_surface(i, bool)
  122.     if bool == nil then
  123.           bool = self.fade_rooms[i].force_under == nil and true or (not self.fade_rooms[i].force_under)
  124.         end
  125.     self.fade_rooms[i].force_under = bool
  126.   end
  127. end

You might have a hero that have other size than Link, you can change the trigger range in here
Code: Lua
  1. rooms.under = (x >= rooms.x - 9 and x <= rooms.x + rooms.width + 9) and (y >= rooms.y - 6 and y <= rooms.y + rooms.height + 23)

I did everything I've done but nothing work, give monney back

This is what you should do in your map script in order to make this to work
Let's have the video example above

You can use this texture for testing
https://i.imgur.com/0BwDrP8.png

and rename it "forest_roof_txt0.png"

Code: Lua
  1. local map = ...
  2.  
  3. local fade_roofs = {
  4.   {
  5.     texture = {
  6.       src = "forest_roof_txt0",
  7.       opacity = 120
  8.     },
  9.     x = 80,
  10.           y = 256,
  11.     width = 272,
  12.     height = 200,
  13.           color = {56, 40, 40}
  14.   },
  15.  
  16.   {
  17.     x = 80,
  18.           y = 16,
  19.     width = 272,
  20.     height = 200,
  21.           color = {56, 40, 40}
  22.   },
  23. }
  24.  
  25. map.fade_rooms = fade_rooms
  26.  

As you can see, there are 6 needed parameters

Code: Lua
  1. {
  2.   texture = {src = src of the image, opacity = opacity (0 - 255}
  3.   x = x position of the roof
  4.   y = y position of the roof
  5.   width = horizontal lenght of the roof
  6.   height = vertical lenght of the roof
  7.   color = {r, g, b} (color of the roof)
  8. }
  9.  

If you forget one of them, your computer might explode and then stuff in red will appear, Diarandor might send you cats, you've been warned.

Errors might not exists since everything is generated by the user.

If the script don't work:
- One of your map script use the map:on_started() function rather than map:register_event("on_started")
- One of your map script use the map:on_draw() function rather than map:register_event("on_draw")
- Bad script path

Credits:
Not needed, you are free to decide.
« Last Edit: March 31, 2018, 03:12:57 pm by MetalZelda »

Diarandor

  • Hero Member
  • *****
  • Posts: 959
  • Cats are cool! (ΦωΦ)
    • View Profile
Re: Roof Fading script
« Reply #1 on: March 26, 2018, 07:42:57 pm »
Nice work! ;D
If you forget one of them, your computer might explode and then stuff in red will appear, Diarandor might send you cats, you've been warned.
I'll be preparing my cats, just in case. :-\
“If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you.”

MetalZelda

  • Hero Member
  • *****
  • Posts: 546
    • View Profile
Re: Roof Fading script
« Reply #2 on: March 26, 2018, 08:41:01 pm »
 
Nice work! ;D
If you forget one of them, your computer might explode and then stuff in red will appear, Diarandor might send you cats, you've been warned.
I'll be preparing my cats, just in case. :-\

 :P

I fixed something odd, instead of keeping the same opacity within map:get_game():is_paused() I used a return which will only draw 1 surface.
Now it works perfectly, I might update it someday to give proper functions such as freezing entities when opacity = 255, possibility to fade the opacity manually (in case of camera movement)
« Last Edit: March 26, 2018, 09:02:26 pm by MetalZelda »

Diarandor

  • Hero Member
  • *****
  • Posts: 959
  • Cats are cool! (ΦωΦ)
    • View Profile
Re: Roof Fading script
« Reply #3 on: March 26, 2018, 10:01:31 pm »
The use of the script should be just this line
Code: Lua
  1. require(path_of_the_script)
instead of
Code: Lua
  1. local map_metatable = sol.main.get_metatable("map")
  2. require(path_of_the_script)(map_metatable)
because you can get metatables inside any script.
“If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you.”

MetalZelda

  • Hero Member
  • *****
  • Posts: 546
    • View Profile
Re: Roof Fading script
« Reply #4 on: March 31, 2018, 03:07:04 pm »
Updated script

#1 - User can now use a texture for the roof rather than a static color by using these parameters

Code: Lua
  1.   texture = {
  2.     src = "source_file_name",
  3.     opacity = opacity,
  4.   }
  5.  

The best way is to use a 8x8, 16x16, 8x16 pattern, the script will do the rest
You can combine both texture and color, using a semi transparent texture and apply a color underneath is possible

#2 - You can dim any roof surface you want by using

Code: Lua
  1. map:dim_room_surface(i, bool)

where i = the identifier number of the roof
           bool = true or false

Useful for camera movements