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.

Topics - Diarandor

Pages: 1 [2] 3 4
Your scripts / Animated sprites for dialogs (custom dialog script)
« on: January 08, 2017, 11:39:57 AM »
I was asked by @Porksteak to explain how to use the animation sprites of my custom dialog box:
My old script does not explain how to use this feature (I forgot to add these explanations). I post this here so anyone will know how to use it:

An example would be this dialog:
Code: (Lua) [Select]
  id = "old_man.thanks",
  animation = "talking",
  animation_sprite = "dialog_old_man",
  text = [[
Thanks for saving my
cats, young man.
See you later!

The (optional) sprite of the character has to be located in the path given by the concatenated string:
"dialogs/" .. dialog.animation_sprite
and the animation used is the one given by the string: dialog.animation

Your projects / A Zelda game by Kory Toombs
« on: December 05, 2016, 06:30:03 AM »
Hi! I found a Zelda game made with the Solarus engine by Kory Toombs, this is the website:
I thought it would be a good idea to create a topic about this; but I have not played this game so I know nothing about it.

Your scripts / Raft script
« on: November 08, 2016, 11:15:00 PM »
Hi! I was asked by @Porksteak in a personal message if I could share the platform-raft script that I use in this video:

So here goes the code. But note that some parts of the code are a bit old and could be improved (for instance, I should use "require" instead of "load_file" in the raft script, to make the code faster), and some things of the script may require other scripts. My raft script requires my platform script to work, so I include both scripts here. It is recommended that you study the code to make another script that suits better for your purposes, and remove unnecesary things from my code (for instance, you probably do not need the raft to move secondary heroes or custom entities, so you should delete these parts of the code and other similar things).

generic_platform.lua script:
Code: (Lua) [Select]
-- Platform: entity which moves in either horizontally or vertically (depending on direction)
-- and carries the hero on it.
local entity = ...
local map = entity:get_map()
local game = entity:get_game()
local hero = map:get_hero()

entity.can_save_state = true

local time_stopped = 1000
local is_moving = false
-- Remark: speeds bigger than 12 give problems for water platforms (rafts) when trying to enter or go out. No problem above holes.
entity.speed = 50 -- Set speed.

function entity:on_created()
  self:set_size(32, 32)
  self:set_origin(16, 13) -- Important: the 32x32 sprite must have center in (16,13).
  -- Set dynamic solid ground position for the hero to avoid problems.
  sol.timer.start(entity, 10, function()
    -- Do nothing if hero is not on solid ground.
    local is_hero_on_solid_ground = map:is_solid_ground(hero:get_ground_position())
    if hero.is_jumping or not is_hero_on_solid_ground then return true end
    -- Save or clear solid ground position on this platform.
    if map.current_hero_platform ~= entity and self:is_on_platform(hero) then
      map.current_hero_platform = entity
      self:save_hero_position() -- Save solid ground on the platform.
    elseif map.current_hero_platform == entity and (not self:is_on_platform(hero)) then
      map.current_hero_platform = nil
      hero:reset_solid_ground() -- Clear solid ground.
    return true

  -- Custom function.
  if entity.on_custom_created then
  -- Initialize properties.
  self:set_can_traverse("jumper", true)
  self:set_can_traverse_ground("hole", true)
  self:set_can_traverse_ground("deep_water", true)
  self:set_can_traverse_ground("traversable", true)
  self:set_can_traverse_ground("shallow_water", true)
  self:set_can_traverse_ground("wall", false)

  -- Start movement.
  local direction = self:get_direction()
  local m = sol.movement.create("path")
  m:set_path{direction * 2}; m:set_speed(entity.speed)
  m:set_loop(true); m:start(self)
  is_moving = true


-- Function to save hero position on the platform.
function entity:save_hero_position()
    --[[ When the hero reappears, the camera moves towards the new position,
    which produces a delay, and the platform has already moved when the hero appers.
    To fix this problem, change the position of the hero directly, so the movement
    will be instantaneous with no delay. To avoid this we must not call
    "hero:get_solid_ground_position()", or there will be problems with platforms.
    local x, y, layer = entity:get_center_position()
    -- Change position at next cycle to avoid engine problems (keep this timer!).
    sol.timer.start(self, 1, function()
      hero:set_blinking(true, 1000)
      hero:set_invincible(true, 1000)
      hero:set_position(x, y, layer)
    return x, y, layer

-- Update shifting variables for the translation.
local function get_shifts()
  local direction = entity:get_direction()
  local dx, dy = 0, 0 -- Variables for the translation.
  if direction == 0 then dx = 1 elseif direction == 1 then dy = -1
  elseif direction == 2 then dx = -1 elseif direction == 3 then dy = 1 end
  return dx, dy

-- Get movable entities that were on the previous position of the platform.
function entity:get_movable_entities()
  local movable_entities = {}
  for other in map:get_entities_in_rectangle(entity:get_bounding_box()) do
    -- Check only entities that can be moved, including the hero.
    if other.moved_on_platform or other:get_type() == "hero" then
      -- Check if the entity was on the platform before the movement.
      if entity:was_on_platform(other) and entity:is_on_platform(other) then
        -- Exclude portable entities unless they are on the ground.
        if (not other.is_portable) or other.state == "on_ground" then
          table.insert(movable_entities, other)
  return movable_entities

-- Return true if an entity is on the platform.
-- IMPORTANT: This function is only used in the script generic_portable.lua.
function entity:is_on_platform(other)
  local x, y, layer = other:get_ground_position()
  return entity:overlaps(x, y)

-- Return true if an entity was on the platform before the movement.
function entity:was_on_platform(other)
  local dx, dy = get_shifts()
  local ox, oy, oz = other:get_ground_position()
  local bx, by, w, h = entity:get_bounding_box()
  local pbx, pby = bx-dx, by-dy -- Previous position of bounding box (before the movement).
  return ox >= pbx and ox < pbx+w and oy >= pby and oy < pby+h

function entity:on_obstacle_reached(movement)
  --Make the platform turn back.
  local direction = self:get_direction()
  movement:stop(); is_moving = false
  movement = sol.movement.create("path")   
  direction = (direction+2)%4
  movement:set_path{direction * 2}
  sol.timer.start(self, time_stopped, function()
    is_moving = true 

-- Move the movable entities that were on the platform before the movement.
function entity:on_position_changed()
  -- Get the movable entities that were on the platform before the change of position.
  local dx, dy = get_shifts() -- Variables for the translation.
  local movable_entities = entity:get_movable_entities()
  local ex, ey, ez = self:get_position()
  local bx, by, w, h = self:get_bounding_box()
  local pbx, pby = bx-dx, by-dy -- Previous position of bounding box (before the movement).
  for _, other in pairs(movable_entities) do
    local ox, oy, oz = other:get_position()
    -- Move the entity with the platform.
    if not other:test_obstacles(dx, dy, oz) then
      other:set_position(ox + dx, oy + dy, oz)

raft.lua script:
Code: (Lua) [Select]
local entity = ...
-- Raft entity.

local sea_foam_sprite -- Foam sprite for the raft.
entity.speed = 20 -- Set speed.

function entity:on_custom_created()
  -- Set custom properties.
  time_stopped = 1000
  self:set_can_traverse_ground("deep_water", true)
  self:set_can_traverse_ground("wall", false)
  self:set_can_traverse("jumper", false)
  self:set_can_traverse_ground("hole", false)
  self:set_can_traverse_ground("traversable", true)
  self:set_can_traverse_ground("shallow_water", false)
  self:set_can_traverse_ground("grass", false)
  -- Customize movement.
  local direction = self:get_direction()
  local m = sol.movement.create("path")
  m:set_path{direction * 2}; m:set_speed(entity.speed)
  m:set_loop(true); m:start(self)
  is_moving = true
  -- Start the sea foam and wavering.
  self:start_wavering() -- Start moving raft sprite to simulate the waves.

----------------- Raft functions:

-- Add the sea foam sprite.
function entity:add_sea_foam()
  -- Remark: The variable sea_foam_sprite is already local in this script!
  sea_foam_sprite = self:create_sprite("things/platform")

-- Make the sprite move up and down.
function entity:start_wavering()
  local sprite = self:get_sprite()
  -- Define vectors with the shifts of each "frame" of the sprite and time for each pause between "frames".
  local raft_dy = {0,-1,-2,-1} -- Shifts for the "y" coordinate of the sprite.
  local entities_dy = {1,-1,-1,1} -- Shifts for the "y" coordinate of position of entities.
  local pause_time = {200,1000,200,1000} -- Pause times between "frames".
  -- Move the movable entities located over the platform, if possible.
  local function shift_entities(dy_shift)
    local movable_entities = entity:get_movable_entities()
    local x, y, z = self:get_position()
    local bx, by, w, h = self:get_bounding_box()
    for _, something in pairs(movable_entities) do   
      if entity:is_on_platform(something, bx, by, w, h) then   
      local sx, sy, sz = something:get_position()
        -- Move only entities that can be moved.
        local needs_move = false
        if something:get_type() == "hero" then
          if something:get_animation() ~= "walking" then
            needs_move = true
        elseif something:get_sprite() then
          if something:get_sprite():get_animation() ~= "walking" then
            needs_move = true
        -- Check for obstacles.
        local found_obstacles = something:test_obstacles(0, dy_shift, sz)
        -- Finally check if the entity is not in the "bad border" to move it without getting out the platform.
        if needs_move and (not found_obstacles) then
          if (sy + dy_shift) >= by+2 and (sy + dy_shift) <= by+h-3 then sy = sy +dy_shift end
          something:set_position(sx, sy, sz)

  -- Shift sprite and move entities.
  local function set_frame_loop(frame_nb)
    -- Shift the sprite. Shift entities above the rift, if possible.
    sprite:set_xy(0, raft_dy[frame_nb])
    -- Restart the loop.
    frame_nb = (frame_nb %4) +1 -- Next frame index.
    sol.timer.start(entity, pause_time[frame_nb], function() set_frame_loop(frame_nb) end)
  -- Start the wavering loop. 

General discussion / Poll: Crystal platforms vs mushrooms
« on: October 16, 2016, 02:02:27 PM »
Hi solarusiens!
I was thinking that for the project Children of Solarus we could use mushrooms that go up/down instead of crystal platforms. That would make the game more different from Zelda ALTTP, which would be nice. But I do not know if you like the idea, so I made this poll. Which option do you prefer?

Hi! One of the many things I will be working on is the creation of new free enemies with original art and fully scripted. I will keep adding them to the sample quest, and many of them are planned to be used in the project Children of Solarus. Some of my current work is here:

Feedback wanted: If you have some cool and original idea of some type of enemy you want, then post it here. If I like the idea, I might make them when I get free time (but please, be patient). If the behavior is a bit complicated I might not do it, because I prefer to focus more on making free art than coding strange things, so think of basic stuff (no bosses or similar things); but also try to think of enemies with different and new original behaviors too, so that we will have more variety of enemies. Try to give as much details as possible, for the graphic part and also the behavior of the enemy.

Here you can also share your own original enemies, with both sprites and code, and maybe a link to some video to show them in action.
Quest makers, I challenge you to make something cool and post it here!!! hehehe! :D

Game art & music / Did you know about ZREO?
« on: July 28, 2016, 07:18:36 AM »

I'm pretty sure that many of you have already heard about ZREO ("Zelda Reorchestrated"), which is a team of many people that make covers and orchestrated versions of the music of Zelda games. I thought they deserved to be mentioned here since we all are Zelda fans here. If you are interested, you can listen to their music in their official website and their youtube channel:

General discussion / Overworld maps: screen size or bigger?
« on: July 22, 2016, 09:57:12 PM »
Hi pals! Just by curiosity, I would like to know if you prefer screen-sized overworld maps like in Zelda games of the gameboy, or bigger overworld maps like in A Link To The Past. I mean overworld maps, not for levels/dungeons. I may take into account these opinions when I start mapping someday; but that will be in the far far future (probably Mercuri's Chest will be finished before then, hahah). Anyway, this may be interesting info for new developers too. You can put your opinion and discuss about this.

PS: I personally have preference for small overworld maps that are screen-sized and very dense (i.e., with many things on them: entities, secrets, easter eggs, etc), like in Link's Awakening. However, I prefer bigger maps for dungeons, like the oracle games did. I may change my mind depending on your opinions.

Let the poll and discussion begin! :D

General discussion / chip music vs non-chip music?
« on: June 18, 2016, 03:46:14 AM »
Hi comrades!

Some time ago I made a few compositions with Famitracker. These are 16-bit music.
I was wondering if it would be better to try to remake these songs with LMMS (so the sounds would have "higher quality", i.e., it will be non-chip music).

Well, 8/16-bit music was a limitation of old consoles, but it is nowadays a style with a lot of charm (in the same way pixel art is for the graphics). There are impressive compositions made with 16-bit style in recent games (you can listen to Shovel Knight OST for instance), so chip music should not be considered bad quality music. (Unfortunately, many people do not understand this style of music of video games nowadays.)

Since I need to take a decision, I opened this poll. You can change your vote if you change your mind.
I will post later some of my few and rudimentary compositions. :P

Hi pals! I am a very curious person, and I was wondering which elements of the gameplay of a Zelda-like game are more important for most of the players (which is quite subjective to each one's opinion), so I created this poll.

The result can be useful to quest makers in order to make a game with balanced gameplay/mechanics according to what most of the people want.

You can vote for 2 options, to choose the 2 options you think are more important. I think it is a bit hard to choose since all elements are very important in my opinion.

PS: do not vote random, please! :)

Development / Fixing direction and walking/stopped animations
« on: April 07, 2016, 02:56:49 AM »
Hi, here is part of a script I made to (re)define some functions of the metatable of the hero. In this piece of code a few functions which allow fixing direction and walking and stopped animations are defined. The trick I am using was an idea that MetalZelda posted in an older topic (,448.0.html). It was not possible until now that Christopho has improved solarus in the development version of 1.5.

My custom functions:
-The direction fix allows to walk sideways, which is useful for some weapons. The following functions are defined:
Code: (Lua) [Select]
-The fixing animation function allows to simplify some code in case you are changing the stopped/walking animations of the tunic of the hero for some purposes. In my case, I was changing to a jumping tunic (for a custom jump) and a carrying tunic (for a custom carry that allows carrying custom entities). This now can be done without changing the tunic sprite, using the functions:
Code: (Lua) [Select]
hero:set_fixed_animations(stopped_animation, walking_animation)

The code can be put in some script apart. Be careful since it may override some function or event of the hero metatable in case you have defined it elsewhere. The code is here:
Code: (Lua) [Select]
local hero_meta = sol.main.get_metatable("hero")

-- Function to set a fixed direction for the hero (or nil to disable it).
function hero_meta:set_fixed_direction(direction)
  self.fixed_direction = direction
  if direction then
-- Function to get a fixed direction for the hero.
function hero_meta:get_fixed_direction()
  return self.fixed_direction
-- Function to set fixed stopped/walking animations for the hero (or nil to disable it).
function hero_meta:set_fixed_animations(stopped_animation, walking_animation)
  self.fixed_stopped_animation = stopped_animation
  self.fixed_walking_animation = walking_animation
-- Function to get fixed stopped/walking animations for the hero.
function hero_meta:get_fixed_animations()
  return self.fixed_stopped_animation, self.fixed_walking_animation

-- Initialize events to fix direction and animation for the tunic sprite of the hero.
-- To do it, we redefine the on_created and set_tunic_sprite_id events using the hero metatable.
  local function initialize_fixing_functions(hero)
    -- Define events for the tunic sprite.
    local sprite = hero:get_sprite("tunic")
    function sprite:on_animation_changed(animation)
      local fixed_stopped_animation = hero.fixed_stopped_animation
      local fixed_walking_animation = hero.fixed_walking_animation
      local tunic_animation = sprite:get_animation()
      if tunic_animation == "stopped" and fixed_stopped_animation ~= nil then
        if fixed_stopped_animation ~= tunic_animation then
      elseif tunic_animation == "walking" and fixed_walking_animation ~= nil then
        if fixed_walking_animation ~= tunic_animation then
    function sprite:on_direction_changed(animation, direction)
      local fixed_direction = hero.fixed_direction
      local tunic_direction = sprite:get_direction()
      if fixed_direction ~= nil and fixed_direction ~= tunic_direction then
  -- Initialize fixing functions when the hero is created.
  function hero_meta:on_created()
  -- Initialize fixing functions for the new sprite when the sprite is replaced for a new one.
  local old_set_tunic = hero_meta.set_tunic_sprite_id -- Redefine this function.
  function hero_meta:set_tunic_sprite_id(sprite_id)
    old_set_tunic(self, sprite_id)

Game art & music / Original art
« on: February 06, 2016, 03:02:41 PM »
Greetings! I'm gonna upload some of my (unfinished) sprites to devianart.
It may take between 1 and 3 years of work until I have finished all of this since I am doing this in my free time as a hobby.
You can download them from here:
but you need to have a devianart account and login there to see images.

At present I have only uploaded a few sprite sheets, but I will keep uploading things from time to time. These sprites will probably be used for the game "Children of Solarus" of the Solarus Team.

Development / Unfinished scripted boots
« on: January 15, 2016, 10:00:26 AM »
Hi! I want to share my script for the boots item. It's not finished yet, but it can help others.
The aim of this script is to allow to combine the boots with other non built-in items, like a custom jump/feather, a custom sword, and maybe others. The behaviour will be the same as in Link's Awakening, and fully customizable.

It remains to add the collision detection with custom entities that can be broken with the boots,
which can be easily done by using the new functions
Code: [Select]
entity:has_collision(collision_test, other_entity)
when Solarus 1.5 is released.

Code: (Lua) [Select]
Unfinished script for the boots item.
The aim is to allow to combine the boots with other non built-in items,
like the jump/feather and the sword, and maybe others.
local item = ...

local speed = 250

function item:on_created()

function item:on_obtained()
  local hero_index = item:get_game():get_hero():get_index()
  local inventory = item:get_game():get_inventory()
  inventory:add_item(hero_index, item)

-- Function to start the running sequence before the movement.
function item:on_using()
  local game = self:get_game()
  local hero = game:get_hero()
  -- Get slot associated to this item.
  local command = "item_1"
  if game:get_item_assigned(2) == item then command = "item_2" end
  local can_start_run = false
  -- Start running animation.
  -- Timer to check if the command button is being pressed enough time to use the boots.
  local timer = sol.timer.start(item, 1000, function() can_start_run = true end)
  -- Check if the command button is being pressed enough time to use the boots.
  sol.timer.start(item, 1, function()
    if not game:is_command_pressed(command) then
      return false
    elseif can_start_run then
      return false
    return true

-- Function to start the running movement.
function item:start_running()
  local game = self:get_game()
  local hero = game:get_hero()
  local dir = hero:get_direction()
  local dirs = {[0]="right",[1]="up",[2]="left",[3]="down"}
  local command_dir = dirs[dir] -- Current direction.
  -- Create movement and check for collisions with walls.
  local m = sol.movement.create("straight")
  function m:on_obstacle_reached()
  -- Check for commands pressed to interrupt movement or use weapons.
  local is_using_other_item = false
  sol.timer.start(item, 1, function()
    -- Stop movement if some direction command (different from
    -- the current direction) is pressed.
    local interrupt = false
    for _,str_dir in pairs(dirs) do
      interrupt = interrupt or
        (game:is_command_pressed(str_dir) and command_dir ~= str_dir)
    if interrupt then
      return false
    -- TODO: Check if custom items (feather, sword,...) are used, for a combined use.
    if game:is_command_pressed("attack") and (not is_using_other_item) then
      is_using_other_item = true
    -- Keep checking.
    return true

-- Function for the crash effect against walls.
function item:smash_wall()
  -- Crash animation and sound.
  local hero = self:get_game():get_hero()"boots_crash")
  -- TODO: detect collision with custom entities (to break them). To do
  -- when some functions (like map.get_entities_in_rectangle and hero.has_collision)
  -- are made in Solarus 1.5.
  -- Call a collision event if the hero crashes with a destructible entity.
  local x, y, width, height = hero:get_bounding_box()
  for e in map:get_entities_in_rectangle(x, y, width, height)
    if hero:has_collision("facing", other_entity) then
      if other_entity.on_boots_crash ~= nil then
  -- Create bounce movement.
  local dir = hero:get_direction()
  dir = (dir+2)%4
  local m = sol.movement.create("straight")
  function m:on_obstacle_reached()
  function m:on_finished()

Development / Start the sword attack from an item script?
« on: January 10, 2016, 11:29:51 AM »
Hi! I was trying to script a weapon menu like the one in Link's awakening (but with 3 slots and any weapon could be assigned to each of them). I wanted to make it possible to unassign the sword of the attack button (with the possibility of assigning other items to the attack button), but also I want the possibility of assigning the sword to other buttons, is it possible? The problem that I have is that I don't know how to start the built-in sword attack from an item script...

(Note that calling the command "game:simulate_command_pressed("attack")" is not a solution since the sword would be already unassigned from the attack command.)

Could this be possible with solarus 1.5 using some access to the sword sprite? And in that case how?

General discussion / Are Zelda items/weapons copyrighted?
« on: January 06, 2016, 11:16:18 PM »
I would like to know if I could use some weapons/items like the Roc's Feather and the Pegasus Boots in my own game without copyright infringement. I am creating from scratch my own art, which is completely different from the art of Nintendo (although the style has some influence sometimes), so there would not be any infringement from the art part.

But still, I am not sure if using a similar weapon/item that has the same name could be considered a copyright infringement. Also, do you think that I could use the names "Roc's Feather" and "Pegasus Boots" for my game? (I suppose that I can because Roc and Pegasus were mythological beings after all, and not invented by Nintendo...)

Probably there will be no problem and this is all legal, but  I want just to be sure. It's just that I have not seen these items in non-Zelda games (which is probably normal because they do not need them and game players would claim they copied that). Sorry if these are silly questions, it's just I am quite paranoid.

Development / How to choose order to draw sprites of custom entity?
« on: December 24, 2015, 12:27:37 PM »
How can I choose the order to draw the sprites of a custom entity? I mean, how can I draw a sprite above/below other sprites of a given custom entity?

Until now, the only way I found to simulate this was to create a new custom entity with the new sprite, set it to draw on Y-order, and put it in position (x,y+2,z), where (x,y,z) is the position of the original entity; also we need to update the position to follow the original entity. I don't like to have to use this trick each time I want to draw a sprite avobe... Is there some other way to do it at present?

EDIT: just in case, I opened an issue for this, here:

Pages: 1 [2] 3 4