Friday, November 1, 2013

Petit Computer Journal #23


6. Loop with Player input + multi-thread


This time, we're going to do something that is common in complex games: multi-threading.

Multi-threading is a rather sophisticated and complex way to have multiple process going on at the same time. It is also extremely difficult to get right, especially if different processes depends on other processes. What I'm going to do is to simplify the problem, so that there is no dependency to the process.

We're going to set up and do multiple timers. Except, we're not going to do it the simple way using sprites. We're going to do it the hard way using internal timers: MAINCNTL.

MAINCNTL is the counting of frames since the program launched. Since there is a limit in the numerical accuracy, it is only able to count up to 145 minutes at a time. After that, it rolls over. So, our program must be able to handle that scenario.

The standard way to handle it, is to check MAINCNTH. However, in order to simplify the program, I'm not going to do that. What I'm going to do, is to store the MAINCNTL value for each thread, and compare it to the current MAINCNTL value. Then increase the timer for the difference. Surely, that method will lose a few frames over time, but I'm not worried. When the timer has minute resolution, a few frames missing isn't going to be a big deal.



  1. CLS:CLEAR
  2. DIM N(20)
  3. DIM M(20)
  4. DIM C(20)
  5. DIM L(20)
  6. DIM A(20)
  7. DIM T$(20)


  8. @TMRDATA
  9. DATA 0,99,"MAXTIMER"
  10. DATA 1,1,"QUICK TIMER"
  11. DATA 2,2,"SLOW TIMER"
  12. DATA 3,3,"EGG TIMER"
  13. DATA 4,4,"SNOOZER"
  14. DATA -1,-1,"DONE"

  15. @INIT
  16. CLS
  17. LOCATE 0,22:?"A START  ","B PAUSE  ","X RESET"
  18. P=1:RESTORE @TMRDATA
  19. FOR I=0 TO 19
  20. A[I]=FALSE
  21. IF P THEN READ N[I]:'TIMER NUMBER
  22. IF P THEN READ M[I]:M[I]=M[I]*3600:'TIMER MINUTES
  23. IF P THEN READ T$[I]:'TIMER LABEL
  24. IF N[I]<0 THEN P=0:TC=I-1
  25. NEXT
  26. CS=0:'CURSOR
  27. TH=0:'THREAD


Timers will have these operations on them: (A)START, (B)PAUSE, (X)RESET. It will have these data on them: (N)Timer Number,(M)Max Tick,(C)Current Tick,(L)Last MAINCNTL,(A)Active Status,(T$)Timer Label. We will also have something to process (TC)Timer Count up to 20.



  1. @LOOP
  2. 'PROCESS INPUT
  3. VSYNC 1:B=BTRIG()
  4. IF (B AND 1) THEN CS=CS-1:IF CS<0 THEN CS=TC
  5. IF (B AND 2) THEN CS=CS+1:IF CS>TC THEN CS=0
  6. IF (B AND 16) THEN A[CS]=TRUE
  7. IF (B AND 32) THEN A[CS]=FALSE
  8. IF (B AND 64) THEN GOSUB @TRESET

  9. 'PROCESS THREAD
  10. TH=TH+1:IF TH>TC THEN TH=0
  11. IF A[TH]==FALSE GOTO @SHOW
  12. IF MAINCNTL>L[TH] THEN C[TH]=C[TH]+(MAINCNTL-L[TH])
  13. IF C[TH]>M[TH] THEN GOSUB @ALARM

  14. @SHOW
  15. IF C[TH]==M[TH] THEN COLOR 13 ELSE COLOR 0
  16. TM=FLOOR((M[TH]-C[TH])/3600)
  17. TS=FLOOR(((M[TH]-C[TH])%3600)/60)
  18. TM$=RIGHT$(("00"+STR$(TM)),2)
  19. TS$=RIGHT$(("00"+STR$(TS)),2)
  20. LOCATE 0,TH:?" "*31
  21. IF CS==TH THEN LOCATE 0,TH:?">";
  22. LOCATE 3,TH:?N[TH];
  23. LOCATE 6,TH:TM$;":";TS$,T$[I]
  24. L[TH]=MAINCNTL
  25. GOTO @LOOP

  26. @TRESET
  27. A[CS]=FALSE
  28. C[CS]=0
  29. BGMSTOP
  30. RETURN

  31. @ALARM
  32. BGMPLAY 6
  33. A[TH]=FALSE
  34. C[TH]=M[TH]
  35. RETURN


No comments:

Post a Comment