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

#1
Argh, I was hoping you wouldn't say "Gimp" since this software is really complicated.  :P
But it worked. In fact, when I opened the picutre on Gimp, the alpha channel was already set ! I saved the picture again, tried to lanch the game, and the switches worked well and had a transparent background. I suppose I can do the same operation with bushes.
Thanks for your explanations and your patience with my little problems.  ;)
#2
Finally, it's the color mode. I put off the transparency and the switches worked well.

But as a result, I have another problem (independent of Solarus)  :-[ :



Is there a way to make the image transparent without using PhotoFiltre ? I'm afraid this software is doing something I don't want before making the image transparent. For example, I noticed that the sprites included in Mystery of Solarus don't have a transparent background when I open them on PhotoFiltre. I suppose there is another way to make them transparent ?
#3
Development / Re: Some enemies
September 21, 2013, 11:35:37 AM
I didn't remember there were such enemies in Alttp (it's been a while since I played it now :-[ ), maybe it was the caterpillar fireballs in the dark world dungeon 3 ?

Anyway, thank you for this comment.  ;) I'll probably post some other scripts in the next days (and I think the next one will be the "walker" from Chip's Challenge, since it's a variant of the fireball/glider with a random component, it may be quite easy to do).
#4
(sorry for that late answer, I couldn't connect to Internet since last thursday... and I probably won't able to connect again before some days :-[ )

I put the images on ImageBam, if you can't see Xooimage ones.

About what you said, I'd finally say that the matter comes from the pixel perfect collisions, at least for the crystal switches whose shape is different than the original ones ; for the bushes, it's just the "dark world flower from Alttp" version instead of the "light world bushes from Alttp".
Concerning the images, I use PhotoFiltre to make the background color transparent (so it implies a 256 colors conversion before making the background trasparent). Maybe the background must not be transparent ?
I'm pretty sure that I have the latest version of Solarus (plus, I think I'll change it to the 1.1 in the future, since some features are really interesting).

Anyway, I'll check these options and come back with my replies in a few days.
#5
Development / Some enemies
September 11, 2013, 11:41:55 PM
Hello, it's me again. I said in another topic that since I don't have enough stuff to present the project I'm working on, I'd share some scripts, so here I am.  :)
From now on, maybe it's not very spectacular, but maybe it can help beginners with some skills. ^^

I was working on some enemies from a game named Chip's Challenge (a really good retro game by the way) and tried to implement them as enemies for the Solarus quest editor.

Fireballs and gliders

First, I did the fireball and the glider, two enemies which go straight until they hurt an obstacle. In that case, they go to another direction :
- the fireball goes to its right by default ; and if it's not possible, it goes to his left ; and if it's not possible (if there are walls on its left and on its right) it comes back.
- the glider goes to its left by default ; and if it's not possible, it goes to his right ; and if it's not possible (if there are walls on its left and on its right) it comes back.

If you don't see what I mean, I suggest you watch this video of a Chip's Challenge level (the 100th one), where there are only fireballs (the orange monsters) and gliders (the other ones) : http://www.youtube.com/watch?v=12E6DDiHpVE&hd=1 . You should see their movements.


I'll begin with the fireball (the glider is not very different).
First, create a sprite with 4 directions. For the example, I took the pike one, in order to have a more "Zeldastic" sprite instead of the Chip's Challenge one.

walking enemies/pike.png 4 0 -1
0 0 16 16 8 13 1 1
0 0 16 16 8 13 1 1
0 0 16 16 8 13 1 1
0 0 16 16 8 13 1 1


Put the sprite in the appropriate place, then create the .lua script associated.

First, we declare some local variables :

local enemy = ...
local sprite
local next_direction


Then we do the enemy:on_created event. Do whatever you want, the only important thing is the line I put in bold : indeed, it will set a value for the sprite variable.

function enemy:on_created()

  self:set_life(1)
  self:set_damage(2)
  [b]sprite = self:create_sprite("enemies/pike_clockwise")[/b]
  self:set_size(16, 16)
  self:set_origin(8, 13)
  self:set_can_hurt_hero_running(true)
  self:set_invincible()
  self:set_attack_consequence("sword", "protected")
  self:set_attack_consequence("thrown_item", "protected")
  self:set_attack_consequence("arrow", "protected")
  self:set_attack_consequence("hookshot", "protected")
  self:set_attack_consequence("boomerang", "protected")
end



Let's do the enemy:on_restarted() event now. In this one, we'll tell our "pikeball" to go straight in its direction.
For this, we'll take the sprite direction and create a movement based on it :

function enemy:on_restarted()
  [b]next_direction = sprite:get_direction() * 2[/b]
  local m = sol.movement.create("path")
  m:set_path{next_direction}
  m:set_speed(128)
  m:set_loop(true)
  m:start(self)
end


Be careful with the line I put in bold, because it's a trap. You probably wonder why there is a "* 2". In fact, it's because of the numbering used in the Solarus engine.
You probably know there are eight possible directions, each one corresponding to a number :
  • 0 : right
  • 1 : top-right
  • 2 : top
  • 3 : top-left
  • 4 : left
  • 5 : bottom-left
  • 6 : bottom
  • 7 : bottom-right

In our case, the interesting directions/numbers are only horizontal and vertical ones (0, 2, 4 and 6).
The sprite we defined has four directions : nevertheless, they don't match with the ones we want. Indeed, the directions of the sprite are 0, 1, 2 and 3. So we have to multiply these directions by 2 to have the correct ones.


Then we can define the enemy:on_obstacle_reached() event, the most interesting one.
We can divide it into three parts :
  • Testing if the monster can go where it should (i.e. no obstacle on its right)
  • Define the monster's direction
  • Restart its movement

For the first part, we'll need a complex condition such like this :

if (next_direction == 2 and self:test_obstacles(16, 0)) -- If the monster was going up
    or (next_direction == 0 and self:test_obstacles(0, 16)) -- Was going right
    or (next_direction == 6 and self:test_obstacles(-16, 0)) -- Was going down
    or (next_direction == 4 and self:test_obstacles(0, -16)) -- Was going left
then 


If true, it means that there is an obstacle on the monster's right ; so it will have to go left instead.
Let's define the direction for the monster's left :

-- Then go to the monster's left
    next_direction = next_direction + 2
    if next_direction > 7 then
      next_direction = 0
    end


As we don't want the monster to have a diagonal movement, we add 2 to the next_direction variable. We also have to "reset" it if it was equal to 6 : indeed, 6 + 2 = 8, but "8" isn't a good direction. So we restart it.
Now, let's define the "normal" monster's behavior :

else -- The monster can go on its right
    next_direction = next_direction - 2
    if next_direction < 0 then
      next_direction = 6
    end
  end


It's like the previous piece of code, but in the other way.
Finally, let's make the monster restart in the new next_direction :

-- Set the direction and restart the movement
  sprite:set_direction(next_direction / 2)
  self:restart()
end


Note that you have to divide next_direction by 2 this time, for the same reason I was talking about some lines earlier.

Here's a tip. I previously said that the "pikeball" shall go back if it cannot go on this left nor on its right. But I didn't write anything about that case.
In fact, it's not necessary to write someting for it. Indeed, the first condition is quite efficient for that : it checks whether you can go on your right or not, and if not, the "pikeball" goes on its left. But if there's also something on the left, the enemy:on_obstacle_reached() event is activated again, and will test again if there is an obstacle on the right. And it will be the case since that obstacle is the one the "pikeball" hurt at first ; so its only choice will be left. And left + left = go back.
If you didn't understand what I said, don't worry, the most important thing to remember is that you don't have to bother with the "come back" case.  ;)


You can now insert your enemy in the quest editor and... enjoy !

Here is the complete .lua script for the fireball type enemy :

local enemy = ...

-- Enemy that always moves, horizontally or vertically depending on its direction
-- When it hurts an obstacle, it goes on its right ; if impossible, goes to the left or come back
-- If you know Chip's Challenge, it's like the fireball's movement ^^

local sprite
local next_direction

-- Do whatever you want for this part
function enemy:on_created()
 
  self:set_life(1)
  self:set_damage(2)
  sprite = self:create_sprite("enemies/pike_clockwise") -- But don't forget to define "sprite" and set a value
  self:set_size(16, 16)
  self:set_origin(8, 13)
  self:set_can_hurt_hero_running(true)
  self:set_invincible()
  self:set_attack_consequence("sword", "protected")
  self:set_attack_consequence("thrown_item", "protected")
  self:set_attack_consequence("arrow", "protected")
  self:set_attack_consequence("hookshot", "protected")
  self:set_attack_consequence("boomerang", "protected")
end

-- In this part, we define the straight movement
function enemy:on_restarted()

  next_direction = sprite:get_direction() * 2 -- Don't forget the "* 2" factor
  local m = sol.movement.create("path")
  m:set_path{next_direction}
  m:set_speed(128)
  m:set_loop(true)
  m:start(self)
end

-- In this part, we define the monster behavior when it hurts an obstacle
function enemy:on_obstacle_reached()

  -- Test : is there an obstacle on the monster's right ?
  if (next_direction == 2 and self:test_obstacles(16, 0)) -- If the monster was going up
    or (next_direction == 0 and self:test_obstacles(0, 16)) -- Was going right
    or (next_direction == 6 and self:test_obstacles(-16, 0)) -- Was going down
    or (next_direction == 4 and self:test_obstacles(0, -16)) -- Was going left
  then 
    -- Then go to the monster's left
    next_direction = next_direction + 2
    if next_direction > 7 then
      next_direction = 0
    end

  else -- The monster can go on its right
    next_direction = next_direction - 2
    if next_direction < 0 then
      next_direction = 6
    end
  end

  -- Set the direction and restart the movement
  sprite:set_direction(next_direction / 2)
  self:restart()
end



So much for the fireball type.
You can do the glider in order to practice. You'll just have to switch the directions in the enemy:on_obstacle_reached() event, it's as easy as pie.  ;)
#6
Hello, it's me again for another problem.  :-[

I wanted to change some sprites in the game, like the crystal switches and the solid ones.
So I modified the "miscellaneous.png" file like this (don't pay attention to the light blue switch I added, it will be used for a special purpose but I'm not using it yet) :




I didn't modify the .dat files related to this sheet.
And I put them on a test map (don't pay attention to the mess, it's just a test map  ;) ) :




But when I play and I use the sword on them, it's acting like I was using my sword on a wall (there is the sound "tick-tick") and do not activate them.


I had another problem of the same kind several days ago.
Like what I did with the switches, I recolored the example tileset from the tutorial videos, and I modified the entities, replacing bushes by flowers :




And when I play, bushes/flowers don't act as they should do, such as switches. When I use the sword, I'm just hurting a wall :





To put it in a nutshell, I just modified the .png files. And I can't see how that could modify tile properties like this...
I put this issue in the bugs section because it doesn't seem normal for me, but maybe I'm just using the sprites/tilesets not as I should do (we never know), and in that case this topic may go to the development section ?
#7
Hello !

I found a little bug in the 1.6.2 version of Mystery of Solarus XD (the one I found on solarus-games this morning).
In the cave with the bomb bag, we can push and pull the statues to obtain it. But when I push a statue on the bomb bag, I obtain it... and the statue follows me until it's blocked by another obstacle. The game can be continued after this bug, so it's not a frustrating one.
I don't know if it's voluntary (in this game, we never know...  ;D) but it's a little strange.
#8
In fact, there is just one sensor, which is used to activate the conveyor's rotation. But it could be launched from the start, when the map starts. So my first version didn't really need a sensor.

And there is indeed the little problem with the conveyor which can rotate even if the hero is on it, but I don't know if it's really frustrating or not. But I think it could be solved even without a "on_activated" event or twelve sensors ; I read in the documentation that there is a method "entity:get_distance(other_entity)" and it could be useful. For example, we can think about a function which calls "conveyor_x:get_distance(map:get_entity(hero))" and returns true if the distance is short enough (it would mean that the hero is on it).
#9
Quote from: Christopho on August 31, 2013, 05:59:41 PMIn the meantime, what you should do is to make with the map editor 4 conveyor in each spot (one for each direction), and use conveyor:set_enabled() to enable only one of them every time. Do you see what I mean?

In general, using set:enabled() is much easier than removing and re-creating entities. Actually, that's why this bug exist: I almost never remove and re-create entities in my games.
I see. In fact, I was thinking about this possibility, but I considered that it was less complicated to remove and re-create than creating 4 entities for each conveyor. But if it's the best solution now, I guess I'll do this.  :P

But considering what you said about remove_entities(), maybe I also see another possibility : if I put the part of the first function where I re-create the conveyors in another callback function called one or two cycles after, maybe the problem of remove_entities will disappear. I'll try this, just in case.

Quote from: Christopho on August 31, 2013, 05:59:41 PMThat being said, your puzzle looks nice and your code is well commented. I hope you will share your game on this forum soon :P
Thank you.  :)
For now on, I essentially did mapping so I don't think there are many things to say about my project. But I eventually intended to share some scripts meantime (I'm currently working on a Beamos (from Alttp) implementation, maybe some quest developers would be interested).


Edit : finally, the alternative of waiting few cycles seems to work.  :) Of course it's not the best way to do this since there are a few cycles where the conveyors don't appear... but the player won't mind about two cycles missing I guess.  ;D

Here is the new code :

local map = ...
local brouillard
local mouvement_brouillard

local current_conveyor_direction = 0

-- Conveyors position
local random_conveyors = {
{ x = 376, y = 1261 },
{ x = 440, y = 1261 },
{ x = 504, y = 1261 },
{ x = 568, y = 1261 },
{ x = 376, y = 1325 },
{ x = 440, y = 1325 },
{ x = 504, y = 1325 },
{ x = 568, y = 1325 },
{ x = 376, y = 1389 },
{ x = 440, y = 1389 },
{ x = 504, y = 1389 },
{ x = 568, y = 1389 }
}

local function create_conveyors()
-- Remove conveyors before creating them again in another direction
local function remove_conveyors()
map:remove_entities("conveyor_")
sol.timer.start(2, create_conveyors) -- Cannot create the conveyors in the same cycle than the one when they disappear, have to wait.
end

-- Change the direction of conveyors (0 : east, 2 : north, 4 : west, 6 : south)
current_conveyor_direction = current_conveyor_direction + 2
if current_conveyor_direction > 7 then
current_conveyor_direction = 0
end

-- Create conveyors
    for i = 1, 12, 1 do
map:create_conveyor_belt{
name = "conveyor_" .. i,
layer = 1,
x = random_conveyors[i].x,
y = random_conveyors[i].y,
direction = current_conveyor_direction
}
    end

    sol.timer.start(1898, remove_conveyors)
end



-- Activate the change of direction when Link walks on the sensor
function active_random_conveyors:on_activated()
create_conveyors()
active_random_conveyors:set_enabled(false)
end
#10
Hello,

I wanted to use the conveyors, but with a little difference : indeed, I want to make them change direction (east-north-west-south-east-etc.).

I have this map with twelve conveyors respectively called "conveyor_1", "conveyor_2", etc. and a sensor which activates the rotation when Link crosses it :



As the documentation doesn't seem to indicate a method set_direction for conveyors, I made a script in the map.lua which removes and create again the conveyors in a new direction :

local current_conveyor_direction = 0

-- Conveyors position
local random_conveyors = {
{ x = 376, y = 1261 },
{ x = 440, y = 1261 },
{ x = 504, y = 1261 },
{ x = 568, y = 1261 },
{ x = 376, y = 1325 },
{ x = 440, y = 1325 },
{ x = 504, y = 1325 },
{ x = 568, y = 1325 },
{ x = 376, y = 1389 },
{ x = 440, y = 1389 },
{ x = 504, y = 1389 },
{ x = 568, y = 1389 }
}

function change_conveyors_direction()
-- Destruct conveyors before creating them again in another direction
map:remove_entities("conveyor_")

-- Change the direction of conveyors (0 : east, 2 : north, 4 : west, 6 : south)
current_conveyor_direction = current_conveyor_direction + 2
if current_conveyor_direction > 7 then
current_conveyor_direction = 0
end

-- Create conveyors
    for i = 1, 12, 1 do
map:create_conveyor_belt{
name = "conveyor_" .. i,
layer = 1,
x = random_conveyors[i].x,
y = random_conveyors[i].y,
direction = current_conveyor_direction
}
    end

    sol.timer.start(2000, change_conveyors_direction)
end

-- Activate the change of direction when Link walks on the sensor
function active_random_conveyors:on_activated()
change_conveyors_direction()
active_random_conveyors:set_enabled(false)
end


But when the function change_conveyors_direction is called for the second time, the game crashes :
Error: an entity with name 'conveyor_1' already exists.

So is the function map:remove_entities("conveyor_") not working, or are the conveyors removed only at the end of the function ?
#11
General discussion / Re: Welcome!
August 30, 2013, 10:06:30 PM
Well, thanks for the answer and the welcome.  :D
#12
General discussion / Re: Welcome!
August 30, 2013, 09:40:59 PM
Hello !

First of all, I wanted to say a big "Thank you", for the game "Mystery of Solarus" and the Solarus engine, which is really impressive. I have always wanted to make a Zelda fan-game but even though I had the ideas and programming bases, I didn't have the patience to make such a complete and appropriate engine... and maybe with this one, I'll be able to make a game.

I have a question (well, not only one but it'll be easier to ask my next question if I have the answer for this one  ???) : in which section can I ask some help about a Lua script (related to a map) which doesn't work ? I thought it was the "Development" section, but I'm afraid that it's for tutorials only.