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.


Messages - lefthandedhero

Pages: [1]
1
Development / Problem with trying to override a game command
« on: November 03, 2023, 07:40:29 PM »
A while back, I created a custom entity called Follower, who exists to follow the hero. Recently, I created a function entity:swap_sprite() that replaces the Follower's current sprite with the hero's current tunic sprite. Here is that code:
Code: [Select]
function entity:swap_sprite()
  -- obtain the hero's current sprite:
  repsprite = hero:get_tunic_sprite_id()
  -- replace the current sprite with resprite:
  entity:remove_sprite()
  sprite = entity:create_sprite(repsprite)
end

I then created another function meant to override the game command "item_2"; this function will do multiple things, but right now, it just calls the entity:swap_sprite() function. I intend to store this function in a separate metatable, but right now, it is inside the Follower.lua file. Here's the code:
Code: [Select]
function game:on_command_pressed(item_2)
  entity:swap_sprite()
return true
end

However, when I try to run the quest, instead of the sprite changing on command, it occurs at the very beginning of the quest, and the hero can no longer use the sword (movement still works). What could be causing this error?


EDIT: To try to figure out what went wrong, I added two lines of code to the swap_sprite() function that changes the hero's current tunic sprite to the follower's sprite (both are using hero tunic sprites of different colours; the hero's sprite is hero/tunic1 and the follower's is hero/tunic3). The modified function is as follows:
Code: [Select]
function entity:swap_sprite()
  -- obtain the hero's current sprite:
  repsprite = hero:get_tunic_sprite_id()

  -- (For testing) replace hero's sprite with follower's
  local sprite_id = sprite:get_animation_set()
  hero:set_tunic_sprite_id(sprite_id)

  -- replace the current sprite with resprite:
  entity:remove_sprite()
  sprite = entity:create_sprite(repsprite)
end

Now, the two characters swap sprites as intended, but instead of only doing so during the item_2 game command, they do so any time any game command is called: when the hero starts moving, they swap sprites (the hero still starts moving); when the hero changes direction, they swap sprites (the hero still changes direction); When I press "c" for the hero to use their sword, they swap sprites and the sword isn't used; etc.

2
Development / Re: How to Change the Hero's Sprite
« on: October 29, 2023, 02:01:23 AM »
Hi,

Tunic level relates to the Hero's defense level.

For example in Zelda Tunic level 1 is green, level 2 is blue and level 3 is red.

You therefore need to have a different colour sprite for each tunic level for every hero sprite.

That way when you upgrade your tunic in your game you can automatically change all your hero sprites to the next colour.

If you have a look in the sample quest that comes with the Quest Editor, in the sprites/hero folder you can see the three tunic sprite sets. It is the items/tunic script then then calls the relevant variant and updates the hero's sprite colour.

Thank you; that makes a lot of sense. There probably will not be tunic upgrades in the game I am making, so I guess I can ignore the stuff about tunic level.

If you want to set up a different sprite then you just need to add a new animation to tunic1, tunic2 and tunic3 and call that animation from a script, at least i think that is the easiest way to do it.

I see. I should point out that I'm very new to Solarus and I'm still learning how sprites and animations work.

Would adding an animation be sufficient? I want to essentially create another appearance that the hero uses when in a custom state.

3
Development / How to Change an Entity's Sprite
« on: October 28, 2023, 03:11:41 AM »
I am trying to create a custom state for the hero that represents the hero being in a different form (think something like Wolf Link from Twilight Princess): while the hero is in this custom state, the hero uses a different sprite and a different main attack. I was wondering how to change the hero's sprite.


EDIT: I now realize that I probably phrased this question poorly. I was wondering, for any entity, how to program it to use a specific sprite under certain conditions. I watched the video on sprite and animation files, so I know how to create a sprite. But, once I have created a sprite, how do I tell the engine, "under this specific condition, this entity's sprite is now (a specific sprite)"?

I want to know this so I can change the hero's appearance during the game, but I really want to know how to do this with any entity. For instance, I currently have a custom entity that currently only exists to always follow the hero, and I want their appearance to change whenever the hero's appearance changes.


EDIT2: I think I may have found a solution: using entity:remove_sprite() then entity:create_sprite(), I have tested it, and it seems to work.

4
Development / Re: What does this error mean?
« on: June 05, 2023, 03:40:33 AM »
The error message says that it can't find the "hero" entity.
The reason is that you never asked the engine to give it to you in the first place.

Since you intend to make  some generic behavior for the hero -hero_meta-, you should use the hero's metatable (using sol.main.get_metatable), and then define what you need here. it works the same as using the hero directly, but more like a model, so multiples heroes will get the same behavior.
If you know the concept of object-oriented programming, then think of modifying the class instead of the instances.

Thank you. This is very helpful.

I am familiar with object-oriented programming; I am a little rusty at using it since I haven't practiced using it in a few years, but I remember all the fundamental concepts.

5
Development / What does this error mean?
« on: June 01, 2023, 02:39:32 AM »
Recently, I created a script specifically for code related to the hero, that I called hero_meta. Here is the code that's currently in this script:
Code: [Select]
local MAX_BUFFER_SIZE = 48
function hero:on_position_changed(x,y,z)
  local hero = self
  if not hero.position_buffer then hero.position_buffer = {} end
  local hero = self
  local dir = hero:get_sprite():get_direction()
  table.insert(hero.position_buffer, 1, {x=x, y=y, layer=z, direction=dir})

  if #hero.position_buffer > MAX_BUFFER_SIZE then
    table.remove(hero.position_buffer)
  end
end

The purpose of this code is to establish a maximum distance away from the hero and create a table storing the hero's prior movements within that distance.

When I try to run the quest, I keep getting this error:
Quote
Error: In main: scripts/meta/hero_meta.lua:2: attempt to index global 'hero' (a nil value)

What does this error mean? Any idea what is causing it to occur?

6
Development / Re: Need Help With Having an NPC Follow the Hero
« on: June 01, 2023, 02:15:50 AM »
Not sure, but what i would guess is that the on_position_changed event gets triggered the next frame after you stopped moving, so maybe try to have one extra entry in the table and use two indices: one for the current hero step and one for the
NPC that is always 2 steps behind the hero -modulo will be your friend.
By the way, OH uses a standard .solarus zip file so you should be able to check the source code

Thank you.

I asked the developer of Ocean's Heart for the code they used for this, and they provided it, so I have replaced my code with it.

7
Development / Re: Need Help With Having an NPC Follow the Hero
« on: May 21, 2023, 06:01:55 PM »
Using the suggestions above, I have refined the code. Here is the current version:
Code: [Select]
-- Follower's Movement 
  -- Initialize table to store the hero's old coordinates <List[0] = x, List[1] = y>:
  List = {}
  -- Obtain the hero's movement speed
  local speed = hero:get_walking_speed()
  -- Initialize the movement
  local movement = sol.movement.create("target")
  movement:set_target(Follower:get_position())
  movement:set_speed(speed)
  movement:start(Follower)
  -- Movement pathing:
  function hero:on_position_changed(x, y, layer)
  -- Update list and move accordingly
    -- If this is not the hero's first movement:
    if List[0] ~= nil then
      -- Move the NPC to the old coordinates
      movement:set_target(List[0], List[1])
    end
    -- Record the hero's current position:
    List[0] = x
    List[1] = y
  end

Initially, the movement works exactly as I would like. However, there are three problems that appear after the hero either stops moving or changes direction:

1. The NPC "Follower" continues moving after reaching the target position.
2. It is impossible for the hero to move backwards since Follower is in the way.
3. When I move the hero in a new direction, I want Follower to continue moving forward before then moving in the new direction, as I want Follower to follow the exact same path as the hero. Follower does not do this; I suspect this problem is related to problem 1.

Three questions:
1. How do I remove collision between the NPC Follower and the hero?
2. Any suggestions for how to make Follower stop moving when the hero stops moving?
3. Any idea what could be causing the third problem?

Incidentally, after playing Ocean's Heart recently, I reached a point in the game where an NPC follows the hero, and the NPC does exactly what I'm trying to get Follower to do: they follow the exact path the hero just walked. Does anyone know how Ocean's Heart did this?

UPDATE 2: I added the line, "Follower:set_traversable(true)", so now the hero can pass through Follower. The other two problems remain; Follower continues moving either left-and-right if facing up or down or up-and-down if facing left or right after the hero stops moving, and the movement only works the way that I want it to until the hero changes direction:

When I have the hero go in a new direction, Follower should move to the last place the hero was in the first direction before moving in the new direction, since I want Follower to follow the same path as the hero. Instead, Follower stands still for a while and then catches up. Any idea what is causing this?

There's another problem: despite Follower's speed being set to the hero's speed in the code, when I tested it, Follower slowly begins falling behind.

UPDATE 3: I set Follower to ignore obstacles to see if that was the reason it stood still whenever the hero turned to the left or right. It was the reason, and it revealed a different problem: despite the existence of the table being to record where the hero was previously, whenever the hero stops moving, follower stops at the hero's current position, not the hero's position a step previously.

8
Development / Re: Need Help With Having an NPC Follow the Hero
« on: May 09, 2023, 08:17:49 PM »
I don't see any obvious mistake (maybe i would have organized the list in the style 1 entry = an {x=x,y=y} pair but that's just a coding preference) so my guess is that your movement gets overwritten each frame you move and doesn't have time to even start until you stop moving.
So what you should try to do is to detect if the follower NPC already has a movement and update it's target (if possible) instead of recreating a new one each frame, and only create it again if it it reached its actual destination when the hero has stopped moving.

Thank you. That is most likely the reason for the first problem. I am currently working on modifying it as suggested.

9
Development / Re: Need Help With Having an NPC Follow the Hero
« on: May 08, 2023, 07:09:26 PM »
Using the advice above, I created the following code. Note that "Follower" is the name of the NPC:

Code: [Select]
-- Table to store the hero's old postion (List[0] = x, List[1] = y, List[2] = layer):
  List = {}
  -- Follower Movement:
  function hero:on_position_changed(x, y, layer)
    -- If not the hero's first movement:
    if List[0] ~= nil then
      -- Move Follower to the old coordinates
      local movement = sol.movement.create("target")
      -- Set the previous position as the target
      movement:set_target(List[0], List[1])
      -- Make the movement speed match the hero
      movement:set_speed(88)
      -- Move
      movement:start(Follower)
    end
    -- Record the hero's new position
    List[0] = x
    List[1] = y
  end

The current code has two main problems:

1. Follower does not start moving until the moment the hero stops moving, when the idea was that the follower would move while the hero moves and stop when the hero stops.

2. Follower does not stop moving, as if the current target is the hero's current position when it should be the hero's previous position.

Where have I gone wrong in my implementation that is causing these problems?

10
Development / Re: Need Help With Having an NPC Follow the Hero
« on: May 05, 2023, 04:09:45 PM »
Hello, you can use the hero:on_position_changed() event, which is called each frame Link has moved.

Code: [Select]
-- <initialization stuff where you get the hero and NPC entities>

function hero:on_position_changed(x, y, layer)
--update your list here and move the NPC accordingly

end

Thank you very much. This is a big help.

An alternative way is to make a target movement towards the hero, and stop that movement when the distance between the NPC and the hero gets below some threshold. I think it is done that way in the Zelda A Link to the Dream project.
Your choice, I guess it depends on whether you want the NPC to follow exactly the same path as the hero or not.

Thank you. I do want the NPC to follow the same path as the hero; it's important for another component of the game that I'm trying to make that the NPC follow the same path. But I may fall back on that method if I can't get my current plan to work.

11
General discussion / Re: What's Your Favorite Zelda Game?
« on: May 03, 2023, 08:44:10 PM »
1. Spirit Tracks. I recognize that there are better Zelda games, and I myself have some grievances with it; namely that the spirit flute has to be by far the worst Zelda instrument. But the things work about this game are done amazingly well and easily more than make up for its faults. I really like the train, and I love Spirit Zelda: having Princess Zelda be Link's adventuring companion in this game was nothing short of brilliant, to the point where I almost wonder why it wasn't done sooner and I do wonder why it hasn't been done since. Controlling Link and Zelda together is a ton of fun.

2. Ocarina of Time. It introduced me to the Zelda series, so of course it's going to be in the top 3, and it helps that it's still one of the best Zelda games overall.

Nominations for 3rd place: Link's Awakening, Majora's Mask, Wind Waker and Breath of the Wild.

Winner of the position of 3rd place: Wind Waker. There isn't really much to say; like Sprit Tracks, the game has a ton of charm, the sailing is fun, and I really like the deep narrative under the surface and the theme of the winds of change and the idea that Hyrule waiting for a hero to appear was exactly what doomed Hyrule.

12
Development / Need Help With Having an NPC Follow the Hero
« on: May 02, 2023, 07:36:06 PM »
Hello.

I am new to using the Solarus engine. I want to create an NPC that follows the hero as a companion by closely following behind the hero and following the same path as the hero; the type of movement that's used in A Link to the Past when Link escorts Zelda out of Hyrule Castle and when Marin accompanies Link for part of Link's Awakening, and is at as old as the classic snake game genre.

Any suggestions for implementing this in Solarus?


UPDATE 1: After watching some videos of the section of A Link to the Past where Link escorts Zelda out of Hryule Castle for reference, I observed some details of Zelda's movement that may help: upon entering any new area or exiting a set of stairs, Zelda always starts one in-game step behind Link, stays still after Link's first in-game step, then starts moving after Link's second in-game step, with Zelda's steps being the step Link took two steps previously. When Link stops moving, Zelda immediately stops moving at the same time, and when Link resumes moving, Zelda immediately resumes moving.

After observing this, the plan I have created is to essentially store the hero's movements in a linked list of maximum length 1: upon entering a new map section, the linked list will be empty. When the hero moves, their "step" is pushed into the list, and once the list is full, the non-playing character does each step that is "popped" out of the linked list. When the hero stops moving, the non-playing character stops moving.

I know how to create a linked list in Lua, so there are two things I still need:
1. The ideal method of storing each in-game step in the linked list.
2. How to implement, "while (the hero is moving) {}".

Any suggestions for solving those two things?

Pages: [1]