LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Creating Games? Developing something for fun?

Moderators: Klaus, FourthWorld, heatherlaine, kevinmiller, robinmiller

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Mon Oct 11, 2021 7:11 am

Part22b. Tutorial Stack 14: New Player Move Handeling and Ping Pong Warps

I changed the way the player ship is controlled by the mouse. I didn't like the mouse pointer being right on top of the shop most of the time.
So now it works with any change of the Mouse X direction over 20 pixels.

Code: Select all

    if abs(item 1 the mouseLoc - lastMouseX) > 20 then
      
      if item 1 of the mouseLoc < lastMouseX then
         put -1 into pXM
         put 180  into playerDirAngle
         put "left" into flyDir 
      end if
      
      if item 1 of the mouseLoc > lastMouseX then
         put 1 into pXM
         put 0 into playerDirAngle
         put "right"into flyDir
      end if
      
      if item 1 of the mouse is not lastMouseX then put item 1 of the mouseLoc into lastMouseX
   end if
That deprecates MouseLocTargetV . Could play with the distance that causes the mouse to change direction but lower values make it a bit jerky, it's really amazing how short 20 pixels is in distance on modern monitors.


Added this bit of code to WarpJump, now our ship goes in one side and appears to bouch out the other in the opposite direction.

Code: Select all

if flyDir is "right" then
      put "left" into  flyDir
      put item 1 of the mouseLoc+30 into lastMouseX 
   else
      put "right" into  flyDir
      put item 1 of the mouseLoc-30 into lastMouseX
   end if
Giving the lastMouseX an artificial position fools PlayerMove into thinking that the current/same mouse position is a shift for intention to move in a direction.

Added some functions to the stack. Not needed just yet. But they took me a bit of time to find or not find online and then figure out.

MidPoint

Code: Select all

--// find midpoint between two locations
function MidPoint x1,x2,y1,y2
   put floor((x1+x2)/2) into x3
   put floor((y1+y2)/2) into y3
   return x3,y3
end MidPoint
Ever where a bullet will go if it shoots through the target? I think magnitude is the right word? Maybe it's velocity?
EndPoint

Code: Select all

--// find the arbitrary endpoint along a line segment given two points
]function EndPoint x1,x2,y1,y2,magnitude
   put floor((x1+x2)/2)+deltaVal(x1,x2)*magnitude into x3
   put floor((y1+y2)/2)+deltaVal(y1,y2)*magnitude into y3
   return x3,y3
end EndPoint
Go doodle a random line graphic in a Livecode stack then iterate over it's points and apply this function to each line. Magic!
rotatePoints

Code: Select all

--// rotate the points of an object
function rotatePoints x, y, cx, cy, tAngle 
   --// x,     //X coords to rotate - replaced on return
   --// y,     //Y coords to rotate - replaced on return
   --// cx,      //X coordinate of center of rotation
   --// cy,      //Y coordinate of center of rotation
   -- // angle)   //Angle of rotation (radians, counterclockwise)
   put cos(tAngle) into tcos 
   put sin(tAngle) into tsin  
   put ((x-cx)*tcos - (y-cy)*tsin) + cx into Xout 
   put ((x-cx)*tsin + (y-cy)*tcos) + cy into Yout
   return xOut & comma & yOut
end rotatePoints
Oh that Rotate Function needs a lot more to it, Radians!
Here's the first part of the geomantric ritual

Code: Select all

 put "SomeGraphicsName" into myG
   if myG is not empty then
      put the points of graphic myG into tPoints
      put the width of graphic myG into W
      put the loc of graphic myG into mLoc
      put item 1 of mLoc into cx
      put item 2 of mLoc into cy
      repeat with i= 1 to 360
         put (i*144)*(pi/180) into radians
         put empty into newPoints
         repeat for each line L in  tpoints
            if L is not empty then
               put item 1 of L into X
               put item 2 of L into Y
               put rotatePoints(x,y,cx,cy,i) into L
            end if
            put L & cr after newPoints
         end repeat
         set the points of graphic myG to newPoints
      end repeat
   end if
Repeat loops are blocking, so the whole thing will happen at once, but if you apply this in say a scrollbar...it's not blocking and it will draw the whole graphic point by point for every iteration of a value.

This may come into play later, but I fear it'll slow the game down.

Okay I'm in the mood to add more sound effects to the game so I'll upload the stack before making a mess of it.

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Tue Oct 12, 2021 10:15 am

Part 23. Tutorial Stack 15: More Sound Effects!
Stack15Options.png
NOTE: Old SHMUP Tutorial Stacks removed. Will attach latest and greatest stacks to my first and last posts of thread.
  • Changes to Tutorial Stack 15
    1. Added sound effects for Enemies & Bullets
    2. Restructured sounds folder for types of sound effects Enemies,PlayerLaser,Weapons,Explode,PlayerCrash
    3. Added InitSoundEffects on ClearActiveSoundPlayers, PlaySoundEffects and SoundPlayersArdLoaded and MusicPlayersAreLoaded
    4. Added local variables soundCount, soundEffectPlayers, activeSoundPlayers, efectsRefreshDelay,currentFXVolume
    5. Modified Enemy & Bullet scripts to activate their own sounds.
    6. PlaySoundEffects stores FXplayer custom property in enemies to turn off looping sound in InactiveEnemies
    7. Added Sound Effects Volume controls and scripts to OptionsGroup, OptionsGroupSetup and OptionsGroupApplied
    8. OptionsGroup passes OptionsNewFXVolume custom property to the stack for OptionsGroupApplied to adjust currentFXVolume
    9. Card "Play" now sends InitFiles on open, Which does InitMusic, InitSounds, before InitGame is called
    10. InitMusic & InitSoundEffects set bMusicInitPassed & bSoundsInitPassed to tell InitFiles they've suceeded.
    11. InitFiles sets bInitFilesComplete to true, although not sure that's needed at all.
    12.InitSoundEffects attempts to make 20 total players for each type of the files it finds regardless of the number of files.(ie, 20 bullet player, etc)
    13. Player crash into enemy bullet bypasses PlaySoundEffects to play a crash sound based on the number of playerLives
    14. Fixed LoadingScreen it was locking screen before it was showing it's messages.
    15. Added activeSoundPlayers field to "Developer" group, added condition to UpdateListLabel to exit if "Developer" group not visible
    16. Added condition to InactiveEnemies, InactiveBullets, InactiveMissiles to exit if not on card "Play"
Okay InitSoundEffects looks into the Sounds folder and digs around for folders, ignoring loose files in the Sounds folder root.
For every folder it finds, "Enemy" for instance, it creates a player object for each file inside and labels the player object Enemy1, Enemy2, Enemy3 etc.

Oh you can get the sounds and music I've been using here: Data folder with music and sound effects
The Data folder included with the stack is empty place holder
You always just use your own favorite MP3 files.
For sound effects I use BFXR

InitSoundEffects looks just like InitMusic only I went ahead an added an additional loop to create 20 player objects despite the number of actual files.
PlaySoundEffects effect juggles activeSoundPlayers with repeat loop to filter active players from the soundEffectPlayers lists to arrive at a list of available players That's a repeat loop every bullet, every enemy every missile...bleh. Maybe if all goes well with this 20 players for every sound type set up I can just iterate 1...2...3 and skip all looping. Right now I can't tell my ears can only take in so much sound at a time while my brain is busy shooting aliens. Seems to work...
Let's have a look here...in parts.

-------- BEGIN InitSoundEffects ---------

Code: Select all

--// load all sounds in directory path  to players
on InitSoundEffects
   loadingScreen "LOADING SOUNDS"
   --lock screen
   set itemDel to "/"
   
SoundPlayersArdLoaded checks for filenames in all existing player objects, if it returns true we exit InitSoundEffects

Code: Select all

   --// if the player objects already have songs, don't load files
   if SoundPlayersArdLoaded() is true then
      view "all sound players preloaded"
      put true into  bSoundsInitPassed
      exit InitSoundEffects
   end  if
   
If no sound folder exit initSoundEffects

Code: Select all

   put  soundDirectory() into tSoundsFolder
   --// there is no music directory, skip all this handler
   if there is not a folder tSoundsFolder then 
      put true into  bSoundsInitPassed
      exit InitSoundEffects
   end  if
  
Okay we found a Sound folder, but are there subfolders? No? Exit InitSoundEffects

Code: Select all

   set the cursor to busy
   --// if there is a sounds  folder ... 
   set the folder to tSoundsFolder
   put folders() into tSoundsSubDirs
   filter tSoundsSubDirs without ".."
   if number of lines of tSoundsSubDirs is 0 then
      put true into  bSoundsInitPassed
      exit InitSoundEffects
   end if
   
Got subfolders? Now we roll through every folder get the sound files in them via FilteredMusicFiles , that should be FilteredAudioFiles now

Code: Select all

   --// iterate over each sub folder of the Sounds folder
   repeat for each line SD in tSoundsSubDirs
      put soundDirectory() & "/"& SD into curSubDir
      set the folder to curSubDir
      put FilteredMusicFiles(SD) into tSoundFiles
      put curSubDir & cr after allcsds
      put the number of lines of tSoundFiles into tFilesCount
      if tFilesCount is 0 then next Repeat
      set itemDel to comma
      
Even if we only have 3 files, we'll make 20 players and fill them up by iterating over the files again and again

Code: Select all

      put 0 into playersOfTypeSD
      --// why not 20 players for everything?
      repeat while  playersOfTypeSD < 20
      [code]

Collec the files one by one, name the new player object after the folder and the incrementing [i]playersOfTypeSD [/i] value (1..2..3 etc)
[code]
         --// iterate over each file in the subfolder 
         repeat with i = 1 to tFilesCount
            --//player named after folder and file number
            add 1 to playersOfTypeSD
            put SD &   playersOfTypeSD into playerObjName
            put line i of tSoundFiles into theSound
            view "",theSound, playerObjName
            put curSubDir  &"/" & theSound into fPath


if player objects don't exist, create them...offscreen and bury them under the loading screen

Code: Select all

            --//make new player objects if needed
            if exists(player playerObjName) is false then
               --// spawning offscreen to avoid the ugliness
               set the left of the templatePlayer to item 1 of CenterScreen()
               set the bottom of the templatePlayer to -20
               create player
               set the name of the last player to playerObjName
               set the layer of the last player to bottom
            end if
            
Give the player a filename for the sound it'll play, al the other basic sound player settings too

Code: Select all

            put the number of players of this stack ---//oops left that in.
            set the fileName of player playerObjName to fPath
            set the currentTime of player playerObjName to 0
            set the playLoudness of player playerObjName to currentFXVolume
            set the lastTime of player playerObjName to -1
            put cr & playerObjName after   soundEffectPlayers
            --// setting it here, for now, just so we can see that it was made
            set the loc of player  playerObjName to item 1 of CenterScreen(),20
            

Code: Select all

         end repeat
      end repeat 
   end repeat
   
End looping through files
End looping until player count of each type ( ie, subfolder) is 20
End looping through subfolders of the Sound folder

Set the local variable soundCount so we can see how many sound effect players we have at a glance later in scripts.

Code: Select all

   filter soundEffectPlayers without empty
   put the number of lines of soundEffectPlayers into soundCount
   

Code: Select all

   view "","All sounds loaded"
   set the cursor to arrow
   put true into  bSoundsInitPassed
end InitSoundEffects
[code]
Leave a message in the [i]viewer [/i]button, change the cursor back to action arrow mode, set [i]bSoundsInitPassed [/i]to true so that [b]InitFiles [/b]knows it can continue on to [b]InitGame[/b]. Done!
[b]-------------END InitSoundEffects of stack script[/b]


[b]SoundPlayersArdLoaded [/b]was a bulky part of the original [b]InitMusic[/b], that I lifted out into its own function, it got bulkier on it's own!
------ -BEGIN SoundPlayersArdLoaded of stack script
[code]
function SoundPlayersArdLoaded
   put the number of players of this card into nPlayers
   if nPlayers is  0 then return false
   
We don't need to continue if there are no players to sift for data.

Collect a list all the players on the card, remove the music players labeled "Song1","Song2", etc

Code: Select all

   put 0 into soundCount
   set itemDel to "/"
   --// first get a list of the playerNames
   repeat with p = 1 to nPlayers
      put cr & the short name of player P  after soundPLayerNames
   end repeat
   filter soundPLayerNames without empty
   filter soundPLayerNames without "Song*"
   
Here's the meat, looking for filenames in the players, make a new list of positive results

Code: Select all

   --// iterate over soundEffectPlayers to see if they have filenames
   repeat for each line playerObjName in soundPLayerNames
      if exists(player playerObjName) is false then next repeat
      if the filename of player playerObjName is not empty then
         put item -1 of the fileName of player playerObjName into theSound
         put theSound & cr after allSounds
         view "",theSound  
         add 1 to soundCount
      end if
   end repeat  
      filter soundPLayerNames without empty
   
Compare the number of players (that are not songs) with the number of players that have sound filenames properties filled.
Retrurn true to InitSoundEffects if the values are equal so it can skip all that file loading/object making business.

Code: Select all

   put the number of lines of soundPLayerNames into soundplayerCount
   if soundCount = soundplayerCount and soundCount is not 0 then
      put soundPLayerNames into soundEffectPlayers
      return true
   end if
   
If even one player is missing a filename, we'll return false to InitSoundEffects and load up all sounds again from scratch.

Code: Select all

   return false
end SoundPlayersArdLoaded
------ -END SoundPlayersArdLoaded of stack script

We'll continue in the next post.
Last edited by xAction on Fri Oct 15, 2021 12:06 am, edited 1 time in total.

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Tue Oct 12, 2021 11:51 am

Part23b. Tutorial Stack 15. PlaySoundEffects , ClearActiveSoundPlayers, OptionsApplies, OptonsGrouSetup, InitFiles
When the player shoots, an enemy shoots, an enemy travels onto the screen, or when things explode PlaySoundEffects is there to give it a voice.

---------- BEGIN ]PlaySoundEffects of the stack script ----------------

Code: Select all

on PlaySoundEffects tType,tSource
   --if soundCount is 0 then exit PlaySoundEffects
   
This commented code is worth a comment. I don't know why but soundCount keeps resetting to 0 when I leave the game to do some programming stuff. The stack locals get reset when switching from browse to pointer tool? Anyway I had to disable that line or the whole handler would stop running before it even got started.

soundEffectPlayers are the actual player objects on the stack, activeSoundPlayers are the player objects playing sounds at the moment.
We want to store their data in temporary variables here so we can filter them without changing them.

Code: Select all

   put soundEffectPlayers into tPlayersAvailable
   put activeSoundPlayers into tActiveSounds
   
Here we filter for type, for instance if we pressed the mouse button we'd sent it "PlayerLaser"

Code: Select all

   filter tActiveSounds with tType&"*"
   filter tPlayersAvailable with tType&"*"
   
Here's that loop I'd like to get rid of. We remove the active sounds from the available sounds list

Code: Select all

   --// don't use an active sound player
   repeat for each line L in tAciveSounds
      filter tPlayersAvailable without L
   end repeat
   
If there are no players available for this sound type, ClearActiveSoundPlayers will stop one from playing and give us one to use.

Code: Select all

   put the number of lines of tPlayersAvailable into pAva
   if pAva < 1 then
      ClearActiveSoundPlayers tType
      put 1 into pAva
   end if
    
The number of lines of tPlayersAvailable can never be zero with the condition above...This condition will probably get removed.

Code: Select all

   if pAva > 0 then
   
Of pick a random player object of the available player objects. if we picked a existing player then play the sound it contains in its filename property.

Code: Select all

      put random(pAva) into nSound
      put line nSound of tPlayersAvailable into tSoundFXPlayer
      put cr & tSoundFXPlayer after activeSoundPlayers
      filter activeSoundPlayers without empty
      if exists (player tSoundFXPlayer) then
         play player tSoundFXPlayer
         set the lastTime of player tSoundFXPlayer to -1
         
The lastTime custom property was carried ovre from music files, to be used in case I had some long play sound for some reason.

None of the sound effects should last more than one second, I think, so we can clear their players often, but not too often.
If the Type is an enemy we store the name of the player we derived above in the enemy graphic object, to be stopped later in it it's InactivePlayers call. Enemy sounds loop while the enemy is on screen.

Code: Select all

         if tType is not "Enemy" then
            send ClearActiveSoundPlayers && tType to stack (the mainStack of this stack )in 2 seconds
         else
            set the looping of player tSoundFXPlayer to true
            set the FXplayer of graphic tSource to tSoundFxPlayer 
         end if

Code: Select all

      end if
   end if
end PlaySoundEffects
End if available players are > 0
End if there exists a player object with the name randomly selected from available players
end the handler
-------------------END of PlaySoundEffects of stack script --------------------------------------

ClearActiveSoundPlayers Gives us a player of the given type back every 2 seconds.

Code: Select all

on ClearActiveSoundPlayers tType
   put activeSoundPlayers into tPlayerList
   filter tPlayerList with tType&"*"
   put line 1 of tPlayerList into tclearedPlayer
   if tclearedPlayer is empty then exit ClearActiveSoundPlayers
   if exists (player tClearedPlayer) then 
      stop player tclearedPlayer
      set the lastTime of player tclearedPlayer to -1
   end if
   filter  activeSoundPlayers without tclearedPlayer
end ClearActiveSoundPlayers
   

Relevant changes to OptionsGroupSetup look like this

Code: Select all

   
   --// sound effects volume
   put currentFXVolume into FXVal
   put the left of graphic "FXVolumeSlider"+FXVal into FXvolX
   set the loc of graphic "FXVolumeSliderRectangle" to  FXvolX,item 2 the loc of graphic  "FXVolumeSlider"
   put FXVal into field "FXVolumeValue"
OptionsApplied gets a little more complicated since we need to isolate song players, update them, then iterate over sound effects players

Code: Select all

  --// VOLUME
   put the number of players of this stack into nPlayers
   if nPlayers > 0 then 
      repeat with i  = 1 to nPlayers
         put cr & the short name of player i of this stack after allPlayers
      end repeat
      
Player object names acquired. Update to match changes made in OptionsGroup
Music

Code: Select all

      --// music volume
      put the OptionsNewVolume of stack (the mainStack of this stack)into vVal
      put allPlayers into MusicPlayers
      filter Musicplayers with "Song*"
      repeat for each line SoPl in MusicPlayers
         set the playLoudness of player SoPl of this stack to vVal
      end repeat
      put vVal into currentMusicVolume
      
Then sound effects

Code: Select all

      --// sound effects volume
      put the OptionsNewFXVolume of stack (the mainStack of this stack)into fxvVal
      put allPlayers into soundEffectPlayers
      filter soundEffectPlayers without "Song*"
      filter soundEffectPlayers without empty
      repeat for each line SfxPl in soundEffectPlayers
         set the playLoudness of player SfxPl of this stack to fxvVal
      end repeat
      put fxvVal into currentFXVolume
   end if
   put the number of lines of soundEffectPlayers into soundCount[/code
InitFiles now manages the startup of the game, files first, fun after
bMusicInitPassed & bSoundsInitPassed are set true as long as Initmusic and InitSoundEffects don't completely fail to run.
Even if their are no sounds or music, the game can contiue.
This is signaled by the "Play" card script on OpenCard

Code: Select all

on InitFiles
   InitMusic
   InitSoundEffects
   if  bMusicInitPassed is true and bSoundsInitPassed is true then
      put true into bInitFilesComplete
      InitGame 
   end if
end InitFiles
Let's see what's in enemy scripts....the get a new local variable soundActivated that is default to false, then if they are in the screen rect it is set to true, we don't want to keep activing different sound players for one enemy, one will do, so a bool keeps things cool.
The enemy passes it's own name to PlaySoundEffects , so PlaySoundEffects can pass a player name back to the enemy to be disabled when they are.

Code: Select all

   --// enemy is on screen, shoot at the player
   if enemyXY is within stackRect then 
      if soundActivated is false then
         PlaySoundEffects "Enemy",(the short name of me)
         put true into soundActivated
      end if
Bullets get a one shot activation when they launch at the end of PrepareToFire

Code: Select all

on PrepareToFire
--//
---// more script here in the bullet script
---//
   PlaySoundEffects "Weapon"
   BulletFly
end PrepareToFire
Think that covers the sound effects. It's a much more exciting game now. pew pew pew
Last edited by xAction on Sun Oct 17, 2021 12:58 am, edited 3 times in total.

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Wed Oct 13, 2021 12:35 pm

Part 24. Tutorial Stack 16. Updates & Improvements
Stack16OptionsGroup.png
Stack16OptionsGroup.png (17.03 KiB) Viewed 828 times
NOTE: Old SHMUP Tutorial Stacks removed. Will attach latest and greatest stacks to my first and last posts of thread.
  • Changes to Tutorial Stack 16
    1. Changed InactiveMissiles, InactiveBullets, InactiveEnemies to not be plural, so an enemy name can be used to send the message without much fuss
    3. Added GraphicsRestage to stage all the graphics,
    4. Added step in Stagegraphics to clear active object lists
    5. Added ZeroFXPlayers to stop players of a type and set their currentTime to 0
    6. Fixed typo in SoundEffectsARELoaded function name
    7. Added SoundEffectsAreLoaded to ResumeGame to ensure the sounds work, not sure why variables zero out during pause
    8. Added fxPlayersAvailable list variable to keep track of whats available
    9. Removed Repeat loop from PlaySoundEffects, popping players on/off fxPlayersAvailable list keeps track
    10. Added ClearActiveSoundPlayers to FireMissile to ensure a sound player is available when a missile is
    11. Added InactiveFXPlayer to handle Enemy recycling of sound players, could be used for other objects that loop...
    12. Added ClearActiveSoundPlayers "Explode" to explosions DeactiveExplosion handler to make sure their sound players get recycled
    13 Removed send ClearActiveSoundPlayers in 2 seconds line from PlaySoundEffects
    14 Removed some exttra conditions from PlaySoundEffects
    15. Added EnemyCenterTargetLoc as first destination of enemies to be point near center screen, then they pick second target to exit screen
    16. Moved StoreEffectStates out of InitGame and into the object "Make" commands as turning off effects and returning to title screen and back to game was clearing the effects entirely
    17. Added MakeGraphicPlayer for making a player graphic with all it's effects on, since they kept getting reset
    18. Added MakePlayerLives to create the player lives icons as their effects got lost, could have more than 3 lives now.
    19. Added MakeAllGameGraphics to recreate all the graphics in the game, except the mountains
    20. Added Effects Toggle for background mountains to Optionsgroup & UseBackMountainFX custom property t
    21. Updated OptionsGroupSetup and OptionsGroupApplied to handle the new options choices
    22. Added MountainGraphicEffects handler to manage turning on/off graphic effects for mountains
    23. Added DevExit handler for cleaning out the players, recreating all the graphics with effects before save and quit
It appears that the graphics effects on the mountains is the biggest slow down, I suspect because its a graphics effect across 14000 pixels times 3, times the size/spread. I've been curious for a long while now how I could fake the whole scrolling effect by repositioning point values. Like
1...2...3...4...5...6
becomes
6...1...2...3...4....5
etc
That would be line numbers of the points of a graphic, so I really only need to draw what is on screen while the rest of the data is held in an array.

Anyway I took the easy way out and wrote a handler and added a toggle switch to add effects if you like a lazy slow space game, or turn them off if you want some speed back in your life. It's blazing when you drop the graphics level to 1980s quality instead of the fancy 1997 Photoshop effects quality.


Okay where to start? Let's look at the PlaySoundEffects change.

Code: Select all

on PlaySoundEffects tType,tSource
   put fxPlayersAvailable into tPlayersAvailable
   put activeSoundPlayers into tActiveSounds
   filter tActiveSounds with tType&"*"
   filter tPlayersAvailable with tType&"*"
   put the number of lines of tActiveSounds into pAct
   put the number of lines of tPlayersAvailable into pAva
   if pact+1 >= 20   then  ClearActiveSoundPlayers tType

   put random(pava) into nSound
   put line nSound of tPlayersAvailable into tSoundFXPlayer
   put cr & tSoundFXPlayer after activeSoundPlayers
   filter activeSoundPlayers without empty
   if exists (player tSoundFXPlayer) then
      play player tSoundFXPlayer
      set the lastTime of player tSoundFXPlayer to -1
      if tType is  "Enemy" then
         set the looping of player tSoundFXPlayer to true
         set the FXplayer of graphic tSource to tSoundFxPlayer 
      end if
   end if
end PlaySoundEffects
No more Repeat loop, fxPlayersAvailable is a big virtual list of all the players available at a given time minus the active ones.
We check if the activeSounds + 1 is > 20, since we made 20 players for every sound type, then we stop a sound player and put it back on the fxPlayersAvailable list to be used.

Enemies were stopping removing the their personal looping effects player from the activeSoundPlayers list but then I realized those players were stuck at the end of their timeline, so rather than bulk the InactiveEnemy handler I made a new one InactiveFXPlayer Now it's a noisey spacey place full of looping alien sounds.

Code: Select all

on InactiveFXPlayer aName
   put the FXPlayer of graphic aName into tPlayer
   if exists(player tPlayer) then
      stop player tPlayer
   set the currentTime of player tPlayer to 0
   filter activeSoundPlayers without tPlayer
   put cr & tPlayer after fxPlayersAvailable
   filter fxPlayersAvailable without empty
   end if
end InactiveFXPlayer
When we 'stage' graphics offscreen we need to shut down all their players and clear the lists so everything can begin anew.
ZeroFXPlayers handles that

Code: Select all

on ZeroFXPlayers aName
   if aName is "Missile" then put "PlayerLaser" into aName
   put activePlayers into tList
   filter tList with aName&"*"
   repeat for each line P in tList
      if exists(player P) then
         stop player p
         set the currentTime of player P to 0
      end if
   end repeat
   filter activePlayers without aName&"*"
end ZeroFXPlayers
Maybe should have called it ClearAllPlayers? Didn't want to confuse it with ClearActiveSoundPlayers which is single player at a time solution.

Code: Select all

on ClearActiveSoundPlayers tType
   put activeSoundPlayers into tPlayerList
   filter tPlayerList with tType&"*"
   put line 1 of tPlayerList into tclearedPlayer
   if tclearedPlayer is empty then exit ClearActiveSoundPlayers
   if exists (player tClearedPlayer) then 
      stop player tclearedPlayer
      set the currentTime of player tclearedPlayer to 0
      set the lastTime of player tclearedPlayer to -1
      put cr & tClearedplayer after fxPlayersAvailable
      filter fxPlayersAvailable without empty
   end if
   filter  activeSoundPlayers without tclearedPlayer
end ClearActiveSoundPlayers
Sounds are a lot of work, they do make things more fun in the end though.
Lets move over to another post for some more scripts.
Last edited by xAction on Sat Oct 16, 2021 10:26 am, edited 2 times in total.

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Wed Oct 13, 2021 1:42 pm

Part 24b. Tutorial Stack 16, Handlers for graphics, effects, & more interesting enemies

23. Added DevExit handler for cleaning out the players, recreating all the graphics with effects before save and quit

GraphicsRestagellooks like so. I forgot the explosions, I'll have that in the next stack and add it here for completness

Code: Select all

on GraphicsRestage
   stageGraphics "Enemy"
   stageGraphics "Explosion"
   stageGraphics "Bullet"
   stageGraphics "Missile"
end GraphicsRestage
Need to clean up? ClearAllGameGraphics gets the graphics out!

Code: Select all

on ClearAllGameGraphics
   put "Explosion,Enemy,Player,PlayerLives,Missile,Bullet" into grTypes
   repeat for each item I in grTypes
      ClearGraphics I
   end repeat
end ClearAllGameGraphics
Then get yourself a whole new bunch of graphics with MakeAllGameGraphics

Code: Select all

on MakeAllGameGraphics
   MakeGraphicPlayer
   MakeEnemies
   MakeExplosions
   MakeProjectiles "Missile"
   MakeProjectiles "Bullet"
   MakePlayerLives 1
   MakePlayerLives 2
   MakePlayerLives 3
end MakeAllGameGraphics
MakeGraphicPlayer: An all new graphic "Player" with their very own hitbox with

Code: Select all

on MakeGraphicPlayer
   if exists (graphic "Player") then delete graphic "Player"
   create graphic
   set the style of the last graphic to "regular"
   set the lineSize of the last graphic to 2
   set the polySides of the last graphic to 3
   set the foregroundColor of the last graphic to 0,255,0
   set the outerGlow["color"] of the last graphic to 0,255,0
   set the opaque of the last graphic to false
   set the outerGlow["size"] of the last graphic to 18
   set the outerGlow["spread"] of the last graphic to 78
   set the width of the last graphic to 24
   set the height of the last graphic to 18
   set the loc of the last graphic to CenterScreen()
   set the name of the last graphic to "Player"
   StoreEffectStates
   if exists (graphic "PlayerHitBox") then delete graphic "PlayerHitBox"
   create graphic
   set the style of the last graphic to "Rectangle"
   set the opaque of the last graphic to false
   set the linesize of the last graphic to 1
   set the blendLevel of the last graphic to 50
   set the foreGroundcolor of the last graphic to 0,40,0
   set the width of the last graphic to 26
   set the height of the last graphic to 26
   set the loc of the last graphic to CenterScreen()
set the name of the last graphic to "PlayerHItbox"
end MakeGraphicPlayer
MakePlayerLives recreates the playerLives icons

Code: Select all

on MakePlayerLives nLife
   put "PlayerLives"&nLife into tObjectName
   if exists (graphic tObjectName) then delete graphic tObjectName
   create graphic
   set the style of the last graphic to "regular"
   set the lineSize of the last graphic to 1
   set the polySides of the last graphic to 3
   set the angle of the last graphic to 30
   set the foregroundColor of the last graphic to 0,255,0
   set the backgroundColor of the last graphic to 0,127,0
   set the opaque of the last graphic to true
   set the outerGlow["color"] of the last graphic to 0,255,0
   set the outerGlow["size"] of the last graphic to 33
   set the outerGlow["spread"] of the last graphic to 52
   set the colorOverlay of the last graphic to false
   set the width of the last graphic to 24
   set the height of the last graphic to 24
   set the top of the last graphic to 20
   set the left of the last graphic to 250+(30*nLife)
   set the name of the last graphic to tObjectName
   StoreEffectStates
end MakePlayerLives
Do you need glowing mountains or you like 'em plain? Apply MountainGraphicEffects

Code: Select all

on MountainGraphicEffects depth,tObject
   switch depth
      case -1
         set the outerGlow of graphic tObject to false
         break
      case 0
         put random(128)+128 into mColor
         set the foregroundColor of the last graphic to mColor,255,0
         set the outerGlow of the last graphic to true
         set the outerGlow["color"] of the last graphic to mColor,255,0
         set the outerGlow["size"] of the last graphic to 15
         set the outerGlow["spread"] of the last graphic to 63
         break
      case 1
         put random(128)+128 into mColor
         set the foregroundColor of  graphic tObject to 0,255,mColor
         set the outerGlow["color"]  graphic tObject to 0,255,mColor
         set the outerGlow["size"] of  graphic tObject to 18
         set the outerGlow["spread"] of  graphic tObject to 55
         break
      case 2
         --//more blue and less visible as we go back in virtual space
         put random(128)+128 into mColor
         set the foregroundColor of  graphic tObject to 128,128,mColor
         set the outerGlow["color"] of  graphic tObject to 128,128,mColor
         --// more haze
         set the outerGlow["size"] of  graphic tObject to 25
         set the outerGlow["spread"] of  graphic tObject to 83
         break
   end switch
end MountainGraphicEffects
Inside the enemy we now have EnemyCenterTargetLoc, they pick a place near center screen as their first destination
Then use the same old EnemyTargetLoc we've been using to give them a destination offscreen, A lot more interesting.
Tempting to give them more complicatd manuevers, ...like maybe they keep picking EnemyCenterTargetLoc until a random number hits some value then they exit the screen. Will try that tomorrow. Or maybe I bounce them around the inside edges of the screen like a billiard ball? hmm.

Code: Select all

--// pick first target inside the screen
on EnemyCenterTargetLoc
   put CenterScreen() into CSxy
   put the loc of me into enemyXY
   put item 1 of enemyXY into eX
   put item 2 of enemyXY into eY
   put random(300)-random(300) +item 1 of CSXY  into destX
   put random(300)-random(300) +item 2 of CSXY into destY
   put   destX & comma & destY into targetLoc
   put  destX-50, destY-50, destX+50, destY+50 into targetRect
   --// get delta to the target location
   put DeltaToTarget(eX,eY,destX,destY) into DxDy
   --// delta values modify  object location each loop
   put item 1 of DxDy  into EspeedX
   put item 2 of DxDy  into EspeedY
end EnemyCenterTargetLoc
And finally we have DevExit, the developers cleaning handler.
Clears all the graphics, recreates them, clears al the sound players, saves the stack with time and date and then asks if you want to quit.

Code: Select all

on DevExit
   set the tool to "pointer tool"
   if the currentCard of this stack is "Play" then
   ClearPlayers
   ClearAllGameGraphics
   MakeAllGameGraphics
   end if
   set the folder to stackDirectory()
   put the short time & the short date into theSaveNums
   replace space with empty in  theSaveNums
   replace ":" with empty in  theSaveNums
   replace "/" with "_" in  theSaveNums
   put "ShmupTutorialStack_"&theSaveNums &".livecode" into tStackPath
   save stack (the mainStack of this stack) as tStackPath
   answer "Saved. Quit?" with "No" or "Yes"
   if it is "Yes" then send QuitCommand to stack (the mainstack of this stack) in 5 seconds
end DevExit
And now I can sleep, hoorah!

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Thu Oct 14, 2021 11:22 am

Part 25. Tutorial Stack 17: More Efficient Collisions, Warp sounds, and other stuff
NOTE: Old SHMUP Tutorial Stacks removed. Will attach latest and greatest stacks to my first and last posts of thread.
  • Changes to Tutorial Stack 17.
    1. Gave Enemies a random number of destinations after they enter the screen
    2. Added sounds effects to warps
    3. Fix some bugs here and there
    4. CheckCollisions is deprecated
    5. IsMIssileInRect checks all 20 missiles for target rect penetration, returns true to target
    6. ObjectInPlayerRect checks for objects in the player rect
    7. IsMissileInRect and ObjectInRect added with conditions in Enemy Scripts
    8. ObjectInPlayRect added to Bullet Scripts
    9. Removed Script setting from StageGraphics so Bullets could stage themselves.
    10. Added RectInRect function but not using it. checks all corners of a rect for penetration of another rect
    11. Added CrashPlayer handler so Enemies and Bullets could set playerCrash to true
    12. Added StopAllSoundEffects to stop sounds during pause mode
    13. Added PauseEnemySound to enemies so they stop looping during pause and restart on ResumeGame
    14. Set enemy playLoudness to a random level lower than currentFXVolume in PlaySoundEffects
    15. Removed Mouseloc check to exit MIssileFly in bullets, it was causing bullets to get stuck on screen
    16. Added Mouseloc check to exit fireMissile if mouse outside of stack rect
    17. Added random sizing to missiles
    18. Added random graphic style to Enemy Bullets.
So big news, CheckCollisions is deprecated, 3 repeat loops, gone!
Now the enemies and bullets check for collision with the player in one handler from within their own personal travel handler

Code: Select all

function ObjectInPlayerRect tObject
   if the currentCard of this stack is not "Play" then return false
   put the rect of graphic "PlayerHitBox" into PlayerRect
   if the loc of graphic tObject is  within PlayerRect then return true
end ObjectInPlayerRect
The enemies check for collision with all 20 missils in another big ugly handler, just look at it.
IsMissileInRect

Code: Select all

function IsMissileInRect tTarget
   if the currentCard of this stack is not "Play" then return false
   put the rect of graphic tTarget into tarRect
   if the loc of graphic "Missile1" is within tarRect then return true
   if the loc of graphic "Missile2" is within tarRect then return true
   if the loc of graphic "Missile3" is within tarRect then return true
   if the loc of graphic "Missile4" is within tarRect then return true
   if the loc of graphic "Missile5" is within tarRect then return true
   if the loc of graphic "Missile6" is within tarRect then return true
   if the loc of graphic "Missile7" is within tarRect then return true
   if the loc of graphic "Missile8" is within tarRect then return true
   if the loc of graphic "Missile9" is within tarRect then return true
   if the loc of graphic "Missile10" is within tarRect then return true
   if the loc of graphic "Missile11" is within tarRect then return true
   if the loc of graphic "Missile12" is within tarRect then return true
   if the loc of graphic "Missile13" is within tarRect then return true
   if the loc of graphic "Missile14" is within tarRect then return true
   if the loc of graphic "Missile15" is within tarRect then return true
   if the loc of graphic "Missile16" is within tarRect then return true
   if the loc of graphic "Missile17" is within tarRect then return true
   if the loc of graphic "Missile18" is within tarRect then return true
   if the loc of graphic "Missile19" is within tarRect then return true
   if the loc of graphic "Missile20" is within tarRect then return true
   Return False
end IsMissileInRect
No Repeat loop, no blocking, in and out as soon as it's true! But damn what a wall of text.

The relevant part of EnemyTravel looks like this

Code: Select all

 if IsMissileInRect(the short name of me) is true then
      MissileHit 
      EnemyExplosions (enemyXY)
   end if
   if ObjectInPlayerRect(the short name of me) is true then
      DeactivateEnemy 
      CrashPlayer
      PlaySoundEffects "PlayerCrash"
      EnemyExplosions (enemyXY) 
   end if

While we are in their script lets look at their new destination system.
They get a local variable numberOfDestinations
In their ActivateEnemy handler they do

Code: Select all

put random(8) into numberOfDestinations
Then in EnemyTravel

Code: Select all

 --// has enemy reached destination?
   if enemyXY is within targetREct then 
      
      if numberOfDestinations >= 1 then
         --// stay on screen until destinations are used up
         EnemyScreenTargetLoc
      else
         --// pick an exit target outside the screen
         EnemyTargetLoc
      end if
      
      if enemyXy is not within stackRect then
         --// off screen? Deactivate
         put false into enemyActivated  
         DeactivateEnemy
      end if
   end if
This is abbreviated of course.
I left them showing their number of destinations in their label, which makes me think..could add some extra interior graphics decoration with a few choice characters in their label. "When Dingbats Attack!"

Here's a function that might come in handle someday, but not right now. I tried to solve certain enemies not being hit with this but it slowed things done a lot when called in the repeat loop. I might revisit it from the enemy script if some of them still don't get hit.
It checks every corner and the center of one object for penetration of the rect of another object.
I think this function is used in Pong?

Code: Select all

function RectInRect Object1,Object2
   put the loc of graphic object1 into OneLoc
   put the rect of graphic object1 into OneRect
   put the rect of graphic Object2 into TwoRect
   if number of items of OneRect < 4 then return false
   put item 1 of OneRect & comma & item 2 of OneRect into ToLe --// top left
   put item 3 of OneRect & comma & item 4 of OneRect into BoRi --// bottom right
   put item 1 of OneRect & comma & item 4 of OneRect into BoLe --// Bottom left
   put item 2 of OneRect & comma & item 2 of OneRect into ToRi --// top right
   if ToLe is within TwoRect then return true
   if BoRi is within TwoRect then return true
   if BoLe is within TwoRect then return true
   if ToRi is within TwoRect then return true
   if OneLoc is within TwoRect then return true
   Return False
end RectInRect
Adding sound effects to warps was as easy adding two sounds to a folder called Warp and addig two lines of code in WarpJump

Code: Select all

 ClearActiveSoundPlayers "Warp"
   PlaySoundEffects "Warp"
There's plenty of sound effects players for the warps but I figured I'd keep them clear ahead of needing them.
Last edited by xAction on Sat Oct 16, 2021 10:25 am, edited 3 times in total.

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Fri Oct 15, 2021 4:15 am

Trouble in Tune town, the existance of media players on the card add an additional 20 second delay switching cards before the game even inits.
Or under 3 seconds if their fileNames are empty...

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Fri Oct 15, 2021 8:13 am

Part 26. Tutorial Stack 18. Enemy Decorations. Less Player Objects. Touch up on collisions, and more
NOTE: Old SHMUP Tutorial Stacks removed. Will attach latest and greatest stacks to my first and last posts of thread.

Data folder here with music and sounds
  • Changes to Tutorial Stack 18.
    1. Changed Staged objects spawning at over 20,000 units off screen
    2. Put a lot of View "handler" && the long time all over to watch times, will have to clean up
    3. Added setting viewMessages custom property of stack in View handler to record messages
    4. Added ClearView handler to to clear the custom property and spit out a log file ** It's bugged, spits out garbage, oops
    5. Added conditions in enemies to disable them if they are beyond 3000 units positive or negative in space
    6. Added ClearActiveSoundPlayers to InactiveBullets handler
    7. Changed return True in IsMissileInRect to return the name of the missile so it is sent DeactivateMissile
    8. Reduced the max number of players for mosts sound to just the number of sounds in the folder and 10 for the Missiles
    9. Added minimum number of destinations for enemies to be 3+random(8)
    10. Changed Sound folder "Weapons" to "Bullet" to match game properties , changed scripts to match
    11. Added ListAllPlayers function for all the times I have to iterate through media players
    12. Added ZeroFXPlayers aName to StageGraphics,
    13. Disabled looping property of players in ZeroFXPlayers
    14. Enabled ShapeShiftFunk effects in enemies, they have more personality now
    15 Added WingDings characters to Enemy graphics, now they aren't empty shells
    16. Added deleting Mgroup and Backgroup to DevExit
    17. Added SoundPlayersAreLoaded to InitGame, for some reason game started without sounds...
    18. Still have an issue with enemies traveling to 3000 or -3000 in space...what's their deal?
19. Added OriginH and OriginW custom properties to enemies so their original sizes are maintained after the ShapShfitFunk happens.

A lot of tweeks here and there. Mostly its working as a game should except that weirdness with the enemies flying off to god knows where.
Initially I had them staged at a ridiculous calculation of the numeric value of first charcter of their name multiplied by 200, so enemies eneded up at 20200. When I made that command I was thinking A=1 B=2 etc, not E=101

Adding wingdings to enemies was pretty easy, could make a game with just some funky font graphics.
Abbreivate enemy script for reference

Code: Select all

local wingdings="LR]lmnopstuvw{¡¢£¤¥¦§¨©ª«¬­®¯°±²³µ¶"
....
set the label of me to char random(number of chars of wingdings) of wingdings
   set the textFont of me to "Wingdings"
   set the textSize of me to 10+random(10)
Oh guess we can look at ShapeShfitFunk now that it is activated
up in ActivateEnemy we set a little random personality values

Code: Select all

 put 2+random(4) into hMod
   put 2+random(4) into wMod
Then in ShapeShiftFunk we shimmy shake rattle and roll

Code: Select all

   --// funky shape shifting stuff, has side effects that need to be worked out
on ShapeShiftFunk
   --some funky shape shifting stuff
   put hMod*-1 into hMod
   put wMod*-1 into wMod
   set the height of me to (the height of me)+hMod
   set the width of me to (the width of me)+wMod
   put the properties of me into myProps
   put the keys of myProps into myKeys
   filter myKeys without "Arc*"
   if angle is among the lines of myKeys then
      put the angle of me into myAngle
      if myAngle is not empty then
         add 4 to myAngle
         if myAngle >356 then put 0 into myAngle
         set the angle of me to myAngle
      end if
   end if
end ShapeShiftFunk
IsMissileInRect now sends the Missile name back to the enemy so that DeactivateMissile could be called.
In yesterdays version the missile continued at full strength until it left the screen but we lost 5% of our laser strength until it did.
Relevant part of Enemy script looks like this

Code: Select all

put IsMissileInRect(the short name of me) into MissileObj
   if  MissileObj is not false then
      MissileHit 
      EnemyExplosions (enemyXY)
      Send DeactivateMissile to graphic MissileObj
   end if
New collision seems at lot more reactive, and I think we picked up some all around speed in the process.
Last edited by xAction on Sat Oct 16, 2021 10:26 am, edited 1 time in total.

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Sat Oct 16, 2021 10:23 am

Part 27. Tutorial Stack 19: RandomizeEnemies, sound bug fix,
SHMUP_TUTORIAL_STACK_19.zip
(59.43 KiB) Downloaded 12 times
Get the Data folder here.
  • Tutorial Stack 19 Changes
    1. Added FixSoundsForFullScreen as sounds were stopping if going into full screen, this is called from OptionsApplied
    2. Fixed View sloppy typo that broke setting custom property for log file
    3.Added GraphicsRestage to PlayerRepsawn so player didn't respawn in danger
    4. Adjusted StageGraphics not to set things out at ridiculous distance
    5. Moved FireMissile up in the PlayGame message path seems like something is blocking it sometimes
    6. disabled logging in View handler, recent log was 14,000 lines YIKES
    7. Added RandomizeEnemies to change enemy looks every level
    8. Disabled UpdateListLabels in PlayGame trying to troubleshoot the firemissile bug
    9. Enemies now send EnemyTravel to themselves only every 20 milliseconds instead of 2
    10. Updated Changes_log stack custom property, seems I missed a few stacks
So the big news in this stack is new enemies every level easy peasy

Code: Select all

on RandomizeEnemies
   repeat with N = 1 to 20
      put "Enemy"&N into tEnemy
      set the style of graphic tEnemy to "regular"
      set the polySides of graphic tEnemy to 3+random(10)
      put  15+random(30) into eH
      put  15+random(30) into eW
      set the height of graphic tEnemy  to eH
      set the width of graphic tEnemy  to eW
      set the originH of graphic tEnemy  to eH
      set the originW of graphic tEnemy to eW
      put item N of colorList into tColor
      set the foregroundColor of graphic tEnemy to tColor
      put random(10) into dashrand
      if dashrand > 7 then
         set the dashes of graphic tEnemy to random(3)
      end if
   end repeat
   set the lineSize of graphic tEnemy to random(4)
   --Glamour
   --StoreEffectStates
end RandomizeEnemies
I left off setting and storing new effects in case they had been turned off in options, this way they'll keep what they had.

I had a bug in setting the game to fullscreen where sound effects just wouldn't work so I added a fix.

Code: Select all

on FixSoundsForFullScreen
   LoadingScreen "Fixing Sounds"
   put SoundPlayersAreLoaded() into bSoundsLoaded
   put listAllPlayers() into tList
   filter tList without "Song*"
   repeat for each line L in tList
      set the currentTime of player L to 0
      set the playLoudness of player L to 0
      set the looping of player L to false
      start player L
   end repeat
   repeat for each line L in tList
      set the playLoudness of player L to currentFXvolume
      set the currentTime of player L to 0
   end repeat
   LoadingScreen
end FixSoundsForFullScreen
It completely ignores the playLoudness setting, R.I.P. your years.

I don't know what's blocking FireMissile, it'll blast away endlesslly then suddenly be like "I'm tired, maybe later" then go back to shootin'.
I tried disabling missile delay and that just make it hose missiles more often then still cut out. Was really tempted to add another 20 missiles.
Enemies are still traveling off to some strange distance and I don't know why.
They deactivate at 2000 units in any direction now and I turned off the error messages about that.

Okay I think we hit the limit for what this game can do in Livecode. Around level 5 things get impossible to survive and there is a noticeable creeping slow down. Game goes to level 10...I've never gotten past 5.

Another day or two of bug hunting and I think we'll call it done.

xAction
Posts: 80
Joined: Sun Oct 03, 2021 4:14 am

Re: LiveCode Game Tutorial: Side Scrolling Shoot'em'up

Post by xAction » Sun Oct 24, 2021 11:29 am

Part 28: Ready. Set. Release!
DefensiveBanner.png
DEFENSIVE_RELEASE_1.zip
(44.15 KiB) Downloaded 6 times
Looks good to go. Let's build this beast and put it online!

No. Wait.
  • RELEASE STACK 1 Changes through a dozen builds
    1. added developerToolsGroup to Developer Group
    2. Rawkeydown 65470 ie, F1 Key toggles developer group
    3. if developer group is visible when loadingscreen is activated then developer group gets top level
    4. moved the spawnign of enemies, bullets, missiles, and player objects offscreen
    5. Removed alternate mountain/scroll scripts
    6. Added "MAIN" button to Play card OptionsGroup to return to main Title screen
    7. Added ClearAllGameGraphics and MakeAllGameGraphics, to InitGame
    8. disabled pointer tool in on escapeKey
    9. disabled developer group toggle in on arrowkey
    10. Added ResetDefaults handler for the initial default variables, just to shorten InitGame
    11. commented all stack script handlers and functions
    12. Added PreOpenStack scripting to set game center screen at 75% screen size
    13. Fixed some glitchiness with Quit screen cancel
    14. missiles never had activatedMissile set true, broke did not continue after resume game
    15. update stack called too early crashed the game, fixed that with some condition exist checks
    16. stackDepth returned set things wrong sized in fullscreen, fixex that with screenRect() condition
    17. FixSoundsForFullScreen only runs in fullscreen now
    18. Adjusting the volume of the music isn't working, added setting playLoudness before each starting each player
    19. Fixed FullScreen flipping back to window size, useful for development, but awful for release
Okay. Now it's ready for release. Here's the itch.io link to Defensive SHMUP game made in Livecode with all the music and sounds and builds for every PC platform, although I only tested it on Windows.

I'll upload the final stack here for good measure.

It's been an adventure.

Post Reply

Return to “Games”