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

How do I add a time to another time?

Started by _gjkf_, 27 October 2013 - 12:27 PM
_gjkf_ #1
Posted 27 October 2013 - 01:27 PM
Title: How do I add a time to another time?

Hello, I'm doing a game where randomly are "spawned" red pixels, you have to click them to get a point, you lose one if you don't click in the right spot. I want to leave a certain time to the player to click. I thought to get the current time and add for example 3 seconds. I thought to do something like this (is just an example)


local time = os.time()
time = textutils.formatTime(time,true)
print(time)
time = time +3

It doesn't work. Anybody had the same problem?

Thanks to everyone.
CCJJSax #2
Posted 28 October 2013 - 12:24 AM
What exactly isn't working? Do you get an error?

If you are running this in a loop, you are defining time twice in a row. When it print's time, it will be the os.time() and not time + 3.

Just quote this response with the problem and I, or someone else will get back to you.

Edit: actually I see the problem. You are adding 3 to a string. once you do the textutils, it seems that puts it into a string.. Try this



local time = os.time()
time = time +3
time = textutils.formatTime(time,true)
print(time)


yes all I did was move "time = time +3"
CCJJSax #3
Posted 28 October 2013 - 12:54 AM
also, let me add that the +3 adds to the ingame hour, not the second. For what you described the program, you probably are wanting the second to be +3. I'm pretty inexperienced with using os.time(). so this might be a bit inefficient, but it should work. It is pretty late here, so I'm also exhausted :P/>



local CCtime = os.time()
CCtime = textutils.formatTime(CCtime, true)
print("The real time is "..CCtime)
timelen = string.len(CCtime) -- this is needed for the length of characters in the time.

if timelen == 4 then -- separates hour, the colon, and the seconds.
  timeHour = string.sub(CCtime, 1,1)
  timeSec = string.sub(CCtime, 3,4)
elseif timelen == 5 then
  timeHour = string.sub(CCtime, 1,2)
  timeSec = tonumber(string.sub(CCtime, 4,5))
end

print(timeSec) -- prints the real ingame time to the console
timeSec = timeSec + 3 -- adds 3 seconds
print(timeSec)  -- prints ingame seconds + 3

theoriginalbit #4
Posted 28 October 2013 - 01:07 AM
You'll be better off to use os.clock instead of os.time, when adding 3 to os.time you're adding 3 Minecraft hours, whereas os.clock will tell you how long the computer (not your program) has been running.

I can't seem to get this forum to indent properly :(/> sorry.
Use two space indenting, the forum software works best with double space tabs.
CCJJSax #5
Posted 28 October 2013 - 01:21 AM
You'll be better off to use os.clock instead of os.time, when adding 3 to os.time you're adding 3 Minecraft hours, whereas os.clock will tell you how long the computer (not your program) has been running.

I can't seem to get this forum to indent properly :(/> sorry.
Use two space indenting, the forum software works best with double space tabs.

os.clock definitely would be easier than my way.

also, the two spacing thing works. I'll format that right now.
Bomb Bloke #6
Posted 28 October 2013 - 07:17 AM
It's worth pointing out os.startTimer(). Call it to have a timer ID returned, and for an event that fires after the specified amount of seconds have passed. That event itself also returns the timer ID, hence allowing you to keep track of more then one such timer at a time.

local myTimer = os.startTimer(5)
local myEvent

print("You've five seconds to click!")

while true do
  myEvent = {os.pullEvent()}

  if myEvent[1] == "timer" and myEvent[2] == myTimer then
    print("Your five seconds are up!")
    break
  elseif myEvent[1] == "mouse_click" then
    print("You clicked at "..myEvent[3].." by "..myEvent[4]..". Timer reset!")
    myTimer = os.startTimer(5)
  end
end

I assume you'll already be pulling events to determine if your "pixel"'s been clicked, so all you'd need to do is check the type of event being pulled and react accordingly.
_gjkf_ #7
Posted 28 October 2013 - 09:50 AM
Thanks to everyone. I'll try now with the os.startTimer(). I can then tell you if that works. Really thank you for your time. I'll paste my code for everyone who wants to play with it. Thanks again. :)/> :)/> :)/>
theoriginalbit #8
Posted 28 October 2013 - 09:56 AM
Also, do note that if you're not wanting to update any timers or anything, just want to know when it is a particular time, you can also use os.setAlarm instead of os.startTimer, there is no major difference, it could be debated however that os.setAlarm could be more accurate if you just needed to know when it was, for example noon in the Minecraft world.
_gjkf_ #9
Posted 28 October 2013 - 10:15 AM

local pt = 0
local t = 0
local myTimer = os.startTimer(3)
local myEvent

function randomSpawn()
  local xrdn = math.random(51)
  local yrdn = math.random(2,19)
  paintutils.drawPixel(xrdn,yrdn,colors.red)
  while t ~= 1 do
	checkClick(xrdn,yrdn)
	t = t+1
  end
end

function checkClick(xrdn1,yrdn1)
  event,arg,x,y = os.pullEvent("mouse_click")
  if xrdn1 == x and yrdn1 == y then
	paintutils.drawPixel(xrdn1,yrdn1,colors.yellow)
	sleep(0.1)
	paintutils.drawPixel(xrdn1,yrdn1,colors.red)
	pt = pt+1
	term.clear()
	main()
	term.setCursorPos(45,1)
	term.write(pt)
	randomSpawn()
   else
	term.setBackgroundColor(colors.black)
	term.clear()
	main()
	pt = pt-1
	term.setCursorPos(45,1)
	term.write(pt)
	randomSpawn()
   end
end

function main()
  term.setBackgroundColor(colors.black)
  term.clear()
  term.setCursorPos(38,1)
  term.write("Points:")
  term.setCursorPos(45,1)
  term.write(pt)
  term.setCursorPos(1,1)
end

function point()
  term.setCursorPos(45,1)
  pt = pt-1
  term.write(pt)
end

while true do
  myEvent = {os.pullEvent()}
  if myEvent[1] == "timer" and myEvent[2] == myTimer then
	point()
	myTimer = os.startTimer(3)
	randomSpawn()
  elseif myEvent[1] == "mouse_click" then
	myTimer = os.startTimer(3)
	randomSpawn()
  end
end

main()
randomSpawn()

this is my code but when I run it doesn't work. It is the same as this:



local pt = 0
local t = 0

function randomSpawn()
  local xrdn = math.random(51)
  local yrdn = math.random(2,19)
  paintutils.drawPixel(xrdn,yrdn,colors.red)
  while t ~= 1 do
	checkClick(xrdn,yrdn)
	t = t+1
  end
end

function checkClick(xrdn1,yrdn1)
  event,arg,x,y = os.pullEvent("mouse_click")
  if xrdn1 == x and yrdn1 == y then
	paintutils.drawPixel(xrdn1,yrdn1,colors.yellow)
	sleep(0.1)
	paintutils.drawPixel(xrdn1,yrdn1,colors.red)
	pt = pt+1
	term.clear()
	main()
	term.setCursorPos(45,1)
	term.write(pt)
	randomSpawn()
   else
	term.setBackgroundColor(colors.black)
	term.clear()
	main()
	pt = pt-1
	term.setCursorPos(45,1)
	term.write(pt)
	randomSpawn()
   end
end

function main()
  term.setBackgroundColor(colors.black)
  term.clear()
  term.setCursorPos(38,1)
  term.write("Points:")
  term.setCursorPos(45,1)
  term.write(pt)
  term.setCursorPos(1,1)
end

main()
randomSpawn()
theoriginalbit #10
Posted 28 October 2013 - 10:36 AM
this is my code but when I run it doesn't work. It is the same as this:
Define doesn't work. Is there an error? does it just not do as you expected?
_gjkf_ #11
Posted 28 October 2013 - 10:42 AM
The timer doesn't work. I don't get an error but is the same as the other. I can wait for ever before I click.
Bomb Bloke #12
Posted 28 October 2013 - 05:50 PM
Well, let's see…

If the first timer expires or you click, then randomSpawn() gets called.

randomSpawn() then calls checkClick() (it shouldn't). checkClick() then tries to pull a second event (it shouldn't), and regardless as to where that click is, calls randomSpawn() again (it really shouldn't). That then calls checkClick() again, and so on.

Hence you never again check to see if your timers have expired and the program eventually crashes after a hundred clicks or so due to a stack overflow (when a function calls another function, the first function doesn't end until the second one does - if they just keep calling each other recursively like that, then eventually the build-up of running functions causes a crash).

So:
  • randomSpawn() should spawn a dot, and do nothing else. Instead, have the while loop at the bottom of the script call checkClick() directly before calling randomSpawn().
  • xrdn and yrdn would likely be best defined as local to the whole script, not just to the randomSpawn() function. That, or randomSpawn() should return them (though I'd think the former to be easiest).
  • checkClick() should not try to pull another event. Instead, pass the click co-ordinates that the while loop at the bottom of the script already collected to it.
  • Likewise, checkClick() should only check clicks. It shouldn't try to call randomSpawn() again.
It may help your understanding to stress that doing this:

event,button,x,y = os.pullEvent("mouse_click")

Is much the same as doing this:

myEvent = {os.pullEvent("mouse_click")}

Only difference being, the second method takes the event, button and x/y co-ords and dumps them into a table for you. myEvent[1] gets the event name, myEvent[2] gets the button, myEvent[3] gets the x co-ord and you can probably guess where the y co-ord goes.

You may only pull a given event once - it's then removed from the event queue, and can't be pulled a second time. If you don't specify an event type when pulling then any event-type may be returned. If you do specify an event type, then the command pulls as many events as it takes until it gets the sort you asked for - throwing away any it finds that don't match.
theoriginalbit #13
Posted 28 October 2013 - 11:30 PM
Also to extend on what Bomb Bloke said, you cannot use sleep when making event sensitive programs as the sleep function, along with a few others, eats events which you don't want.
_gjkf_ #14
Posted 29 October 2013 - 08:04 AM
thanks, but I don't know how to write that program. I don't have much programming knowledge. My father does. So I think I take what you told me and I'll try to create a new program. Then I'll put it here and ask you if it is good or not. Sorry if I use your time for my problems. :(/> I think I'lll put the code in 2 or 3 days. Thanks again and sorry for the English. It isn't my first language. It's Italian. :)/>
Bomb Bloke #15
Posted 29 October 2013 - 06:46 PM
Aw, shame to throw it away - can't resist giving you a proper example as to how it could be done. :)/>

Spoiler
local pt = 0
local myTimer, myEvent, xrdn, yrdn
local scrx,scry = term.getSize()   -- Better to get the proper screen size then to assume.

local function redraw()
  -- Clear display, draw score:
  term.setBackgroundColor(colors.black)
  term.clear()
  term.setCursorPos(scrx-13,1)
  term.write("Points: "..tostring(pt))  -- Use of "tostring" gets rid of that ".0" business.

  -- Draw next "pixel":
  xrdn = math.random(scrx)
  yrdn = math.random(2,scry)
  paintutils.drawPixel(xrdn,yrdn,colors.red)

  -- Ready next timer:
  myTimer = os.startTimer(3)
end

local function checkClick(clickx,clicky)
  if clickx == xrdn and clicky == yrdn then
    paintutils.drawPixel(xrdn,yrdn,colors.yellow)
    sleep(0.1)
    pt = pt + 1
  else
    pt = pt - 1
  end
end

-- Declarations complete, program "starts" here.

redraw()

while true do
  -- Wait for an event of any type:
  myEvent = {os.pullEvent()}

  -- Then check for events we want:
  if myEvent[1] == "timer" and myEvent[2] == myTimer then
    pt = pt - 1
    redraw()
  elseif myEvent[1] == "mouse_click" then
    checkClick(myEvent[3],myEvent[4])
    redraw()
  end
end
_gjkf_ #16
Posted 30 October 2013 - 08:29 AM
Thanks a lot. Really!!!! Really cool!!! :D/> :D/> Another question: can I copy a part of code and paste the same in another spot of the same code? Can I copy an entire code from e.g. this forum and paste it into my computer? Thanks again and sorry for my bad language. I'm only a 14 years old student.
Bomb Bloke #17
Posted 30 October 2013 - 05:41 PM
In terms of permission, you may do whatever you like with what I post on these forums. I would also consider anyone else's code fair game unless they specifically state otherwise. If you wish to share code you've made out of other people's code, ask their permission if you're not sure whether they'll mind, and give credit where due.

Whether mixing scripts together will work or not depends on what the scripts do (in particular, function/variable names may clash). If you're going to copy code either copy whole scripts unmodified, or copy only very small chunks so you can understand how they work.
theoriginalbit #18
Posted 30 October 2013 - 11:15 PM
As for any code that people have supplied you in Ask a Pro, it is actually your code, they may have made it, but they made it for you to help you out in your problems. As such you can do with the code as you wish without need of giving credit, if the person demands credit for the help they've given then they really shouldn't be helping people, we volunteer our time free of charge to help people, not to help ourselves. All this being said, if someone has really helped you out, the nice thing to do would be to at least put a note on your program's thread thanking them for all the help that they gave.
_gjkf_ #19
Posted 31 October 2013 - 07:58 AM
Ok, thanks for the info. I'll put a credit over the code so every time I edit it I know where is it from. Thanks for all.