Legofarmen / tunics

A roguelike-like Zelda game for the Solarus engine.
http://tunics.legofarmen.se
Other
37 stars 11 forks source link

Blocks fall off the map on creation #86

Closed mattias-p closed 8 years ago

mattias-p commented 8 years ago

In some circumstances blocks fall off the map immediately on creation. Specifically this behavior has been reproduced in zentropy.inject_block() with Solarus 1.5 (seed 1476016760, tier 1, walk north twice).

Blocks created through other means stay put just fine, and blocks created (even this way) with Solarus 1.4 also stay put just fine. It is the combination of Solarus 1.5 and something specific to inject_block(), and possibly the specific seed given above, that triggers this bug.

christopho commented 8 years ago

The fact that they didn't fall before 1.5 was actually an engine bug.

mattias-p commented 8 years ago

The block is created on exactly the same spot as the placeholder tile. Assuming Tunics is doing everything else correctly, shouldn't the block land on top of the placeholder tile in this case?

christopho commented 8 years ago

Ok, if you think this is an engine bug please report it and I can fix it for 1.5.1.

mattias-p commented 8 years ago

I created solarus-games/solarus#995 for this.

mattias-p commented 8 years ago

So the bug is in Tunics after all. The inject_* functions in zentropy.lua should be using entity:get_ground_position() instead of entity:get_origin().

christopho commented 8 years ago

More exactly, use entity:get_ground_position() instead of entity:get_position(). (entity:get_origin() is relative to the entity's upper-left corner, not to the map.)

mattias-p commented 8 years ago

@christopho Right, I didn't read the docs properly. Thanks for pointing that out. However I don't see how entity:get_ground_position() would solve my problem. Here's my thinking.

This is a fairly precise specification of what I need:

The initial entity position needs to be calculated before creation. The final position needs to be calculated after creation (unless initial position == final position).

This is the best way of doing this that I can come up with:

  1. initial position = placeholder:get_position() + 2 px south
  2. final position = placeholder:get_position() + entity:get_origin()

For most entity types I'm able to calculate the final position immediately by using entity_sprite:get_origin(), but AFAIK that's not possible for enemies.

Compared to the general quality of the API, I think this calculate-create-move business is a bit awkward. Here's my two cents for making this use case as lean and mean as the rest of Solarus: Add an optional "alignment"-argument to map:create_*() with the possible values of "position" (default) and "center_position". That way you could just map:create_whatever("center_position", placeholder:get_center_position()).

christopho commented 8 years ago

Ok, if I understand correctly your suggestion, I think this is a good one. I opened an issue: https://github.com/solarus-games/solarus/issues/997

So for now in the meantime, do you have an acceptable workaround or are you really stuck?

mattias-p commented 8 years ago

No, I'm just fine with this approach. I already implemented it and It seems to work, so I'm likely to stick with it. The API change was just an idea I thought was kinda neat, and I wanted to share it.