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 - xavius

#1
I sent you the link.
#2
My god, it has been a long time. Already to version 1.4.2!

I had a computer failure, took me time to get the money to buy a new one.

Yes Christopho, I can send you the project. What is your E-mail? I will give you the link.

Thank you again!
#3
Hi,

It has been a long time since I got the time to develop my game but here I am.

I am having difficulties to update from v1.2 to v1.3. I used the map upgrade from the editor but all my maps that contain entities will just crash the editor when loading and without getting any error. I checked further by trying to run them with the game executable. Here is what I get for one map (see attached)

I checked the dat file and got to the lines in question:
switch{
  layer = 0,
  x = 1544,
  y = 1608,
  name = "secret_chest1",
  subtype = "1",
  needs_block = false,
  inactivate_when_leaving = false,
}

The second argument is suppose to be the ground type if I understood correctly. In my map, it is the x position of the entity itself.

What should I do to change this and be compatible with v1.3?

Thank you!

#4
Your projects / Re: My first video
August 10, 2014, 05:01:41 PM
Thank you Renkineko.

For the death cloud I will check.

For the graphics, I will try to find someone to help me. I really am not the graphic designer type.
#5
Your projects / Re: My first video
August 02, 2014, 05:02:19 PM
Hi Christopho,

For the walls and floors, I though it was ok but I agree that the holes need graphic redraw. I am not a very talented graphic designer plus I am colorblind which does not help much.

For the moving plateform, I used a dynamic tile and a custom entity. I just have an issue to finish, reset the positions and logic every time you past a separator or else you get what you see at the end of the video, desync platforms. When I have cleaned the code, I will release it on the forum.

The conveyors are also a custom entity because the one hard coded pulls you into the middle which I did not like.

The same goes for all the enemies you saw (except bubble). I have to change the graphics yet again.
#6
Your projects / My first video
August 02, 2014, 05:03:46 AM
Hi evrybody,

I just uploaded a video of a part of one of my dungeons. Not the best video ever recorded and have no sound but anyway, Enjoy!

By the way, does anybody have a good desktop recorder I could use, VLC does not want to record my speaker sound.

https://www.youtube.com/watch?v=6IJ_8VDKCAI&feature=youtu.be
#7
Is there a way to get the position and layer of a solid ground? I did not see it a function for this in the documentation.

Thank you again!
#8
Thank you Christopho. Another question on this. Is the character teleported to the saved ground or it is translated to it? I have remarked depending how far you are from the saved ground point, it will take longer to respawn. Is it possible to do a setHeroPosition(blabla)?

Thank you again!
#9
Hi,

I know you can save ground to reset the hero to a position when he falls but is it possible to do the same with lava and water?

Thank you!
#10
Development / Re: Enemies examples
July 13, 2014, 12:07:17 AM
Here is a new entity I have made.

This is simply a bumper. It has to be 16 x 16, I still have to work the code to make it flexible. It is pretty much the same as the bumpers in ALTTP except it is 16 x 16 instead of 32 x 32.


local entities = ...
local boingIsReady = true

--TODO: Make it compatible with separator manager script
function entities:on_created()
 
  -- Call a function every 22 milliseconds.
sol.timer.start(22, function()
if(boingIsReady == true) then
 
-- Get hero position
local hero_x, hero_y, hero_layer = self:get_map():get_entity("hero"):get_position()

-- When changed in engine, get hero width & height here
local hero_width = 16
local hero_height = 16

-- Get entity position
local ent_x, ent_y, ent_layer = self:get_position()
local ent_width, ent_height = self:get_size()

--TODO: change this line, I hate it, not clean at all
if( ( (ent_x - 12) < hero_x) and ( (ent_x + ent_width - 3) > hero_x) and ( (ent_y - 12) < hero_y) and ( (ent_y - 11 + ent_height) > hero_y) ) then
--self:get_map():get_entity("hero"):set_position(hero_x, hero_y + 1, hero_layer)

self:get_map():get_entity("hero"):freeze()

-- Get center point of entity and hero
local ent_center_x = ent_x + (ent_width / 2)
local ent_center_y = ent_y + (ent_height / 2)

local hero_center_x = hero_x + (hero_width / 2)
local hero_center_y = hero_y + (hero_height / 2)

-- Get delta x and delta y
local delta_x =  hero_center_x - ent_center_x
local delta_y =  hero_center_y - ent_center_y

local angle = 0

--Check if value is 0 or else division by 0
if(delta_x == 0) then
if(delta_y <= 0) then
angle = math.pi / 2
else
angle = 3 * math.pi / 2
end
else
-- Get angle with arctan
angle = math.atan(delta_y / delta_x)

-- Check the side of the angle
if(ent_center_x < hero_center_x) then
-- reverse angle, for some weird reason, atan start it's angle at pi instead of 0... Correct me if I am wrong
angle = angle * -1
elseif(ent_center_x > hero_center_x) then
-- Substract from pi
angle = math.pi - angle
end
end

-- Set movement stuff
local m = sol.movement.create("straight")
m:set_speed(130)
m:set_max_distance(32)
m:get_ignore_obstacles(false)

-- Set movement angle
m:set_angle(angle)

-- Start movement
m:start(self:get_map():get_entity("hero"))

-- Boing!
sol.audio.play_sound("bounce")

-- Lock function
boingIsReady = false

sol.timer.start(300, function()

-- Check if hero is still freezed, if not, do nothing
if( self:get_map():get_entity("hero"):get_state() == "freezed") then
self:get_map():get_entity("hero"):unfreeze()
end

-- Unlock function
boingIsReady = true
end)
end --If position
end --if(boingIsReady == true)
return true
end) --main timer
end
#11
Here is a new script.

I added a feature to choose if the enemy will reappear or not. If you want to reset the enemy every time you enter the region, just add "reappear" in the enemy name. If the enemy is dead, it will be recreated. If it is alive, the life counter will be reset.

For a weird reason, when I paste the code, the indentations are not correct. Sorry for this.

manager_separator.lua

-- This script manages enemies when there are separators in a map.
-- Enemies that are prefixed by "auto_enemy" are automatically
-- reset at their initial position when taking separators prefixed by "auto_separator".

local separator_manager = {}

function separator_manager:manage_map(map)

  local enemy_places = {}

  -- Store the position and properties of enemies.
  for enemy in map:get_entities("auto_enemy") do
    local x, y, layer = enemy:get_position()
local spriteTemp = enemy:get_sprite()
local reappear = 0

if( string.find(enemy:get_name(), "reappear") ~= nil ) then
  reappear = 1
else
  reappear = 0
end

    enemy_places[#enemy_places + 1] = {
      x = x,
      y = y,
      layer = layer,
 
      --direction = enemy:get_sprite():get_direction(),
      enemy = enemy,
 
  -- Get breed to recreate it if it has to reappear
  breed = enemy:get_breed(),
  name = enemy:get_name(),
  life = enemy:get_life(),
 
  --Set if enemy should reappear or not
  reappear = reappear,
    }
enemy:set_enabled(false)
  end

  -- Function called when a separator was just taken.
  local function separator_on_activating(separator)
 
    local hero = map:get_hero()
    for _, enemy_place in ipairs(enemy_places) do
 
  local enemy = enemy_place.enemy
 
  --Check if enemy is tagged to reappear unpon entering the screen
  if( enemy_place.reappear == 1 ) then
    -- if enemy is destroyed or about to be
if( enemy:exists() == false ) or ( enemy:get_life() <= 0 ) then
  -- Create enemy
  enemy_place.enemy = map:create_enemy{
  name = enemy_place.name,
  breed = enemy_place.breed,
  x = enemy_place.x,
  y = enemy_place.y,
  layer = enemy_place.layer,
  direction = 0,
}

  enemy = enemy_place.enemy
else
  -- If not destroyed or about to then reset life counter
  enemy:set_life(enemy_place.life)
end
  end

 
      if enemy:exists() then
    if enemy:get_life() > 0 then
          if enemy:is_in_same_region(hero) then
   
enemy:set_position(enemy_place.x, enemy_place.y, enemy_place.layer)
--enemy:get_sprite():set_direction(enemy_place.direction)
enemy:set_enabled(false)
  end
end
      end
    end
  end
 
  -- Function called after a separator was just taken.
  local function separator_on_activated(separator)
    local hero = map:get_hero()
    for _, enemy_place in ipairs(enemy_places) do
      local enemy = enemy_place.enemy

      if enemy:exists() then
    if enemy:get_life() > 0 then
          if enemy:is_in_same_region(hero) then
enemy:set_enabled(true)
enemy:restart()
  end
end
      end
    end
  end

  for separator in map:get_entities("auto_separator") do
    separator.on_activating = separator_on_activating
separator.on_activated = separator_on_activated
  end

end

return separator_manager
#12
I found a bug in the script. In the case you kill an enemy and get out of the screen before the dying animation is finished, it will still exist. Then when reentering the screen, the game will crash because the enemy is supposed to be dead but the script is trying to restart it.

I simply do a check of the life count with the check on exists().

By the way, is it possible to get the enemy entity name in the enemy object itself?

Thank you.

The new code of separator_manager.lua:

-- This script manages enemies when there are separators in a map.
-- Enemies that are prefixed by "auto_enemy" are automatically
-- reset at their initial position when taking separators prefixed by "auto_separator".

local separator_manager = {}

function separator_manager:manage_map(map)

  local enemy_places = {}

  -- Store the position and properties of enemies.
  for enemy in map:get_entities("auto_enemy") do
    local x, y, layer = enemy:get_position()
local spriteTemp = enemy:get_sprite()

    enemy_places[#enemy_places + 1] = {
      x = x,
      y = y,
      layer = layer,
 
      --direction = enemy:get_sprite():get_direction(),
      enemy = enemy,
 
  --Set if enemy should reappear or not
  --reappear = 0,
    }
enemy:set_enabled(false)
  end

  -- Function called when a separator was just taken.
  local function separator_on_activating(separator)
 
    local hero = map:get_hero()
    for _, enemy_place in ipairs(enemy_places) do
      local enemy = enemy_place.enemy

  --string.find(s, pattern [, index [, plain]])
 
      if enemy:exists() then
    if enemy:get_life() <= 0 then
          if enemy:is_in_same_region(hero) then

enemy:set_position(enemy_place.x, enemy_place.y, enemy_place.layer)
--enemy:get_sprite():set_direction(enemy_place.direction)
enemy:set_enabled(false)
  end
end
      end
    end
  end
 
  -- Function called after a separator was just taken.
  local function separator_on_activated(separator)
    local hero = map:get_hero()
    for _, enemy_place in ipairs(enemy_places) do
      local enemy = enemy_place.enemy

      if enemy:exists() then
    if enemy:get_life() <= 0 then
          if enemy:is_in_same_region(hero) then
enemy:set_enabled(true)
enemy:restart()
  end
end
      end
    end
  end

  for separator in map:get_entities("auto_separator") do
    separator.on_activating = separator_on_activating
separator.on_activated = separator_on_activated
  end

end

return separator_manager
#13
Development / Re: Enemies examples
June 14, 2014, 07:34:46 PM
Guruguru bar

This is simply a reproduction of this ennemy: http://zeldawiki.org/Guruguru_Bar

I made two version, one clockwise and the other counter clockwise. Theses two enemies do not have graphics, they are simply the center of the firebar. The firebar itself is composed of another enemy.

I used the graphics of super mario world for the fireballs. See attached.

Here is the fireBall sprite script:
animation{
  name = "walking",
  src_image = "enemies/fireBall.png",
  frame_delay = 50,
  frame_to_loop_on = 0,
  directions = {
    { x = 0, y = 0, frame_width = 16, frame_height = 16, origin_x = 0, origin_y = 0, num_frames = 2 },
    { x = 0, y = 0, frame_width = 16, frame_height = 16, origin_x = 0, origin_y = 0, num_frames = 2 },
    { x = 0, y = 0, frame_width = 16, frame_height = 16, origin_x = 0, origin_y = 0, num_frames = 2 },
    { x = 0, y = 0, frame_width = 16, frame_height = 16, origin_x = 0, origin_y = 0, num_frames = 2 },
  },
}


The fireball ennemy:
local enemy = ...

function enemy:on_created()
  self:set_life(1)
  self:set_damage(2)
  self:create_sprite("fireBall")
  self:set_size(16, 16)
  self:set_origin(8, 8)
  self:set_invincible()
  self:set_obstacle_behavior("flying")
end

-- Circles around the enemy that created it
function enemy:go_circle(center_entity, rayon, notRev)
  local m = sol.movement.create("circle")
  m:set_center(center_entity, -8, -29)
  m:set_radius(rayon)
  m:set_angle_speed(88)
  m:set_ignore_obstacles(true)
  m:set_clockwise(notRev)
  m:start(self)
end


Clockwise firebar:
local enemy = ...
local son, son2, son3, son4

function enemy:on_created()

  self:set_life(1)
  self:set_damage(0)
  self:set_size(16, 16)
  self:set_origin(8, 8)
  self:set_invincible()
  self:set_obstacle_behavior("flying")
 
  son = self:create_enemy{
      name = son_name,
      breed = "fireBall",
      x = 0,
      y = 0,
      layer = 0,
    }
    son:go_circle(self, 16, true)
son:set_optimization_distance(0) -- We do not want the enemy to ever stop if player is too far,
-- take note this is consuming resourcces. Use disabled() function stop.

son2 = self:create_enemy{
      name = son_name,
      breed = "fireBall",
      x = 0,
      y = 0,
      layer = 0,
    }
    son2:go_circle(self, 32, true)
son2:set_optimization_distance(0)

son3 = self:create_enemy{
      name = son_name,
      breed = "fireBall",
      x = 0,
      y = 0,
      layer = 0,
    }
    son3:go_circle(self, 48, true)
son3:set_optimization_distance(0)

son4 = self:create_enemy{
      name = son_name,
      breed = "fireBall",
      x = 0,
      y = 0,
      layer = 0,
    }
    son4:go_circle(self, 64, true)
son4:set_optimization_distance(0)

son:set_enabled(true)
son2:set_enabled(true)
son3:set_enabled(true)
son4:set_enabled(true)
end

function enemy:on_restarted()
son:set_enabled(true)
son2:set_enabled(true)
son3:set_enabled(true)
son4:set_enabled(true)

son:go_circle(self, 16, true)
son:set_optimization_distance(0)
son2:go_circle(self, 32, true)
son2:set_optimization_distance(0)
son3:go_circle(self, 48, true)
son3:set_optimization_distance(0)
son4:go_circle(self, 64, true)
son4:set_optimization_distance(0)
end

function enemy:on_disabled()
son:set_enabled(false)
son2:set_enabled(false)
son3:set_enabled(false)
son4:set_enabled(false)
end


Counter clockwise firebar:
local enemy = ...
local son, son2, son3, son4

function enemy:on_created()

  self:set_life(1)
  self:set_damage(0)
  self:set_size(16, 16)
  self:set_origin(8, 8)
  self:set_invincible()
  self:set_obstacle_behavior("flying")
 
  son = self:create_enemy{
      name = son_name,
      breed = "fireBall",
      x = 0,
      y = 0,
      layer = 0,
    }
    son:go_circle(self, 16, false)
son:set_optimization_distance(0)

son2 = self:create_enemy{
      name = son_name,
      breed = "fireBall",
      x = 0,
      y = 0,
      layer = 0,
    }
    son2:go_circle(self, 32, false)
son2:set_optimization_distance(0)

son3 = self:create_enemy{
      name = son_name,
      breed = "fireBall",
      x = 0,
      y = 0,
      layer = 0,
    }
    son3:go_circle(self, 48, false)
son3:set_optimization_distance(0)

son4 = self:create_enemy{
      name = son_name,
      breed = "fireBall",
      x = 0,
      y = 0,
      layer = 0,
    }
    son4:go_circle(self, 64, false)
son4:set_optimization_distance(0)

son:set_enabled(true)
son2:set_enabled(true)
son3:set_enabled(true)
son4:set_enabled(true)
end

function enemy:on_restarted()
son:set_enabled(true)
son2:set_enabled(true)
son3:set_enabled(true)
son4:set_enabled(true)

son:go_circle(self, 16, false)
son:set_optimization_distance(0)
son2:go_circle(self, 32, false)
son2:set_optimization_distance(0)
son3:go_circle(self, 48, false)
son3:set_optimization_distance(0)
son4:go_circle(self, 64, false)
son4:set_optimization_distance(0)
end

function enemy:on_disabled()
son:set_enabled(false)
son2:set_enabled(false)
son3:set_enabled(false)
son4:set_enabled(false)
end



#14
Development / Enemies examples
June 14, 2014, 07:17:55 PM
Hi everybody,

I want to share some enemies that I have created with you. Could be useful for your projects. All of theses enemies are compatibles with this script http://forum.solarus-games.org/index.php/topic,51.0.html made by Christopho to reset enemies positions when crossing a separator.

I will add enemies time to time as I go in learning lua.

Homing bat
Simply, it is a bat that stands and do nothing. If you come close enough, it will go at you in a straight line. I used the Ganon firebat graphics for this, I changed the graphic script though to make it more realistic.

fire_bat.dat modified script:
animation{
  name = "stopped",
  src_image = "enemies/fire_bat.png",
  directions = {
    { x = 160, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 1 },
    { x = 160, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 1 },
    { x = 160, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 1 },
    { x = 160, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 1 },
  },
}

animation{
  name = "walking",
  src_image = "enemies/fire_bat.png",
  frame_delay = 50,
  frame_to_loop_on = 2,
  directions = {
    { x = 96, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 4 },
    { x = 96, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 4 },
    { x = 96, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 4 },
    { x = 96, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 4 },
  },
}

animation{
  name = "hurt",
  src_image = "enemies/fire_bat.png",
  frame_delay = 50,
  frame_to_loop_on = 0,
  directions = {
    { x = 192, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 2 },
    { x = 192, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 2 },
    { x = 192, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 2 },
    { x = 192, y = 0, frame_width = 32, frame_height = 32, origin_x = 16, origin_y = 16, num_frames = 2 },
  },
}



homing bat script
local enemy = ...
local going_hero = false
local m

function enemy:on_created()
  self:set_life(1)
  self:set_damage(2)
  self:create_sprite("enemies/fire_bat")
 
  self:set_size(16, 8)
  self:set_origin(8, 0)
  self:set_obstacle_behavior("flying")
  m = sol.movement.create("target")
  m:set_ignore_obstacles(false)
  m:set_speed(0)
  m:start(self)
end


function enemy:on_restarted()
  local sprite = self:get_sprite()
  sprite:set_animation("stopped")
  m:set_speed(0)
  going_hero = false

  self:go_random()
  self:check_hero()
end

function enemy:check_hero()
  local hero = self:get_map():get_entity("hero")
  local _, _, layer = self:get_position()
  local _, _, hero_layer = hero:get_position()
  local near_hero = layer == hero_layer
    and self:get_distance(hero) < 150

  if near_hero and not going_hero then
    self:go_hero()
sol.audio.play_sound("bat")

  elseif not near_hero and going_hero then
    self:go_random()
  end
  sol.timer.stop_all(self)
  sol.timer.start(self, 100, function() self:check_hero() end)
end

function enemy:go_random()
  going_hero = false
  local sprite = self:get_sprite()
  sprite:set_animation("stopped")
  m:set_speed(0)
end

function enemy:go_hero()
  going_hero = true
  local sprite = self:get_sprite()
  sprite:set_animation("walking")
  m:set_speed(88)
end




#15
Thank you very much Christopho. Sorry for the delay. I just tried it, works flawlessly.