Menu

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.

Show posts Menu

Messages - PhoenixII54

#46
General discussion / Re: Aide ennemie mur capteur
December 18, 2017, 09:04:14 PM
EN :They actully do have seperate behaviors for hero, enemies and destructibles (and other that i don't recall by head so yeah it will work).

FR : Petit indice : utilise l'evenement <nom du capteur>:on_activated() dans ton script de map, et dans la fonction, il suffit d'appeler map:set_doors_open(<nom de tes portes>,true/false).

D'autre part, l'objet "wall" permet de choisir ce qui peut ou non les traverser (héros, ennemis, objets destructibles, etc)
#47
Your scripts / Re: [WIP] Ceiling dropping effect (ALTTP)
December 18, 2017, 09:01:35 PM
Nice work ! i'm actually relizing Link was not the only entity that could fall from ceilings (there were the blobs in the Dungeon 6's last rooms, plus the primed bombs dropping with a wrong lever pulling). I don't think i would have been able to make a better version myself, so if you manage to finish your enhancements, then credits shall go to you. 8)
#48
General discussion / Re: Okami on Steam
December 16, 2017, 09:53:20 PM
I can only tell one thing : it's a nice game -100%'d it on the Wii version-. Took it on Steam to enjoy the enhanced resolution, wanted to do a small session just to test with an actual controller, playing as if it was the very first time, just following the quest the intended way, and... ended stopping at the start of the first real dungeon 4 hours later ! (one thing i remarked thou is it still has the typos (french) from the Ps2 original release, evec after those years XD)

one note and a personal though : this game will play at the original 30 FPS, which has triggered a big debate on the Steam forums, some people just wanting -not- to buy it just because of this only reason, and refusing to understand the technical issues of unlocking framerate, since the whole mechanic is based on the 30FPS timing. i won't go in more details, and this game needs more than a framerate war to have at last the success it desserves since too long.
#49
Your scripts / [WIP] Ceiling dropping effect (ALTTP)
October 02, 2017, 10:01:07 PM
Hi, in my attempts to reproduce famous effects from ALTTP to compensate the missing effects in Zelda : Mystery of Solarus, here is one of the major ones :

When you fall in e hole that has a floor below, you end up in the said room, falling from the ceiling and dropping onto the floor, after doing a few turns oaround yourself.

Be prepared, besause this is the puropse of this script.
Code ( lua) Select

--Ceiling dropping system (WIP)
--Reproduces the "fall from uper floors" effects

--Usage : Call this script from any game launching system or use the event manager script to set the metatables then do your maps as usuel

--Extracting actual destination and ground from teletransporters since map;on_started(destination) dosen't take special destinations in account, then stirong it to a savegame variable lCan be useful for dungeons like Skull Dungeon (Level 3 of ALTTP, which has many hole entrances).
--Note, here, everything is in a single script, but in a real project you may have multiple file (one for each metatable)

local teletransporter_meta=sol.main.get_metatable("teletransporter")
local map_meta=sol.main.get_metatable("map")

function teletransporter_meta:on_activated()
  local game=self:get_game()
  local ground=self:get_map():get_ground(game:get_hero():get_position())
  game:set_value("tp_ground",ground)
end

--the actual trigger
function map_meta:on_started(destination)
  local hero=self:get_hero()
  local game=self:get_game()
  local x,y=hero:get_position()
  local ground=game:get_value("tp_ground")
  if ground=="hole" then
    --Falling from the ceiling
    hero:set_visible(false)
    hero:freeze()
    --disabling teletransoprters to avoid
    local disabled_teletransoprters={}
    for t in self:get_entities_by_type("teletransporter") do
      if t:is_enabled() then
        disabled_teletransporters[#disabled_teletransporters+1]=v
        t:set_enabled(false)
      end
    end
    --Creating a "stunt actor" moving vertically from the ceiling
    local falling_hero=self:create_custom_entity({
      name="falling_link",
      x=x,
      y=math.max(y-100,24),
      direction=0,
      layer=self:get_max_layer(),
      sprite=hero:get_tunic_sprite_id(),
      width=24,
      height=24,
    })
    falling_hero:get_sprite():set_animation("stopped")
    falling_hero:set_can_traverse_ground("wall",true)
    falling_hero:set_can_traverse_ground("empty",true)
    falling_hero:set_can_traverse_ground("traversable",true)

    --Creating a reception platform (prevents the hero from falling into consecutive holes during the animation)
    local platform=self:create_custom_entity({
      name="platform",
      direction=0,
      layer=layer,
      x=x,
      y=y,
      width=32,
      height=32,
      sprite="entities/shadow",
    })
    platform:bring_to_front()
    platform:get_sprite():set_animation("big")
    platform:set_modified_ground("traversable")

    --Creating the actual movement for the stunt actor
    local movement=sol.movement.create("target")
    movement:set_target(x,y)
    movement:set_speed(96)  --The falling speed.
    --Spinning the stunt actor on itself
    sol.timer.start(falling_hero, 100, function()
      falling_hero:set_direction((falling_hero:get_direction()+1)%4)
      return true
    end)
    movement:start(falling_hero, function()
      --Movement is now complete, restoring the disabled teletransoprters and getting rid of the temporary entities
      sol.audio.play_sound("hero_lands")
      platform:remove()
      falling_hero:remove()
      hero:set_visible(true)
      hero:unfreeze()
      for _,t in pairs(disabled_teletransporters) do
        t:set_enabled(true)
      end
    end)
    --]]
  end
end


Hope it will be useful, but it may have have bugs, so don't hasitate to report them to me. And remember, it is not fully finished so expect changes to happpen.
Remember that you may want to modify this script to make it compatible with Christopho's Multi-event script, which i don't use (yet) in my experiments to keep total control over my tests.

Anyway, enjoy !

edit#1 : Actually finished the v1.0 version, with ground detection on teletransportation.
Update (2017/10/23) : Modified the script to remove the extra sprite requirement and to add more flexibility. This is now likely a final version unless someone finds a more efficient way.
#50
Your scripts / Fractals !
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) Select
--[[
A useless-thus-indispensable Mandelbrot set renderer

How it works :
the Mandelbrod set consists of a 2d grid of complex numbers,
which are an extension of real numbers and are written in, the form :
a+b*i, where a and b are two real numbers, and i is the square root of -1,
also called the imaginary nuimber.

For each point of the grid, let(s call it c, we gererate a new complex, number called z by applying the following formula :
initial z value : 0
new z = (z to the power of <whatever you want>) + c
then we compare the new value to (2 to the power of <the same exponent as before>
then, we continue in one of the wollowing cases :
   if z is lower than the powered 2, then we do the above steps again, unless we reached the maximum number if iterations
   if, however, we are equal or higher than the powered 2,
   then we stop iterating since the next calculated numbers wil keep growing forever, namely, we escaped the 2-range stability area

Anyway, once we have finished calculatins the final value for a given number, we color it according to it's behaviour :
-if we escaped, then we color the corresponding point using the number of cleared iterations to index the color from a palette
taking the mod from table size
-else, we color it pitch black

this process goes on and on until all visible points are rendered.

For more information, feel free to check on the Wiki or any math article

How to use :
1. create a map of the size of your choice
2. copy/paste this whole code in the map script.
3. setup the config table with your own parameters
4. Run the map !
--]]

local map = ...
local game = map:get_game()


-- the configuration table
local config={
  -- Size of the rendering area in game pixels.
  -- Must be lower than the map size to render properly
  grid={
    width=401,
    height=401
  },
  -- the maximum number of iterations for each point.
  maxIterations=1000,
  -- the calculation power. Defaulr : 2
  powerExponent=2,
  -- the starting complex numbers boundaries
  numberBoundaries={
    x={
      min=-2,
      max=2,
    },
    y={
      min=-2,
      max=2,
    },
  },
  step={},
}

local start_time
-- returns the module of any complex number, aka the length of the vector represented by this number
local function get_module(c)
  return c.real*c.real+c.imag*c.imag
end

--calculates z^N with z=real+i*imag and N>0
local function complex_power(c, exponent)
  local squaredModule=get_module(c)
  local newModule=math.pow(squaredModule,exponent/2)
  local argument=math.atan2(c.imag,c.real)
  return {
    real=math.cos(exponent*argument)*newModule,
    imag=math.sin(exponent*argument)*newModule,
  }
end

local currentNumber={
  real=config.numberBoundaries.x.min,
  imag=config.numberBoundaries.y.max,
}

local currentPoint={
  x=0,
  y=0,
}
-- a 1*1 surface used as a pixel, to compensate the lack of proper API pixel manipulatinf functions
local pixel=sol.surface.create(1,1)

local fractalRender=sol.surface.create(config.grid.width,config.grid.height)
-- the actual color palette. Feel free to modify it with your own colors (any size will work)
local color_palette={
  {255,255,0},
  {255,223,31},
  {255,191,63},
  {255,159,95},
  {255,127,127},
  {255,95,159},
  {255,63,191},
  {255,31,223},
  {223,0,255},
  {255,31,255},
  {191,63,255},
  {159,95,255},
  {127,127,255},
  {95,159,255},
  {63,191,255},
  {31,223,255},
  {0,255,255},
  {31,255,223},
  {63,255,191},
  {95,255,159},
  {127,255,127},
  {159,255,95},
  {191,255,63},
  {223,255,31},
}
-- the rendering call
local function draw_point(x,y,i)
  local color
  if i==config.maxIterations then
    color={0,0,0}
  else
    local index=(i%#color_palette)+1
    color=color_palette[index]
  end
  pixel:fill_color(color)
  pixel:draw(fractalRender,x,y)
end
-- the core functions. Called once per map update.
-- i don't use for loops to get each point, but increase indices at the end of this function instead.
-- to save the engine from lagging/crashing
local function calculateNextPoint()
  local z={
    real=0,
    imag=0,
  }
  local real=currentNumber.real
  local imag=currentNumber.imag
  local i=0
  local e=config.powerExponent
  --The core calculation loop. see the explaination at the beginning of the script
  while (i<config.maxIterations and get_module(z)<=math.pow(2,e)) do
    local temp=complex_power(z,e)
    z.real=temp.real+real
    z.imag=temp.imag+imag
    i=i+1
  end
  --render point
  draw_point(currentPoint.x,currentPoint.y,i)
  --Prepare for next loop
  currentPoint.x=currentPoint.x+1
  currentNumber.real = real + config.step.x

  --End of horizontal line
  if real > config.numberBoundaries.x.max then
    currentNumber.real = config.numberBoundaries.x.min
    currentNumber.imag = imag-config.step.y
    currentPoint.x=0
    currentPoint.y=currentPoint.y+1
  end
 
  if imag<config.numberBoundaries.y.min then
  --All points have been processed. We can stop the function from starting again

    --Debug lines for render time benchmarking? uncomment the next two lines to activate
    --print("done !")
    --print("time elapsed :"..os.clock()-start_time .."s")

    return false
  end
  return true
end

function map:on_started()
  map:get_hero():set_visible(false)
end

function map:on_finished()
  map:get_hero():set_visible(true)
end
-- starting the whole process
function map:on_opening_transition_finished()
  config.step.x=(config.numberBoundaries.x.max-config.numberBoundaries.x.min)/(config.grid.width-1)
  config.step.y=(config.numberBoundaries.y.max-config.numberBoundaries.y.min)/(config.grid.height-1)
  --print("step X="..config.step.x..",step Y="..config.step.y)

  --getting the current time for later usage, if you want to benchmark the rendering duration, just uncomment the next line
  --start_time=os.clock()

  sol.timer.start(1, calculateNextPoint)
end
function map:on_draw(dst)
  local camera=map:get_camera()
  local x,y=camera:get_position()
  local w,h=sol.video.get_quest_size()
  fractalRender:draw_region(x,y,w,h,dst)
end

Here is a screenshot of a render using the default exponent (2) :

2. the Sierpinsky Triangle
Code ( lua) Select
--[[
The Sierpinsky triangle.
On of the well known fractals, often used as a demonstration for calculators programming
When rendered, it shows a Triforce-like shape, with each triangle being a raduction of the base figure.
like this

       /\
      /--\
     /\  /\
    /__\/__\
   /\      /\
  /__\    /__\
/\  /\  /\  /\
/__\/__\/__\/__\

For more information, feel free to check on the Wiki or any math article

How to use :
1. create a map of the size of your choice
2. copy/paste this whole code in the map script.
3. setup the config variables with your own parameters
4. Run the map !
--]]

local map = ...

-- Must be lower or equel to map size to render properly
local grid={
  width=200,
  height=200
}
local maxIterations=10000
-- the outer triangle summits
local summits={
   {0,0},
   {grid.width,0},
   {grid.width/2,grid.height},
}
local point

-- initial position
local x=grid.width/2
local y=grid.height/2

local iter
local fractalRender= sol.surface.create(grid.width,grid.height)
local pixel=sol.surface.create(1,1)
pixel:fill_color({0,0,0})
local game = map:get_game()

-- Event called at initialization time, as soon as this map becomes is loaded.
function map:on_started()
  map:get_hero():set_visible(false)
  iter=0
  --print("initial point : X="..x..", Y="..y)

end

function map:on_finished()
  map:get_hero():set_visible(true)
end

function map:on_update()

  if iter <maxIterations then
    --these three lines are all the calculation. Yes, this fractal is very easy to setup.
    --Note, they directly come from internet, so feel free to change to your own.
    point=summits[math.random(3)]
    x=(x+point[1])/2
    y=(y+point[2])/2
 
    --[[

    -- my calculator's example script from the instruction book. Kept here for historical reasons, feel free to remove.
    random=math.random(999)
    --local random
    --print("random number : "..random)
    if random<=333 then
      x=x/2
      y=y/2
    elseif random >333 and random <=666 then
      x=(x+(base_size/2))/2
      y=(y+base_size)/2
    else
      x=(x+base_size)/2
      y=y/2
    end   
  --]]
  --print("new point on cycle "..count..": X="..x..", Y="..y)
  pixel:draw(fractalRender, x,grid.height-y)
  iter=iter+1
  end


end

function map:on_draw(dst)
  fractalRender:draw(dst)
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.
#51
Your scripts / Re: Turtle Rock (Alttp) Pipe system
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) Select
map:get_entity(target)
since  the sensors now use the same name convention.

edit : code is now updated to apply the modification.
#52
Your scripts / Re: Turtle Rock (Alttp) Pipe system
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!
#53
Mea culpa, j'avais pas vu que j'avais laissé le "=" dans mon code. En tout cas, ravi d'avoir pu être utile
#54
En fait, tu peux simplifier ton script en faisant
Code ( lua) Select
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" ;)
#55
Your scripts / Turtle Rock (Alttp) Pipe system
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) Select
--A simple string splitter, found on the Internet.
--Used for extracting parameters in the sensor name.
--You might want to use your own version to avoid possible license issues

local function string_split(source, delimiters)
  local elements = {}
  local pattern = '([^'..delimiters..']+)'
  string.gsub(source, pattern, function(value)
    elements[#elements + 1] = value
  end)
  return elements
end

--A simple yet powerful pipe system like in A link to the Past Turtle Rock
--Usage : Place a series of sensors on the map, then name them as this :
--pipe_<path_id>_<path_index>
--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.
--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
--as it overwrites the sensors' on_activated event

local sensor_meta=sol.main.get_metatable("sensor")

function sensor_meta:on_activated()
  local name=self:get_name()
  local map=self:get_map()
  local hero=map:get_hero()
  if name~=nil then
    local type=string_split(name,"_")
       
    if type[1]=="pipe" then
    --We are now in the pipe, either on en end or in the middle of it.
      if not sensor_meta.pipe_active then
        --Actually entering the pipe
        length=map:get_entities_count("pipe_"..type[2])
        hero:freeze()
        hero:set_visible(false)
        --detecting whether we are going in the increasing index order or not
        local reversed=(tonumber(type[3])==length)
        local next
        if reversed then
          next=length-1
        else
          next=2
        end
        --Saving settings in the metatable for later usage
        sensor_meta.pipe_next=next
        sensor_meta.pipe_is_reversed=reversed
        sensor_meta.pipe_length=length
        sensor_meta.pipe_active=true
     
      else
        --Already in the pipe and continuing the movement
        if sensor_meta.pipe_is_reversed then
          sensor_meta.pipe_next=sensor_meta.pipe_next-1
        else
          sensor_meta.pipe_next=sensor_meta.pipe_next+1
        end
      end
 
      --Actually start the movement
      if sensor_meta.pipe_next==0 or sensor_meta.pipe_next==sensor_meta.pipe_length+1 then
      --We are about to finish the move : make the hero walk out of the pipe
        local movement=sol.movement.create("path")
        local dir=sensor_meta.pipe_outDir or 0
        local path={dir,dir}
        movement:set_path(path)
        hero:set_visible(true)
        hero:set_direction(dir/2)
        hero:set_animation("walking")
        movement:start(hero,function()
          hero:unfreeze()
          sensor_meta.pipe_active=false
        end)
      else
        --making the quick auto move in the pipe (and bonk in the corners)
        --Feel free to change this sound to your own !
        sol.audio.play_sound("bomb")
        local movement=sol.movement.create("target")
        local target="pipe_"..type[2].."_"..sensor_meta.pipe_next
        movement:set_target(map:get_entity(target))
        movement:set_speed(192)
        movement:start(hero)
        --Saving the movement direction for when we will leave the pipe
        sensor_meta.pipe_outDir=2*movement:get_direction4()
      end
    end
  end
  --And that(s all folks !
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.
#56
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.
#57
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
#58
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.