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

#1
if drawables could be accessed as arrays of bytes in a quick and efficient manner, it wouldn't be difficult to code a seek and replace function.

Better still if images could be defined from the start as palettized rather than full color, they could be altered by simply changing 32 bytes or so.

Really the only requirement for supporting palette swapping is allowing access to the memory that defines the image, which is something most engines don't do, presumably for either lack of necessity or lack of desire to deal with user-created issues.

I feel like a 2D pixellated engine would benefit a lot from handling this kind of interaction, but I also realize as a coder, how much hassle it could create.

If solarus ever picks up support for compiled shaders, it wouldn't be difficult to use a fairly lightweight shader to handle palette swapping...
however, shaders are their own box of problems to implement.

It all comes down to time and labor really.

Edit: one of the massive advantages palettes have over duplicated sprites, that hasn't been mentioned, is the ability to alter the colors of the sprite while it is in the middle of an animation, without losing track of frames or having to reload any sprites.
This is how the link-is-damaged flashing was achieved in in all of the 2D zeldas (and most 2D games from the 16 and 8 bit eras in fact).
This is how link can be flashing invincible, while still walking around. His palette would be replaced by red yellow and black or some similar series of colors.
This is also how a lot of water and fire animation was achieved. A single static image of a waterfall would exist in the game, and it would have a palette that rotated from dark to light.

This would be easy to achieve in a more modern way with per-object shaders. I've already written a very simple shader to do it, but I don't know how or if it is possible to apply it to anything in the engine as of now. The entity page is listed as mentioning shaders in the 1.6.0 documents' search, but it does not contain any references to shaders.
#2
Bugs & Feature requests / Re: hero:set_size
April 12, 2018, 02:49:02 AM
Quote from: MetalZelda on March 18, 2018, 06:18:02 PM
There is a workaround where, you can make a custom entity that define the hero's collision size and make all collision detections through that entity
That's certainly true, yes, but at that point one would be rewriting a significant part of the engine in lua, which is slower and more prone to logic errors (by way of being self coded rather than a meticulously bugtested project under review of multiple coders and testers)... and considering how much of the engine is already contact based, it would essentially be almost as fast to start without an engine at all.

I had considered (as I'm sure many who have wanted to change the collision size have) rewriting the collisions, but once I realized how many functions would have to also be recoded, I realized it wasn't worth the effort, for my purposes.

If I could figure out how to get my build environment to fully compile (which is my problem to deal with, not a complaint) I would probably look into the C++ side of things to try modifying it that way.
I did look briefly at one point, but as the environment wasn't completing the build, and the code itself seemed to have a lot of places where the collision was a hard coded real value instead of a named constant, variable, or object reference to be altered from a single source, I was never able to really determine what needed changing, or whether said changes would even work.

As I am currently having new ideas for potential zelda-styled games, I may try again in the near future... assuming I can ever get mingw to stop fussing.
I'm still eager to see the feature, but for now I'm just hoping it'll be addressed in the next public release.
#3
Development / Re: Change map graphics during play
December 08, 2017, 06:20:05 AM
I actually missed it while I was reading, but if I make a duplicate of each tileset, with the specific graphical alterations I need, there IS a function to swap tilesets while the map is loaded.

map:set_tileset(tileset_id)

It'll mean duplicating all my tilesets, but it'll work in lieu of waiting around for shaders...which I may not even figure out how to use.
#4
So, I find a lot of circumstances where I need to push or pull the player around, but I don't want them to lose the ability to push and pull in return...

That is, objects that suck the player toward them or push them away, or platforms that move around, but the player can always move around in conjunction with this other applied force.

I know this CAN be done by calling hero:set_position(...) in a timer, but as I've been finding multiple reasons to need to do this, I'm starting to think I should at least ask if I'm doing it the hard way and there actually is some way to multiply force vectors together on an existing movement or something... yknow, just literally anything other than continually hardcoding the hero's X and Y positions, which I'm led to believe is somewhat going against the 'intent' of solarus' movement system.

(I noticed that if I call a timer at 0ms interval, and move the hero 1 px each time, it only equates to about 60 px/s, as a hero walking at speed 60 will basically stand still under that force, using my method... but 0ms and 1px SHOULD be a force >1000px/s... interestingly enough this force does drastically decrease when set to 1ms interval, such that a player moving at speed 60 can easily walk right through it. This is the other reason I want a different 'better' method. I can't control the 'speed' in a logical way using timers and set_position... it just doesn't behave the way it logically should, given that 1 pixel every millisecond equals 1000px/s, and the timer system only seems to go as high as 60px/s.)
#5
Development / Re: NPC routines
December 06, 2017, 08:22:08 PM
you'll probably need more than 24, since each NPC will have a different daily schedule.

Also, are you aware that a table can have a function as a member just like any variable?

if you define table[8] = function [...] end

then calling for the value of table[8] will execute that function.

if you really wanted to make this be a universal AI module, you're looking at a lot of scripts. Don't get me wrong, it's a great idea, but it will take some effort.

For example, you'll have to develop your own sort of scripting shorthand language to handle pathfinding, which is a script to itself.
You'd have to write a pathfinding algorithm for go_home, that doesn't know where home or any of its waypoints are, (because they're unique to each NPC) but instead must be fed a table of waypoints from its calling NPC. That NPC would have a table named go_home, possibly inside a bigger table of things including other entries like go_work, etc.

an NPC's schedule would likely be a table as well, defined as you did in the first post with [8]="go_work" and so forth.

You'll want all of the actual handling to be done in one file, so you don't have to copy all of it to each NPC, so...
What you could do, is write a file that reads "go_" instructions and uses a specific function for all of them, looking up the appropriately named tables inside the calling NPC ( schedule_table["go_work"] ) to find the list of waypoints the NPC needs to be pushed toward.

similarly you'd have a function that exclusively handled "do_" functions, for things like playing animations and such without moving.

This script would be called with a require at the top of each NPC who uses the schedule system, and you'd have a timer that calls the scheduler function every x milliseconds (the duration of one game hour) or something similar.

#6
Development / Re: NPC routines
December 06, 2017, 05:13:04 AM
Why not call the table as an array that's indexed by the hour?

as in,
Code (lua) Select

local current_routine = routine_table[current_hour] or current_routine
--If the routine at the current_hour is nil this will default back to previous value
entity:do_routine(current_routine)


If the current_hour variable is 8, that would call whatever routine is set to 8, in your example, "to_shop".
On hour 9, it might return nil, but because of the or, it will retain the value at 8. You can of course remove the 'or current_routine' and do something like
Code (lua) Select
if current_routine ~= nil then [...do some code...] end

Or maybe I'm misunderstanding the question.


EDIT: to clarify a point
In lua, if you set any variable to "nil or [some value]" [some_value] will always be the new value of the variable, as nil is treated as a last resort value.
The same is true of var=value or nil. var will equal value, not nil.
#7
Development / [SOLVED]Change map graphics during play
December 04, 2017, 02:25:25 AM
I want to change the colors of the map, either to harsh black and white or some sort of inverted color or some similar effect.

I don't have the slightest idea of how that might be accomplished. My instinct is that it isn't possible with the current version of solarus...
I didn't see any functions that dealt directly with tilesets, and I don't think maps are drawn as Drawables that can be altered using blend modes...

I'm asking as a sort of last resort, does anyone have any ideas how I might change the look of the map in real time? (the whole map at once)
#8
Bugs & Feature requests / Re: Sword tapping crash
November 29, 2017, 01:05:00 AM
Yes, if the sword and hero have the same animation properties and frame counts, the hero will become stuck in the tapping state.
If the sword is not set to loop, the game crashes because it can't find the sword sprite animation.
If the hero is not set to loop, he just sticks the sword out and never moves again.

I will open a bug report.

EDIT:
I have submitted it.
#9
Bugs & Feature requests / Sword tapping crash
November 28, 2017, 11:59:02 PM
I feel like I encountered this once before but I can't find a post about it and the bug tracker doesn't seem to mention it either...
I'm also not sure if I'm supposed to ask before posting to the bug tracker... so I'll explain it here and wait for advice.

If I define a sword_tapping animation that has fewer than 7 frames the game will either crash, or lock the hero into a tapping state, depending on loop flags.
(I did ensure that I had a tapping animation for both sword and hero.)

My animation only required 2 frames of animation (Link's Awakening style). If I set the animation to 2 frames, not looping, on the Sword, the game crashes stating that there is no animation for Sword's sword_tapping.

If I set the animation to loop, the Hero continually taps the sword without ever stopping.

If I stretch the animation to have 7 frames, everything works normally again. (Except I had to make a new texture for the animation because it didn't fit the other file anymore, but that's just an OCD thing.)
#10
just an addendum to ensure the [var] thing is understood.
Code ( lua) Select

--These are just so the variables are defined
local path = "000222444666"
local loop = false
local ignore_obstacles = true

hero:walk(path)
hero:walk(path, loop)
hero:walk(path, loop, ignore_obstacles)

These are all valid. But the next option will cause problematic behavior
Code ( lua) Select

--These are just so the variables are defined
local path = "000222444666"
local loop = false
local ignore_obstacles = true

hero:walk(path, ignore_obstacles)

The second argument is being supplied with "ignore_obstacles", but the second argument is always "loop" so you're just feeding the loop argument the value of ignore_obstacles. The game will still treat it as the loop argument regardless of its variable name.

If you want a path that will not loop, but will ignore obstacles, you have to supply both arguments. You cannot omit an argument from the middle of the list if you plan on using one farther down that list.

I hope that hasn't muddied the issue any.

I personally like the official Lua 5.1 reference manual. Its clean, and concise, and generally pretty self explanatory.
https://www.lua.org/manual/5.1/
Some things are covered in separate chapters though, so be sure to at least glance at some of the earlier pages even if the one you need is later on.
#11
Bugs & Feature requests / Re: Solarus like Rpg Maker 2003
November 24, 2017, 10:15:13 PM
I'd like to mention just in case its unclear, that RPG Maker's event system isn't magic.
They literally just wrote a script inside the game engine that interprets what those mean and adds whatever text they wrote there into another script file at run-time.

If you look at RMXP you can even read and replace all the code that handles what the event buttons do. You could create your own custom events.
Rather than adding this to Solarus proper, someone could write a simple executable that reads a Lua definition file to create buttons, label them, and define what kind of text gets added some output script or another.

Its essentially just a macro like you'd find in any IDE. A slightly less versatile Intellisense.

I'd hazard (if he was so inclined, which he seems not) Diarandor would be plenty able to make such a thing himself.

The only things you have to keep in mind are how Solarus operates (to base your insertted code around) and what functions do (which objects they operate on, what arguments they take)... and... lastly... what functions do you need?

No one person can ever truly think of every possible function you could need tied to a button( even if arguably only one or a few people wrote the functions ).

This isn't a bad idea per se, but I think it should be limited to a tool, rather than something integrated into the core.
#12
Bugs & Feature requests / hero:set_size
November 23, 2017, 11:49:51 PM
This one just keeps being a problem every time I have an idea to use solarus for.

LTTP is a sot of odd game in that its the only free movement game I've ever played where the hero actually takes up a full 16x16 collision rectangle.

Every other game I can think of from Chrono Trigger to Seiken Densetsu, to almost every 2D Zelda game has allowed the bounding box to be smaller than a full map tile and also allowed the player's sprite to clip into the wall a little bit.

For example, I know that Link's sprite in both Oracle games and Link's Awakening ( and LADX ) is 16x16, but his collision area is only 8x10, focused at the bottom center of his feet. He doesn't clip into the wall from the bottom, but he has a little room to walk around inside a 1x1 tile (16x16px) box, and a bit of space to gently kiss the walls.

In Minish Cap, Link's bounding box is 11x8 while his sprite is 18x24.

In The Legend of Zelda (NES) Link is 16x16px in sprite size, but his bounding box is only 16x8.

This is a feature that is extremely important to me for both accuracy and game-feel, as well as aesthetics.

I tried adding the set_size function to the hero entity list and recompiling solarus, but with all the library dependencies and compiler quirks, I couldn't get the thing to compile. After 8 hours (no I'm not exaggerating) I gave up.

Could you be so kind as to consider making the player's size alterable. The engine seems to be coded well enough that it shouldn't break anything, since it doesn't cause any problems for other entities.


EDIT:
I notice now that this has been recently discussed partially in another thread.
I'm leaving this here for emphasis and potential discussion of why it would be useful.
#13
Development / Re: Solarus 1.5 development snapshot
July 18, 2016, 08:51:21 AM
Aha! You fixed the behavior I felt was far too petty to really bring up!
That will almost certainly be useful to me in the future. Its not really so much that it does something new... but it makes something existing, much faster to work with.

(something some other devs I know don't seem to understand. Why can't they be more like you, haha)

...If I might suggest a similar tweak... Moving assets into folders?
Sometimes I end up deciding to organize things into new folders after I've created too many of them to manage. Being able to move a sprite into a folder without having to copy/cut/paste/edit the storage data manually, etc would be a boost to efficiency...
Though, its not something I'd want you to take time from more important features to work on...
#14
The newest revision snapshot actually has a special drawing property for this very purpose. Glance through this thread if you want more details.

That said,
I have noticed that layering multiple semitransparent objects on top of each other does tend to make them look darker. I believe this is because when a drawable is blended with semitransparent alpha, and there's not enough alpha to completely add up to 255, it gets blended with black... I can't quite articulate what I mean, if that doesn't make sense. It is a problem I've been considering for a while, but have no suggestions yet.

However, if you draw your window glare into a surface with blend mode set to additive and draw that on your map surface, it should look better. (it may be too bright, that's easily solved by making the colors in the glare sprite darker.)

A tip about additive and multiply/modulate sprites is that they work better with a solid background, rather than being transparent.

Good luck


EDIT: sorry I misread some of that. But still check out the blend modes I mentioned!
#15
Well... I'm not sure exactly why you're not getting the effect you need, but here's how I did mine (note that I used all hard coded values for stuff in this specific map, because its just testing things.)

Code (lua) Select
local map = ...
s = sol.surface.create(512,256)--s is my shadow
s2 = sol.surface.create(512,256)--s2 is my light
s:set_blend_mode("color_modulate")
s2:set_blend_mode("additive_blending")
local ss = sol.surface.create()--ss is my final surface for drawing the screen
function map:on_draw(ss)
  local x,y = map:get_camera():get_position()
  local w,h = map:get_camera():get_size()
  s:clear()
  s:fill_color({032,064,128,255})
  s2:clear()
  for e in map:get_entities("lit_") do
    local xx,yy = e:get_position()
    local sp = sol.sprite.create(e.sprite or "glow")
    sp:set_blend_mode("alpha_blending")
    sp:draw(s2,xx,yy)
  end
  s2:draw_region(x,y,w,h,s,x,y)
  s:draw_region(x,y,w,h,ss)
end


in your code I think
Code (lua) Select

local mapsurface = sol.surface.create()
function map:on_draw(mapsurface)
-------------------------------------------------
    shadow:fill_color({32,32,255,255})
    shadow:set_blend_mode("color_modulate")
    light_mask:set_blend_mode("additive_blending")
    for entity in map:get_entities("statue") do
      local x, y, z = entity:get_position()
      local sprite = sol.sprite.create("entities/torch_light")
      sprite:set_xy(x, y)
      sprite:draw(light_mask)
    end
    light_mask:draw(shadow)
    ------------------------------------------
    shadow:draw_region()--...stuff for camera here, my code has an example of how to get the portion of the surface to draw
end


You need three surfaces at least, as far as I can manage.
You draw your lights onto the additive surface
you draw the additive onto the modulate
and you draw the modulate onto the map's on_draw surface

I got the coords and size of the camera, so I could draw a portion of the map that was only as big as the screen, but my shadow and light surfaces were the full size of the map. (I only drew portions of them at a time though)

Setting sprites to additive directly, doesn't seem to work correctly right now. But try looking at my code (sorry its so undescriptive with its names...) to see where yours differs. Mine works for me.

EDIT:
I'd like to point out I'm no expert on the workings of surfaces in Solarus. I only just started messing with them when the blendmode snapshot came out.
I just kept trying things until I found what worked. I have some experience with blend modes and lua previous to this, but otherwise its all just something I'm learning as I go. Just a disclaimer in case there's a question I can't answer.