Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - PhoenixII54

Pages: [1]
1
Your scripts / Fractals !
« on: September 15, 2017, 11:10:58 am »
No, you didn't misread, what i'm about to give you is a series of scripts normally used in mathematics.
They don't desserve any porpose other than having fun with the engine, so enjoy !

1. the Mandelbrot set
Code: Lua
  1. --[[
  2. A useless-thus-indispensable Mandelbrot set renderer
  3.  
  4. How it works :
  5. the Mandelbrod set consists of a 2d grid of complex numbers,
  6. which are an extension of real numbers and are written in, the form :
  7. a+b*i, where a and b are two real numbers, and i is the square root of -1,
  8. also called the imaginary nuimber.
  9.  
  10. For each point of the grid, let(s call it c, we gererate a new complex, number called z by applying the following formula :
  11. initial z value : 0
  12. new z = (z to the power of <whatever you want>) + c
  13. then we compare the new value to (2 to the power of <the same exponent as before>
  14. then, we continue in one of the wollowing cases :
  15.    if z is lower than the powered 2, then we do the above steps again, unless we reached the maximum number if iterations
  16.    if, however, we are equal or higher than the powered 2,
  17.    then we stop iterating since the next calculated numbers wil keep growing forever, namely, we escaped the 2-range stability area
  18.  
  19. Anyway, once we have finished calculatins the final value for a given number, we color it according to it's behaviour :
  20. -if we escaped, then we color the corresponding point using the number of cleared iterations to index the color from a palette
  21. taking the mod from table size
  22. -else, we color it pitch black
  23.  
  24. this process goes on and on until all visible points are rendered.
  25.  
  26. For more information, feel free to check on the Wiki or any math article
  27.  
  28. How to use :
  29. 1. create a map of the size of your choice
  30. 2. copy/paste this whole code in the map script.
  31. 3. setup the config table with your own parameters
  32. 4. Run the map !
  33. --]]
  34.  
  35. local map = ...
  36. local game = map:get_game()
  37.  
  38.  
  39. -- the configuration table
  40. local config={
  41.   -- Size of the rendering area in game pixels.
  42.   -- Must be lower than the map size to render properly
  43.   grid={
  44.     width=401,
  45.     height=401
  46.   },
  47.   -- the maximum number of iterations for each point.
  48.   maxIterations=1000,
  49.   -- the calculation power. Defaulr : 2
  50.   powerExponent=2,
  51.   -- the starting complex numbers boundaries
  52.   numberBoundaries={
  53.     x={
  54.       min=-2,
  55.       max=2,
  56.     },
  57.     y={
  58.       min=-2,
  59.       max=2,
  60.     },
  61.   },
  62.   step={},
  63. }
  64.  
  65. local start_time
  66. -- returns the module of any complex number, aka the length of the vector represented by this number
  67. local function get_module(c)
  68.   return c.real*c.real+c.imag*c.imag
  69. end
  70.  
  71. --calculates z^N with z=real+i*imag and N>0
  72. local function complex_power(c, exponent)
  73.   local squaredModule=get_module(c)
  74.   local newModule=math.pow(squaredModule,exponent/2)
  75.   local argument=math.atan2(c.imag,c.real)
  76.   return {
  77.     real=math.cos(exponent*argument)*newModule,
  78.     imag=math.sin(exponent*argument)*newModule,
  79.   }
  80. end
  81.  
  82. local currentNumber={
  83.   real=config.numberBoundaries.x.min,
  84.   imag=config.numberBoundaries.y.max,
  85. }
  86.  
  87. local currentPoint={
  88.   x=0,
  89.   y=0,
  90. }
  91. -- a 1*1 surface used as a pixel, to compensate the lack of proper API pixel manipulatinf functions
  92. local pixel=sol.surface.create(1,1)
  93.  
  94. local fractalRender=sol.surface.create(config.grid.width,config.grid.height)
  95. -- the actual color palette. Feel free to modify it with your own colors (any size will work)
  96. local color_palette={
  97.   {255,255,0},
  98.   {255,223,31},
  99.   {255,191,63},
  100.   {255,159,95},
  101.   {255,127,127},
  102.   {255,95,159},
  103.   {255,63,191},
  104.   {255,31,223},
  105.   {223,0,255},
  106.   {255,31,255},
  107.   {191,63,255},
  108.   {159,95,255},
  109.   {127,127,255},
  110.   {95,159,255},
  111.   {63,191,255},
  112.   {31,223,255},
  113.   {0,255,255},
  114.   {31,255,223},
  115.   {63,255,191},
  116.   {95,255,159},
  117.   {127,255,127},
  118.   {159,255,95},
  119.   {191,255,63},
  120.   {223,255,31},
  121. }
  122. -- the rendering call
  123. local function draw_point(x,y,i)
  124.   local color
  125.   if i==config.maxIterations then
  126.     color={0,0,0}
  127.   else
  128.     local index=(i%#color_palette)+1
  129.     color=color_palette[index]
  130.   end
  131.   pixel:fill_color(color)
  132.   pixel:draw(fractalRender,x,y)
  133. end
  134. -- the core functions. Called once per map update.
  135. -- i don't use for loops to get each point, but increase indices at the end of this function instead.
  136. -- to save the engine from lagging/crashing
  137. local function calculateNextPoint()
  138.   local z={
  139.     real=0,
  140.     imag=0,
  141.   }
  142.   local real=currentNumber.real
  143.   local imag=currentNumber.imag
  144.   local i=0
  145.   local e=config.powerExponent
  146.   --The core calculation loop. see the explaination at the beginning of the script
  147.   while (i<config.maxIterations and get_module(z)<=math.pow(2,e)) do
  148.     local temp=complex_power(z,e)
  149.     z.real=temp.real+real
  150.     z.imag=temp.imag+imag
  151.     i=i+1
  152.   end
  153.   --render point
  154.   draw_point(currentPoint.x,currentPoint.y,i)
  155.   --Prepare for next loop
  156.   currentPoint.x=currentPoint.x+1
  157.   currentNumber.real = real + config.step.x
  158.  
  159.   --End of horizontal line
  160.   if real > config.numberBoundaries.x.max then
  161.     currentNumber.real = config.numberBoundaries.x.min
  162.     currentNumber.imag = imag-config.step.y
  163.     currentPoint.x=0
  164.     currentPoint.y=currentPoint.y+1
  165.   end
  166.  
  167.   if imag<config.numberBoundaries.y.min then
  168.   --All points have been processed. We can stop the function from starting again
  169.  
  170.     --Debug lines for render time benchmarking? uncomment the next two lines to activate
  171.     --print("done !")
  172.     --print("time elapsed :"..os.clock()-start_time .."s")
  173.  
  174.     return false
  175.   end
  176.   return true
  177. end
  178.  
  179. function map:on_started()
  180.   map:get_hero():set_visible(false)
  181. end
  182.  
  183. function map:on_finished()
  184.   map:get_hero():set_visible(true)
  185. end
  186. -- starting the whole process
  187. function map:on_opening_transition_finished()
  188.   config.step.x=(config.numberBoundaries.x.max-config.numberBoundaries.x.min)/(config.grid.width-1)
  189.   config.step.y=(config.numberBoundaries.y.max-config.numberBoundaries.y.min)/(config.grid.height-1)
  190.   --print("step X="..config.step.x..",step Y="..config.step.y)
  191.  
  192.   --getting the current time for later usage, if you want to benchmark the rendering duration, just uncomment the next line
  193.   --start_time=os.clock()
  194.  
  195.   sol.timer.start(1, calculateNextPoint)
  196. end
  197. function map:on_draw(dst)
  198.   local camera=map:get_camera()
  199.   local x,y=camera:get_position()
  200.   local w,h=sol.video.get_quest_size()
  201.   fractalRender:draw_region(x,y,w,h,dst)
  202. end
Here is a screenshot of a render using the default exponent (2) :

2. the Sierpinsky Triangle
Code: Lua
  1. --[[
  2. The Sierpinsky triangle.
  3. On of the well known fractals, often used as a demonstration for calculators programming
  4. When rendered, it shows a Triforce-like shape, with each triangle being a raduction of the base figure.
  5. like this
  6.  
  7.        /\
  8.       /--\
  9.      /\  /\
  10.     /__\/__\
  11.    /\      /\
  12.   /__\    /__\
  13.  /\  /\  /\  /\
  14. /__\/__\/__\/__\
  15.  
  16. For more information, feel free to check on the Wiki or any math article
  17.  
  18. How to use :
  19. 1. create a map of the size of your choice
  20. 2. copy/paste this whole code in the map script.
  21. 3. setup the config variables with your own parameters
  22. 4. Run the map !
  23. --]]
  24.  
  25. local map = ...
  26.  
  27. -- Must be lower or equel to map size to render properly
  28. local grid={
  29.   width=200,
  30.   height=200
  31. }
  32. local maxIterations=10000
  33. -- the outer triangle summits
  34. local summits={
  35.    {0,0},
  36.    {grid.width,0},
  37.    {grid.width/2,grid.height},
  38. }
  39. local point
  40.  
  41. -- initial position
  42. local x=grid.width/2
  43. local y=grid.height/2
  44.  
  45. local iter
  46. local fractalRender= sol.surface.create(grid.width,grid.height)
  47. local pixel=sol.surface.create(1,1)
  48. pixel:fill_color({0,0,0})
  49. local game = map:get_game()
  50.  
  51. -- Event called at initialization time, as soon as this map becomes is loaded.
  52. function map:on_started()
  53.   map:get_hero():set_visible(false)
  54.   iter=0
  55.   --print("initial point : X="..x..", Y="..y)
  56.  
  57. end
  58.  
  59. function map:on_finished()
  60.   map:get_hero():set_visible(true)
  61. end
  62.  
  63. function map:on_update()
  64.  
  65.   if iter <maxIterations then
  66.     --these three lines are all the calculation. Yes, this fractal is very easy to setup.
  67.     --Note, they directly come from internet, so feel free to change to your own.
  68.     point=summits[math.random(3)]
  69.     x=(x+point[1])/2
  70.     y=(y+point[2])/2
  71.  
  72.     --[[
  73.  
  74.     -- my calculator's example script from the instruction book. Kept here for historical reasons, feel free to remove.
  75.     random=math.random(999)
  76.     --local random
  77.     --print("random number : "..random)
  78.     if random<=333 then
  79.       x=x/2
  80.       y=y/2
  81.     elseif random >333 and random <=666 then
  82.       x=(x+(base_size/2))/2
  83.       y=(y+base_size)/2
  84.     else
  85.       x=(x+base_size)/2
  86.       y=y/2
  87.     end    
  88.   --]]
  89.   --print("new point on cycle "..count..": X="..x..", Y="..y)
  90.   pixel:draw(fractalRender, x,grid.height-y)
  91.   iter=iter+1
  92.   end
  93.  
  94.  
  95. end
  96.  
  97. function map:on_draw(dst)
  98.   fractalRender:draw(dst)
  99. end
Screenshot of the render :


That's all for now! More to come later.... maybe !
Feel free to test, but be warned : it can, and will, take some time to get a full render, depending of your computer power and the parameters you chose.
if you have suggestions for improvements, feel free to.
Enjoy !

Edit (2017/09/21) : Added screenshots of the renders.

2
Your scripts / Re: Turtle Rock (Alttp) Pipe system
« on: September 07, 2017, 02:00:34 pm »
Actually this is a reminiscence of an experimental way where i used the name to code the output direction when at the end of a pipe, which caused problems since i could''t get the next entity if i was at the very start of the chain, but since then i found that using the direction of the actual movement is way easier, so you can replace it by
Code: Lua
  1. map:get_entity(target)
since  the sensors now use the same name convention.

edit : code is now updated to apply the modification.

3
Your scripts / Re: Turtle Rock (Alttp) Pipe system
« on: September 06, 2017, 05:28:15 pm »
You know what ? that's what i did in a first version with custom entities instead of the sensors, it worked well too, but wanted something "universal", as in just place any number of sensors carefully named and voila!

Anyways, thanks!

4
Development / Re: Diagonales avec le mouvement de type "straight"
« on: September 06, 2017, 05:24:26 pm »
Mea culpa, j'avais pas vu que j'avais laissĂ© le "=" dans mon code. En tout cas, ravi d'avoir pu ĂȘtre utile

5
Development / Re: Diagonales avec le mouvement de type "straight"
« on: September 05, 2017, 08:54:17 pm »
En fait, tu peux simplifier ton script en faisant
Code: Lua
  1. movement:set_angle=(math.pi*(2*direction.angle-1)%8)/4
'Faut faire un peu de gymnastique du cerveau mais sauf erreur de ma part tu as une formule "universelle" ;)

6
Your scripts / Turtle Rock (Alttp) Pipe system
« on: September 05, 2017, 08:46:37 pm »
Hi !

Have you ever wanted to have those pipes in Crystal Palace of MoS DX move your characters automagically ? Then this script is for you !

Code: Lua
  1. --A simple string splitter, found on the Internet.
  2. --Used for extracting parameters in the sensor name.
  3. --You might want to use your own version to avoid possible license issues
  4.  
  5. local function string_split(source, delimiters)
  6.   local elements = {}
  7.   local pattern = '([^'..delimiters..']+)'
  8.   string.gsub(source, pattern, function(value)
  9.     elements[#elements + 1] = value
  10.   end)
  11.   return elements
  12. end
  13.  
  14. --A simple yet powerful pipe system like in A link to the Past Turtle Rock
  15. --Usage : Place a series of sensors on the map, then name them as this :
  16. --pipe_<path_id>_<path_index>
  17. --Warning : you MUST set the indexes to a continuous way (1,2,3,...) or else you will be stuck in the middle of the movement.
  18. --Notice : While it requires nothing but requiring this script in the main file to run, you might want to use en event register like in Christopho's projects
  19. --as it overwrites the sensors' on_activated event
  20.  
  21. local sensor_meta=sol.main.get_metatable("sensor")
  22.  
  23. function sensor_meta:on_activated()
  24.   local name=self:get_name()
  25.   local map=self:get_map()
  26.   local hero=map:get_hero()
  27.   if name~=nil then
  28.     local type=string_split(name,"_")
  29.        
  30.     if type[1]=="pipe" then
  31.     --We are now in the pipe, either on en end or in the middle of it.
  32.       if not sensor_meta.pipe_active then
  33.         --Actually entering the pipe
  34.         length=map:get_entities_count("pipe_"..type[2])
  35.         hero:freeze()
  36.         hero:set_visible(false)
  37.         --detecting whether we are going in the increasing index order or not
  38.         local reversed=(tonumber(type[3])==length)
  39.         local next
  40.         if reversed then
  41.           next=length-1
  42.         else
  43.           next=2
  44.         end
  45.         --Saving settings in the metatable for later usage
  46.         sensor_meta.pipe_next=next
  47.         sensor_meta.pipe_is_reversed=reversed
  48.         sensor_meta.pipe_length=length
  49.         sensor_meta.pipe_active=true
  50.      
  51.       else
  52.         --Already in the pipe and continuing the movement
  53.         if sensor_meta.pipe_is_reversed then
  54.           sensor_meta.pipe_next=sensor_meta.pipe_next-1
  55.         else
  56.           sensor_meta.pipe_next=sensor_meta.pipe_next+1
  57.         end
  58.       end
  59.          
  60.       --Actually start the movement
  61.       if sensor_meta.pipe_next==0 or sensor_meta.pipe_next==sensor_meta.pipe_length+1 then
  62.       --We are about to finish the move : make the hero walk out of the pipe
  63.         local movement=sol.movement.create("path")
  64.         local dir=sensor_meta.pipe_outDir or 0
  65.         local path={dir,dir}
  66.         movement:set_path(path)
  67.         hero:set_visible(true)
  68.         hero:set_direction(dir/2)
  69.         hero:set_animation("walking")
  70.         movement:start(hero,function()
  71.           hero:unfreeze()
  72.           sensor_meta.pipe_active=false
  73.         end)
  74.       else
  75.         --making the quick auto move in the pipe (and bonk in the corners)
  76.         --Feel free to change this sound to your own !
  77.         sol.audio.play_sound("bomb")
  78.         local movement=sol.movement.create("target")
  79.         local target="pipe_"..type[2].."_"..sensor_meta.pipe_next
  80.         movement:set_target(map:get_entity(target))
  81.         movement:set_speed(192)
  82.         movement:start(hero)
  83.         --Saving the movement direction for when we will leave the pipe
  84.         sensor_meta.pipe_outDir=2*movement:get_direction4()
  85.       end
  86.     end
  87.   end
  88.   --And that(s all folks !
  89. end

Note: if you find a simpler way, don't hesitate to tell me, i'll be happy to rework my code as a challenge !
Enjoy !

edit : correction of misnamed function call originally using another file.
edit #2 : correction of movement:set_garget :
It used map:get_entities(target)(1), now it uses map:set_entity(target) since now you should have ensured all sensors have a unique ID.
edit #3 : fixed a possible issue when you try to make a pipe with only 1 sensor.
+ fixed comments indentation, removed some typo and removed remaining debug prints.

7
Development / Re: Problem with save variables in custom game manager
« on: June 16, 2015, 12:15:41 pm »
OK, thanks for testing.

Just tested and it worked fine too...

Sounds funny as the last time i tried it just didn't work. Maybe restarting the editor and/or the computer did help.

8
Development / Re: Problem with save variables in custom game manager
« on: June 16, 2015, 10:46:07 am »
Here it is. Hope it helps you.



https://drive.google.com/folderview?id=0BzXzhPafClIMfkV3a2FESnVrUDdCNlRzbWpyZ3JYMmRQZkZ1aUhySzBpQXlTTWNuTld5Tzg&usp=sharing


Note : Feel free to switch the "debug" variable in main to see the cell viewer i made to find the problem with streams

9
In my test game, i made a custon central game and save manager.
When creating a game, everything seems fine but it doesn"t seem to take the save and get savegame values function in account. For example, in initialization, i set max life to 10 and two option values for the sound and music volumes in costom named variables, but when calling the game:save() function, max life reverts to 1 and the option variables just don't exist. No error is thrown.
My question is : did i make something wrong or is there a bus with the save management ?

I attached the game manager script so you can chack foir any error.

Thanks in advance for your answer.

Pages: [1]