Posts: 303
Threads: 10
Joined: Apr 2022
Reputation:
44
(10-14-2022, 05:22 AM)Pete Wrote: Hi Matt,
I've already modified the code to the SELECT CASE snippet I posted, which solved the slow down the h = SCREEN() created. I do have a backup copy of the one with the speed killing situation. No, $CHECKING:OFF does nothing to offset the decreased speed issue in the backup copy with the speed reduction problem.
h, btw is an integer, defined by a DEFINT H-K at the top of the program.
Pete
Thanks for trying I'll have to give it some more thinking. Unfortunately on my machine just putting that logic into a loop (with some dummy types to make it compile) comes out with it running slightly faster if you store the value in `h` rather than use `SCREEN()` three times (as you originally assumed would be the case).
I'm not sure this is what you're doing, but I would note that the usage of `h` gets more expensive if it's in a `SUB` or `FUNCTION` and you're constantly calling it - there's some allocation overhead that goes on for `h` every time you enter the `SUB` or `FUNCTION` it is declared in. This is also a notable difference from `SELECT CASE`, as the internal variable that stores the value you're selecting on (to do the comparisons with each `CASE`) does not get allocated the same way and thus does not have that overhead. None of my testing on this can get close to a 5x slowdown though
Posts: 2,698
Threads: 327
Joined: Apr 2022
Reputation:
217
(10-14-2022, 05:50 AM)Pete Wrote: Steve must have missed my second post.
Pete
I did, but it's amazing how similar we're thinking -- except, of course, you're once again thinking WRONG.
Code: (Select All) FOR i = 0 TO LEN(a.ship) - 1
SELECT CASE SCREEN(j, k + i)
CASE ASC(g.flagship)
ii = 1
EXIT FOR
CASE g.m_asc
ii = 2
END SELECT
NEXT
I'd simplify this with one out of loop step, and then I wouldn't forget my EXIT and bug my code like you are:
Code: (Select All) A = ASC(g.flagship) 'we do nothing to change the value of g.flagship in the loop. Why do we need to calculate this value over and over repeatedly?
FOR i = k TO k + LEN(a.ship) - 1
SELECT CASE SCREEN(j, i) 'no need to have a math operation here with each pass. Do the math once in the FOR statement and be done with it.
CASE A 'unchanging value of ASC(g.flagship) -- again, no need for multiple unchanging function calls to get this value.
ii = 1
EXIT FOR
CASE g.m_asc
ii = 2
EXIT FOR 'Whoops! Pete forgot the EXIT which the original had here.
END SELECT
NEXT
So now maybe Pete can see why I only ever read about half his posts and code -- at best, they're only about half as good as a Steve(tm) Post!
Posts: 732
Threads: 30
Joined: Apr 2022
Reputation:
43
Typing out a small loop with all the lines does run faster than a loop, yeah. I saw this demonstrated by 8 Bit Guy on YouTube. He showed how the old BASIC programs often had small loops just written all the way out.
Tread on those who tread on you
Posts: 2,164
Threads: 222
Joined: Apr 2022
Reputation:
103
10-14-2022, 05:55 PM
(This post was last modified: 10-14-2022, 05:56 PM by Pete.)
Steve is pretty good with graphics, but his text ability is pretty half-ASCII.
Hey guys, banter aside, just don't miss the point of why I made this post in the first place, to call attention to a peculiar slow-down event, caused by assigning a variable to SCREEN(). Look at it this way, if assigning a variable to avoid repeated asc() checking should speed things up, assigning a variable to SCREEN() should also speed things up; ah, but it didn't. It markedly slowed the animation down. Steve's other suggestion of creating and assigning a new variable to ASC() is correct, but is imperceptible in regard to speed, the difference in speed change by assigning a variable to SCREEN(), in my routine, again, is markedly noteable.
BTW - The CASE 2 part is simply unfinished. I was in the process of adding another condition when this occurred, that's why it is empty with no EXIT FOR, so ignore it, it's not the problem, anyway.
@DSman195276
If it helps, I stripped 70% of the code out to make it easier.
Code example 1 demos the speed as it should be.
Code example 2 demos assigning h to SCREEN(), which slows it down 5x.
To find the code in question, search: Check area through width of ship
Code Example #1
Code: (Select All) DEFINT H-K
$RESIZE:ON
_RESIZE OFF
RANDOMIZE TIMER
' Note: timer is not adjusted for stroke of midnight event, so don't stay up late playing this.
REM Main
f1 = 22 ' Sets font size to 22 and calculates the max screen height and width for your desktop.
h = (_DESKTOPHEIGHT - 60) \ f1
w = _DESKTOPWIDTH \ (f1 / 1.66)
WIDTH w, h
_SCREENMOVE 0, 0
fontpath$ = ENVIRON$("SYSTEMROOT") + "\fonts\lucon.ttf" 'Find Windows Folder Path.
font& = _LOADFONT(fontpath$, f1, "monospace")
_FONT font&
_DELAY .25
_RESIZE ON , _SMOOTH ' Allows resizing. Note: this is for slight adjustments. As of this version there is no compensitory function to change the font size during screen size changes.
TYPE gen_var
intro AS INTEGER ' Runs a protion of the alien subroutine as part of the intro.
nol AS INTEGER ' Number of game levels.
level AS INTEGER ' Current game level.
level_up AS INTEGER ' Routes code to next game level.
top AS INTEGER ' Top boundary. (Changeable).
bottom AS INTEGER ' Bottom boundary. (Changeable).
left AS INTEGER ' Left boundary. (Changeable).
right AS INTEGER ' Right boundary. (Changeable).
kb_access AS INTEGER ' Routes code to either Guardian/Alien or general keyboard routine. -1 Guardian/Alien, 0 keyboard.
mouse_or_key_move AS INTEGER
play AS INTEGER
snd1 AS LONG ' Explosion sound effect.
snd2 AS LONG ' Explosion sound effect.
END TYPE
DIM SHARED v AS gen_var
TYPE guardian
num AS INTEGER ' Number of Guardians aka lives.
diry AS INTEGER ' Guardian row move. +1, 0, -1.
dirx AS INTEGER ' Guardian column move. +2, 0, -2. Equals vertical pixel movement. 16x8.
y AS INTEGER ' Guardian coordinates row.
x AS INTEGER ' Guardian coordinates column.
thrusters AS INTEGER ' Guardian speed. (User Determined).
m_max AS INTEGER ' Restricts # of missiles fired in one direction.
m_status AS INTEGER ' Missile status. -1 when fired, 1 while moving.
m_fired AS INTEGER ' The number of missile deployed and still active.
m_n AS INTEGER ' FOR/NEXT counter variable shared by other routines to index through the number of missiles fired in a specific direction.
m_d AS INTEGER ' Missile direction. (1-8).
m_y AS INTEGER ' Missile row advancement increment: +1, 0, -1 Note: Missile row and column coordinates are defined in arrays.
m_x AS INTEGER ' Missile column advancement increment: +2, 0, -2. Equals vertical pixel movement. 16x8.
m_asc AS INTEGER ' ASCII charater representing a fired missile.
m_launcher AS STRING
icon AS STRING ' Gardian comm icon. For this edition, it is the same as the flagship: "*"
flagship AS STRING ' Guardian ascii character.
END TYPE
DIM SHARED g AS guardian
TYPE alien
max AS INTEGER ' Maximum # of alien ships on screen.
count AS INTEGER ' Number of alien ships. (Counter).
itr AS INTEGER ' Iteration array number to cycle through the active alien ships. (Counter).
cycle_delay AS SINGLE ' Timer cycle controls how fast alien ships move.
ship AS STRING ' Alien ship ASCII design.
END TYPE
DIM SHARED a AS alien
DO
GOSUB set_arrays
SELECT CASE v.play
CASE 1
CALL set_up
CALL comm
v.level = -1: CALL game_level: v.level_up = 0
CASE 0
CALL set_up
CALL comm
CALL intro
v.intro = 0: a.max = 0
GOSUB set_arrays
v.level = -1: CALL game_level: v.level_up = 0 ' This variable is canceled here so game will play instead of go another level up.
END SELECT
g.y = (v.bottom - v.top) \ 2 + v.top: g.x = (v.right - v.left + 1) \ 2 + v.left ' Set initial column and row for Guardian craft.
CALL game
GOSUB zero_variables
LOOP
set_arrays:
ii = 15 ' Default max setting for number of alien ships used here to intially dim arrays.
g.m_max = 8 ' * missiles max per direction.
REDIM SHARED a_y(ii), a_x(ii), a_mask_y(ii), a_mask_x(ii), a_inertia(ii) ' Alien movement.
REDIM SHARED a_ran(ii), a_olda_ran(ii), a_y_loc(ii), a_x_loc(ii) ' Alien motvement.
REDIM SHARED m_n(g.m_max), m_x(g.m_max, 8), m_y(g.m_max, 8) ' Guardian missiles.
' Array descriptions and actions.
' a_y() , a_x() Alien ship postions rows and columns.
' a_mask_y(), a_mask_x() Alien ship last position. Masked on next move.
' a_inertia(ii) Number of moves in one direction selected by random for an alien ship.
' a_ran(ii), a_olda_ran(ii) Determines the direction in which the inertia will travel and the prior direction is kept to disallow the same direction twice.
' a_y_loc(ii), a_x_loc(ii) The row and column cordinates of the aliens ships.
' m_n(g.m_max), m_x(g.m_max, 8), m_y(g.m_max, 8) Missile number and Missile index 1 to g.m_max for position. 8 is the fixed number of 8 different directions.
RETURN
zero_variables:
' Zero variables.
g.diry = 0: g.dirx = 0: g.m_status = 0: g.m_fired = 0: g.m_d = 0: g.m_y = 0: g.m_x = 0
a.count = 0: a.itr = 0: a.cycle_delay = 0: v.level_up = 0: v.mouse_or_key_move = 0: g.m_launcher = ""
RETURN
skipintro:
RETURN
' Error handler.
offscreen: ' Prevents error if blast particles row and column are off-screen. Effect is a partial blast on side of screen.
IF ERR = 5 THEN er = -1: RESUME NEXT
PRINT "Opps, unexpected error"; ERR
END
SUB intro
j = (v.bottom - v.top) \ 2 + v.top
k = (v.right - v.left) \ 2 + v.left
v.intro = -1: a.max = 10
FOR i = 1 TO 90
SOUND 900, .05
CALL alien_move
LOCATE j, k: COLOR 15: PRINT g.flagship;: COLOR 7
_DELAY .07
NEXT
END SUB
SUB set_up
v.top = 3: v.bottom = _HEIGHT: v.left = 1: v.right = _WIDTH
g.flagship = CHR$(15)
a.ship = "-<>-"
g.num = 3 ' 3 Guardian (lives) to start.
g.thrusters = 10 ' Shows 1/2 thrust at start up on comm.
g.icon = g.flagship
g.m_asc = 250: g.diry = -1: ' Initiate missile ASCII character. g.diry = -1 initiates fire upwards if unmoved.
IF _FILEEXISTS("Thunder1.ogg") AND _FILEEXISTS("Thunder1.ogg") AND _FILEEXISTS("Thunder1.ogg") AND _FILEEXISTS("Thunder1.ogg") THEN ' Sound effects provided by TheBOB, Bob Seguin, from The QBasic Forum.
v.snd1 = _SNDOPEN("Thunder1.ogg", "SYNC")
v.snd2 = _SNDOPEN("Thunder7.ogg", "SYNC")
END IF
v.play = -1 ' Skip into on replay.
LOCATE 2, 1: PRINT STRING$(_WIDTH, CHR$(196));
_KEYCLEAR ' Clear any previous key presses in buffer.
END SUB
SUB game
END SUB
SUB comm
END SUB
SUB Guardian_missiles
END SUB
SUB missile_check (k)
END SUB
SUB alien_move
STATIC z5
y_restore = CSRLIN: x_restore = POS(0) ' Restore column and row upon exit.
IF ABS(z5 - TIMER) > a.cycle_delay OR v.intro THEN ' z5 is a time delay for alien space ship maneuvers. It can be altered in the "game" subroutine.
IF v.intro = 0 THEN hh = INT(RND * a.max) + 1 ELSE hh = 15
FOR h = 1 TO hh
a.itr = a.itr + 1: IF a.itr > a.max THEN a.itr = 1 ' Needed to offset the EXIT DO hover event, which on exit does not affect the a.itr variable.
IF a_ran(a.itr) <> -1 THEN ' This is how a destroyed ship is bypassed. -1 is a destroyed alien ship. Code moves to end of DO:LOOP.
IF a_inertia(a.itr) = 0 THEN ' Determine how many moves in one direction.
a_inertia(a.itr) = INT(RND * (v.bottom - v.top) / 2) + 1 ' How many moves to go in any one direction.
a_ran(a.itr) = INT(RND * 8) + 1 ' Choose 1 of 8 possible directions.
IF a_ran(a.itr) = a_olda_ran(a.itr) OR a_mask_y(a.itr) = 0 AND a_mask_x(a.itr) = 0 AND ran = 1 OR a_mask_y(a.itr) = 0 AND a_mask_x(a.itr) = 0 AND ran = 5 THEN
EXIT FOR ' Just hover if direction was not changed on existing alien space ship or if a new alien space ship is entering from the sides and up or down was generated.
END IF
SELECT CASE a_ran(a.itr) ' Get changes in column and row coordinates.
CASE 1: a_y_loc(a.itr) = -1: a_x_loc(a.itr) = 0 ' Up.
CASE 2: a_y_loc(a.itr) = -1: a_x_loc(a.itr) = 2 ' Up and right.
CASE 3: a_y_loc(a.itr) = 0: a_x_loc(a.itr) = 2 ' Right.
CASE 4: a_y_loc(a.itr) = 1: a_x_loc(a.itr) = 2 ' Down and right.
CASE 5: a_y_loc(a.itr) = 1: a_x_loc(a.itr) = 0 ' Down.
CASE 6: a_y_loc(a.itr) = 1: a_x_loc(a.itr) = -2 ' Down and left.
CASE 7: a_y_loc(a.itr) = 0: a_x_loc(a.itr) = -2 ' Left.
CASE 8: a_y_loc(a.itr) = -1: a_x_loc(a.itr) = -2 ' Up and left.
END SELECT
IF a_y(a.itr) = 0 AND a_x(a.itr) = 0 AND a_ran(a.itr) <> -1 THEN ' New alien space ship enters the screen.
i = RND * (v.bottom - v.top) \ 4
a_y(a.itr) = (v.bottom - v.top) \ 4 + i + v.top
IF a_ran(a.itr) < 5 THEN ' Determine side of entry from initial direction.
IF SCREEN(a_y(a.itr), v.left + LEN(a.ship)) = 32 THEN
a_x(a.itr) = v.left + 1 ' Enter from the left side and go right.
ELSE
CALL a_erase
EXIT FOR
END IF
ELSE
IF SCREEN(a_y(a.itr), v.right - LEN(a.ship) + 1) = 32 THEN
a_x(a.itr) = v.right - LEN(a.ship) ' Enter from the right side and go left.
ELSE
CALL a_erase
EXIT FOR
END IF
END IF
END IF
a_olda_ran(a.itr) = a_ran(a.itr) ' Remember last direction. Another line uses this to disallow any RND that chooses the same direction twice.
ELSE
a_inertia(a.itr) = a_inertia(a.itr) - 1 ' Count down the number of moves in any one direction. When zero, switch direction.
END IF
FOR i = 1 TO a.max
IF i <> a.itr AND a_y(i) <> 0 THEN
IF a_y(a.itr) + a_y_loc(a.itr) = a_y(i) THEN
IF a_x(a.itr) + a_x_loc(a.itr) + LEN(a.ship) > a_x(i) AND a_x(a.itr) + a_x_loc(a.itr) < a_x(i) + LEN(a.ship) THEN
collide = 1
EXIT FOR
END IF
END IF
END IF
NEXT
IF collide = 1 THEN
j = a_y(a.itr): k = a_x(a.itr)
a_y_loc(a.itr) = 0: a_x_loc(a.itr) = 0: a_inertia(a.itr) = 0
collide = 0 ' Collision detection off. Collision was detected and avoided.
ELSE
j = a_y(a.itr) + a_y_loc(a.itr): k = a_x(a.itr) + a_x_loc(a.itr)
END IF
IF j <= v.top OR k <= v.left OR k + LEN(a.ship) > v.right THEN ' Alien ship out of range off screen.
a_inertia(a.itr) = 0 ' These two lines keep the out of range ship(s) reasonably nearby.
IF j > v.top - 4 AND k < v.right + 3 AND k > v.left - 4 THEN a_y(a.itr) = j: a_x(a.itr) = k
IF a_mask_y(a.itr) <> 0 AND a_mask_x(a.itr) <> 0 THEN
LOCATE a_mask_y(a.itr), a_mask_x(a.itr)
PRINT SPACE$(LEN(a.ship)); ' Mask old position here because the show part of the mask and show routine cannot be used when out of range.
END IF
a_mask_y(a.itr) = 0: a_mask_x(a.itr) = 0
ELSE
' Check for v.bottom collision and reverse course if detected.
COLOR a.itr
IF j >= v.bottom THEN
a_y_loc(a.itr) = -a_y_loc(a.itr): a_x_loc(a.itr) = -a_x_loc(a.itr)
ELSE
a_y(a.itr) = j: a_x(a.itr) = k ' Next move coordinates.
ii = 0
FOR i = 0 TO LEN(a.ship) - 1 ' Check area through width of ship. Remember all or parts of ship are still present on screen.
IF SCREEN(j, k + i) = ASC(g.flagship) OR SCREEN(j, k + i) = g.m_asc THEN ' Check for contact (collision) with Guardian or missile.
IF SCREEN(j, k + i) = ASC(g.flagship) THEN
ii = 1 ' Indicates contact with flagship and evokes call abduction routine a few lines down.
EXIT FOR
ELSE
ii = 2 ' Indicates ship into missile collision.
EXIT FOR
END IF
END IF
NEXT
IF ii <> 2 THEN
'--------------------------------------------Move alien ship-------------------------------------------------
IF a_mask_y(a.itr) <> 0 AND a_mask_x(a.itr) <> 0 THEN LOCATE a_mask_y(a.itr), a_mask_x(a.itr): PRINT SPACE$(LEN(a.ship));
LOCATE j, k: PRINT a.ship;
a_mask_y(a.itr) = j: a_mask_x(a.itr) = k ' Remember these coordinates to erase alien space ship on next loop.
'------------------------------------------------------------------------------------------------------------
END IF
SELECT CASE ii
CASE 1
CALL guardian_abduction: EXIT FOR ' Exit loop.
CASE 2
'''BEEP: BEEP: BEEP: DO: _LIMIT 10: LOOP UNTIL INKEY$ = CHR$(13)
END SELECT
END IF
COLOR 7
END IF
END IF ' a_ran(a.itr) > -1 exit point.
IF a.itr = a.max THEN a.itr = 0: EXIT FOR ' Finished loop. Keep this outside the IF/THEN statement.
NEXT h
z5 = TIMER
LOCATE y_restore, x_restore ' Restore entry column and row positions.
END IF ' End time event.
END SUB
SUB explosion
END SUB
SUB remove_missile
END SUB
SUB mask_missiles
END SUB
SUB a_erase
a_y(a.itr) = 0: a_x(a.itr) = 0: a_mask_y(a.itr) = 0: a_mask_x(a.itr) = 0: a_inertia(a.itr) = 0: a_ran(a.itr) = 0: a_y_loc(a.itr) = 0: a_x_loc(a.itr) = 0: a_olda_ran(a.itr) = 0
END SUB
SUB remove_ship
END SUB
SUB guardian_abduction
END SUB
SUB game_level ' Evaluates both alien defeated on a level and Guardian abduction.
END SUB
SUB mouse (mouse_event1, mouse_event2)
END SUB
Code Example #2, the slow-down problem.
Code: (Select All) DEFINT H-K
$RESIZE:ON
_RESIZE OFF
RANDOMIZE TIMER
' Note: timer is not adjusted for stroke of midnight event, so don't stay up late playing this.
REM Main
f1 = 22 ' Sets font size to 22 and calculates the max screen height and width for your desktop.
h = (_DESKTOPHEIGHT - 60) \ f1
w = _DESKTOPWIDTH \ (f1 / 1.66)
WIDTH w, h
_SCREENMOVE 0, 0
fontpath$ = ENVIRON$("SYSTEMROOT") + "\fonts\lucon.ttf" 'Find Windows Folder Path.
font& = _LOADFONT(fontpath$, f1, "monospace")
_FONT font&
_DELAY .25
_RESIZE ON , _SMOOTH ' Allows resizing. Note: this is for slight adjustments. As of this version there is no compensitory function to change the font size during screen size changes.
TYPE gen_var
intro AS INTEGER ' Runs a protion of the alien subroutine as part of the intro.
nol AS INTEGER ' Number of game levels.
level AS INTEGER ' Current game level.
level_up AS INTEGER ' Routes code to next game level.
top AS INTEGER ' Top boundary. (Changeable).
bottom AS INTEGER ' Bottom boundary. (Changeable).
left AS INTEGER ' Left boundary. (Changeable).
right AS INTEGER ' Right boundary. (Changeable).
kb_access AS INTEGER ' Routes code to either Guardian/Alien or general keyboard routine. -1 Guardian/Alien, 0 keyboard.
mouse_or_key_move AS INTEGER
play AS INTEGER
snd1 AS LONG ' Explosion sound effect.
snd2 AS LONG ' Explosion sound effect.
END TYPE
DIM SHARED v AS gen_var
TYPE guardian
num AS INTEGER ' Number of Guardians aka lives.
diry AS INTEGER ' Guardian row move. +1, 0, -1.
dirx AS INTEGER ' Guardian column move. +2, 0, -2. Equals vertical pixel movement. 16x8.
y AS INTEGER ' Guardian coordinates row.
x AS INTEGER ' Guardian coordinates column.
thrusters AS INTEGER ' Guardian speed. (User Determined).
m_max AS INTEGER ' Restricts # of missiles fired in one direction.
m_status AS INTEGER ' Missile status. -1 when fired, 1 while moving.
m_fired AS INTEGER ' The number of missile deployed and still active.
m_n AS INTEGER ' FOR/NEXT counter variable shared by other routines to index through the number of missiles fired in a specific direction.
m_d AS INTEGER ' Missile direction. (1-8).
m_y AS INTEGER ' Missile row advancement increment: +1, 0, -1 Note: Missile row and column coordinates are defined in arrays.
m_x AS INTEGER ' Missile column advancement increment: +2, 0, -2. Equals vertical pixel movement. 16x8.
m_asc AS INTEGER ' ASCII charater representing a fired missile.
m_launcher AS STRING
icon AS STRING ' Gardian comm icon. For this edition, it is the same as the flagship: "*"
flagship AS STRING ' Guardian ascii character.
END TYPE
DIM SHARED g AS guardian
TYPE alien
max AS INTEGER ' Maximum # of alien ships on screen.
count AS INTEGER ' Number of alien ships. (Counter).
itr AS INTEGER ' Iteration array number to cycle through the active alien ships. (Counter).
cycle_delay AS SINGLE ' Timer cycle controls how fast alien ships move.
ship AS STRING ' Alien ship ASCII design.
END TYPE
DIM SHARED a AS alien
DO
GOSUB set_arrays
SELECT CASE v.play
CASE 1
CALL set_up
CALL comm
v.level = -1: CALL game_level: v.level_up = 0
CASE 0
CALL set_up
CALL comm
CALL intro
v.intro = 0: a.max = 0
GOSUB set_arrays
v.level = -1: CALL game_level: v.level_up = 0 ' This variable is canceled here so game will play instead of go another level up.
END SELECT
g.y = (v.bottom - v.top) \ 2 + v.top: g.x = (v.right - v.left + 1) \ 2 + v.left ' Set initial column and row for Guardian craft.
CALL game
GOSUB zero_variables
LOOP
set_arrays:
ii = 15 ' Default max setting for number of alien ships used here to intially dim arrays.
g.m_max = 8 ' * missiles max per direction.
REDIM SHARED a_y(ii), a_x(ii), a_mask_y(ii), a_mask_x(ii), a_inertia(ii) ' Alien movement.
REDIM SHARED a_ran(ii), a_olda_ran(ii), a_y_loc(ii), a_x_loc(ii) ' Alien motvement.
REDIM SHARED m_n(g.m_max), m_x(g.m_max, 8), m_y(g.m_max, 8) ' Guardian missiles.
' Array descriptions and actions.
' a_y() , a_x() Alien ship postions rows and columns.
' a_mask_y(), a_mask_x() Alien ship last position. Masked on next move.
' a_inertia(ii) Number of moves in one direction selected by random for an alien ship.
' a_ran(ii), a_olda_ran(ii) Determines the direction in which the inertia will travel and the prior direction is kept to disallow the same direction twice.
' a_y_loc(ii), a_x_loc(ii) The row and column cordinates of the aliens ships.
' m_n(g.m_max), m_x(g.m_max, 8), m_y(g.m_max, 8) Missile number and Missile index 1 to g.m_max for position. 8 is the fixed number of 8 different directions.
RETURN
zero_variables:
' Zero variables.
g.diry = 0: g.dirx = 0: g.m_status = 0: g.m_fired = 0: g.m_d = 0: g.m_y = 0: g.m_x = 0
a.count = 0: a.itr = 0: a.cycle_delay = 0: v.level_up = 0: v.mouse_or_key_move = 0: g.m_launcher = ""
RETURN
skipintro:
RETURN
' Error handler.
offscreen: ' Prevents error if blast particles row and column are off-screen. Effect is a partial blast on side of screen.
IF ERR = 5 THEN er = -1: RESUME NEXT
PRINT "Opps, unexpected error"; ERR
END
SUB intro
j = (v.bottom - v.top) \ 2 + v.top
k = (v.right - v.left) \ 2 + v.left
v.intro = -1: a.max = 10
FOR i = 1 TO 90
SOUND 900, .05
CALL alien_move
LOCATE j, k: COLOR 15: PRINT g.flagship;: COLOR 7
_DELAY .07
NEXT
END SUB
SUB set_up
v.top = 3: v.bottom = _HEIGHT: v.left = 1: v.right = _WIDTH
g.flagship = CHR$(15)
a.ship = "-<>-"
g.num = 3 ' 3 Guardian (lives) to start.
g.thrusters = 10 ' Shows 1/2 thrust at start up on comm.
g.icon = g.flagship
g.m_asc = 250: g.diry = -1: ' Initiate missile ASCII character. g.diry = -1 initiates fire upwards if unmoved.
IF _FILEEXISTS("Thunder1.ogg") AND _FILEEXISTS("Thunder1.ogg") AND _FILEEXISTS("Thunder1.ogg") AND _FILEEXISTS("Thunder1.ogg") THEN ' Sound effects provided by TheBOB, Bob Seguin, from The QBasic Forum.
v.snd1 = _SNDOPEN("Thunder1.ogg", "SYNC")
v.snd2 = _SNDOPEN("Thunder7.ogg", "SYNC")
END IF
v.play = -1 ' Skip into on replay.
LOCATE 2, 1: PRINT STRING$(_WIDTH, CHR$(196));
_KEYCLEAR ' Clear any previous key presses in buffer.
END SUB
SUB game
END SUB
SUB comm
END SUB
SUB Guardian_missiles
END SUB
SUB missile_check (k)
END SUB
SUB alien_move
STATIC z5
y_restore = CSRLIN: x_restore = POS(0) ' Restore column and row upon exit.
IF ABS(z5 - TIMER) > a.cycle_delay OR v.intro THEN ' z5 is a time delay for alien space ship maneuvers. It can be altered in the "game" subroutine.
IF v.intro = 0 THEN hh = INT(RND * a.max) + 1 ELSE hh = 15
FOR h = 1 TO hh
a.itr = a.itr + 1: IF a.itr > a.max THEN a.itr = 1 ' Needed to offset the EXIT DO hover event, which on exit does not affect the a.itr variable.
IF a_ran(a.itr) <> -1 THEN ' This is how a destroyed ship is bypassed. -1 is a destroyed alien ship. Code moves to end of DO:LOOP.
IF a_inertia(a.itr) = 0 THEN ' Determine how many moves in one direction.
a_inertia(a.itr) = INT(RND * (v.bottom - v.top) / 2) + 1 ' How many moves to go in any one direction.
a_ran(a.itr) = INT(RND * 8) + 1 ' Choose 1 of 8 possible directions.
IF a_ran(a.itr) = a_olda_ran(a.itr) OR a_mask_y(a.itr) = 0 AND a_mask_x(a.itr) = 0 AND ran = 1 OR a_mask_y(a.itr) = 0 AND a_mask_x(a.itr) = 0 AND ran = 5 THEN
EXIT FOR ' Just hover if direction was not changed on existing alien space ship or if a new alien space ship is entering from the sides and up or down was generated.
END IF
SELECT CASE a_ran(a.itr) ' Get changes in column and row coordinates.
CASE 1: a_y_loc(a.itr) = -1: a_x_loc(a.itr) = 0 ' Up.
CASE 2: a_y_loc(a.itr) = -1: a_x_loc(a.itr) = 2 ' Up and right.
CASE 3: a_y_loc(a.itr) = 0: a_x_loc(a.itr) = 2 ' Right.
CASE 4: a_y_loc(a.itr) = 1: a_x_loc(a.itr) = 2 ' Down and right.
CASE 5: a_y_loc(a.itr) = 1: a_x_loc(a.itr) = 0 ' Down.
CASE 6: a_y_loc(a.itr) = 1: a_x_loc(a.itr) = -2 ' Down and left.
CASE 7: a_y_loc(a.itr) = 0: a_x_loc(a.itr) = -2 ' Left.
CASE 8: a_y_loc(a.itr) = -1: a_x_loc(a.itr) = -2 ' Up and left.
END SELECT
IF a_y(a.itr) = 0 AND a_x(a.itr) = 0 AND a_ran(a.itr) <> -1 THEN ' New alien space ship enters the screen.
i = RND * (v.bottom - v.top) \ 4
a_y(a.itr) = (v.bottom - v.top) \ 4 + i + v.top
IF a_ran(a.itr) < 5 THEN ' Determine side of entry from initial direction.
IF SCREEN(a_y(a.itr), v.left + LEN(a.ship)) = 32 THEN
a_x(a.itr) = v.left + 1 ' Enter from the left side and go right.
ELSE
CALL a_erase
EXIT FOR
END IF
ELSE
IF SCREEN(a_y(a.itr), v.right - LEN(a.ship) + 1) = 32 THEN
a_x(a.itr) = v.right - LEN(a.ship) ' Enter from the right side and go left.
ELSE
CALL a_erase
EXIT FOR
END IF
END IF
END IF
a_olda_ran(a.itr) = a_ran(a.itr) ' Remember last direction. Another line uses this to disallow any RND that chooses the same direction twice.
ELSE
a_inertia(a.itr) = a_inertia(a.itr) - 1 ' Count down the number of moves in any one direction. When zero, switch direction.
END IF
FOR i = 1 TO a.max
IF i <> a.itr AND a_y(i) <> 0 THEN
IF a_y(a.itr) + a_y_loc(a.itr) = a_y(i) THEN
IF a_x(a.itr) + a_x_loc(a.itr) + LEN(a.ship) > a_x(i) AND a_x(a.itr) + a_x_loc(a.itr) < a_x(i) + LEN(a.ship) THEN
collide = 1
EXIT FOR
END IF
END IF
END IF
NEXT
IF collide = 1 THEN
j = a_y(a.itr): k = a_x(a.itr)
a_y_loc(a.itr) = 0: a_x_loc(a.itr) = 0: a_inertia(a.itr) = 0
collide = 0 ' Collision detection off. Collision was detected and avoided.
ELSE
j = a_y(a.itr) + a_y_loc(a.itr): k = a_x(a.itr) + a_x_loc(a.itr)
END IF
IF j <= v.top OR k <= v.left OR k + LEN(a.ship) > v.right THEN ' Alien ship out of range off screen.
a_inertia(a.itr) = 0 ' These two lines keep the out of range ship(s) reasonably nearby.
IF j > v.top - 4 AND k < v.right + 3 AND k > v.left - 4 THEN a_y(a.itr) = j: a_x(a.itr) = k
IF a_mask_y(a.itr) <> 0 AND a_mask_x(a.itr) <> 0 THEN
LOCATE a_mask_y(a.itr), a_mask_x(a.itr)
PRINT SPACE$(LEN(a.ship)); ' Mask old position here because the show part of the mask and show routine cannot be used when out of range.
END IF
a_mask_y(a.itr) = 0: a_mask_x(a.itr) = 0
ELSE
' Check for v.bottom collision and reverse course if detected.
COLOR a.itr
IF j >= v.bottom THEN
a_y_loc(a.itr) = -a_y_loc(a.itr): a_x_loc(a.itr) = -a_x_loc(a.itr)
ELSE
a_y(a.itr) = j: a_x(a.itr) = k ' Next move coordinates.
ii = 0
FOR i = 0 TO LEN(a.ship) - 1 ' Check area through width of ship. Remember all or parts of ship are still present on screen.
h = SCREEN(j, k + i)
IF h = ASC(g.flagship) OR h = g.m_asc THEN ' Check for contact (collision) with Guardian or missile.
IF h = ASC(g.flagship) THEN
ii = 1 ' Indicates contact with flagship and evokes call abduction routine a few lines down.
EXIT FOR
ELSE
ii = 2 ' Indicates ship into missile collision.
EXIT FOR
END IF
END IF
NEXT
IF ii <> 2 THEN
'--------------------------------------------Move alien ship-------------------------------------------------
IF a_mask_y(a.itr) <> 0 AND a_mask_x(a.itr) <> 0 THEN LOCATE a_mask_y(a.itr), a_mask_x(a.itr): PRINT SPACE$(LEN(a.ship));
LOCATE j, k: PRINT a.ship;
a_mask_y(a.itr) = j: a_mask_x(a.itr) = k ' Remember these coordinates to erase alien space ship on next loop.
'------------------------------------------------------------------------------------------------------------
END IF
SELECT CASE ii
CASE 1
CALL guardian_abduction: EXIT FOR ' Exit loop.
CASE 2
'''BEEP: BEEP: BEEP: DO: _LIMIT 10: LOOP UNTIL INKEY$ = CHR$(13)
END SELECT
END IF
COLOR 7
END IF
END IF ' a_ran(a.itr) > -1 exit point.
IF a.itr = a.max THEN a.itr = 0: EXIT FOR ' Finished loop. Keep this outside the IF/THEN statement.
NEXT h
z5 = TIMER
LOCATE y_restore, x_restore ' Restore entry column and row positions.
END IF ' End time event.
END SUB
SUB explosion
END SUB
SUB remove_missile
END SUB
SUB mask_missiles
END SUB
SUB a_erase
a_y(a.itr) = 0: a_x(a.itr) = 0: a_mask_y(a.itr) = 0: a_mask_x(a.itr) = 0: a_inertia(a.itr) = 0: a_ran(a.itr) = 0: a_y_loc(a.itr) = 0: a_x_loc(a.itr) = 0: a_olda_ran(a.itr) = 0
END SUB
SUB remove_ship
END SUB
SUB guardian_abduction
END SUB
SUB game_level ' Evaluates both alien defeated on a level and Guardian abduction.
END SUB
SUB mouse (mouse_event1, mouse_event2)
END SUB
Pete
Posts: 2,698
Threads: 327
Joined: Apr 2022
Reputation:
217
(10-14-2022, 05:55 PM)Pete Wrote: Hey guys, banter aside, just don't miss the point of why I made this post in the first place, to call attention to a peculiar slow-down event, caused by assigning a variable to SCREEN().
I'm just not seeing that type of behavior. Something else is causing your slow-down event, but I don't think it's the use of SCREEN being assigned a variable. See this little timed demo below:
Code: (Select All) Cls , 4
t# = Timer
For i = 1 To 10000000
If Screen(1, 1) Then
If Screen(1, 1) <> Screen(1, 1) Then End
End If
Next
t1# = Timer
For i = 1 To 10000000
h = Screen(1, 1)
If h Then
If h <> h Then End
End If
Next
t2# = Timer
Print Using "###.#### seconds with 3 screen"; t1# - t#
Print Using "###.#### seconds with 3 variables"; t2# - t1#
And the screenshot of my results -- ran first without any c-optimizations, and then a second time by clicking the option to enable c-optimations.
First run was 0.2 seconds vs 0.05 seconds.
Second run was 0.17 seconds vs 0.05 seconds.
In both cases, it was noticeably faster to assign the value of SCREEN to a variable, than it was to make 3 distinct calls to that same SCREEN statement. (OF course, keep in mind that this is also over 10,000,000 iterations, so the overall difference in speed is almost negligible one way or the other.)
There's nothing here, however, that seems to indicate that using SCREEN is faster than using a variable holding the value of SCREEN. You might be seeing a speed difference in your code, but I don't think it's from what you're attributing it to.
Posts: 2,164
Threads: 222
Joined: Apr 2022
Reputation:
103
Did you run my 2 code examples?
That's why I posted the two code examples in post #14, because by those few lines alone, I can't find it either. We need to include the accompanying animation code. With the accompanying code, there is an estimated 5x speed difference in how fast the alien ships move on the intro screen. Since the only difference in the two code snippets is the two ways shown to use SCREEN(), something involving that function sure seems to be the only thing causing the animation slowdown.
Pete
Posts: 1,277
Threads: 120
Joined: Apr 2022
Reputation:
100
10-14-2022, 08:33 PM
(This post was last modified: 10-14-2022, 08:33 PM by TerryRitchie.)
(10-14-2022, 07:25 PM)Pete Wrote: Did you run my 2 code examples?
That's why I posted the two code examples in post #14, because by those few lines alone, I can't find it either. We need to include the accompanying animation code. With the accompanying code, there is an estimated 5x speed difference in how fast the alien ships move on the intro screen. Since the only difference in the two code snippets is the two ways shown to use SCREEN(), something involving that function sure seems to be the only thing causing the animation slowdown.
Pete
Code 1 was definitely faster than code 2. I'm always looking for ways to optimize code (do ... loop instead of for ... next for example). It seems counter-intuitive to have functions called over and over again instead of just once to get faster results. Maybe a section in the Wiki on optimization techniques would be beneficial. When better ways are discovered they can be added to the entry.
Posts: 2,164
Threads: 222
Joined: Apr 2022
Reputation:
103
10-14-2022, 08:51 PM
(This post was last modified: 10-14-2022, 08:51 PM by Pete.)
@TerryRitchie
I know, right? I think this one still has the devs a bit mystified. I had Steve mesmerized for days the time I pulled a rabbit out of my hat. He said it caught him off guard, because he was so used to me pulling ideas out of my other end. Ah, misdirection, my favorite tool in my SCREEN ZERO magic kit!
Pete
Shoot first and shoot people who ask questions, later.
Posts: 303
Threads: 10
Joined: Apr 2022
Reputation:
44
@Pete check line 168, that's the issue. `h` is already used as a loop variable, so by reusing it for the assignment you're messing with that loop and presumably it ends up running many more times than just 1 to `hh`.
Posts: 2,164
Threads: 222
Joined: Apr 2022
Reputation:
103
10-14-2022, 09:49 PM
(This post was last modified: 10-14-2022, 09:58 PM by Pete.)
Eeeeeeeks! It looks like I sent you guys on a snipe hunt this time around. My apologizes for wasting your time.
That's it, double use of a looping variable. I'm usually on the lookout for this kind of error. In the code, there are a lot of uses of the local variables h, i, j, and k. So much so, I had to make some exceptions to avoid the problem, you just found, by going to names like k2 or ii.
Well this puts a platter of eggs on my face, but I'm actually glad it isn't some internal compiler problem. Thanks for figuring it out. The important thing is... you beat Steve!
Pete
Edited thread title to reflect "Resolved."
|