In the spirit of Terry's Tutorials - GUARDIAN Alien Space Ship Game - Pete - 10-04-2022
When I build a program, I do so by making subs that can often act independently. It's a very easy way to join things together for bigger project. It also makes debugging a whole lot easier.
So I thought, since Terry provides excellent tutorials for newbies to fast track coding, I would join in the spirit of that perspective and put up some little project which shows step-wise development.
Alien Space Ship is an ASCII -<>- that, for starters, that flies randomly throughout the screen. The code is adaptable to various screen sizes. I'll start with a single ship for now. I'll show how to make a married ship, later.
Stage 1)
Code: (Select All) DIM SHARED top, bottom, left, right
a = 120: b = 42
WIDTH a, b
_SCREENMOVE 0, 0
top = 3: bottom = _HEIGHT: left = 0: right = _WIDTH
msg$ = "Alien space ship movement demo."
LOCATE 1, (right - left) \ 2 - LEN(msg$) \ 2
PRINT msg$;
LOCATE 1, 2: PRINT STRING$(_WIDTH, "_");
DO
_LIMIT 30
alien_move
LOOP
SUB alien_move:
STATIC a_y, a_x, olda_y, olda_x, alien$, inertia, ran, ran_y, ran_x, oldran, z5
IF ABS(z5 - TIMER) > .1 THEN ' Time delay.
y_restore = CSRLIN: x_restore = POS(0) ' Restore column and row upon exit.
IF alien$ = "" THEN alien$ = "-<>-"
IF olda_y <> 0 AND olda_x <> 0 THEN
LOCATE olda_y, olda_x: PRINT SPACE$(LEN(alien$));
ELSE
a_y = (bottom - top) \ 2: a_x = (right - left) \ 2 ' Center sreen.
END IF
IF inertia = 0 THEN
inertia = INT(RND * (bottom - top) / 2) + 1 ' How many moves to go in any one direction.
ran = INT(RND * 8) + 1 ' Choose 1 of 8 possible directions.
IF ran = oldran THEN LOCATE y_restore, x_restore: EXIT SUB ' Just hover if direction was not changed.
SELECT CASE ran ' Get changes in column and row coordinates.
CASE 1: ran_y = -1: ran_x = 0
CASE 2: ran_y = -1: ran_x = 1
CASE 3: ran_y = 0: ran_x = 1
CASE 4: ran_y = 1: ran_x = 1
CASE 5: ran_y = 1: ran_x = 0
CASE 6: ran_y = 1: ran_x = -1
CASE 7: ran_y = 0: ran_x = -1
CASE 8: ran_y = -1: ran_x = -1
END SELECT
oldran = ran ' Remember last direction.
ELSE
inertia = inertia - 1 ' Count down the number of moves in any one direction. When zero, switch direction.
END IF
a_y = a_y + ran_y: a_x = a_x + ran_x * 2 ' Next move coordinates. I use * 2 for horizontal movement to match the 16x8 pixel height over width factor.
IF a_y < top OR a_y > bottom OR a_x <= left OR a_x + LEN(alien$) > right THEN
olda_x = 0: olda_y = 0: inertia = 0: oldran = 0 ' Out of bounds and off the screen.
ELSE
LOCATE a_y, a_x: PRINT alien$; ' Move alien ship.
olda_y = a_y: olda_x = a_x ' Remember these coordinates to erase ship on next loop.
END IF
z5 = TIMER
LOCATE y_restore, x_restore ' Restore entry column and row positions.
END IF
END SUB
The next stage will demonstrate a way to start a ship on the screen from the left or right side, determined by initial right or left direction, at a somewhat random vertical starting point. Hey, if you develop a shooter game, it's not much of a challenge if you know in advance where the enemy vessel will appear.
Pete out.
RE: In the spirit of Terry's Tutorials - Alien Space Ship - TerryRitchie - 10-04-2022
Awesome!
RE: In the spirit of Terry's Tutorials - Alien Space Ship - Pete - 10-04-2022
Next we will start the alien ship at a random upper location in either the right or left side of the screen. Right or left is determined by the inital direction, so if the ship is traveling right, it will enter from the left. How about if up or down is the initial direction. Well, we disallowed this as part of an addition to and existing statement that exits the sub if either of those directions get selected.
Code: (Select All) IF ran = oldran OR olda_y = 0 AND olda_x = 0 AND ran = 1 OR olda_y = 0 AND olda_x = 0 AND ran = 5 THEN
The other code added to achieve the side entry is:
Code: (Select All) IF olda_y = 0 AND olda_x = 0 THEN ' New alien space ship enters the screen.
a_y = (bottom - top) \ 2: a_x = (right - left) \ 2 ' Center sreen.
a_y = (bottom - top) \ 4 + RND * (bottom - top) \ 4
IF ran < 5 THEN ' Determine side of entry from initial direction.
a_x = left + 1 ' Enter from the left side and go right.
ELSE
a_x = right - LEN(alien$) ' Enter from the right side and go left.
END IF
END IF
Stage 2)
Code: (Select All) DIM SHARED top, bottom, left, right
a = 120: b = 42
WIDTH a, b
_SCREENMOVE 0, 0
top = 3: bottom = _HEIGHT: left = 0: right = _WIDTH
msg$ = "Alien space ship movement demo."
LOCATE 1, (right - left) \ 2 - LEN(msg$) \ 2
PRINT msg$;
LOCATE 1, 2: PRINT STRING$(_WIDTH, "_");
DO
_LIMIT 30
alien_move
LOOP
SUB alien_move:
STATIC a_y, a_x, olda_y, olda_x, alien$, inertia, ran, ran_y, ran_x, oldran, z5
IF ABS(z5 - TIMER) > .1 THEN ' Time delay.
y_restore = CSRLIN: x_restore = POS(0) ' Restore column and row upon exit.
IF alien$ = "" THEN alien$ = "-<>-"
IF olda_y <> 0 AND olda_x <> 0 THEN LOCATE olda_y, olda_x: PRINT SPACE$(LEN(alien$));
IF inertia = 0 THEN
inertia = INT(RND * (bottom - top) / 2) + 1 ' How many moves to go in any one direction.
ran = INT(RND * 8) + 1 ' Choose 1 of 8 possible directions.
IF ran = oldran OR olda_y = 0 AND olda_x = 0 AND ran = 1 OR olda_y = 0 AND olda_x = 0 AND ran = 5 THEN
LOCATE y_restore, x_restore: EXIT SUB ' 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 ran ' Get changes in column and row coordinates.
CASE 1: ran_y = -1: ran_x = 0 ' Up.
CASE 2: ran_y = -1: ran_x = 1 ' Up and right.
CASE 3: ran_y = 0: ran_x = 1 ' Right.
CASE 4: ran_y = 1: ran_x = 1 ' Down and right.
CASE 5: ran_y = 1: ran_x = 0 ' Down.
CASE 6: ran_y = 1: ran_x = -1 ' Down and left.
CASE 7: ran_y = 0: ran_x = -1 ' Left.
CASE 8: ran_y = -1: ran_x = -1 ' Up and left.
END SELECT
IF olda_y = 0 AND olda_x = 0 THEN ' New alien space ship enters the screen.
a_y = (bottom - top) \ 2: a_x = (right - left) \ 2 ' Center sreen.
a_y = (bottom - top) \ 4 + RND * (bottom - top) \ 4
IF ran < 5 THEN ' Determine side of entry from initial direction.
a_x = left + 1 ' Enter from the left side and go right.
ELSE
a_x = right - LEN(alien$) ' Enter from the right side and go left.
END IF
END IF
oldran = ran ' Remember last direction. Another line uses this to disallow any RND that chooses the same direction twice.
ELSE
inertia = inertia - 1 ' Count down the number of moves in any one direction. When zero, switch direction.
END IF
a_y = a_y + ran_y: a_x = a_x + ran_x * 2 ' Next move coordinates. I use * 2 for horizontal movement to match the 16x8 pixel height over width factor.
IF a_y < top OR a_y > bottom OR a_x <= left OR a_x + LEN(alien$) > right THEN
olda_x = 0: olda_y = 0: inertia = 0: oldran = 0 ' Out of bounds and off the screen.
ELSE
LOCATE a_y, a_x: PRINT alien$; ' Move alien space ship.
olda_y = a_y: olda_x = a_x ' Remember these coordinates to erase alien space ship on next loop.
END IF
z5 = TIMER
LOCATE y_restore, x_restore ' Restore entry column and row positions.
END IF
END SUB
The next stage will demonstrate how to use arrays to put two or more ships on the screen.
Pete
RE: In the spirit of Terry's Tutorials - Alien Space Ship - Pete - 10-05-2022
Okay, how about we put 5 alien space ships in on the screen? It's actually easier than it sounds. All we need is a iteration counter (I'll use the variable name itr for that) and the variables already in use, all being changed into arrays. So if we had ship we would replace it with ship(itr). The QB64 IDE has a nice CHANGE routine so if you already coded ship in 20 places, the change feature would change it to ship(itr) in all 20 places at once. I did almost all of the edits from my last post to this post using that method.
With all the variables changed to arrays, we simply DIM or value of 5 space ships in the STATIC statement:
Code: (Select All) STATIC a_y(5), a_x(5), olda_y(5), olda_x(5), inertia(5), ran(5), ran_y(5), ran_x(5), oldran(5), z5, itr, alien_ship_max
Sorry, but you have to hard code the number. The STATIC statement won't compile with a variable.
Now we need the space ship max variable added: IF alien$ = "" THEN alien$ = "-<>-": alien_ship_max = 5 ' Initiate.
Finally we just wrap what we already have in a DO:LOOP that moves each of the 5 space ships before exiting.
Stage 3)
Code: (Select All) DIM SHARED top, bottom, left, right
a = 120: b = 42
WIDTH a, b
_SCREENMOVE 0, 0
top = 3: bottom = _HEIGHT: left = 0: right = _WIDTH
msg$ = "Alien space ship movement demo."
LOCATE 1, (right - left) \ 2 - LEN(msg$) \ 2
PRINT msg$;
LOCATE 1, 2: PRINT STRING$(_WIDTH, "_");
DO
_LIMIT 30
alien_move
LOOP
SUB alien_move:
STATIC a_y(5), a_x(5), olda_y(5), olda_x(5), inertia(5), ran(5), ran_y(5), ran_x(5), oldran(5), z5, itr, alien_ship_max
IF alien$ = "" THEN alien$ = "-<>-": alien_ship_max = 5 ' Initiate.
IF ABS(z5 - TIMER) > .1 THEN ' Time delay.
DO
itr = itr + 1: IF itr > alien_ship_max THEN itr = 1 ' Needed to offset the EXIT DO hover event, which on exit does not affect the itr variable.
y_restore = CSRLIN: x_restore = POS(0) ' Restore column and row upon exit.
IF olda_y(itr) <> 0 AND olda_x(itr) <> 0 THEN LOCATE olda_y(itr), olda_x(itr): PRINT SPACE$(LEN(alien$));
IF inertia(itr) = 0 THEN
inertia(itr) = INT(RND * (bottom - top) / 2) + 1 ' How many moves to go in any one direction.
ran(itr) = INT(RND * 8) + 1 ' Choose 1 of 8 possible directions.
IF ran(itr) = oldran(itr) OR olda_y(itr) = 0 AND olda_x(itr) = 0 AND ran = 1 OR olda_y(itr) = 0 AND olda_x(itr) = 0 AND ran = 5 THEN
EXIT DO ' 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 ran(itr) ' Get changes in column and row coordinates.
CASE 1: ran_y(itr) = -1: ran_x(itr) = 0 ' Up.
CASE 2: ran_y(itr) = -1: ran_x(itr) = 1 ' Up and right.
CASE 3: ran_y(itr) = 0: ran_x(itr) = 1 ' Right.
CASE 4: ran_y(itr) = 1: ran_x(itr) = 1 ' Down and right.
CASE 5: ran_y(itr) = 1: ran_x(itr) = 0 ' Down.
CASE 6: ran_y(itr) = 1: ran_x(itr) = -1 ' Down and left.
CASE 7: ran_y(itr) = 0: ran_x(itr) = -1 ' Left.
CASE 8: ran_y(itr) = -1: ran_x(itr) = -1 ' Up and left.
END SELECT
IF olda_y(itr) = 0 AND olda_x(itr) = 0 THEN ' New alien space ship enters the screen.
a_y(itr) = (bottom - top) \ 2: a_x(itr) = (right - left) \ 2 ' Center sreen.
a_y(itr) = (bottom - top) \ 4 + RND * (bottom - top) \ 4
IF ran(itr) < 5 THEN ' Determine side of entry from initial direction.
a_x(itr) = left + 1 ' Enter from the left side and go right.
ELSE
a_x(itr) = right - LEN(alien$) ' Enter from the right side and go left.
END IF
END IF
oldran(itr) = ran(itr) ' Remember last direction. Another line uses this to disallow any RND that chooses the same direction twice.
ELSE
inertia(itr) = inertia(itr) - 1 ' Count down the number of moves in any one direction. When zero, switch direction.
END IF
a_y(itr) = a_y(itr) + ran_y(itr): a_x(itr) = a_x(itr) + ran_x(itr) * 2 ' Next move coordinates. I use * 2 for horizontal movement to match the 16x8 pixel height over width factor.
IF a_y(itr) < top OR a_y(itr) > bottom OR a_x(itr) <= left OR a_x(itr) + LEN(alien$) > right THEN
olda_x(itr) = 0: olda_y(itr) = 0: inertia(itr) = 0: oldran(itr) = 0 ' Out of bounds and off the screen.
ELSE
LOCATE a_y(itr), a_x(itr): PRINT alien$; ' Move alien space ship.
olda_y(itr) = a_y(itr): olda_x(itr) = a_x(itr) ' Remember these coordinates to erase alien space ship on next loop.
END IF
IF itr = alien_ship_max THEN itr = 0: EXIT DO
LOOP
z5 = TIMER
LOCATE y_restore, x_restore ' Restore entry column and row positions.
END IF
END SUB
The next adjustment will be a "flow through" modification. Flow through makes it possible to do other things rather than just be stuck in a task loop until the task is finished. This is a very important timing element for gaming.
Pete
RE: In the spirit of Terry's Tutorials - Alien Space Ship - mnrvovrfc - 10-05-2022
QB64PE is so fast we don't even care about defining anything as integer! The "default SINGLE" type is good enough to declare variables that would hold numbers. Now somebody is going to want to run performance tests to compare variables, integers to floating-point. This is what I've actually learned in this tutorial, but great job with the game building and teaching.
RE: In the spirit of Terry's Tutorials - Alien Space Ship - Pete - 10-05-2022
(10-05-2022, 12:54 AM)mnrvovrfc Wrote: QB64PE is so fast we don't even care about defining anything as integer! The "default SINGLE" type is good enough to declare variables that would hold numbers. Now somebody is going to want to run performance tests to compare variables, integers to floating-point. This is what I've actually learned in this tutorial, but great job with the game building and teaching.
Good ol' QJurassic days. I used DEFINT i to y just to speed things up a bit back then. Nice trick, but not needed in QB64; however, I was going to include variable typing and TYPE variables somewhere in this project. Normally, if I see I'm getting into a lot of code, I switch it all up to TYPE variables. That's especially good practice when passing variables to subs and functions because it can pass several variables as a type rather than a long list of elements in the sub or function call.
Thanks for the comment, and the memories. (Now I sound like Bob Hope, talk about Jurassic.)
Pete
RE: In the spirit of Terry's Tutorials - Alien Space Ship - Pete - 10-05-2022
Okay, so now will demo the "flow through" for the alien space ships by adding yet another timer to the mix, and some keys to press to speed up or slow down the action.
Press or hold the left Ctrl key to speed it up, the right Alt key to slow things down. Press something else like an arrow key to make a tiny sound. Why? Just to show how the player has a lot of input while everything around the screen is moving. That's what I mean by designing a game to have a "flow through" structure.
Stage 4)
Code: (Select All) DIM SHARED top, bottom, left, right, s_delay
a = 120: b = 42
WIDTH a, b
_SCREENMOVE 0, 0
top = 3: bottom = _HEIGHT: left = 0: right = _WIDTH
msg$ = "Alien space ship movement demo."
LOCATE 1, (right - left) \ 2 - LEN(msg$) \ 2
PRINT msg$;
LOCATE 1, 2: PRINT STRING$(_WIDTH, "_");
s_delay = 100
DO
_LIMIT 30
IF _KEYDOWN(100306) THEN IF s_delay - 5 > 0 THEN s_delay = s_delay - 5: LOCATE 1, 2: PRINT "Speed delay ="; s_delay / 100; " ";
IF _KEYDOWN(100308) THEN IF s_delay < 500 THEN s_delay = s_delay + 5: LOCATE 1, 2: PRINT "Speed delay ="; s_delay / 100; " ";
IF LEN(INKEY$) THEN SOUND 1000, .1
alien_move
LOOP
SUB alien_move:
STATIC a_y(5), a_x(5), olda_y(5), olda_x(5), inertia(5), ran(5), ran_y(5), ran_x(5), oldran(5), z5, z6, itr, alien_ship_max
IF alien$ = "" THEN alien$ = "-<>-": alien_ship_max = 5 ' Initiate.
IF ABS(z5 - TIMER) > s_delay / 1000 THEN ' Time delay.
DO
itr = itr + 1: IF itr > alien_ship_max THEN itr = 1 ' Needed to offset the EXIT DO hover event, which on exit does not affect the itr variable.
y_restore = CSRLIN: x_restore = POS(0) ' Restore column and row upon exit.
IF olda_y(itr) <> 0 AND olda_x(itr) <> 0 THEN LOCATE olda_y(itr), olda_x(itr): PRINT SPACE$(LEN(alien$));
IF inertia(itr) = 0 THEN
inertia(itr) = INT(RND * (bottom - top) / 2) + 1 ' How many moves to go in any one direction.
ran(itr) = INT(RND * 8) + 1 ' Choose 1 of 8 possible directions.
IF ran(itr) = oldran(itr) OR olda_y(itr) = 0 AND olda_x(itr) = 0 AND ran = 1 OR olda_y(itr) = 0 AND olda_x(itr) = 0 AND ran = 5 THEN
EXIT DO ' 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 ran(itr) ' Get changes in column and row coordinates.
CASE 1: ran_y(itr) = -1: ran_x(itr) = 0 ' Up.
CASE 2: ran_y(itr) = -1: ran_x(itr) = 1 ' Up and right.
CASE 3: ran_y(itr) = 0: ran_x(itr) = 1 ' Right.
CASE 4: ran_y(itr) = 1: ran_x(itr) = 1 ' Down and right.
CASE 5: ran_y(itr) = 1: ran_x(itr) = 0 ' Down.
CASE 6: ran_y(itr) = 1: ran_x(itr) = -1 ' Down and left.
CASE 7: ran_y(itr) = 0: ran_x(itr) = -1 ' Left.
CASE 8: ran_y(itr) = -1: ran_x(itr) = -1 ' Up and left.
END SELECT
IF olda_y(itr) = 0 AND olda_x(itr) = 0 THEN ' New alien space ship enters the screen.
a_y(itr) = (bottom - top) \ 2: a_x(itr) = (right - left) \ 2 ' Center sreen.
a_y(itr) = (bottom - top) \ 4 + RND * (bottom - top) \ 4
IF ran(itr) < 5 THEN ' Determine side of entry from initial direction.
a_x(itr) = left + 1 ' Enter from the left side and go right.
ELSE
a_x(itr) = right - LEN(alien$) ' Enter from the right side and go left.
END IF
END IF
oldran(itr) = ran(itr) ' Remember last direction. Another line uses this to disallow any RND that chooses the same direction twice.
ELSE
inertia(itr) = inertia(itr) - 1 ' Count down the number of moves in any one direction. When zero, switch direction.
END IF
a_y(itr) = a_y(itr) + ran_y(itr): a_x(itr) = a_x(itr) + ran_x(itr) * 2 ' Next move coordinates. I use * 2 for horizontal movement to match the 16x8 pixel height over width factor.
IF a_y(itr) < top OR a_y(itr) > bottom OR a_x(itr) <= left OR a_x(itr) + LEN(alien$) > right THEN
olda_x(itr) = 0: olda_y(itr) = 0: inertia(itr) = 0: oldran(itr) = 0 ' Out of bounds and off the screen.
ELSE
LOCATE a_y(itr), a_x(itr): PRINT alien$; ' Move alien space ship.
olda_y(itr) = a_y(itr): olda_x(itr) = a_x(itr) ' Remember these coordinates to erase alien space ship on next loop.
END IF
IF itr = alien_ship_max THEN itr = 0: EXIT DO
IF ABS(z6 - TIMER) > s_delay / 2 THEN skipz5 = -1: EXIT DO
LOOP
IF skipz5 = 0 THEN z5 = TIMER
z6 = TIMER
LOCATE y_restore, x_restore ' Restore entry column and row positions.
END IF
END SUB
Next up, how about we see what happens when those idiot aliens run into each other?
Pete
RE: In the spirit of Terry's Tutorials - Alien Space Ship - Pete - 10-05-2022
To make an explosion with a collision, a simple FOR/NEXT loop is created to check the coordinates of each space ship. If they intersect, the program call the sub "explosion." The explosion sub consists of a particle burst, flashing screen, produced with a palette loop, and thunder sounds, which require downloading and unzipping the attached zip containing the .ogg sound file.
Stage 5)
Code: (Select All) DIM SHARED top, bottom, left, right, s_delay
a = 120: b = 42
WIDTH a, b
_SCREENMOVE 0, 0
top = 3: bottom = _HEIGHT: left = 0: right = _WIDTH
msg$ = "Alien space ship movement demo."
LOCATE 1, (right - left) \ 2 - LEN(msg$) \ 2
PRINT msg$;
LOCATE 1, 2: PRINT STRING$(_WIDTH, "_");
VIEW PRINT top TO bottom ' Needed to set print error parameters.
s_delay = 100
DO
_LIMIT 30
IF _KEYDOWN(100306) THEN IF s_delay - 5 > 0 THEN s_delay = s_delay - 5: LOCATE 1, 2: PRINT "Speed delay ="; s_delay / 100; " ";
IF _KEYDOWN(100308) THEN IF s_delay < 500 THEN s_delay = s_delay + 5: LOCATE 1, 2: PRINT "Speed delay ="; s_delay / 100; " ";
IF LEN(INKEY$) THEN SOUND 1000, .1
alien_move
LOOP
offscreen:
IF ERR = 5 THEN er = -1: RESUME NEXT
PRINT "Opps, you have an error"; ERR
END
SUB alien_move:
STATIC alien$, a_y(5), a_x(5), olda_y(5), olda_x(5), inertia(5), ran(5), ran_y(5), ran_x(5), oldran(5), z5, z6, itr, alien_ship_max
IF alien$ = "" THEN
alien$ = "-<>-": alien_ship_max = 5 ' Initiate.
CALL explosion ' Loads sound files on first call.
END IF
IF ABS(z5 - TIMER) > s_delay / 1000 THEN ' Time delay.
DO
itr = itr + 1: IF itr > alien_ship_max THEN itr = 1 ' Needed to offset the EXIT DO hover event, which on exit does not affect the itr variable.
y_restore = CSRLIN: x_restore = POS(0) ' Restore column and row upon exit.
IF olda_y(itr) <> 0 AND olda_x(itr) <> 0 THEN LOCATE olda_y(itr), olda_x(itr): PRINT SPACE$(LEN(alien$));
IF inertia(itr) = 0 THEN
inertia(itr) = INT(RND * (bottom - top) / 2) + 1 ' How many moves to go in any one direction.
ran(itr) = INT(RND * 8) + 1 ' Choose 1 of 8 possible directions.
IF ran(itr) = oldran(itr) OR olda_y(itr) = 0 AND olda_x(itr) = 0 AND ran = 1 OR olda_y(itr) = 0 AND olda_x(itr) = 0 AND ran = 5 THEN
EXIT DO ' 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 ran(itr) ' Get changes in column and row coordinates.
CASE 1: ran_y(itr) = -1: ran_x(itr) = 0 ' Up.
CASE 2: ran_y(itr) = -1: ran_x(itr) = 1 ' Up and right.
CASE 3: ran_y(itr) = 0: ran_x(itr) = 1 ' Right.
CASE 4: ran_y(itr) = 1: ran_x(itr) = 1 ' Down and right.
CASE 5: ran_y(itr) = 1: ran_x(itr) = 0 ' Down.
CASE 6: ran_y(itr) = 1: ran_x(itr) = -1 ' Down and left.
CASE 7: ran_y(itr) = 0: ran_x(itr) = -1 ' Left.
CASE 8: ran_y(itr) = -1: ran_x(itr) = -1 ' Up and left.
END SELECT
IF olda_y(itr) = 0 AND olda_x(itr) = 0 THEN ' New alien space ship enters the screen.
a_y(itr) = (bottom - top) \ 2: a_x(itr) = (right - left) \ 2 ' Center sreen.
a_y(itr) = (bottom - top) \ 4 + RND * (bottom - top) \ 4
IF ran(itr) < 5 THEN ' Determine side of entry from initial direction.
a_x(itr) = left + 1 ' Enter from the left side and go right.
ELSE
a_x(itr) = right - LEN(alien$) ' Enter from the right side and go left.
END IF
END IF
oldran(itr) = ran(itr) ' Remember last direction. Another line uses this to disallow any RND that chooses the same direction twice.
ELSE
inertia(itr) = inertia(itr) - 1 ' Count down the number of moves in any one direction. When zero, switch direction.
END IF
a_y(itr) = a_y(itr) + ran_y(itr): a_x(itr) = a_x(itr) + ran_x(itr) * 2 ' Next move coordinates. I use * 2 for horizontal movement to match the 16x8 pixel height over width factor.
IF a_y(itr) < top OR a_y(itr) > bottom OR a_x(itr) <= left OR a_x(itr) + LEN(alien$) > right THEN
olda_x(itr) = 0: olda_y(itr) = 0: inertia(itr) = 0: oldran(itr) = 0 ' Out of bounds and off the screen.
ELSE
LOCATE a_y(itr), a_x(itr): PRINT alien$; ' Move alien space ship.
' Check for collisions.
FOR i = 1 TO alien_ship_max
IF i <> itr AND a_y(i) <> 0 THEN
IF a_y(itr) = a_y(i) AND a_x(itr) >= a_x(i) AND a_x(itr) < a_x(i) + LEN(alien$) THEN
LOCATE a_y(i), a_x(i): PRINT SPACE$(LEN(alien$));: LOCATE a_y(itr), a_x(itr): PRINT SPACE$(LEN(alien$));
CALL explosion
a_y(irt) = 0: a_x(i) = 0 ' Remove exploded alien space ships.
END IF
END IF
NEXT
olda_y(itr) = a_y(itr): olda_x(itr) = a_x(itr) ' Remember these coordinates to erase alien space ship on next loop.
END IF
IF itr = alien_ship_max THEN itr = 0: EXIT DO
IF ABS(z6 - TIMER) > s_delay / 2 THEN skipz5 = -1: EXIT DO
LOOP
IF skipz5 = 0 THEN z5 = TIMER
z6 = TIMER
LOCATE y_restore, x_restore ' Restore entry column and row positions.
END IF
END SUB
SUB explosion
STATIC sound_check, soundfile%, t1&, t6&, t7&, t8&
IF sound_check = 0 THEN
IF _FILEEXISTS("Thunder1.ogg") AND _FILEEXISTS("Thunder1.ogg") AND _FILEEXISTS("Thunder1.ogg") AND _FILEEXISTS("Thunder1.ogg") THEN soundfile% = -1
IF soundfile% THEN
t1& = _SNDOPEN("Thunder1.ogg", "SYNC")
t6& = _SNDOPEN("Thunder6.ogg", "SYNC")
t7& = _SNDOPEN("Thunder7.ogg", "SYNC")
t8& = _SNDOPEN("Thunder8.ogg", "SYNC")
END IF
sound_check = -1
EXIT SUB
END IF
b_y1 = CSRLIN: b_x1 = POS(0)
h = 0
ON ERROR GOTO offscreen
DO
IF h = 1 THEN burst$ = " " ELSE burst$ = CHR$(249)
h = h + 1
GOSUB flash
FOR i = 1 TO 5
SELECT CASE i
CASE 1
COLOR 15
LOCATE b_y1, b_x1: PRINT burst$;
_DELAY .1
CASE 2
IF burst$ = CHR$(249) THEN burst$ = CHR$(250)
COLOR 14, 0
LOCATE b_y1 - 1, b_x1
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1, b_x1 - 1
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1, b_x1
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1, b_x1 + 1
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1 + 1, b_x1
IF er = 0 THEN PRINT burst$; ELSE er = 0
_DELAY .1
CASE 3
LOCATE b_y1 - 1, b_x1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1, b_x1 - 1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1, b_x1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1, b_x1 + 1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1 + 1, b_x1
IF er = 0 THEN PRINT " "; ELSE er = 0
CASE 4
COLOR 4
LOCATE b_y1 - 1, b_x1 - 1
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1 - 1, b_x1 + 1
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1, b_x1 - 2
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1, b_x1
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1, b_x1 + 2
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1 + 1, b_x1 - 1
IF er = 0 THEN PRINT burst$; ELSE er = 0
LOCATE b_y1 + 1, b_x1 + 1
IF er = 0 THEN PRINT burst$; ELSE er = 0
_DELAY .3
CASE 5
LOCATE b_y1 - 1, b_x1 - 1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1 - 1, b_x1 + 1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1, b_x1 - 2
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1, b_x1 - 1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1, b_x1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1, b_x1 + 1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1, b_x1 + 2
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1 + 1, b_x1 - 1
IF er = 0 THEN PRINT " "; ELSE er = 0
LOCATE b_y1 + 1, b_x1 + 1
IF er = 0 THEN PRINT " "; ELSE er = 0
END SELECT
NEXT
IF h = 1 THEN h = 0: EXIT DO
LOOP
ON ERROR GOTO 0
COLOR 7
EXIT SUB
flash:
IF eflag THEN
IF ABS(z7 - TIMER) > .1 THEN
eflag = 0
PALETTE 0, 0
z7 = TIMER
ELSE
j = -j * -1
IF j = 0 THEN
PALETTE 0, 63
_DELAY .05
ELSE
PALETTE 0, 0
_DELAY .05
END IF
END IF
END IF
IF eflag = 0 THEN
PALETTE 0, 36
IF soundfile% THEN
_SNDPLAY t1&
_DELAY .05
PALETTE 0, 0
_SNDPLAY t7&
ELSE
_DELAY .075
END IF
eflag = -1
z7 = TIMER
END IF
PALETTE 0, 0
RETURN
END SUB
In the next update the aliens will be given a bit more A.I. to avoid colliding with one another.
Pete
RE: In the spirit of Terry's Tutorials - Alien Space Ship - vince - 10-05-2022
cool, this is like Steve's style of tutorial where the code is the tutorial and vice versa, but nice try guys
RE: In the spirit of Terry's Tutorials - Alien Space Ship - Pete - 10-05-2022
(10-05-2022, 07:53 PM)vince Wrote: cool, this is like Steve's style of tutorial where the code is the tutorial and vice versa, but nice try guys
It is. In my younger days, I used to code in all caps, no indentation, and no remark statements. Pushing into my 70's, I can't imagine I could understand my projects if I went back to that coding style. So this is a bit overboard in the other direction, but who knows, a decade from now it might be what keeps me coding.
Pete
|