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 - wizard_wizzle (aka ZeldaHistorian)

#241
Development / Particle system
June 07, 2014, 07:55:06 AM
I've been playing around with the idea of creating a particle system in pure Lua that can run on the Solarus engine. Unfortunately, I'm pretty new to Lua and the draft that I'm working on now doesn't appear to be working. I think the idea behind it is sound, but I can't get it to display correctly so I can test it!

particles.lua (based off of a Love engine particle system, found at https://github.com/SimonLarsen/sienna/blob/master/particles.lua)
local particle_system = {}

function particle_system:new(game)
  local object = {}
  setmetatable(object, self)
  self.__index = self
  object:initialize(game)
  return object
end

function particle_system:initialize(game)
  self.game = game
  if not self.time then self.time = 1 end
  if not self.count then self.count = 5 end
  if not self.color then self.color = {255, 255, 255} end

  if self.type == "sparkle" then
    self.alive = true
    self.particles = {}
    for i=1, self.count do
      self.particles[i] = {}
      self.particles[i].x = x
      self.particles[i].xspeed = math.random(-100,100)
      self.particles[i].y = y
      self.particles[i].yspeed = math.random(-200,50) + (self.ysp or 0)
    end
    return self
  elseif self.type == "dust" then
    self.alive = true
    self.time = 0
    self.x = x
    self.y = y
    return self
  end
end

function particle_system:on_update()
  self.time = self.time - 1

  if self.type == "sparkle" then
    if self.time < 0 then
      self.alive = false
      return
    end
    for i,v in ipairs(self.particles) do
      v.x = v.x + v.xspeed*dt
      v.yspeed = v.yspeed + 500*dt
      v.y = v.y + v.yspeed*dt
    end
  elseif self.type == "dust" then
    if self.time > 0.25 then
      self.alive = false
      return
    end
  end
end

function particle_system:on_draw(dst_surface)
  if self.type == "sparkle" then
    for i,v in ipairs(self.particles) do
      dst_surface:fill_color(self.color, 0.5+v.x, 0.5+v.y, 1, 1)
    end
  elseif self.type == "dust" then
    dst_surface:fill_color(self.color, self.x-self.time*16, self.y-self.time*16, 1, 1)
    dst_surface:fill_color(self.color, self.x+self.time*16, self.y-self.time*16, 1, 1)
    dst_surface:fill_color(self.color, self.x-self.time*16, self.y+self.time*16, 1, 1)
    dst_surface:fill_color(self.color, self.x+self.time*16, self.y+self.time*16, 1, 1)
  else
    dst_surface:clear()
  end
end

function particle_system:set_type(type)
  self.type = type
end

function particle_system:set_position(x, y, layer)
  self.x = x
  self.y = y
  self.layer = layer or 1
end

function particle_system:set_particle_count(count)
  self.count = count
end

function particle_system:set_particle_color(color)
  self.color = color
end

function particle_system:set_decay_time(time)
  self.time = time
end

function particle_system:set_y_speed(ysp)
  self.ysp = ysp
end

return particle_system


An example map script:
local map = ...
local game = map:get_game()
local particle_system = require("particles")

function sensor:on_activated()
  local emitter = particle_system:new(game)
  emitter:set_type("sparkle")
  emitter:set_position(100, 100)
end

function map:on_update()
  if emitter ~= nil then emitter:on_update() end
end

function map:on_draw(dst_surface)
  if emitter ~= nil then emitter:on_draw(dst_surface) end
end


Any thoughts? Is this a lost cause or am I just way off base?
#242
Development / Re: Referencing global timers
May 25, 2014, 11:07:02 PM
Still chugging along! Thanks your all your great work on this engine!
#243
Development / Re: Referencing global timers
May 20, 2014, 03:19:33 AM
Works perfectly now - you're amazing! Thanks!

As far as the savegame variables - I fall into the same category as ZSDX on this one. I've been following the engine from the beginning and developing very early on, so I already had a large number of savegame variables established and it was easier to stick with the numbers. I have a system in place now and I actually like them! :-)
#244
Development / Re: Referencing global timers
May 19, 2014, 02:06:39 PM
Hmm... I think I understand what you're saying. My case is a tricky one though. It's basically a race that takes place over two different maps. So regardless of which map you're on, when the timer runs out, you lose the race. This is why I was hoping the timer callback would be persistent. I had even declared that end_race_lost function in each map, and it still didn't appear to be working. For reference, here's the function (those torch entities exist on both maps):

sol.audio.play_sound("wrong")
game:set_value("i1028", 4);
torch_1:get_sprite():set_animation("unlit")
torch_2:get_sprite():set_animation("unlit")
torch_3:get_sprite():set_animation("unlit")
game.race_timer = nil



Do you know of any way to make this work?
#245
Development / Re: Referencing global timers
May 18, 2014, 11:30:54 PM
Wow, that was fast! Thanks Christopho!

EDIT: Even with the new code in place, the callback of the timer (in the case above, "end_race_lost") won't run on another map. Erro is "bad argument #3 to '__index' (This map is not running).
#246
Development / Referencing global timers
May 18, 2014, 09:07:11 PM
If I have a timer that I've declared in the "game" context, and my character moves to a different map while the timer is still active, I can't figure out how to reference that timer.


race_timer = sol.timer.start(game, 140000, end_race_lost)
race_timer:set_with_sound(true)


Timer declared as above. I know the timer is still active when the map changes because the sound still plays. I also have the time displayed on screen using race_timer:get_remaining_time(). When the hero changes maps, the timer display disappears.


  if race_timer ~= nil then
    function map:on_draw(dst_surface)
      local timer_icon = sol.surface.create("hud/timer.png")
      local timer_time = race_timer:get_remaining_time() / 1000
      local timer_text = sol.text_surface.create{
        font = "white_digits",
        horizontal_alignment = "left",
        vertical_alignment = "top",
      }
      timer_icon:draw(dst_surface, 20, 55)
      timer_text:set_text(timer_time)
      timer_text:draw(dst_surface, 40, 60)
    end
  end


The display is disappearing because the timer reference goes to nil, which I'm intentionally checking for. If I comment out the check, I get an error message of "attempt to index global 'race_timer' (a nil value), but the value shouldn't be nil since the timer is in a "game" context, right? Should I be referencing it a different way, or is this a bug in the engine?
#247
Development / Re: Tips for cutscenes
April 23, 2014, 11:51:39 PM
Haha, thanks. I'm glad I'm not the only one who came up with that quick and dirty solution :-)
#248
Development / Tips for cutscenes
April 23, 2014, 01:24:51 AM
I'm wondering if anyone has ideas on how to implement cutscenes in Solarus?

Unless I'm missing something in the documentation, it appears that the only option for moving the camera is with map:move_camera which always returns to the hero after the delay is completed - otherwise the engine always centers the camera on the hero.

Is there some trick to center the camera on a different entity, such as an NPC, so RPG-like cutscenes could be created? I even tried making the hero invisible, moving him to the area where the action was taking place and then moving him back and making him visible again after the scene was over, but I couldn't get it to work correctly.
#249
Development / Re: Help: Enemy disappearing
March 24, 2014, 03:51:58 AM
Wow, thanks so much Renkineko!

If you were referring to the difficulty of the boss - now that the script works, I've fine-tuned the boss's difficulty level :-)
#250
Development / Re: Help: Enemy disappearing
March 20, 2014, 01:38:22 AM
Christopho- no luck on the optimization distance trick, thanks though.

Renkineko- I did double check the sprite, but I always could have missed something!

https://github.com/wrightmat/zbom/blob/master/data/sprites/enemies/gohma.png
#251
Good call, thanks!
#252
Development / HUD Script: Small Keys (ALBW Style)
March 19, 2014, 02:18:49 AM
If anyone's interested, I modified the small keys script provided by christopho in zsdx to display the keys in a manner more consistent with A Link Between Worlds rather than A Link to the Past. By that, I mean that keys are displayed as a number of small icons (consistent with the number of keys obtained) rather than a small key icon and a number.

-- Allows small keys to be displayed on maps with small keys enabled.
-- Done in ALBW style, a key icon is shown for each key obtained (no counter or icon)

local small_keys = {}

function small_keys:new(game)
  local object = {}
  setmetatable(object, self)
  self.__index = self

  object:initialize(game)
  return object
end

function small_keys:initialize(game)
  local nb_keys_displayed = 0

  self.game = game
  self.visible = false
  self.surface = sol.surface.create(80, 16)

  self:check()
  self:rebuild_surface()
end

function small_keys:check()
  local need_rebuild = false

  -- Check the number of small keys.
  if self.game:are_small_keys_enabled() then
    local nb_keys = self.game:get_num_small_keys()
    if nb_keys_displayed ~= nb_keys then
      need_rebuild = true
    end
  end

  local visible = self.game:are_small_keys_enabled()
  if visible ~= self.visible then
    self.visible = visible
    need_rebuild = true
  end

  -- Redraw the surface is something has changed.
  if need_rebuild then
    self:rebuild_surface()
  end

  -- Schedule the next check.
  sol.timer.start(self.game, 40, function()
    self:check()
  end)
end

function small_keys:rebuild_surface()
  self.surface:clear()
  if self.game:are_small_keys_enabled() then
    for i=0,self.game:get_num_small_keys()-1 do
      self.icon_img = sol.surface.create("hud/small_key.png")
      self.icon_img:draw(self.surface,i*14)
      if nb_keys_displayed ~= nil then
        nb_keys_displayed = nb_keys_displayed + 1
      else
        nb_keys_displayed = 1
      end
    end
  end
end

function small_keys:set_dst_position(x, y)
  self.dst_x = x
  self.dst_y = y
end

function small_keys:on_draw(dst_surface)
  if self.visible then
    local x, y = self.dst_x, self.dst_y
    local width, height = dst_surface:get_size()
    if x < 0 then
      x = width + x
    end
    if y < 0 then
      y = height + y
    end
    self.surface:draw(dst_surface, x, y)
  end
end

return small_keys


Feel free to use as you wish! I also modified hud/hud.lua to display the small keys at the bottom left above the rupees like they are in ALBW. The script also uses a small key icon of your choice in sprites/hud/small_key.png
#253
Development / Help: Enemy disappearing
March 19, 2014, 02:13:40 AM
Hoping for a little help on one of my bosses. For some reason he keeps disappearing when that's not what I'm intending with my script, so I must be missing something. It seems to happen primarily as he's finishing the "opening" phase.

Enemy script:
local enemy = ...

-- Gohma: Boss who has to be shot in the eye with an arrow to be hurt

function enemy:on_created()
  self:set_life(9)
  self:set_damage(2)
  self:create_sprite("enemies/gohma")
  self:set_hurt_style("boss")
  self:set_size(64, 32)
  self:set_origin(32, 29)
  self:set_attack_consequence("sword", "protected")
  self:get_sprite():set_animation("walking")
end

function enemy:check_action()
  local action = math.random(10)
  if self:get_life() > 6 then
    -- first phase: if less than three hits then mostly just move around (slowly), and create tektites
    local son_name = self:get_name().."_son"
    self:create_enemy{
      name = son_name,
      breed = "tektite_green",
      treasure_name = "heart"
    }
    if action >= 1 and action <= 7 then self:go(96) else self:blink() end
  elseif self:get_life() > 3 and self:get_life() <= 6 then
    -- second phase: if more than 3 but less than 6 hits then blink a lot more, and create tektites
    if action >= 1 and action <= 7 then self:blink() else self:go(96) end
    local son_name = self:get_name().."_son"
    self:create_enemy{
      name = son_name,
      breed = "tektite_green"
    }
  elseif self:get_life() < 3 and self:get_life() > 0 then
    -- final phase: if more than 6 hits then move a lot faster, and create tektites!
    if action >= 1 and action <= 6 then self:blink() else self:go(128) end
    local son_name = self:get_name().."_son"
    self:create_enemy{
      name = son_name,
      breed = "tektite_green"
    }
  end
  sol.timer.start(self, 100, function() self:open() end)
end

function enemy:go(speed)
  self:get_sprite():set_animation("walking")
  self:set_attack_consequence("arrow", 1)
  local m = sol.movement.create("random")
  m:set_speed(speed)
  m:set_max_distance(24)
  m:start(self)
end

function enemy:blink()
  self:set_attack_consequence("arrow", "protected")
  self:get_sprite():set_animation("blinking")
end

function enemy:open()
  self:set_attack_consequence("arrow", 1)
  self:get_sprite():set_animation("opening")
end

function enemy:on_restarted()
  self:get_sprite():set_animation("walking")
  self:check_action()
end

function enemy:on_obstacle_reached()
  self:check_action()
end

function enemy:on_animation_finished(sprite, animation)
  self:set_attack_consequence("arrow", "protected")
  if animation == "blinking" then
    self:get_sprite():set_animation("closed")
    sol.timer.start(self, random(6)*1000, function() self:open() end)
    self:go(64)
  elseif animation == "opening" then
    self:get_sprite():set_animation("walking")
    sol.timer.start(self, 1000, function() self:check_action() end)
  end
end


Sprite file:
animation{
  name = "walking",
  src_image = "enemies/gohma.png",
  frame_delay = 200,
  frame_to_loop_on = 0,
  directions = {
    { x = 0, y = 128, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
    { x = 0, y = 64, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
    { x = 0, y = 96, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
    { x = 0, y = 32, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
  },
}

animation{
  name = "shaking",
  src_image = "enemies/gohma.png",
  frame_delay = 100,
  frame_to_loop_on = 0,
  directions = {
    { x = 64, y = 128, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 2 },
    { x = 64, y = 64, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 2 },
    { x = 64, y = 96, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 2 },
    { x = 64, y = 32, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 2 },
  },
}

animation{
  name = "hurt",
  src_image = "enemies/gohma.png",
  frame_delay = 100,
  frame_to_loop_on = 0,
  directions = {
    { x = 256, y = 32, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
    { x = 256, y = 32, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
    { x = 256, y = 32, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
    { x = 256, y = 32, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
  },
}

animation{
  name = "closed",
  src_image = "enemies/gohma.png",
  frame_delay = 200,
  frame_to_loop_on = 0,
  directions = {
    { x = 256, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
    { x = 256, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
    { x = 256, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
    { x = 256, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 4 },
  },
}

animation{
  name = "blinking",
  src_image = "enemies/gohma.png",
  frame_delay = 150,
  directions = {
    { x = 0, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 3 },
    { x = 0, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 3 },
    { x = 0, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 3 },
    { x = 0, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 3 },
  },
}

animation{
  name = "opening",
  src_image = "enemies/gohma.png",
  frame_delay = 150,
  directions = {
    { x = 128, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 2 },
    { x = 128, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 2 },
    { x = 128, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 2 },
    { x = 128, y = 0, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29, num_frames = 2 },
  },
}

animation{
  name = "immobilized",
  src_image = "enemies/gohma.png",
  directions = {
    { x = 0, y = 128, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29 },
    { x = 0, y = 64, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29 },
    { x = 0, y = 96, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29 },
    { x = 0, y = 32, frame_width = 64, frame_height = 32, origin_x = 32, origin_y = 29 },
  },
}
#254
Hmmm... I'll triple check my system config - I just thought I'd check with you too!
#255
I went to compile the newest code, and all the sudden I'm getting a cmake error about not being able to find OpenAL which I didn't get yesterday when I compiled older code. I double-checked and my system does have libopenal installed.

-- Looking for include file pthread.h
-- Looking for include file pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE 
-- Found SDL2: /usr/local/lib/libSDL2main.a;/usr/local/lib/libSDL2.so;-lpthread (Required is at least version "2")
-- Found SDL2_image: /usr/include/SDL2 (found suitable version "2.0.0", minimum required is "2")
-- Found SDL2_ttf: /usr/local/include/SDL2 (found suitable version "2.0.12", minimum required is "2.0.12")
CMake Error at /usr/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:108 (message):
  Could NOT find OpenAL (missing: OPENAL_LIBRARY)
Call Stack (most recent call first):
  /usr/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:315 (_FPHSA_FAILURE_MESSAGE)
  /usr/share/cmake-2.8/Modules/FindOpenAL.cmake:97 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  CMakeLists.txt:18 (find_package)


-- Configuring incomplete, errors occurred!