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.
- CLS:CLEAR
- DIM N(20)
- DIM M(20)
- DIM C(20)
- DIM L(20)
- DIM A(20)
- DIM T$(20)
- @TMRDATA
- DATA 0,99,"MAXTIMER"
- DATA 1,1,"QUICK TIMER"
- DATA 2,2,"SLOW TIMER"
- DATA 3,3,"EGG TIMER"
- DATA 4,4,"SNOOZER"
- DATA -1,-1,"DONE"
- @INIT
- CLS
- LOCATE 0,22:?"A START ","B PAUSE ","X RESET"
- P=1:RESTORE @TMRDATA
- FOR I=0 TO 19
- A[I]=FALSE
- IF P THEN READ N[I]:'TIMER NUMBER
- IF P THEN READ M[I]:M[I]=M[I]*3600:'TIMER MINUTES
- IF P THEN READ T$[I]:'TIMER LABEL
- IF N[I]<0 THEN P=0:TC=I-1
- NEXT
- CS=0:'CURSOR
- 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.
- @LOOP
- 'PROCESS INPUT
- VSYNC 1:B=BTRIG()
- IF (B AND 1) THEN CS=CS-1:IF CS<0 THEN CS=TC
- IF (B AND 2) THEN CS=CS+1:IF CS>TC THEN CS=0
- IF (B AND 16) THEN A[CS]=TRUE
- IF (B AND 32) THEN A[CS]=FALSE
- IF (B AND 64) THEN GOSUB @TRESET
- 'PROCESS THREAD
- TH=TH+1:IF TH>TC THEN TH=0
- IF A[TH]==FALSE GOTO @SHOW
- IF MAINCNTL>L[TH] THEN C[TH]=C[TH]+(MAINCNTL-L[TH])
- IF C[TH]>M[TH] THEN GOSUB @ALARM
- @SHOW
- IF C[TH]==M[TH] THEN COLOR 13 ELSE COLOR 0
- TM=FLOOR((M[TH]-C[TH])/3600)
- TS=FLOOR(((M[TH]-C[TH])%3600)/60)
- TM$=RIGHT$(("00"+STR$(TM)),2)
- TS$=RIGHT$(("00"+STR$(TS)),2)
- LOCATE 0,TH:?" "*31
- IF CS==TH THEN LOCATE 0,TH:?">";
- LOCATE 3,TH:?N[TH];
- LOCATE 6,TH:TM$;":";TS$,T$[I]
- L[TH]=MAINCNTL
- GOTO @LOOP
- @TRESET
- A[CS]=FALSE
- C[CS]=0
- BGMSTOP
- RETURN
- @ALARM
- BGMPLAY 6
- A[TH]=FALSE
- C[TH]=M[TH]
- RETURN
No comments:
Post a Comment