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

Topics - polyglot762

#1
Development / Custom Hero?
November 09, 2015, 01:30:55 PM
Hi All,
I am looking to change the collision with the hero but haven't yet found anything in the documentation to do this.
Should I just start to investigate how it could be done as a custom entity?
Thanks,
PG
#2
Development / Color Rotations in Solarus
September 29, 2015, 10:38:40 PM
Hi all,
I just got done looking through the API looking for a way to have my sprites rotate colors with out having them actually have to be painted that way.
Is there a way to code this into solarus presently? I was thinking about using the font surface but I'm sure there is a cleaner way to do it with a custom entity or some such method.
Thanks for the help,
Poly
#3
Development / Game Feel in Solarus 1.4
September 26, 2015, 01:33:13 AM
Hello All,
I have recently encountered the term "game feel" in the following youtube videos.
"Why your game death animation sucks"
https://www.youtube.com/watch?v=HdXoRcq64zQ
"Game Makers Tool kit"
https://www.youtube.com/watch?v=216_5nu4aVQ
"The art of screenshake"
https://youtu.be/AJdEqssNZ-U
"The 4 Hour Game Design"
https://www.youtube.com/watch?v=sgwlJu8Ql2o
"Juice it or lose it"
https://www.youtube.com/watch?v=Fy0aCDmgnxg

The "Juice it or lose it" break out demo clone program is here.
https://github.com/grapefrukt/juicy-breakout

I know there are ways to make some of these type of effects manually in Solarus.
Such as screen shake, and particle effects via sprite art.

Is there a way create these effects without manually editing the sprites with effects?

Or an even better question...
Is there a way we can add these in the code as a manager?

Thanks,
Poly


#4
Zelda Return of the Hylian SE / Awesome Features...
August 20, 2015, 07:08:18 PM
Hi Devs,
Every amount of awesome content and code deserves recognition.
While trying a playthrough of the beta I just thought I would give a shout out for the great work that has been done on this project as of Aug 2015.
The new menu animations are great!
I love the new "run" mode for link.
The menu system using "hot keys" really works for speed runs.
The enemy movement speed really fits with the speed run game design.
I also like the use of the custom entities in the bombs_counter code to create a more original Zelda feel.

The organization of the code in the scripts into libraries is much cleaner and more utilitarian.
The custom objects like the hookshot(though presently suffers from some performance issues.) are great!
Also the ice_rod coded to change the tiles from water to ice blew my mind.
I love how you included the custom transformations into the "rabbit" code in the game_manager.

I also like how the dungeon_manager records in real time where you have explored in the HUD and in the savegame file.
I have downloaded the most recent version and am looking to try another playthough later this week.
Seriously... you all do Awesome Work! Thankyou!
#5
Hello Again,
I have been working steadily on methods to create a targeting system for my custom entities and enemies.
Is there any way to target map entities with out giving them a name?
That right now is the biggest hurdle I have come across.

Currently, the system I am working on uses collision detection with an invisible circular sprite to create the illusion of a line of sight search...
But this is just a work around...
Any suggestions? Better ideas? Things I'm missing?
Thanks.
#6
Your projects / Day Zero
July 29, 2015, 06:33:23 PM
Hello all,
I am currently developing away from the standard Zelda themed quests.

The time-line
PRE-ALPHA for the end of the year for the coding.
ALPHA: well over a year for the sprites and art.
BETA: ~ 2 Years.

I am far enough along to post this as this version will be finished.

The current goals list and change log are posted below.

GOALS LIST: For Summer 2015
Finish the Custom Entity Allies.
Finish the Enemy types: IE Melee, Scout, Ranged, Leader + New Weapon Types.
Finish New Weapon Type behaviors: Knife, Pistol, Shotgun, Rifle, Grenades,
Finish HUD for Allies. Finish Pause Screen for Allies and Equipment.
Start Minigame Implimentation.
Start Dialog and Map Coding.

I hope this will give some scope and focus to the type of game that is in process.

FIXED BUG: Created ally behavior so that it isn't constantly running over the hero.
FIXED ERROR: DLL No longer crashes. Make sure to enclose all maps.
FIXED ERROR: Do set optomization distances.
FIXED Flee function: Make the enemy/ally run away.
FEATURE: Enemies now run away/ towards hero when enemy has low health. (to a distance away)
FEATURE: Enemies now regenerate health with the "regen" in properties.
FEATURE: Rudimentary weapons effect.
FEATURE: Created leader generic enemy that spawns a number of enemies outside the view of the player.
FEATURE: Finished generic ranged enemy that spawns bullets of sorts.
FEATURE: Created allies system...
BUGGY: Working on leaders and commoners code to detect various enemy groups.

The story is done, (Conceptually).

The allies system progress is below.
--DONE! ENEMY/ALLIES_BEHAVIOURS: Melee, Run when weak(Low health)
--DONE! ENEMY/ALLIES_BEHAVIOURS: Ranged, Stay far, run when weak, attack far.
--DONE! ENEMY/ALLIES_BEHAVIOURS: Leader, Attack close, Spawn enemies, attack far, stay far.

IF you want to help shoot me a post.
IF you want to discuss how to implement or create these features please start a separate post in the development section.
When in ALPHA the game code will be released and you will be able to tinker with it then.
#7
Development / New Enemy Features Code
July 28, 2015, 09:31:24 PM
Hi All,
I thought I would contribute to the scripting community.

Below are a number of scripts and features that I have been working on.

This particular has the following features that you will be able to tease out.
Life regen, Projectile shooting, Enemy spawning, Run away at half health, pathfinding.

I'd like to credit wrightmat with the projectile code.

local enemy = ...

-- ranged leader type
local properties = {}
local main_sprite = nil
local towards_hero = false
local away_hero = false
local attacked_hero = false
local towards_enemy = false
local timer, fire_timer

function enemy:set_properties(prop)
  properties = prop
  if properties.life == nil then
    properties.life = 2
  end
  if properties.damage == nil then
    properties.damage = 2
  end
  if properties.play_hero_seen_sound == nil then
    properties.play_hero_seen_sound = false
  end
  if properties.stopped_speed == nil then
    properties.stopped_speed = 0
  end
  if properties.normal_speed == nil then
    properties.normal_speed = 32
  end
  if properties.faster_speed == nil then
    properties.faster_speed = 64
  end
  if properties.hurt_style == nil then
    properties.hurt_style = "normal"
  end
    if properties.regen == nil then
    properties.regen = 0
  end
end

function enemy:on_created()
  self:set_life(properties.life)
  self:set_damage(properties.damage)
  self:set_hurt_style(properties.hurt_style)
  main_sprite = self:create_sprite(properties.main_sprite)
  self:set_size(16, 16)
  self:set_origin(8, 13)
  self:set_attack_consequence("sword", 1)
  self:begin()
end

function enemy:begin()
  local get_life = enemy:get_life()
  local ehalflife = .5 * properties.life
  local hero = self:get_map():get_entity("hero")
  local _, _, layer = self:get_position()
  local _, _, hero_layer = hero:get_position()
  local spawn_line = layer == hero_layer
     and self:get_distance(hero) > 200
  local sight_line = layer == hero_layer
     and self:get_distance(hero) < 100
  local life_recharge = enemy:get_life() < properties.life
  local life_low = enemy:get_life() < ehalflife
     and self:get_distance(hero) < 64
  if spawn_line then
    self:go_spawn()
  elseif not sight_line then
    self:go_random()
  elseif sight_line and not towards_hero and not away_hero then
    self:go_hero()
  elseif not sight_line and not towards_hero then
    self:go_random()
  elseif sight_line and towards_hero then
    if not fire_timer then self:fire()
  elseif life then
    self:go_away()
  else
    self:go_random()
    end
  if life_recharge then
    self:get_game():add_life(properties.regen)
  end
  timer = sol.timer.start(self, 1000, function() self:begin()
  return true
  end)
  end
end

function enemy:on_restarted()
  timer = sol.timer.start(self, 1000, function() self:begin()
  return true
  end)
end

function enemy:on_hurt()
  if timer ~= nil then
    timer:stop()
    timer = nil
  end
  self:begin()
end

function enemy:on_movement_changed(movement)
  local direction4 = movement:get_direction4()
  main_sprite:set_direction(direction4)
end

function enemy:go_spawn()
    local x, y, layer = self:get_position()
    local direction = self:get_sprite():get_direction()
   
  if self:get_map():get_entities_count("lizalfos") <= 3 then
     if direction == 0 then
     x = x + 32
     elseif direction == 1 then
     y = y - 32
     elseif direction == 2 then
     x = x - 32
     elseif direction == 3 then
     y = y + 32
     end

    local spawn = enemy:create_enemy{
      name = "lizalfos",
      breed = "lizalfos",
      x = x,
      y = y,
      layer = layer,
      direction = direction,
      treasure_name = "random"
    }
    spawn:set_position(x, y, layer)
    spawn:set_optimization_distance(0)
  end
end

function enemy:go_away()
  local x, y = self:get_map():get_entity("hero"):get_position()
  local direction = self:get_sprite():get_direction()
    if direction == 0 then
    x = x + 128
    elseif direction == 1 then
    y = y - 128
    elseif direction == 2 then
    x = x - 128
    elseif direction == 3 then
    y = y + 128
    end
 
  local m = sol.movement.create("target")
  m:set_speed(properties.faster_speed)
  m:set_target(x, y)
  m:set_ignore_obstacles(false)
  m:start(self)
  away_hero = true
  towards_hero = false
end

function enemy:go_random()
  self:get_sprite():set_animation("walking")
  local m = sol.movement.create("random_path")
  m:set_speed(properties.normal_speed)
  m:start(self)
  towards_hero = false
  away_hero = false
end

function enemy:go_hero()
  local m = sol.movement.create("target")
  m:set_speed(properties.normal_speed)
  m:start(self)
  towards_hero = true
  away_hero = false
end

function enemy:go_static()
  local m = sol.movement.create("target")
  m:set_speed(0)
  m:start(self)
  towards_hero = false
end

function enemy:fire()
  self:get_sprite():set_animation("firing")
  fire_timer = sol.timer.start(self, 100, function()
    local x, y, layer = self:get_position()
    local direction = self:get_sprite():get_direction()
   
    if direction == 0 then
      x = x + 16
    elseif direction == 1 then
      y = y - 16
    elseif direction == 2 then
      x = x - 16
    elseif direction == 3 then
      y = y + 16
    end
    if rock == nil or not rock:exists() then
    local rock = enemy:create_enemy{
      x = x,
      y = y,
      layer = layer,
      direction = direction,
      breed = "projectile"
    }
    self.created = true
    rock:set_position(x, y, layer)
    rock:set_optimization_distance(0)
    end
    end)
    sol.timer.start(self, 1000, function()
      fire_timer = nil
      self:begin()
    end)
  end


just use the generic format from solarus dx to make enemies like this.

good luck.
Comments and code corrections are welcome.
#8
Development / Custom Entity: Ally Creation issue
July 22, 2015, 12:55:13 AM
Hi all,
I have been working on implementing code like this into my solarus game
though it works and the companions spawn I am having trouble getting
the companions to spawn near the hero.
The typical methods such as altering the x and y have not worked.
Any suggestions?

Code sample attached.
Code (lua) Select
  local hero = self:get_map():get_entity("hero")
  local x, y, layer = hero:get_position()
  local direction = hero:get_direction()

  if game:get_value("a1000") and game:get_value("a1006")
  then
  ally1 = map:create_custom_entity{
      name = "a_butterfly",
      x = x,
      y = x,
      layer = layer,
      direction = direction,
      sprite = "allies/a_butterfly",
      model = "ally_butterfly"
    }
  self.created = true
  local ally1 = true
  local allynumber = 1
  end
#9
Hello Dev team,
I would like the ability to select the death animation for various enemies or custom entities.
As far as I have searched through the source code I haven't found anything exactly like this.
in the enemy.cpp there is a section kind of like what I am hoping to do but I would like to make it more customizable to the breed or custom entity.

Some solutions... (I thought of in lieu of the feature)
remove the general death animation...
then create items for each enemy that are looped after the item death animation.
I am not sure though how well this type of jerryrigging would affect performance.

Observation... looping the death animation creates some hilarious results.

Thanks for the consideration,
PG
#10
Hi all,
I have been working on creating a new pause inventory screen dealing with allies.
I have gotten the pause screen working but I haven't figured out how to create a colored surface
for the icons to rest on.
I was also wondering about adding a new Ally Icon system with a custom key binding.
Any help and comments to help get this working.
Thanks.

The Allies Pause Inventory.
local submenu = require("menus/pause_submenu")
local allies_status_submenu = submenu:new()
--

local item_names = {

  "ally_butterfly",

}

function allies_status_submenu:on_started()

  submenu.on_started(self)

  self.cursor_sprite = sol.sprite.create("menus/pause_cursor")
  self.sprites = {}
  self.counters = {}
  self.captions = {}

  for k = 1, #item_names do
    -- Get the item, its possession state and amount.
    local item = self.game:get_item(item_names[k])
    local variant = item:get_variant()

    if variant > 0 then
      if item:has_amount() then
        -- Show a counter in this case.
        local amount = item:get_amount()
        local maximum = item:get_max_amount()

        self.counters[k] = sol.text_surface.create{
          horizontal_alignment = "center",
          vertical_alignment = "top",
          text = item:get_amount(),
          font = (amount == maximum) and "green_digits" or "white_digits",
        }
      end

      -- Initialize the sprite and the caption string.
      self.sprites[k] = sol.sprite.create("entities/items")
      self.sprites[k]:set_animation(item_names[k])
      self.sprites[k]:set_direction(variant - 1)
    end
  end

  -- Initialize the cursor
  local index = self.game:get_value("pause_inventory_last_item_index") or 0
  local row = math.floor(index / 8)
  local column = index % 8
  self:set_cursor_position(row, column)
end

function allies_status_submenu:on_finished()

  if submenu.on_finished then
    submenu.on_finished(self)
  end

  if self:is_assigning_item() then
    self:finish_assigning_item()
  end

  if self.game.hud ~= nil then
    self.game.hud.allies_icon_1.surface:set_opacity(255)
  end
end

function allies_status_submenu:set_cursor_position(row, column)

  self.cursor_row = row
  self.cursor_column = column

  local index = row * 8 + column
  self.game:set_value("pause_inventory_last_item_index", index)

  -- Update the caption text and the action icon.
  local item_name = item_names[index + 1]
  local item = item_name and self.game:get_item(item_name) or nil
  local variant = item and item:get_variant() or 0

  local item_icon_opacity = 128
  if variant > 0 then
    self:set_caption("inventory.caption.item." .. item_name .. "." .. variant)
    self.game:set_custom_command_effect("action", "info")
    if item:is_assignable() then
      item_icon_opacity = 255
    end
  else
    self:set_caption(nil)
    self.game:set_custom_command_effect("action", nil)
  end
  self.game.hud.allies_icon_1.surface:set_opacity(item_icon_opacity)
end

function allies_status_submenu:get_selected_index()

  return self.cursor_row * 7 + self.cursor_column
end

function allies_status_submenu:is_item_selected()

  local item_name = item_names[self:get_selected_index() + 1]
  return self.game:get_item(item_name):get_variant() > 0
end

function allies_status_submenu:on_command_pressed(command)
 
  local handled = submenu.on_command_pressed(self, command)

  if not handled then

    if command == "action" then
      if self.game:get_command_effect("action") == nil
            and self.game:get_custom_command_effect("action") == "info" then
        self:show_info_message()
        handled = true
      end

    elseif command == "ally_1" then
      if self:is_item_selected() then
        self:assign_item(1)
        handled = true
      end

    elseif command == "left" then
      if self.cursor_column == 0 then
        self:previous_submenu()
      else
        sol.audio.play_sound("cursor")
        self:set_cursor_position(self.cursor_row, self.cursor_column - 1)
      end
      handled = true

    elseif command == "right" then
      if self.cursor_column == 6 then
        self:next_submenu()
      else
        sol.audio.play_sound("cursor")
        self:set_cursor_position(self.cursor_row, self.cursor_column + 1)
      end
      handled = true

    elseif command == "up" then
      sol.audio.play_sound("cursor")
      self:set_cursor_position((self.cursor_row + 3) % 4, self.cursor_column)
      handled = true

    elseif command == "down" then
      sol.audio.play_sound("cursor")
      self:set_cursor_position((self.cursor_row + 1) % 4, self.cursor_column)
      handled = true

    end
  end

  return handled
end

function allies_status_submenu:on_draw(dst_surface)

  self:draw_background(dst_surface)
  self:draw_caption(dst_surface)

  -- Draw each inventory item.
  local quest_width, quest_height = dst_surface:get_size()
  local initial_x = quest_width / 2 - 96
  local initial_y = quest_height / 2 - 38
  local y = initial_y
  local k = 0

  for i = 0, 3 do
    local x = initial_x

    for j = 0, 6 do
      k = k + 1
      if item_names[k] ~= nil then
        local item = self.game:get_item(item_names[k])
        if item:get_variant() > 0 then
          -- The player has this item: draw it.
          self.sprites[k]:draw(dst_surface, x, y)
          if self.counters[k] ~= nil then
            self.counters[k]:draw(dst_surface, x + 8, y)
          end
        end
      end
      x = x + 32
    end
    y = y + 32
  end

  -- Draw the cursor.
  self.cursor_sprite:draw(dst_surface, initial_x + 32 * self.cursor_column, initial_y - 5 + 32 * self.cursor_row)

  -- Draw the item being assigned if any.
  if self:is_assigning_item() then
    self.item_assigned_sprite:draw(dst_surface)
  end

  self:draw_save_dialog_if_any(dst_surface)
end

-- Shows a message describing the item currently selected.
-- The player is supposed to have this item.
function allies_status_submenu:show_info_message()

  local item_name = item_names[self:get_selected_index() + 1]
  local variant = self.game:get_item(item_name):get_variant()
  local map = self.game:get_map()

  -- Position of the dialog (top or bottom).
  if self.cursor_row >= 2 then
    self.game:set_dialog_position("top")  -- Top of the screen.
  else
    self.game:set_dialog_position("bottom")  -- Bottom of the screen.
  end

  self.game:set_custom_command_effect("action", nil)
  self.game:set_custom_command_effect("attack", nil)
  self.game:start_dialog("_item_description." .. item_name .. "." .. variant, function()
    self.game:set_custom_command_effect("action", "info")
    self.game:set_custom_command_effect("attack", "save")
    self.game:set_dialog_position("auto")  -- Back to automatic position.
  end)

end

-- Assigns the selected item to a slot (1 or 2).
-- The operation does not take effect immediately: the item picture is thrown to
-- its destination icon, then the assignment is done.
-- Nothing is done if the item is not assignable.
function allies_status_submenu:assign_item(slot)

  local index = self:get_selected_index() + 1
  local item_name = item_names[index]
  local item = self.game:get_item(item_name)

  -- If this item is not assignable, do nothing.
  if not item:is_assignable() then
    return
  end

  -- If another item is being assigned, finish it immediately.
  if self:is_assigning_item() then
    self:finish_assigning_item()
  end

  -- Memorize this item.
  self.item_assigned = item
  self.item_assigned_sprite = sol.sprite.create("entities/items")
  self.item_assigned_sprite:set_animation(item_name)
  self.item_assigned_sprite:set_direction(item:get_variant() - 1)
  self.item_assigned_destination = slot

  -- Play the sound.
  sol.audio.play_sound("throw")

  -- Compute the movement.
  local x1 = 60 + 32 * self.cursor_column
  local y1 = 75 + 32 * self.cursor_row
  local x2 = (slot == 1) and 20 or 72
  local y2 = 46

  self.item_assigned_sprite:set_xy(x1, y1)
  local movement = sol.movement.create("target")
  movement:set_target(x2, y2)
  movement:set_speed(500)
  movement:start(self.item_assigned_sprite, function()
    self:finish_assigning_item()
  end)
end

-- Returns whether an item is currently being thrown to an icon.
function allies_status_submenu:is_assigning_item()
  return self.item_assigned_sprite ~= nil
end

-- Stops assigning the item right now.
-- This function is called when we want to assign the item without
-- waiting for its throwing movement to end, for example when the inventory submenu
-- is being closed.
function allies_status_submenu:finish_assigning_item()

  -- If the item to assign is already assigned to the other icon, switch both items.
  local slot = self.item_assigned_destination
  local current_item = self.game:get_item_assigned(slot)
  local other_item = self.game:get_item_assigned(3 - slot)

  if other_item == self.item_assigned then
    self.game:set_item_assigned(3 - slot, current_item)
  end
  self.game:set_item_assigned(slot, self.item_assigned)

  self.item_assigned_sprite:stop_movement()
  self.item_assigned_sprite = nil
  self.item_assigned = nil
end


return allies_status_submenu




Allies Hud Icon
-- An icon that shows the inventory item assigned to a slot.

local allies_icon = {}

function allies_icon:new(game, slot)

  local object = {}
  setmetatable(object, self)
  self.__index = self

  object:initialize(game, slot)

  return object
end

function allies_icon:initialize(game, slot)

  self.game = game
  self.slot = slot
  self.surface = sol.surface.create(32, 28)
  self.background_img = sol.surface.create("hud/item_icon_" .. slot .. ".png")
  self.item_sprite = sol.sprite.create("entities/items")
  self.item_displayed = nil
  self.item_variant_displayed = 0
  self.amount_text = sol.text_surface.create{
    horizontal_alignment = "center",
    vertical_alignment = "top"
  }
  self.amount_displayed = nil
  self.max_amount_displayed = nil

  self:check()
  self:rebuild_surface()
end

function allies_icon:check()

  local need_rebuild = false

  -- Item assigned.
  local item = self.game:get_item_assigned(self.slot)
  if self.item_displayed ~= item then
    need_rebuild = true
    self.item_displayed = item
    self.item_variant_displayed = nil
    if item ~= nil then
      self.item_sprite:set_animation(item:get_name())
    end
  end

  if item ~= nil then
    -- Variant of the item.
    local item_variant = item:get_variant()
    if self.item_variant_displayed ~= item_variant then
      need_rebuild = true
      self.item_variant_displayed = item_variant
      self.item_sprite:set_direction(item_variant - 1)
    end

    -- Amount.
    if item:has_amount() then
      local amount = item:get_amount()
      local max_amount = item:get_max_amount()
      if self.amount_displayed ~= amount
          or self.max_amount_displayed ~= max_amount then
        need_rebuild = true
        self.amount_displayed = amount
        self.max_amount_displayed = max_amount
      end
    elseif self.amount_displayed ~= nil then
      need_rebuild = true
      self.amount_displayed = nil
      self.max_amount_displayed = nil
    end
  elseif self.amount_displayed ~= nil then
    need_rebuild = true
    self.amount_displayed = nil
    self.max_amount_displayed = nil
  end

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

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

function allies_icon:rebuild_surface()

  self.surface:clear()

  -- Background image.
  self.background_img:draw(self.surface)

  if self.item_displayed ~= nil then
    -- Item.
    self.item_sprite:draw(self.surface, 12, 17)
    if self.amount_displayed ~= nil then
      -- Amount.
      self.amount_text:set_text(tostring(self.amount_displayed))
      if self.amount_displayed == self.max_amount_displayed then
        self.amount_text:set_font("green_digits")
      else
        self.amount_text:set_font("white_digits")
      end
      self.amount_text:draw(self.surface, 18, 16)
    end
  end
end

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

function allies_icon:on_draw(dst_surface)

  if not self.game:is_dialog_enabled() 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 allies_icon

#11
Development / Jumping Limitations
June 11, 2015, 10:36:34 PM
Hi all,
I was wondering... Is the jumping mechanic hard coded to only traverse the layer that the character is currently on?
Or is there a way to have the hero character for example grab onto a ledge and pull himself up or jump between layers?
Thanks.