Lua question, global variables

A key part of my game involves moving two characters at the same time. The first version of the game is here http://www.stencyl.com/game/play/35569 and you should definitely try it.

In that version, movement was controlled by one script that took input from the arrow keys and then changed a global variable, called “direction”, which could either be up, down, left, right, or 0. Then, each character had their own script, based on the “direction” variable.

In lua/defold, I’m having some trouble with global variables. So far, I have this:

function init(self)
msg.post(".", "acquire_input_focus")
global_speed = 0.5 -- LOWER NUMBERS ARE FASTER
global_tilesize = 200
global_up=0
global_down=0
global_left=0
global_right=0
global_imoving=false
global_amoving=false
end

And it all works fine for one of the characters. The other character, which basically has the same script but without defining the variables at the start, gives this message:

ERROR:SCRIPT: main/Alexmover.script:16: attempt to perform arithmetic on global 'tilesize' (a nil value)
stack traceback:
	main/Alexmover.script:16: in function <main/Alexmover.script:12>

If anyone could kindly help me out with the correct integration of global variables, or tell me if there’s anything obvious that I’m missing, I’d be grateful. I have look at a few lua and defold manuals online and I can’t find anything useful.

(both scripts are contained within seperate game objects)

I have solved this now. It was down to human error. MAN I WISH I WAS A ROBOT

Okay…

The good news is that it wasn’t human error, it’s about the speed of input confusing things. If i press the keys one key at a time, it goes fine, but the same key presses slightly faster confuses thing!

I understand that it’s pretty difficult to help with that kind of thing via internet, so i’m going to try and merge both scripts into one. That should keep everything nice and synchronised… right???

I can’t believe i managed to do this so quickly, but in just three hours i managed to rewrite all my code into a single script that gets the input and moves both characters and deals with collisions only using triggers!!

I even had to start tabbing my code at the end like a real pro.

i’ve never done any coding before (except with blocks in stencyl) and I’m really proud of what I’ve achieved with Lua in just 4 days (started on sunday).

here’s my masterpiece:

function init(self)
-- world stuff
global_speed = 0.5 -- LOWER NUMBER IS ACTUALLY FASTER HERE
global_tilesize = 200

--What keys are being pressed
global_up=0
global_down=0
global_left=0
global_right=0

--Are they moving
moving=false


-- get input focus
msg.post(".", "acquire_input_focus")

end



--This code recieves the message that an animation has finished
local function done(self, url, property)
moving=false
end







--THIS CODE TAKES THE INPUT 
function on_input(self, action_id, action)
if action_id == hash("up") and action.pressed then
global_up =1
print("input recieved")
elseif action_id == hash("up") and action.released then
global_up =0
end
if action_id == hash("down") and action.pressed then
global_down =1
elseif action_id == hash("down") and action.released then
global_down =0
end
if action_id == hash("left") and action.pressed then
global_left =1
elseif action_id == hash("left") and action.released then
global_left =0
end
if action_id == hash("right") and action.pressed then
global_right =1
elseif action_id == hash("right") and action.released then
global_right =0
end
if action_id == hash("enter") and action.pressed then

end
end


function update(self, dt)
apos = go.get_position("alex")
ipos = go.get_position("isabel")
inputstring = (global_up..global_down..global_left..global_right)
	if ipos.x%global_tilesize + ipos.y%global_tilesize==0 then
	ialigned=true
end
	if apos.x%global_tilesize + apos.y%global_tilesize==0 then
	aaligned=true

end


--THIS CODE CREATES A STRING BASED ON THE INPUT AND TURNS IT INTO ONE "direction" VARIABLE (U,D,L,R or 0)
--IT ALSO DOESN'T ALLOW YOU TO CHANGE DIRECTION OR STOP UNLESS ALIGNED TO THE GRID
if inputstring == "1000" then
direction = "u"
auptarget= apos.y + global_tilesize 
iuptarget= ipos.y + global_tilesize 
elseif inputstring == "0100"  then
direction = "d"
adowntarget= apos.y - global_tilesize  
idowntarget= ipos.y - global_tilesize  
elseif inputstring == "0010" then
direction = "l"
alefttarget= apos.x - global_tilesize  
ilefttarget= ipos.x - global_tilesize  
elseif inputstring == "0001" then
direction = "r"
arighttarget= apos.x + global_tilesize 
irighttarget= ipos.x + global_tilesize 
elseif inputstring == "0000" then
direction = "0"
end

print("megatsunami")
print(moving)
print(ialigned)
print(aaligned)
print(direction)
--THIS CODE TURNS THE "direction" variable into movement (WITH ANIMATION IN UP SECTION)
if not moving and ialigned and aaligned then
	if direction == "u" then
		if not global_atouchingdown then
			go.animate("alex", "position.y", go.PLAYBACK_ONCE_FORWARD, auptarget, go.EASING_LINEAR, global_speed, 0, done)
			moving=true
			print("alex moving up")
			end
				if not global_itouchingdown then
				go.animate("isabel", "position.y", go.PLAYBACK_ONCE_FORWARD, iuptarget, go.EASING_LINEAR, global_speed, 0, done)
				moving=true
				print("isabel moving up")
		end
	end
	if direction == "d" then
		if not global_atouchingup then
			go.animate("alex", "position.y", go.PLAYBACK_ONCE_FORWARD, adowntarget, go.EASING_LINEAR, global_speed, 0, done)
			moving=true
			print("alex moving down")
			end
				if not global_itouchingup then
				go.animate("isabel", "position.y", go.PLAYBACK_ONCE_FORWARD, idowntarget, go.EASING_LINEAR, global_speed, 0, done)
				moving=true
				print("isabel moving down")
				end
		end
	
	if direction == "l" then
		if not global_atouchingright then
			go.animate("alex", "position.x", go.PLAYBACK_ONCE_FORWARD, alefttarget, go.EASING_LINEAR, global_speed, 0, done)
			moving=true
			print("alex moving left")
				end
				if not global_itouchingright then
				go.animate("isabel", "position.x", go.PLAYBACK_ONCE_FORWARD, ilefttarget, go.EASING_LINEAR, global_speed, 0, done)
				moving=true
				print("isabel moving left")
				end
	end
	if direction == "r" then
 		if not global_atouchingleft then
			go.animate("alex", "position.x", go.PLAYBACK_ONCE_FORWARD, arighttarget, go.EASING_LINEAR, global_speed, 0, done)
			moving=true
			print("alex moving right")
				end
				if not global_itouchingleft then
				go.animate("isabel", "position.x", go.PLAYBACK_ONCE_FORWARD, irighttarget, go.EASING_LINEAR, global_speed, 0, done)
				moving=true
				print("isabel moving right")
				end
		
	end
end

end --ends updates self 
4 Likes

Nice game! Some thoughts:

In general global variables are frowned upon, since it can become hard to follow how and from where global values are modified. There is also the risk that two or more scripts happen to modify the same global variable, resulting in very strange behaviour.

I would have one main script that receives input and does a msg.post with this input (action_id and action) to the two player characters. The player script receives the input in on_message, moves the game object, takes care of collisions and posts back to the main script if the donut is reached or the game object has fallen off the game board.

In the end I used one global variable, which is only modified in the one script (the “brain”). The individual character scripts depend on it, but cannot change it. I wonder if that’s better or worse than using messages.

I would almost always say that a global variable is worse, but it really depends. In your case I would prefer to solve it using message passing, OR I’d create a Lua module that holds the shared state and let the two players require that Lua module and read the state from the module instead of the global table.

@britzl, some time ago you wrote a list of when it was appropriate to use local variables, global variables, self.properties, and messaging. I can’t remember where that list was posted on the forum. If you could re-post it (or link me to something similiar), I’d be curious to read it.

Here you go: Simple Lua question? Maybe?

1 Like

…wow. Seeing that this post was from 2 months ago, I just realised how quickly I was able to build the game. That’s crazy. I am a genius!!!

1 Like