Mordred Posted February 7, 2014 Share Posted February 7, 2014 Hello Leadwerkers, i have an issue that i really do not understand. I have made a function that draws basically an image, depending of the mouse position ("hover over Button"). I need to have access to the "current context" within this function, but as soon as i try to get access to the "Context:GetCurrent()" i do get a crash (no errormessage in Leadwerks, just "MyGame.exe has stopped running"). I tried it the following ways. 1st: define "context" within the function --> context = Context:GetCurrent() --> results in crash 2nd: define "context" as globa within the whole script --> "context = Context:GetCurrent()" in the first row --> crash 3rd: Passing "context" from the PostRender into the function like: "function menu (context, label, x, y)--> crash. 4th: creating another context named "xcontext = Context:GetCurrent()" to prevent from using the same variable twice --> crash. Now my problem is: Why does the game crash at launch as soon as i try to pass or access the context into or within the function? I do have to pass the context somehow into the function or the "context" within the function will be unknown. For a better understanding here's the script (the error occurs within the "menu" function): Script.player = nil --entity "Player" function Script:Start() window = Window:GetCurrent() local context = Context:GetCurrent() self.button = Texture:Load("Materials/HUD/Btn_not_pressed.tex") self.button_pressed = Texture:Load("Materials/HUD/Btn_pressed.tex") local font = Font:Load("Materials/Fonts/arial.ttf", 20) context:SetFont(font) font:Release() context:Release() end function Script:HUD() end local menuopen = 0 function Script:PostRender(context) local windowWidth = window:GetWidth() local windowHeight = window:GetHeight() if window:KeyHit(Key.T) then if menuopen == 0 then menuopen = 1 else menuopen = 0 end end if menuopen == 1 then context:Clear() context:SetColor(1,1,1) context:SetBlendMode(Blend.Alpha) end menu("Start", 9, 7) context:SetBlendMode(Blend.Solid) end function menu(label, x, y) local mousepos = window:GetMousePosition() local mx = mousepos.x local my = mousepos.y window:ShowMouse() if mx >= x and my >= y and mx <= x+200 and my <= y+35 then context:DrawImage(button_pressed, x, y) context:DrawText(label, x+5, y+3) else context:DrawImage(button, x, y) context:DrawText(label, x+5, y+3) end end [Edit] Found my error, i defined the button variables as "self.button" and tried to access them via "button" since "self.button" didnt work in the funtion. I renamed the variables to plain "button" (instead of self.) and it did work. Yay, the context wasn't the error at all! Quote Link to comment Share on other sites More sharing options...
Rick Posted February 7, 2014 Share Posted February 7, 2014 In the script you have in your post, where are you passing context into menu? You aren't. Also note that your menu function is now global the way you set it up. To make a script level function (which is almost 100% what you want in this case) do the following: function Script:PostRender(context) self:Menu(context, lbl, 5, 6) -- note the colon and not period to call functions instead of access variables end function Script:Menu(context, label, x, y) -- now you can use context in here end This would be what I call the right way to do this. You can also access the global App to get the context via App.context. local context = Context:GetCurrent() You must think this is how you can use context in menu without passing it? The keyword local makes it only viewable inside the function it's created in. In your case the variable context is only available in the Start() function. Also note that your window variable is global the way you have it setup too. To make script level variables use self like: self.window = Window:GetCurrentWindow() Now you can use self.window in this entire script. Quote Link to comment Share on other sites More sharing options...
Mordred Posted February 7, 2014 Author Share Posted February 7, 2014 And again it's Rick Thanks for your reply, as mentioned in my edit above the error itself is already found. But thanks for your further suggestions. The context wasn't passed in this special snipplet, since i already had my changes redone. So, if i understand you correctly the "button = Texture:Load...." in the "Script:Start" is global too and should therefore be "self.button"? Quote Link to comment Share on other sites More sharing options...
Rick Posted February 7, 2014 Share Posted February 7, 2014 Your script already has self.button (even before your edit), but yes. Just remember this: Inside an entity script 99% of the time you only want to use local if the variable only needs to be used in said function, and use self.variable if it needs to be accessed anywhere in the script. Also make your script function like: function Script:MyFunction() end And call them like: self:MyFunction() Don't make anything global or you could get some really hard to find bugs that you just can't figure out what is happening because 5 different scripts could be altering the same global variable at different times without you realizing it because it's just too hard to keep track of global variables. Quote Link to comment Share on other sites More sharing options...
Mordred Posted February 7, 2014 Author Share Posted February 7, 2014 Hey Rick, thanks again for explaining it, i had feard in the first place that i somewhere did change "context" to get the error, but luckily it was easier than that . Okay, now in case someone is interested in knowing the result / maybe someone might use this as a hint on how to start, i made a simple script that opens a small menu when hitting "T" within the game, if you hover your mouse over the "start" button it switches to a green colored texture file, if you press the mouse the text shown switches between "Start" and "Hit!". It's far from being finished yet, but maybe it's usefull for some newbies like me I gonna attach it at this posting. Basic_Menu.zip Quote Link to comment Share on other sites More sharing options...
Rick Posted February 7, 2014 Share Posted February 7, 2014 No problem. A couple notes which aren't major: You have menuopen defined before PostRender outside of any function. The good news with that is you used local so it's local to this script, and you can do it this way, but it's a little inconsistent. If this is a variable needed in this script then it's probably best to define it in Start() with self.menuopen. You already get the window in Start() and assign it to self.window but you do it again in your Menu() and assign it to a local window variable. No need to do it again. Inside Menu just use self.window. It refers to the same window. Quote Link to comment Share on other sites More sharing options...
Mordred Posted February 7, 2014 Author Share Posted February 7, 2014 Okay, i did change that too, i gonna edit my previous posting and edit the file too Btw. how can i make it so that hitting the "Exit" button actually does close the window from within the function? I cannot use "return false end" (--> just does nothing) and there's no "Window:Close()" function. Or do i have to use "Window:Release()"? Quote Link to comment Share on other sites More sharing options...
Rick Posted February 7, 2014 Share Posted February 7, 2014 This is where the App object (which is in App.lua) comes into play. App is a global object and anything defined in it you have access anywhere from your scripts. I wish there were a better way as I dislike globals, but right now that's what we have. So knowing that, and knowing that the only way you can close the application is by returning false in App:Loop(), a good method would be to create a function in App.lua that will set a variable to false and always return that variable from App:Loop(). ie. App.lua function App:Start() self.running = true end function App:ExitGame() self.running = false end function App:Loop() -- all the other stuff in here -- notice we are returning a variable here. it's set to true, but from our script we call the QuitGame function which sets this to false meaning when the world:Update() method that's in here returns back to this function it'll return false because self.running was changed to false by our script. Note all entity scripts are executed from world:Update() return self.running end Your script: function Script:Menu() -- if click exit button App:ExitGame() end Quote Link to comment Share on other sites More sharing options...
Mordred Posted February 7, 2014 Author Share Posted February 7, 2014 Ah okay, i remembered you saying "never touch app.lua" so i didn't even think about it Thanks again, that does work. Quote Link to comment Share on other sites More sharing options...
Rick Posted February 7, 2014 Share Posted February 7, 2014 If I said that I might have said avoid touching App.lua at all costs, but with something like this, and saving data like in my tutorial, you sort of get stuck doing it. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.