This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
majesty2450's profile picture

help with os.pullEvent and Blockscape

Started by majesty2450, 18 April 2013 - 07:29 AM
majesty2450 #1
Posted 18 April 2013 - 09:29 AM
I am currently writing an api that I will be using for an os I will make, but I think I have stumbled apon a bug with the os.pullEvent function. I am wondering if that function naturally gets delayed the more it collects events. This may be a bug with my code, but I cannot figure it out. Please help, any help you give me I thank you for in advance.

My code is rather long and comment barren at the moment so I will not give it out unless you want it. The code you see on my site is not up to date with the code I am working on, so you will probably not see the bug on that code.
Lyqyd #2
Posted 19 April 2013 - 04:44 AM
Split into new topic.

We can't see what you've done wrong without the current code. You have almost certainly not found a bug with os.pullEvent, though.
majesty2450 #3
Posted 19 April 2013 - 05:20 AM
Heres the code in full, I uploaded it. In order to see the bug run the file in the examples folder in minecraft. Press 'p' over and over again and you will see it will start to delay.

http://www.wackelin.com/downloads/blockscape_1_2.zip
Bubba #4
Posted 19 April 2013 - 10:55 AM
None of your code works due to capitalization errors (You have this: os.loadAPI('disk/blockscape/blockstandardlibrary/class') when it should be this: os.loadAPI("disk/BlockScape/BlockStandardLibrary/class"))

It's not a huge coding error, but you load a lot of apis and I doubt many people feel like going through and fixing them all just to test a bug.

As to the there being lag in os.pullEvent, I personally have not ever experienced an issue with it despite sending constant timer events every 0.05 seconds (the minimum amount).
majesty2450 #5
Posted 19 April 2013 - 11:32 AM
- The files do not need fixing for me. I can run them with a new computer(no api's loaded) and they will work, I am not going to fix them if they work. I don't know about non-windows platforms though and if that matters then I will fix them.

- If you do not touch any code and just run the file 'moving_sprites', then the bug will produce after several "pauses"(pressing 'p' and waiting for the pause to show and then pressing 'p' to close the pause). Also if you put the os.startTimer(0.05) in then the program will noticeable lag when getting key events, worse than the original. (Keep in mind I am not mentioning lag in the sprite animation, just responding to events).
Smiley43210 #6
Posted 19 April 2013 - 11:35 AM
Im pretty sure on systems like Linux (or is it Unix?), the file names must match the case of the files in the filesystem.
Bubba #7
Posted 19 April 2013 - 11:45 AM
- The files do not need fixing for me. I can run them with a new computer(no api's loaded) and they will work, I am not going to fix them if they work. I don't know about non-windows platforms though and if that matters then I will fix them.

- If you do not touch any code and just run the file 'moving_sprites', then the bug will produce after several "pauses"(pressing 'p' and waiting for the pause to show and then pressing 'p' to close the pause). Also if you put the os.startTimer(0.05) in then the program will noticeable lag when getting key events, worse than the original. (Keep in mind I am not mentioning lag in the sprite animation, just responding to events).
-snip-

It looks like os.loadAPI automatically handles case errors (but keep in mind that the rest of Lua is case sensitive so you will usually have to open files with the correct case!). So I'm not sure why part of your code worked after me correcting the case, but it did. Anyway, I still have not successfully run your program so I may need to do a bit of debugging.

And I still have never experienced your error, and yes I have made something similar to this. The only thing I can think of that might be affecting this "lag" would be if your draw function takes an inordinate amount of time to execute. Even then, it should consume the key events as opposed to lagging them.
Bubba #8
Posted 19 April 2013 - 12:04 PM
Okay, I managed to get your program to run, and indeed it does seem to have lag issues. You've got a lot of code here, but my guess is that your issue lies in this function:

function KeyEvent:getEvent()
	self.keycode = nil
	os.startTimer(0.001)
	event, p1 = os.pullEventRaw()
	if (event == "key") then
		self.keycode = p1
	end
end
First off the minimum for a timer is 0.05. It will still queue timer events fine, but only every 0.05 seconds which is the length of a tick.

Second, your timer event is going to be queued continuously, even if it's not being consumed (e.g. another event such as a key is pressed before the timer goes off; the old timer is still running and when the function is called again, you'll have two timers being queued). Due to this, you'll develop a backlog of timer events which might cause lag. I don't have time right now to investigate any more, but that is just a first glance reaction that I'm having.
Bubba #9
Posted 19 April 2013 - 01:31 PM
I've changed a few things in your code and managed to get it working without lag. I don't really know why you have such a complicated system set up: it's unnecessary. I can understand the temptation to mimic classes and use that to simplify certain things, but events and key input is really not something that needs it.

In your Moving_Sprites program, I changed the while loop to this:

while(running == true) do
	-- Get input
	local e = {os.pullEvent()}
	if e[1] == "key" then
		if e[2] == keys.p then
			s3.visible = false --I have no idea what s3.visible does, but I left it in anyway
			os.pullEvent("key")
			timer = os.startTimer(0.05)
		end
	elseif e[1] == "timer" and e[2] == timer then
		-- Move your sprites
		if (s1.y > device2d.backbuffer.height - s1.image.height) then
			s1state = 1
		elseif (s1.y == 1) then
			s1state = 0
		end
		if (s1state == 0) then
			s1.y = s1.y + 1
		else
			s1.y = s1.y - 1
		end
		if (s2.x > device2d.backbuffer.width - s2.image.width) then
			s2state = 1
		elseif (s2.x == 1) then
			s2state = 0
		end
		if (s2state == 0) then
			s2.x = s2.x + 1
		else
			s2.x = s2.x - 1
		end
		timer = os.startTimer(0.05)
	end
	-- First clear the backbuffer to the fill then draw.
	device2d:clearBackbuffer()
	
	ss:draw(device2d.backbuffer)

	-- Swap the frontbuffer with the backbuffer.
	device2d:swapBuffer()
	device2d:render()

end

It's not as "pretty" as your code, but it's functional. I don't know the inner details of your rendering system and I don't really feel like trying to mess with them either, but this does the job. If you feel it absolutely necessary to prettify things with an api, do something more like this:

local timer = false
function eventListen(opt)
  timer = os.startTimer(0.05)
  while true do
	local e = {os.pullEvent()}
	if e[1] == "timer" and e[2] == timer then
	  return
	elseif e[1] == "key" then
	   if opt[e[2]] then
		 opt[e[2]]()
		 return
	   end
	end
  end
end

Then use it like so:

--Your main game loop
while true do
  input.eventListen({
  [keys.p] = function()
	os.pullEvent("key") --My version of pausing the program: perhaps not how you want to go about it, but it's functional
  end;
  [keys.enter] = function()
	running = false
  end;
  })
  --Handle GUI updates here.
end
majesty2450 #10
Posted 19 April 2013 - 01:59 PM
Wow! Thank you a lot, you fixed it. By the way if you were wonder what s3.visible = false means, it just handles whether the "pause" message is seen or not. I'll make sure to say you helped me in the read-me.
Bubba #11
Posted 19 April 2013 - 02:10 PM
Glad it works for you :)/>

Just out of curiosity, have you programmed in Java or a similar language prior to Lua? Most people wouldn't think to use classes for a scripting language unless they have experience with them.
majesty2450 #12
Posted 19 April 2013 - 02:51 PM
C++, it was the first one I tried and have stuck with it. I can say, once you get used to that language its hard to get away.
Bubba #13
Posted 19 April 2013 - 03:16 PM
Ah, yes I can understand that. In fact, C++ was my first language as well, although I never really got very far. I was started a bit too young to understand what I was doing and ended up getting bored with it. Ended up moving on to scripting languages, which were easier to understand, and then going back towards intermediate-level languages such as Java, which I find far more enjoyable than I remember C++ being. Probably just the fact that I'm able to understand it helps though.
majesty2450 #14
Posted 19 April 2013 - 04:07 PM
Ya, I got bored of it when I first started too. I guess the only reason I didn't change languages was because I was learning from a text book and that text book really made things easier. When advanced topics that made the language different from others came up, I found the text book made it easy to understand and reading real paper is easier for me than on a screen.