Jump to content

Averice

Members
  • Posts

    36
  • Joined

  • Last visited

Blog Entries posted by Averice

  1. Averice
    I think I posted this module on the forums in order to help someone a few weeks ago, but I thought It'd get more use if I created a blog post so it doesn't get diluted down in the forums.
     
    I've written this event module to make it easy to add keyboard and mouse button binds and it's come in handy to me for quite a few little scripts.
     
    Once again excuse the poor spacing as copy and paste here seems to remove my tabs.
     
    event.lua

    -- Event module written by Averice event = {} event.inputBinds = {} event.mouseBinds = {} function event.CheckInput() local succ, err; for key,tab in pairs(event.inputBinds) do if( App.window:KeyHit(key) ) then for k, v in pairs(tab) do if( not v.Held ) then succ, err = pcall(v.Func, unpack(v.Args)); if not succ then print("Event Error[Key]["..k.."]: "..err); end end end end if( App.window:KeyDown(key) ) then for k, v in pairs(tab) do if( v.Held ) then succ, err = pcall(v.Func, unpack(v.Args)); if not succ then print("Event Error[Key]["..k.."]: "..err); end end end end end for but, tab in pairs(event.mouseBinds) do if( App.window:MouseDown(but) ) then for k, v in pairs(tab) do succ, err = pcall(v.Func, unpack(v.Args)); if not succ then print("Event Error[Mouse]["..k.."]: "..err); end end end end end function event.AddInputBind(key, name, held, func, ...) local newInput = { Func = func, Args = {...}, Held = held or false } event.inputBinds[key] = event.inputBinds[key] or {}; event.inputBinds[key][name] = newInput; end function event.AddMouseBind(but, name, func, ...) local newInput = { Func = func, Args = {...} } event.mouseBinds[but] = event.mouseBinds[but] or {} event.mouseBinds[but][name] = newInput; end function event.RemoveInputBind(key, name) if( event.inputBinds[key] and event.inputBinds[key][name] ) then event.inputBinds[key][name] = nil; end end function event.RemoveMouseBind(but, name) if( event.mouseBinds[but] and event.mouseBinds[but][name] ) then event.mouseBinds[but][name] = nil; end end
     
    It's usage is really straight forward, you import the script, and in your App.loop you'll put

    event.CheckInput();
    This will check for your binds and run them if needed so you don't have to fill your App.loop with key binds.
     
    To add a keyboard bind "event.AddInputBind(key, name, held, function, args);

    local function printStuff(...) print("Hello", ...); end event.AddInputBind(Key.A, "RandomName", false, printStuff, "How", "are", "you") -- varargs once again. --when the A key is pushed it should output, "Hello How are you"; -- if 'held' is true it will keep printing while it's held. --To remove it we use it's name and key. event.RemoveInputBind(Key.A, "RandomName"); -- Mouse bind functions are the same, just use event.AddMouseBind and event.RemoveMouseBind -- mouse bind functions are considered always held. Add a check to your function if you only -- want it done per click.
     
    A quick snippet that I use in my splash screen with my StateManager module to cancel the splash if escape is pushed.

    event.AddInputBind(Key.Escape, "__SHARDSPLASH", false, function() StateManager:Pop() end);
  2. Averice
    I released an OOP class sytem for leadwerks last time this time I'm going to post my StateManager class which I use to control all the gamestates for the game I am working on.
     
    If you don't know what a Statemanager is or what my interpretation of one is I'll run through it quickly.
    Generally speaking it's just a stack full of 'states' each state has a list of functions with identical names but different internal functionality, the game will call these functions but ONLY for the active state, say your game has a Draw function but you want a splash screen with a Draw function, you'll separate these into different States for the stack, now when your splash state is active only the splash's Draw function will be called. State stacks almost always run [L]ast n [F]irst [O]ut, so the last state you push onto the stack will be the one the game starts using, so to have a splash screen -> menu -> game order in your stack you would push the game onto the stack first, the menu second and the splash last so that the splash is the first thing the end user sees.
     
    Enough ramblings let me post some code.
     
    statemanager.lua
    requires the class scripts.

    class "CStateManager"; function CStateManager:Init() self.States = {} end function CStateManager:Push(state, init) if( ctype(state) == "CState" ) then self.States[#self.States+1] = state; if( init ) then if( self.States[#self.States-1] and self.States[#self.States-1].isinit ) then self.States[#self.States-1]:Shutdown(); self.States[#self.States-1].isinit = false; end self.States[#self.States]:Init(App.context); self.States[#self.States].isinit = true; end else print("StateManager: CStateManager.Push expected CState got: "..ctype(state)); end end function CStateManager:InitCurrentState() if( self.States[1] and not self.States[#self.States].isinit ) then self.States[#self.States]:Init(App.context); self.States[#self.States].isinit = true; end end function CStateManager:Pop() if( self.States[1] ) then if( self.States[#self.States].isinit ) then self.States[#self.States].isinit = false; self.States[#self.States]:Shutdown(); end local oldState = self.States[#self.States]; self.States[#self.States] = nil; self:InitCurrentState(); return oldState; end print("StateManager: Called CStateManager.Pop with empty stack"); end function CStateManager:GetAll() return self.States end function CStateManager:GetActive() if( self.States[1] and self.States[#self.States].isinit ) then return self.States[#self.States]; end print("StateManager: Called CStateManager.GetActive with no running states"); end function CStateManager:Pause(state) if( ctype(state) == "CState" ) then state.paused = true; end end function CStateManager:Resume(state) if( ctype(state) == "CState" ) then state.paused = false; end end function CStateManager:IsPaused(state) if( ctype(state) == "CState" ) then return state.paused; end end function CStateManager:Call(func, ...) if( self.States[1] and self.States[#self.States].isinit and not self.States[#self.States].paused ) then if( self.States[#self.States][func] ) then self.States[#self.States][func](self.States[#self.States], ...); end end end
     
    state.lua

    -- Tiny file this one. really just a declaration and a nilfix file. class "CState"; function CState:Init() end function CState:Shutdown() end
     
    Example useage.

    -- Our splash screen. SplashScreen = new "CState" function SplashScreen:Init() self.Something = "HELLO"; end function SplashScreen:Think() self.Something = self.Something.."O"; end function SplashScreen:Draw() App.context:DrawText(self.Something, 100, 100); end -- Now something else. Random = new "CState" function Random:Draw() App.context:DrawText("Second State", 100, 200); end
     
    -- Now in our main file to initialize out statemanager and load our states.

    function App:Start() StateManager = new "CStateManager"; StateManager:Push(Random); -- Remember this goes before the splash so we see it AFTER the splash StateManager:Push(SplashScreen, true); the true means we want to initialize this, as it's the last state being pushed we may aswell tell the statemanager we are ready to begin. end function App:Loop() StateManager:Call("Think") -- Can name your functions anything, Init and Shutdown are always the same though. StateManager:Call("Draw", "some", "arguments", "here", "if", "you", "want"); end
     
    To remove the current state from the stack and initialize the next, we use StateManager:Pop();
    I hope people get some use out of this, and I hope I've explained it nice enough.
  3. Averice
    So I've got a few of these little helper modules I've written while making my game, I figured I needed a place to post them so others can get some use from it, I'll be selective with what I release as some of them I would like to keep private but everytime I get a spare moment I'll try to write up a blog post with a new module release and how it's used.
     
    So anyone familiar with OOP will hopefully get some use from this module, Lua already has a semi-OOP system with it's 'metatables' and this module just extends those to be used in a class system with inheritance.
     
    -- This is the definition of the system, only a small file but it does a lot.
    class.lua

    -- Class system written by Averice _shardClass = {} _shardClass.__index = _shardClass; function class(nme) if( _G[nme] ) then print("Class: "..nme.." already exists."); return; end _G[nme] = {} setmetatable(_G[nme], _shardClass) _G[nme].istype = nme; return _G[nme]; end -- Really no reason for the shardClass metatable but it provides nice looking functionality -- class "CAnimatedEntity" : extends "CBaseEntity" <-- is now correct syntax function _shardClass:extends(superclass) if( _G[superclass] ) then self.parent = superclass; self.__index = _G[superclass]; end end function new(class) if( _G[class] ) then local newClass = {} setmetatable(newClass, _G[class]); for k, v in pairs(_G[class]) do newClass[k] = v; -- For some reason metamethods weren't being accessed properly, here's a hacky fix. end if( newClass.Init ) then newClass:Init(); end return newClass; end print("Class: "..class.." does not exist."); end function ctype(class) return class.istype or type(class); end
     
    Alright, if your hoping to use this and know OOP programming the above should be self-explanatory.
    Simple put to define a new class you do this.

    class "MyClass";
    To define a class that inherits from another you do this.

    class "MySecondClass" : extends "MyClass";
    To create a new instance of a class you do this.

    my_class_instance = new "MySecondClass";
     
    If there is an 'Init()' function it will be called automatically when a new instance of the class is created.
     
    Here is an example.

    class "ExampleClass"; function ExampleClass:Init() self.Number = 10; end function ExampleClass:SimpleFunction() print(self.Number); end class "NewExampleClass" : extends "ExampleClass"; function NewExampleClass:Init() self.Number = 15; end -- Now we create an instance. MyClass = new "NewExampleClass"; MyClass:SimpleFunction() -- notice this function was inherited from "ExampleClass" not "NewExampleClass" -- will print 15;
  4. Averice
    Been doing more GUI work, mainly porting more of my GUI lib, but I did decide to finally get around to Dropdown menus which the library was missing from the beginning, I like this sudden feeling of productivity, the hardest part was porting my TabPanel over. I must have written the original on a bad day and going over the old code made no sense to me, it's new and improved now.
     
    - Sliders and DropLists.


     
    - Tabs and the usual ScrollPanel.

  5. Averice
    Over the past few days I've been porting a GUI library I've written in Lua, it's been a pretty successful and struggle free move over to Leadwerks which has excited me over the future of my time with Leadwerks.
     
    I'll give a rundown of what features I've implemented.
    - Text entry panels with carrat positioning and text clipping.
    - Labels with multi-line wrapping.
    - Scroll panels with mousewheel support.
    - Panel hierarchy with parent-child clipping.
    - Button and hover events, keytouch events and focus events.
    - Panel order of precedence via shardui.paintOver(myPanel)
    - Tool tips for those vague looking buttons.
    - Scissor rect support - shardui.scrissorStart(x, y, w, h) shardui.scissorEnd()
    - Simple way of creating your own unique UI items.
    - Skin system.
     
    To give an idea of how it's used I'll show a bit of code.

    -- In App.start after you've created your graphics context you simple load the ui lib. import "Scripts/shardui/shard.lua"; -- This will include all sub files and folders -- in App.loop - After world rendering so the UI is ontop. shardui.think(); -- Always before paint. shardui.paint(); -- And that's it, the UI lib has been loaded successfully. -- Now to create a panel ( do not create panels in App.loop, they only need to be made once. ); myPanel = shardui.createPanel("ShardFrame") -- second argument to this would be the panel to parent it too, you'll see later on. myPanel:SetPos(100, 100); -- x, y positioning myPanel:SetSize(400, 500); myPanel:SetTitle("TestPanel"); myPanel:SetVisible(true); -- visibility toggling. myPanel:EnableDragging(true); -- Enable dragging by grabbing the title bar.

    -- Now we'll add a label in the panel.

    myLabel = shardui.createPanel("ShardLabel", myPanel) -- myPanel is the parent panel. myLabel:SetPos(2, 22); -- Relative positioning to parents positiong. myLabel:SetSize(100, 20); myLabel:SetMaxWidth(100); -- max width, it will line wrap if it's longer than 100 pixels. myLabel:SetColor(ColorL(255, 100, 100, 255)); -- If you don't like the skins color but don't want to create a skin, use this. myLabel:SetText("Hello Leadwerks Community");

    Easy as.
     
    A console with lua script support I created with the library.

×
×
  • Create New...