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

#16
As I try to code an entity that can be picked up and placed, I find myself becoming somewhat overwhelmed by all the cases I'd have to test for to ensure that the hero behaves correctly as though the 'carrying' state is set.

Not only do I have to make sure the entity works, but also the hero itself.

I find that it would be much simpler if it was possible to turn an entity into a carried_object, having it fire events when lifted, when released/thrown/placed/whatever, and when destroyed... If those were accessible it would be somewhat trivial to create a variety of non-standard liftables, such as those that are placed gently when let go, those that are thrown but don't explode, and even some that are destroyed immediately upon being lifted (if that was needed).

Not being able to access the hero's state directly, or pass an entity to the hero as a carried_object reference, largely prevents me from doing that.

(specifically I'm currently just trying to make an object that remains on the map when set down, and isn't automatically tossed across the room... its more difficult than I imagined when I started.)

As for a Zelda related example of an object that fits this pattern, Link's Awakening (as Diarandor reminded me) has an iron ball, which I believe was used in either a boss battle or puzzle. Link would lift it and throw it back at the boss, or try to topple a pillar with it or something, but it wasn't destroyed when it was thrown. Instead, it rolled around a little bit (and could also be pushed, like a big marble)

Hard-coding all of that behavior wouldn't be necessary, as that could largely be handled by custom_entity scripting, if it was possible tell the hero that the entity should be carried.

I feel like there are a lot of built in features that would be a lot more flexible if they had some more lua control, but most of those features can be recreated to an extent using items or entities... lifting and carrying seems to be a much more complicated problem on the other hand.

But as the title states, this is less a formal request and more of a suggestion for how the engine might be more flexible.
#17
Well if its just naming convention, most engines simplify it to 'None', 'Alpha'/'Blend', 'Add', 'Multiply'
Some engines also have a variant of additive that is subtractive ( (-1*source) +destination )** which is sort of similar in effect to multiply, but applied differently and with different side effects... (still used usually for the same goal, darkening).

But if its preference for naming... none, alpha, add, multiply are the most directly intuitive (not only because that's what many engines call them, but also because that's the operation they do mathematically)

@Diarandor
the four modes Christopho added were predefined by the SDL library. It would likely require a much deeper amount of digging into that to supply a custom blend mode. Not to say it wouldn't be a neat feature, but it would likely be more difficult to implement.

**There are also 'power' /'exponent' and 'divide' modes... none of which I've ever actually seen used outside of purely mathematic calculations.


Incidentally, it seems like certain blend modes don't work well on sprites. I may just be testing it wrong, but switching a sprite to additive_blending or color_modulate seems to make them not draw at all on a surface. (It might be that I'm misunderstanding them though. I'm using sprites like any other surface, with a simple sprite:set_blend_mode("additiv_blending") sprite:draw(dst_surface,x,y) )

That might be something to test and look into.. I'm not sure. (Sprites inherit from drawable, but they also have a lot more code, so I don't know)
#18
Development / Re: Solarus 1.5 development snapshot
July 13, 2016, 01:54:39 AM
Quote from: froggy77 on July 13, 2016, 01:47:52 AM
Merci Christopho!

I encountered a small problem with the last snapshot and I would like to share to the community how I solved it.
I worked on an old snapshot of Solarus v1.5 ( "solarus-1.5.0-snapshot-20151107-win32") and I wanted to use the last version (solarus-1.5.0-snapshot-20160712-win32).
Impatient as a child discovering a new toy, I started the project to test new functionalities 8) . When the map was loading, ouch!!!  :'(
Quote[Solarus]Error: Failed to load map: ...5.0-snapshot-20160712-win32/solarus/data/maps/memory.dat:1: bad argument #1 to properties (Bad field 'min_layer' (integer expected, got nil))

I think you will  not have this problem if your previous version was a v1.4 or a not too old snapshot of v1.5.
If you have that kind of error:
- Just edit your quest.dat and change 'solarus_version = "1.5"' into 'solarus_version = "1.4"'.  Of course, save  quest.dat.
- Then execute "solarus-quest-editor" to start the upgrade; your *.dat of your maps will be modify automatically.
- In your *.dat, you will see new lines in the properties:
  min_layer = 0,
  max_layer = 2,


I had a few errors like that with 'height and width' properties being omitted for entities.

After going back to the previous snapshot, the maps still failed to load with the same error... I don't know what happened there.
It seems like a weird error in general. (was too busy playing with new functions to worry about it though.)
#19
Quote from: MetalZelda on July 13, 2016, 12:43:22 AM
I wanted to make something similar to your second screen , but I'm satisfied with the current result, sunrise, sunset and night feels right, and much vibrant than before
Well, I don't remember the exact values I used in the original screenshot, but
shadow_surface:fill_color({32,64,240,255})
shadow_surface:set_blend_mode("color_modulate")

Gets really close to it.

And yeah, your sunrise/set look pretty rich and nice.
#20
Its doing both e:return_no_effect() and e:on_zelda_lullaby_interaction() because you're checking all entities that have those functions.
So say you have 5 possible entities 'e'
What's happening is
e:return_no_effect()                   --first e found
e:return_no_effect()                   --second e found
e:on_zelda_lullaby_interaction()--third e found
e:return_no_effect()                   --fourth e found
e:return_no_effect()                   --fifth e found

That's assuming you've programmed your ocarina_zelda entities correctly, and there's no problems with your search.

What I would do, is make the ocarina_zelda_whatever entities do a collision test, and in that collision test, check to see of the hero is using the ocarina.
There's a number of things that might be going wrong.

First of all, if return_no_effect() doesn't do anything, just remove your else altogether. I think most likely the Else is what's screwing you up, as I understand your statement.


But lets say you need to track the event that the Hero isn't overlapping ANY such entity, and return a message that says nothing happened.

What you would then do is
Code (lua) Select

    -- these are example, h = hero
    --ocarina_zelda_x = event id on the map
    local overlapping = false
        -- for e in m:get_entities("ocarina_zelda") do
              -- if h:overlaps(e) then
                -- e:on_zelda_lullaby_interaction()
                overlapping = true

               -------------No Else
              -- end
            -- end
   if not overlapping then
     -- display your 'not overlapping any valid entities' effect here
     overlapping = false
   end
            -- end

#21
It depends. What effect are you trying to achieve?

If you want the daytime to be bright, set the surface to pure white, and it will not be darkened at all.
If you want the daytime to be yellow tinted, set the color to fully bright yellow. (255,255,0,255)
if you want the scene to turn blue, set the color to (0,0,255,255).
If you want the scene to be slightly darker, with a little bit of a blue tint, set it to something like (192,192,255,255)
If you want it really dark and slightly blue, set it to (64,64,128,255)

The reason to use modulate blending is to darken the scene without making it look smokey and desaturated, like what happens when you just use a regular semitransparent solid color on top of it.

That is, if you used a dark color, with blend mode Blend, at 50% transparent, the blacks would lighten and the lights would darken.
With color_modulate the darks stay dark, but the lights get darker too.

With additive, the lights stay light, and the darks get lighter, but colors stay bright, instead of being washed out, like the same that happens in the previous example.

Color choice is really important  with blend modes.

Additive blend is really good for things like fire and light beams and mirages, modulate is better for things like shadows and color tinting.

Light colored mods are best for slight effects, while dark colored mods will have more severe effects. Pure white mods will be invisible. (multiplying 1 * whatever)

Dark colored adds will be better for slight effects, like a dim glow from a candle, while brighter adds will more sharply glow (until they reach pure white). Pure black adds are completely invisible (adding 0 + whatever)
#22
a lot of neat effects can be gained by drawing surfaces with different blend modes onto each other, before finally rendering them on the screen. This is exactly what I hoped for.

For those who don't fully comprehend blend modes, here's a quick rule of thumb:

Treat the 0-255 values as though they are 0-100% or 0.0-1.0
(You still have to type them in as 0-255, but the math they do is more equivalent to 0.0 to 1.0)

Multiplication works this way. If you have 0.5 * 0.5 (which would be 128*128 RGB) what you end up with is 0.25 (which turns into 64 in RGB equivalent.)

Additive works the same basic way. If you add 0.75 (or 192) to 0.75 (192) you end up with 1.5 (technically 384, but it gets capped at 255)

Keeping that in mind, you just have to imagine whether you want to make something darker (by making the numbers smaller, by multiplying their percentages) or brighter (by adding them together).


If you set up 2 surfaces, lets say

local shadow = sol.surface.create()
local light_mask = sol.surface.create()
--You can then set them to two different blend modes
shadow:set_blend_mode("color_modulate")
light_mask:set_blend_mode("additive_blending")
--now, lets pretend each entity in the map will draw a 'glow sprite' onto the light_mask surface
--having drawn those entities' sprites in light_mask, we can use it to cut away selective dark areas in shadow
--by simply drawing it into the shadow surface
light_mask:draw(shadow)
--and finally we can draw it in our scene like so

local scene_surface = sol.surface.create()

map:on_draw(scene_surface)
  shadow:draw(scene_surface)
end

and our map will be darkened everywhere there is not an entity drawing a light mask sprite

*Note that trying to change the blend mode on [map:on_draw(scene_surface)] directly, it doesn't seem to have an effect.
#24
Development / Re: Lifting a custom_entity?
July 11, 2016, 06:42:23 AM
Alright thanks for the reply. I'll start thinking about how I need this to work.

I already created a way to run faster using a different animation, while holding the shift key... I'm guessing I'll have to do some extrapolation of that for the carrying animation...

Perhaps define a secondary 'state' variable...depending on whether I can make "state" accessible and whether it automatically reverts if no carried object reference is found...

Welp... Its a good thing I wasn't doing this a year ago, or I'd never have understood lua well enough to do any of it.
Despite all the trouble I'm having with custom entity code, I'm actually getting some cool stuff done, from a framework perspective.
...oh well. Back to work with me.
#25
Development / Lifting a custom_entity?
July 11, 2016, 06:02:06 AM
so, I've been coding a custom entity that I can push around and lift...
Pushing isn't really a problem, but I've run into a curious issue...

I don't know how to tell the engine the hero is in the lifting or carrying states, nor how to generate a carried object...
I can't simply use a destructible, since the hero will be setting down the object later...

I can probably add a 'set_state(param)' to type hero if I alter the metatable... but even so, that won't automatically create a carried object... and the documents don't seem to suggest that it is possible to do so through the lua interface...

Am I going to have to code everything from the lifting to the walking, and placing/throwing manually?
For the first time in a while I'm 100% stumped as to how to proceed.
#26
Quote from: Diarandor on July 11, 2016, 03:11:02 AM
I think you are changing the position of your custom entity instead of the position of the hero, i.e., the collision test is probably detecting the custom entity as colliding with itself, so the layer of the custom entity is changed and then there is no collision with the hero since they are in different layers. I might be wrong with this, so you have to check if this is what is happening. In that case, you will need to add a condition in the collision test to check that the other entity is the hero, something like: "if other:get_type() == "hero" then ....blablabla".

Anyway, as Starlock says, the simplest way is probably to use a sensor instead of a custom entity with a collision test, unless you need to make more things that cannot be done with a sensor entity.

There is a nice tutorial made by ffomega which shows how to make bridges, which use sensors to change the layer of the hero. If you are having problems, then you should take a look (it is exactly the same link that Starlock has given above):
http://solarus_resource.site88.net/tutorial/bridges.htm
http://forum.solarus-games.org/index.php/topic,654.msg3361.html#msg3361

EDIT: Another possible cause of your problem could be if the ground on the second layer is of type "empty". That would make the hero fall automatically to the low layer again, because that is the behavior coded in the engine. However, other entities do not fall to lower layers if they are over an "empty" ground, so this would explain your problem too.

I had not considered that empty tiles would automatically cause the player to fall. That seems to be the most likely case here, as the second layer is empty.
As for the entity colliding with itself, it is not. I've tested that already, 'other' is appropriately the Hero, and also works on other entities like blocks and destructibles.
Now that I've tested it with appropriate flooring installed, the hero does in fact move up to the second layer.

...now to really use this how I intended I have to figure out how to make an entity be solid on layer 0, and traversable on layer 1....

I'm attempting to create a stackable entities...I have my reasons.
#27
I need to manually switch the hero's layer, without altering their position, instantly. (For reasons dealing with how collision happens, which are too complicated to explain for the purposes of this question)

What I've tried is:
local entity = ...
entity:set_size(16,16)
entity:set_origin(8,12)
entity:add_collision_test("origin", function(me, other) 
  debug.message = "layerchange"
  local posx,posy,posl = other:get_position()
  other:set_position(posx,posy,math.min(posl+1,2))
end)


Now... this all works as it seems like it should, except that it does not change the layer.
I also tried this in the debug console by simply accessing sol.main.game:get_hero():set_position(hero x,hero y, new layer)
and the hero does move to whatever hero x and hero y are, but new layer is ignored.

In short, hero:set_position() is ignoring the layer no matter what I do... is there another way to handle layer switching?
(Stairs force the player to move, which is not what I want to happen, I just want the hero to be on a different layer, at the same location)

EDIT:
Other entities that move across this layerswitch entity DO get their layer's changed... Only the hero is ignored.
#28
In hindsight, it seems not to be possible to replace a fully opaque pixel with a transparent one...
I'm assuming this is a consequence of SDL_BLENDMODE_BLEND in the source. This is an occasion where SDL_BLENDMODE_NONE would allow for more freedome, as you could use it to cut a section of the surface out and replace it completely (no blending) with the new section you drew...

if I understood the whole C++/lua interface thing I'd try my hand at making an unofficial branch with the feature, but alas, I don't get the C++ end at all. It'll be up to Christopho to add the lua function, whenever or if ever he does that.

A different option is required until then... I tried making a big lua table of filled and empty 'darkness' tiles and looping through them each frame, drawing them into the surface... which... kind of worked... but not well... and also caused a lot of lag... I'm still hopeful there is a method that will work... but I get the feeling it'll require some heady math.

If I could figure out how to graph 'everything but these 5 rectangles' as a limit... that might work... but would be speed dependant...
I'll let you know if I come up with any more ideas you can try.
#29
technically those are still rectangles. You could get them in the same way you would get the yellow parts, but just imagining where the connecting lines would be between them.
Draw the biggest black rectangle you can find in the non-yellow space, and where there's an oddly shaped corner, fill it in with another separate rectangle.

Also, if you're trying to paint in the empty space, you can draw on the surface before you draw whatever goes in the yellow, and draw the yellow spaces afterward, and whatever's in the yellow should be drawn over whatever you filled the surface with before...

At least that's how I understand surfaces. (Similar with on_pre_draw and on_post_draw for sprites)

Like this:


EDIT:
If you're doing a 'lighting' script, where yellow spaces would be lights you want to 'cut out' of the blackness, I might have to rethink how to do that.. its something I've been wanting to try too.
Still, if you could define your yellow blocks before they're drawn... there should be a way to replace the black area with a transparent space... by specifying an shape made of some color like 0xFFFFFF00, which is pure white, but with 0 alpha opacity...

Maybe that helps maybe not. Get back to us if you come up with something that does, I'd like to see it.
#30
The documentation directly states:
Quote
A carried object is created automatically by the engine when the hero lifts a map entity. Map entities that can be lifted include destructible objects and bombs. The carried object takes the sprite and the features of the lifted entity it is created from.

The hero can then walk with his carried object and throw it. He can even go to another map: the carried object is preserved.
I tried this by creating a destructible object, and carried it to a teletransporter into the next map, but when I arrived at the next map, there was no longer an item being carried and the character's state has been set back to "free" rather than "carrying".

Is this a bug, or ambiguity on the part of the documentation?