(shouting)

Lua help thread

If you lost something come look for it here
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: Lua help thread

Post by Hoeloe »

Rednaxela wrote:
Hoeloe wrote:(still not published yet, still waiting on OpenGL commands).
Could you clarify what you're looking for out of it? The very initial pass at it won't contain any extra Lua APIs (except perhaps a enable/disable legacy compatibility thing). It's certainly not hard to add some "draw rectangle" stuff shortly after though. (As a note, made some good progress getting the OpenGL renderer closer to prime time last night)
I'm basically hoping for access to direct OpenGL calls (i.e. polygon drawing). This way I can render polygons to the screen, and it would vastly open up what we can do with it (especially if we allow textures and shaders).
Rednaxela wrote:My current thought is that if we had proper spatial search structures, there would be little need to make large polygon colliders from groups of blocks, and the spatial search structures can be more generally useful than just collisions. Also it may be worth doing deeper research into what data structure SMBX is doing internally already using for collisions with blocks, because I know from the result of manipulating the block structure that it has to be storing some collision data elsewhere and it's likely doing it for efficiency reasons.
Sure, it was more an "either-or" thing. Deeper research into the collisions is a good idea. That is certainly interesting. My initial guess is it's storing collision volumes elsewhere, and part of the problem with moving layers is that it invalidates this cache and recomputes these collision volumes.
Image
Image
Image
Image
Image
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: Lua help thread

Post by Rednaxela »

Hoeloe wrote:I'm basically hoping for access to direct OpenGL calls (i.e. polygon drawing). This way I can render polygons to the screen, and it would vastly open up what we can do with it (especially if we allow textures and shaders).
I think it would have to be some sort of subset of useful-and-not-too-complicated subset of OpenGL calls. Do note that there's a one-way serialized and asynchronous interface to the rendering thread, such that I could easily enough allow Lua code access to calls sufficient to draw some polygons, but any OpenGL calls that require data to be returned from them to be useful, wouldn't really be possible.

For example if one wanted to create a new texture, Lua code couldn't be given the real texture id, nor could it have any method for doing error handling if the OpenGL call will fail. It could get messy. For that reason it would probably be best that at least certain tasks, if made possible, be made into a higher level operation rather than direct OpenGL calls.

I'd like to keep things to the smallest number of distinct calls that can be highly versatile and useful. Allowing custom shaders to be specified is one thing that could probably give a lot of bang for how little effort it would be, but texture creation/binding/manipulation calls more granular than a simple "try to make make <image filename> the current texture" (with caching the mapping from filename to texture id done internally of course) would get far too messy.
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: Lua help thread

Post by Hoeloe »

Rednaxela wrote:
Hoeloe wrote:I'm basically hoping for access to direct OpenGL calls (i.e. polygon drawing). This way I can render polygons to the screen, and it would vastly open up what we can do with it (especially if we allow textures and shaders).
I think it would have to be some sort of subset of useful-and-not-too-complicated subset of OpenGL calls. Do note that there's a one-way serialized and asynchronous interface to the rendering thread, such that I could easily enough allow Lua code access to calls sufficient to draw some polygons, but any OpenGL calls that require data to be returned from them to be useful, wouldn't really be possible.

For example if one wanted to create a new texture, Lua code couldn't be given the real texture id, nor could it have any method for doing error handling if the OpenGL call will fail. It could get messy. For that reason it would probably be best that at least certain tasks, if made possible, be made into a higher level operation rather than direct OpenGL calls.

I'd like to keep things to the smallest number of distinct calls that can be highly versatile and useful. Allowing custom shaders to be specified is one thing that could probably give a lot of bang for how little effort it would be, but texture creation/binding/manipulation calls more granular than a simple "try to make make <image filename> the current texture" (with caching the mapping from filename to texture id done internally of course) would get far too messy.
I've worked around similar limitations before. The standard way to do it is to cache the commands and execute them all at once later in the update cycle. That way, it doesn't matter that the correct values aren't returned, because the Lua code never needs to know about those IDs, it just uses a translation from the Lua object to the OpenGL ID, and a list of commands to execute associated with the Lua ID. With that in place, the commands can be executed once the map between IDs has been created, later in execution. This could be complicated to implement though. In C++. I believe it would require storing function pointers, though I'm not certain about how C++ deals with functions as objects.
Image
Image
Image
Image
Image
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: Lua help thread

Post by Rednaxela »

Hoeloe wrote:I've worked around similar limitations before. The standard way to do it is to cache the commands and execute them all at once later in the update cycle. That way, it doesn't matter that the correct values aren't returned, because the Lua code never needs to know about those IDs, it just uses a translation from the Lua object to the OpenGL ID, and a list of commands to execute associated with the Lua ID. With that in place, the commands can be executed once the map between IDs has been created, later in execution. This could be complicated to implement though. In C++. I believe it would require storing function pointers, though I'm not certain about how C++ deals with functions as objects.
Caching them all at once and executing later in the update cycle is what is done. The mechanism currently in place uses the very C-style pattern of an enumeration to define the list of commands, and a union of structs to define the arguments for each of them. Such translation between OpenGL IDs and Lua objects would indeed get somewhat messy, though a simpler alternative might be simply having a resource identifier from the Lua side driving things... and that resource identifier could be the filename that needs to be loaded for that resource.

In any case, making the whole of the OpenGL API available is quite simply impractical, so perhaps if you send me a list of what you think a useful subset would be, we could discuss that. Because of what's involved in serializing with serializing the commands (mostly talking in terms of human effort to implement all that, but computational overhead applies too), it's vastly preferable to have a smaller number of more powerful commands (i.e. draw this vertex array in the specified mode), rather than a large number simple ones (i.e. glBegin, glVertex, glEnd). This is kind of the way OpenGL itself has evolved over time too really. My current thinking is that the list of commands could perhaps be as simple as "setColorAndTexture" (which accepts texture a a filename or nil, and color as three numbers), "setShader" (which accepts the shader as a filename), "drawVertices" (accepts a mode (i.e. triangles, lines), vertex array, and optionally accepting texture coordinates), and perhaps a "setScreenShader" (for shader effects applied to the whole screen). This is just some very initial thinking though.
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: Lua help thread

Post by Hoeloe »

Rednaxela wrote: In any case, making the whole of the OpenGL API available is quite simply impractical, so perhaps if you send me a list of what you think a useful subset would be, we could discuss that. Because of what's involved in serializing with serializing the commands (mostly talking in terms of human effort to implement all that, but computational overhead applies too), it's vastly preferable to have a smaller number of more powerful commands (i.e. draw this vertex array in the specified mode), rather than a large number simple ones (i.e. glBegin, glVertex, glEnd). This is kind of the way OpenGL itself has evolved over time too really. My current thinking is that the list of commands could perhaps be as simple as "setColorAndTexture" (which accepts texture a a filename or nil, and color as three numbers), "setShader" (which accepts the shader as a filename), "drawVertices" (accepts a mode (i.e. triangles, lines), vertex array, and optionally accepting texture coordinates), and perhaps a "setScreenShader" (for shader effects applied to the whole screen). This is just some very initial thinking though.
Sure, I wasn't suggesting that implementing all of OpenGL would be a good idea, just that some of those things that may be more awkward could be done.

Those sound like reasonable options, though I would suggest two things:

First of all, the "setScreenShader" command should be "applyScreenShader", and should allow multiple shader passes for added flexibility.
Secondly, drawing textures to the screen should use the same syntax for OpenGL as without it (though for advanced features such as texture mapping a polygon, that can use it's own syntax, as there is no non-OpenGL equivalent), so that APIs can utilise OpenGL functions in the safe knowledge that a fallback will be in place. Failing that, a check for "is OpenGL enabled?" would be just as good, as that would allow the fallback option to be implemented as the API developer sees fit.
Image
Image
Image
Image
Image
Quman
Posts: 31
Joined: 11 years ago

Re: Lua help thread

Post by Quman »

According to the wiki, triggerEvent() "Triggers a event by the given name". I assumed that it referred to SMBX events, since the onEvent() event refers to SMBX events, but... well, Lua does have events of its own, so I figure I should ask for clarification. The thing I'm trying to do isn't working, and I'm trying to figure out why.

I'm trying to make it so after the player has completed a challenge once, the level will automatically remove the barrier on subsequent playthroughs so they don't have to complete the challenge again. Here's the relevant section

Code: Select all

local DDLcheckpoint = {}

function onLoad()
	if(DDLcheckpoint[1] == 1)
	then triggerEvent(ChallegeComplete)
	end
end

function onEvent(RemoveBarrier)
	if(DDLcheckpoint[1] ~= 1)
	then DDLcheckpoint[1] = 1
	end
end
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: Lua help thread

Post by Rednaxela »

Quman wrote:According to the wiki, triggerEvent() "Triggers a event by the given name". I assumed that it referred to SMBX events, since the onEvent() event refers to SMBX events, but... well, Lua does have events of its own, so I figure I should ask for clarification. The thing I'm trying to do isn't working, and I'm trying to figure out why.
Correct that triggerEvent and onEvent both refer to SMBX events.
Quman wrote:

Code: Select all

local DDLcheckpoint = {}

function onLoad()
	if(DDLcheckpoint[1] == 1)
	then triggerEvent(ChallegeComplete)
	end
end

function onEvent(RemoveBarrier)
	if(DDLcheckpoint[1] ~= 1)
	then DDLcheckpoint[1] = 1
	end
end
So...
  • triggerEvent accepts a string with the name of the event you want to trigger, and strings need to be quoted. Assuming that ChallengeComplete isn't defined in a variable above, what you really should write in that first section is:

    Code: Select all

    function onLoad()
    	if(DDLcheckpoint[1] == 1)
    	then triggerEvent("ChallegeComplete")
    	end
    end
  • Functions (such as onEvent) accept arguments and put them into variables named according to what you specify in the function definition. See here for a relevant tutorial. What you probably meant in the second part is

    Code: Select all

    function onEvent(eventName)
    	if (eventName == "RemoveBarrier") then
    		if(DDLcheckpoint[1] ~= 1)
    		then DDLcheckpoint[1] = 1
    		end
    	end
    end
Quman
Posts: 31
Joined: 11 years ago

Re: Lua help thread

Post by Quman »

Are variables saved between lives? If I change the first section to onLoop I can now get ChallengeComplete to trigger right after RemoveBarrier does, which wasn't happening before. But ChallengeComplete isn't triggering at the start of the level if I leave that section set to onLoad. I thought maybe the problem was that the game can't activate triggers until the level has been fully initiated, so tried the following, but that also isn't working.

Code: Select all

local DDLcheckpoint = {}
local myCounter

function onLoad()
	myCounter = 0
end

function onLoop()
	if myCounter == 0 then
		myCounter = 1
		if(DDLcheckpoint[1] == 1) then
			triggerEvent("ChallengeComplete")
		end
	end
end
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: Lua help thread

Post by Rednaxela »

Quman wrote:Are variables saved between lives?
No.

The Lua environment is unloaded whenever the level is unloaded, and is re-loaded any time the level is re-loaded. This means variables will not be saved across lives.

If you want anything to be saved across lives, use the "Data" class documented here.
Zygl
Posts: 616
Joined: 11 years ago

Re: Lua help thread

Post by Zygl »

Is there any way to make an NPC that normally dies from spinjumping (i.e. a paratroopa), uh, not do that? I'm pretty sure if all else fails I could just stick one that fits that description on top of it and make it invisible but that's kinda super kludgy and i'd rather not do it that way.
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: Lua help thread

Post by Hoeloe »

Zyglrox Odyssey wrote:Is there any way to make an NPC that normally dies from spinjumping (i.e. a paratroopa), uh, not do that? I'm pretty sure if all else fails I could just stick one that fits that description on top of it and make it invisible but that's kinda super kludgy and i'd rather not do it that way.
Yes. Colliders.lua should be able to do exactly what you need.

What you're looking for is this:

Code: Select all

for _,v in pairs(findnpcs(NPCID,player.section)) do
	local bounce,spin = colliders.bounce(player, v);
	if(bounce and spin) then
		colliders.bounceResponse(player);
	end
end
That should force you to bounce off the top of the enemy before you kill it with your spinjump. If you want to be extra sure, you could set the NPC to friendly and handle all the collisions with Lua, too.
Image
Image
Image
Image
Image
User avatar
WestonSmith
Bunny
Posts: 188
Joined: 11 years ago

Re: Lua help thread

Post by WestonSmith »

So I spent my morning trying to learn lua, and I have a few questions:
So I'm trying to get a proper SMB style timer to work. What I need to do:
(1) Create a variable that counts down to zero
(2) Get that timer to stop at zero, not continue counting
(3) Trigger a death layer once it reaches zero
(4) Cease counting down once the goal has been reached and/or a particular SMBX event is triggered

In theory, I understand how to do all this. In practice, I'm having some difficulties.

(1) I've set up the variable to count down to zero. It's set so that it counts down by (1 / 60). However, SMBX shows the decimal places when doing this. Is there a way to set how many decimal places appear when printing variables to SMBX?

(2) Getting the timer to stop at zero should be a simple matter of only running the Countdown function if the variable is above zero. Once it reaches zero, the countdown should cease. However, when I run code as such, the entire script stops working. Do I have to define an 'else' statement to do this?

(3) I don't understand how to make a layer appear via Lua. Is it run as a seperate function ala OnLoop, or is it run as an if statement within a function? The wiki doesn't seem to spend much time on how to work with layers.

(4) Can Lua stop an OnLoop function (the timer counting down) via an OnEvent function?
Any help is much appreciated. I'm not a real techy, and my last experience with programming was roughly a decade ago in an introductory highschool course. So apologies for the stupid questions.
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: Lua help thread

Post by Rednaxela »

WestonSmith wrote:(1) I've set up the variable to count down to zero. It's set so that it counts down by (1 / 60). However, SMBX shows the decimal places when doing this. Is there a way to set how many decimal places appear when printing variables to SMBX?
So, you're converting a floating point number to a string, and you don't want decimal places? Two ways come to mind: 1) Use the lua function "math.floor" or "math.ceil" to convert the number to an integer before you concatenate with your string, or 2) Use the "string.format" function which gives you good control over exactly how many decimal places (if any) among other handy things
Btw, you may want 1/65 rather than 1/60, because SMBX uses a strange 65 FPS.
WestonSmith wrote:(2) Getting the timer to stop at zero should be a simple matter of only running the Countdown function if the variable is above zero. Once it reaches zero, the countdown should cease. However, when I run code as such, the entire script stops working. Do I have to define an 'else' statement to do this?
It's hard to know why it stops working without being able to know exactly how you tried to accomplish it (i.e. what change in the code did you make precisely? Post the code?). Shouldn't require an 'else' generally.
WestonSmith wrote:(3) I don't understand how to make a layer appear via Lua. Is it run as a seperate function ala OnLoop, or is it run as an if statement within a function? The wiki doesn't seem to spend much time on how to work with layers.
As of the most recent official release (LunaDLL 6.1.1) there's no way to directly make a layer visible, instead you have to create a SMBX event in the level to control layer visibility and then use the triggerEvent function in Lua. In the next version of LunaDLL (0.7) there will be ways to directly control layer visibility though.
WestonSmith wrote:(4) Can Lua stop an OnLoop function (the timer counting down) via an OnEvent function?
Nothing can ever stop the onLoop function, but you can put an if statement in your onLoop so that the relevant code doesn't run after some variable gets set by your onEvent function.
Zygl
Posts: 616
Joined: 11 years ago

Re: Lua help thread

Post by Zygl »

Hoeloe wrote:Yes. Colliders.lua should be able to do exactly what you need.

What you're looking for is this:

Code: Select all

for _,v in pairs(findnpcs(NPCID,player.section)) do
	local bounce,spin = colliders.bounce(player, v);
	if(bounce and spin) then
		colliders.bounceResponse(player);
	end
end
That should force you to bounce off the top of the enemy before you kill it with your spinjump. If you want to be extra sure, you could set the NPC to friendly and handle all the collisions with Lua, too.
That seems to work like 99 times out of 100 but it occasionally just kinda... doesn't. And I'm not 100% sure why, it's likely about the thing's Y-speed (it's a Paratroopa set to go left and right with the "don't move" flag set) but it seemed like it was doing it whenever it felt like it. I take it this is what you meant by "if you want to be extra sure"?
WestonSmith wrote:So I'm trying to get a proper SMB style timer to work.
May be worth noting LunaDLL has a Timer command built into it, that may suit your needs a bit more simply if you don't need to do anything fancy with it or anything.
KingTwelveSixteen
? Title Title Title Title ?
Posts: 30
Joined: 14 years ago
Location: USA

Re: Lua help thread

Post by KingTwelveSixteen »

WestonSmith wrote:So I spent my morning trying to learn lua, and I have a few questions:


(3) Trigger a death layer once it reaches zero
Can't you just use lua to kill the player directly instead?
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: Lua help thread

Post by Hoeloe »

Zyglrox Odyssey wrote: That seems to work like 99 times out of 100 but it occasionally just kinda... doesn't. And I'm not 100% sure why, it's likely about the thing's Y-speed (it's a Paratroopa set to go left and right with the "don't move" flag set) but it seemed like it was doing it whenever it felt like it. I take it this is what you meant by "if you want to be extra sure"?
So this uses the colliders "speedCollide" option to do this. This works by calculating where the hitboxes will be on the next frame (taking into account their relative speeds), and performing the response a frame early. This isn't noticeable to the human eye, but means it will always occur before any existing collision logic. The problem occurs when, a frame after the collisions, the colliders are still touching, then you get this occurrence:

>Spinjump
>Speed-adjusted colliders touch
>Player bounces
>Colliders are still touching
>SMBX logic kicks in

By setting an NPC to friendly, you remove SMBX's interaction with the player entirely, and this allows you to use Lua colliders without the risk of this occurring.
WestonSmith wrote:So I'm trying to get a proper SMB style timer to work.
I would suggest checking out eventu.lua. It's a Lua extension that supports easy timers. To do what you want, you can use something like this:

Code: Select all

local eventu = loadAPI("eventu"); --Load the eventu library
local seconds = 60; --Number of seconds your timer should run for

--Runs when the level starts
function onLoad()
	timer = eventu.setTimer(seconds, function() player:kill() end); --Create a timer that kills the player when it finishes.
end

--Runs every frame
function onLoop()
	printText(tostring(math.floor(eventu.getTimer(timer))),0,0); --Draw the remaining time on the timer in the top left of the screen
end
That should create a 60 second timer, which kills the player when it ends.
Image
Image
Image
Image
Image
User avatar
WestonSmith
Bunny
Posts: 188
Joined: 11 years ago

Re: Lua help thread

Post by WestonSmith »

Hoeloe wrote:

Code: Select all

local eventu = loadAPI("eventu"); --Load the eventu library
local seconds = 60; --Number of seconds your timer should run for

--Runs when the level starts
function onLoad()
	timer = eventu.setTimer(seconds, function() player:kill() end); --Create a timer that kills the player when it finishes.
end

--Runs every frame
function onLoop()
	printText(tostring(math.floor(eventu.getTimer(timer))),0,0); --Draw the remaining time on the timer in the top left of the screen
end
That should create a 60 second timer, which kills the player when it ends.
Well, this certainly does create a death clock. My only problem now is getting it to stop via an event. I tried skimming the eventu code itself and found it terribly confusing, but it looks like there is a function built to pause the countdown. I'd assume I could somehow trigger this via an onEvent function to stop the clock? I originally intended to use an "if" condition / argument / whatever, but that seems like it would only work if the clock functioned via an onLoop event.

Sorry to pester on this (and thanks for the initial code - it functions perfectly!)
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: Lua help thread

Post by Hoeloe »

WestonSmith wrote: Well, this certainly does create a death clock. My only problem now is getting it to stop via an event. I tried skimming the eventu code itself and found it terribly confusing, but it looks like there is a function built to pause the countdown. I'd assume I could somehow trigger this via an onEvent function to stop the clock? I originally intended to use an "if" condition / argument / whatever, but that seems like it would only work if the clock functioned via an onLoop event.

Sorry to pester on this (and thanks for the initial code - it functions perfectly!)
The timer is running independently from any of the standard LunaLua events, but that doesn't mean you can't access it via any of them. In fact, the code I posted already accesses the timer in onLoop in order to draw the timer to the screen. If you want to pause it, you can just call:

Code: Select all

timer.pauseTimer()
whenever you like, and the timer will freeze. It doesn't matter whether it's called from onLoop or onEvent or anything else, as long as that line of code gets run when you want to pause the timer.

I do plan to add a stopTimer() function at some point, which will stop the timer in a way that can't be restarted (there are reasons for this), but for now, pauseTimer should do what you want.
Image
Image
Image
Image
Image
User avatar
WestonSmith
Bunny
Posts: 188
Joined: 11 years ago

Re: Lua help thread

Post by WestonSmith »

Alright, now I'm just feeling dumb.
local eventu = loadAPI("eventu"); --Load the eventu library
local seconds = 100; --Number of seconds your timer should run for
local stopper = false; --Check to see if level is completed

--Runs when the level starts
function onLoad()
timer = eventu.setTimer(seconds, function() player:kill() end); --Create a timer that kills the player when it finishes.
end

--Runs every frame
function onLoop()
printText(tostring(math.floor(eventu.getTimer(timer))),740,50); --Draw the remaining time on the timer in the top left of the screen
end


--Set value to true to stop timer at end of level
function onEvent(Flag1)
stopper = true;
end

function onLoop()
if (stopper == true) then
eventu.pauseTimer(); --I've also tried this with timer.pauseTimer() and with timer = ...
end
end
WIthout the stuff I add, it works great. With the stopper variable and the onEvent function, it works fine. But trying to call pauseTimer causes an error message and the timer disappears. I've tried running the same code in the onEvent section directly (no stopper variable, just calling pauseTImer) to no avail.

What am I missing? The eventU library suggests that there should be a variable set for pauseTImer, and certainly adding one makes the error disappear, but the timer still doesn't work.
S1eth
Posts: 291
Joined: 9 years ago

Re: Lua help thread

Post by S1eth »

onEvent works this way:

Code: Select all

function onEvent(eventName)
  if (eventName == "Flag1") then
  	stopper = true;
  end
end
You need to check the parameter that is given to onEvent. Currently, you set stopper to true if ANY event is called, even if the event is not named "Flag1".

And when you call eventu.pauseTimer, you have to tell it which timer it has to pause. You do that by giving it the timer as a parameter within parenthesis ().

Code: Select all

eventu.pauseTimer(timer);
A problem here is that you set your timer in onLoad with the name "timer", which makes it a global variable "timer". Do like this:

Code: Select all

local eventu = loadAPI("eventu"); --Load the eventu library
local seconds = 100; --Number of seconds your timer should run for
local stopper = false; --Check to see if level is completed
local deathTimer = nil;

-- and in onLoad
deathTimer = eventu.setTimer(seconds, function() player:kill() end); --Create a timer that kills the player when it finishes.

-- and when you pause it:
eventu.pauseTimer(deathTimer);

To make sure that stopper is actually assigned the value "TRUE", you could also add another printText to your onLoop:

Code: Select all

printText("stopper: "..tostring(stopper),3,0,90);
EDIT: And I totally forgot. You have 2 onLoop functions! You should only have 1. Put the code all into a single onLoop.
Image
User avatar
WestonSmith
Bunny
Posts: 188
Joined: 11 years ago

Re: Lua help thread

Post by WestonSmith »

Major thanks to both Hoeloe and S1eth. I've got the timer working perfectly and couldn't be gladder.

Cheers!
User avatar
snoruntpyro
cutest girl 2023
Posts: 884
Joined: 9 years ago
Pronouns: she/her
Contact:

Re: Lua help thread

Post by snoruntpyro »

I'm just learning Lua and I'm trying to make a controllable layer, and I'm trying to make it so you can only move it if you're actually in the same section as it. However, it won't move now, period.

What am I doing wrong?

Code: Select all

function onLoopSection2(asdf)
	if asdf == 1 then
		function onKeyDown(keycode)
			if (keycode == KEY_UP) then
				triggerEvent("Torpedo Tom Up")
				--Horizontal Speed is 1, Vertical Speed is -1
			end
			if (keycode == KEY_DOWN) then
				triggerEvent("Torpedo Tom Down")
				--Horizontal Speed is 1, Vertical Speed is 1
			end
		end
		function onKeyUp(keycode)
			if (keycode == KEY_UP) then
				triggerEvent("Torpedo Tom Stop")
				--Horizontal Speed is 1, Vertical Speed is 0
			end
			if (keycode == KEY_DOWN) then
				triggerEvent("Torpedo Tom Stop")
				--Horizontal Speed is 1, Vertical Speed is 0
			end
		end
	end
end
Image
Image
Image
Image
Image
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: Lua help thread

Post by Rednaxela »

Pyro wrote:What am I doing wrong?
You can't put your event handler functions inside another function, they simply won't get called that way. Keep your functions at the top level.
Zygl
Posts: 616
Joined: 11 years ago

Re: Lua help thread

Post by Zygl »

Hoeloe wrote:So this uses the colliders "speedCollide" option to do this. This works by calculating where the hitboxes will be on the next frame (taking into account their relative speeds), and performing the response a frame early. This isn't noticeable to the human eye, but means it will always occur before any existing collision logic. The problem occurs when, a frame after the collisions, the colliders are still touching, then you get this occurrence:

>Spinjump
>Speed-adjusted colliders touch
>Player bounces
>Colliders are still touching
>SMBX logic kicks in

By setting an NPC to friendly, you remove SMBX's interaction with the player entirely, and this allows you to use Lua colliders without the risk of this occurring.
Okay it doesn't kill the enemy anymore but now instead if I hold the spinjump button the player dies? Or gets hurt, at least.
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: Lua help thread

Post by Hoeloe »

Zyglrox Odyssey wrote:Okay it doesn't kill the enemy anymore but now instead if I hold the spinjump button the player dies? Or gets hurt, at least.
You should be using the regular "collides" function for damaging the player, and the "bounce" function for spinjumping. Otherwise, this is the same problem. What you can do it add a delay after a spinjump so that you have a few frames of invincibility to that enemy after a spinjump. I realise that's not exactly elegant, but most of SMBX isn't, either.
Image
Image
Image
Image
Image
Post Reply