Navi - a message library (6/11 demo)

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
TechnoCat
Inner party member
Posts: 1611
Joined: Thu Jul 30, 2009 12:31 am
Location: Denver, CO
Contact:

Re: A message system

Post by TechnoCat »

How are return values from messages retrieved?
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: A message system

Post by Roland_Yonaba »

litearc wrote:Wow, ok, you guys convinced me!
Great.
litearc wrote: I'm still new to lua and learning
Indeed, you do well.
litearc wrote: so if people actually spend time looking through my code, it'd be really helpful.
Why not ? So I went into the code of this attachment.
I may have some proposals...

First, in general, I hate global variables. But that's my opinion.
So in general, when i have to write external snippets to be loaded as third-parties, I write them as locals inside their own file, using "return" to capture them.
Thus, using "require" elsewhere won't pollute the global space.

So "mymath.lua" will result in:

Code: Select all

-- round number
local function round(num, idp)
    local mult = 10^(idp or 0)
    return math.floor(num * mult + 0.5) / mult
end

return round
And then in the header of "text.lua" :

Code: Select all

local round = require "mymath"
--etc
This way, I am keeping private routines that should not be accessed by the user when "requiring" the library.

Indeed, "test.lua" can be refactorized to make functions like draw_test, draw_list,unformat,... private. "Bloc" class also should be hidden internally. "Message" class can also be kept internal, returning it at the end of the file, packing the function play_messages inside in order to be accessible from the user. Don't make it message:play_messages, use a dot instead of a colon.

Code: Select all


-- other stuff
message = { --class definition}
function message:new(...)  ... end
function message:init(...) ... end
function message:play(...) ... end
function message.play_messages(m) ... end

return message

-- EOF
This way, one can simply make it working:

Code: Select all

-- main.lua

function love.load()
local MessageSystem = require "text"
local mess = { 'bla','bla','foo','bla',...}
local myMessages = {}
for i,m in ipairs(mess) do myMessages[i] = MessageSystem:new(...)  end 
...
end

function love.draw()
...
MessageSystem.play_messages(myMessages)
...
end

Also, since you're not using a class managing system, you might want to consider hardcoding a hackety trick to call message class constructor (message:new() ) with a shortcut message(...).

Code: Select all

message.__call = function(self,...) return message:new(...) end
-- message(...) will be the same as message:new(...)
I guess that's it... I'm not saying that's the best way...I just find this looks nicer, IMHO.
User avatar
TechnoCat
Inner party member
Posts: 1611
Joined: Thu Jul 30, 2009 12:31 am
Location: Denver, CO
Contact:

Re: A message system

Post by TechnoCat »

I agree with Roland on avoiding globals. Especially in libraries such as this.
User avatar
litearc
Citizen
Posts: 57
Joined: Thu May 17, 2012 12:40 am

Re: A message system

Post by litearc »

@Roland_Yonaba: Thanks! The "return" idea will be very useful for the reason you stated. One change I've made since the first release is packing almost all the functions into objects, i.e. all the "draw" functions are now part of a draw object, which reduces clutter. But using a return will help even further. The __call is great - will implement that as well.
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: A message system

Post by Ref »

Two items.

'z' key doesn't allow you to break out of a time delay line (e.g. s[2]).

I find that if you replace:

Code: Select all

if cfg.textsh then				-- add character shadow (if desired)
   lg.setColor( color.shadow)
   lg.print( self.s:sub( 1, nc ), x + self.x + 1, y + self.y + 1)
end
with

Code: Select all

local sh = 0.1
   if cfg.textsh then				-- add character shadow (if desired)
   lg.setColor( {sh*c[1],sh*c[2],sh*c[3], c[4]})
   lg.print( self.s:sub( 1, nc ), x + self.x + 1, y + self.y + 1)
end
gives a little better shadow effect for colored text - just me 2 cents :roll:
User avatar
litearc
Citizen
Posts: 57
Joined: Thu May 17, 2012 12:40 am

Re: A message system

Post by litearc »

@Ref: The message for s[2] uses a wait instead of keypress to end it, so I didn't want the player to skip the message and then have it immediately end. If you don't want to wait, use wait = nil instead of a number, which ends the message upon a keypress. Honestly though, it's kinda awkward to use both skip and wait options since skip off + wait on are meant to control timing during certain cutscenes. I just wanted to show off the features of the system here.
That shadow would be a darker shade of the text color, which is a nice effect and might work better for darker colors. I also think I found a bug when testing your code. Thanks!

EDIT: Bug fixed! In case you're wondering.
In text.lua, this:
_,_,r,g,b,a = s:find('(%x%x+)(%x%x+)(%x%x+)(%x%x+)',3)
was wrong, and should've been:
_,_,r,g,b,a = s:find('(%x%x)(%x%x)(%x%x)(%x%x)',3)
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: A message system

Post by Roland_Yonaba »

litearc wrote:@Roland_Yonaba: Thanks! The "return" idea will be very useful for the reason you stated. One change I've made since the first release is packing almost all the functions into objects, i.e. all the "draw" functions are now part of a draw object, which reduces clutter. But using a return will help even further. The __call is great - will implement that as well.
That's pretty nice!
Well, another question. Actually, how do you handle the box height ? Does it get adaptated to the very number of messages inputted ?
I was wondering, if one need the box height to be fixed (most of RPGs I've seen are does this), it would be interesting adding a console-like style ?
Display a portion of the messages inputted, keeping the typewriter effect (which is amazing)! :ultrahappy:
--Assuming #msg = 10
-- Assuming box_height can only afford 4 lines.

Display msg 1 to 4, waiting for 'z' to be pressed...
Skip msg[1], make the 3 other left slide 1 line up...
Display msg[5], waiting for 'z' to be pressed...

Skip msg[2], make the 3 other left slide 1 line up...
Display msg[6], waiting for 'z' to be pressed...

Skip msg[3], make the 3 other left slide 1 line up...
Display msg[7], waiting for 'z' to be pressed...

...etc
Can be implemented as one option, providing a way to the user to choose that style or keep the default one.
Also, can the typewriter effect speed be adjusted ?
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: A message system

Post by Ref »

Just jumping the gun here.
I added to my copy hard coded width & heights for window.
Not pretty, but gets the job done.
Sure final version will be much more automatic.

Code: Select all

cfg.w = {200,200,200,100,200,200,200}
cfg.h = { 80, 60, 50, 60, 80, 60, 60}	
Window drawing then becomes:

Code: Select all

for i = 1, #m do
   if not m[i].over then
      if not m[i].started then m[i]:init() end
      window.draw( cfg.x, cfg.y, cfg.w[i]+15, cfg.h[i] )	--< CHANGED
      m[i]:play( cfg.x+10, cfg.y+10, m[i].wait )    -- were cfb.x & cfg.y is screen location of window
      break
      end
   end
If you set all the heights to the same value - obviously - the window height remains constant. :P
Text scrolling speed is set in:

Code: Select all

cfg = {		-- display parameters
   msgspd	= 30,	-- scroll speed
   wincol	= color.window,
   textsh	= true,	-- show text shadow
   }
In my copy I've moved everythihg out of main.lua into text.lua except for 's' & cfg tables so that text.lua becomes more like a library.
Trying hard not to screwup some really nice work!
Best
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: A message system

Post by Jasoco »

Really really cool. Needs some tweaking though but really cool.

Can the "Press Z" prompt be turned off? Can we get an option to instead show an icon instead? Can the Z key be changed to something else? I notice that it relies on a global "key.ent" variable. I think instead it should be something that's defined when you initialize the library via an initialization function instead of having it initialize when the "text.lua" file is required. Stuff like the key used to continue and the color of the shadow and such should be set up with an initialize function that's called in love.load() or whenever you want to initialize the library.

I also think the way the special commands are contained is a little clumpy. I like the way Robin's RTF library did them with commands inside {brackets}. It's a little easier to read if you ask me.

Also, I notice you require a second file called "mymath" which only has one function. Can you remove this requirement from the next version and just put that function inside the "text" file so we don't have to require two files. Or is "mymath" not used by the library? I just don't want to have to require a second file.
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: A message system

Post by Roland_Yonaba »

Indeed, it is being used. It contains actually just one function, used to round values.
But maybe he did want to keep it separated because this is about to grow next, with new math utilities and helpers.

Though...I am pretty sure "mymath" is required first to add the rounding utility in the global scope, so that it'll be accessible to routines inside "text.lua".
Well, the structure can remain as it is, actually. Routines inside "mymath.lua" should be kept local in their chunk, then required internally inside "text.lua".
So that the user will just have to call that very last chunk...
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 55 guests