i'm struggling to follow what you're doing but it seems you're concerned with the # of sprites that you're creating.
Quote: "i have coded a little piano game with falling tiles."
short version for this: only create sprites that are (about to become) visible and remove them when they're not.
i've never written a rhythm game but here's my take on functionality & handling the sprites/falling tiles:
// Project: Rhythm
// Created: 2021-06-22
// By: Virtual Nomad
// show all errors
SetErrorMode(2)
// set window properties
SetWindowTitle( "Rhythm" )
SetWindowSize( 800,600, 0 )
SetWindowAllowResize( 1 )
// set display properties
SetVirtualResolution( 800,600)
SetOrientationAllowed( 1, 1, 1, 1 )
SetSyncRate( 30, 0 )
SetScissor( 0,0,0,0 )
UseNewDefaultFonts( 1 )
SetPrintSize(30)
Cyan = MakeColor(0,255,255)
For x = 1 to 8
ThisTxt = CreateText(STR(x))
SetTextPosition(ThisTxt, x*30+15, 320)
SetTextSize(ThisTxt,30)
SetTextAlignment(ThisTxt,1)
Next x
GLOBAL Song$ as String []
GLOBAL Notes as Integer []
MakeSong(20)
CurrentRow = 0
SetRow(CurrentRow)
NextTime# = Timer() + 1.0
do
If GetRawKeyState(27) then Exit
ThisTime# = Timer()
If NextTime# <= ThisTime#
INC CurrentRow
If CurrentRow > Song$.Length then CurrentRow = 0
SetRow(CurrentRow)
NextTime# = ThisTime# + 1.0
EndIf
If Notes.Length > -1 then PlaySong()
DrawLine(30,300,270,300,Cyan,Cyan)
Print(GetManagedSpriteCount())
Sync()
loop
Function PlaySong()
For x = Notes.Length to 0 Step -1
ThisNote = Notes[x]
ThisY = GetspriteY(ThisNote)
SetSpriteY(ThisNote, ThisY + 1)
If ThisY >= 270 and ThisY < 300
ThisNum = GetSpriteX(ThisNote)/30
If GetRawKeyPressed(48+ThisNum)
SetSpriteColor(ThisNote,0,255,0,255)
EndIf
Endif
If ThisY >= 300 and GetSpriteColorBlue(ThisNote) = 255 then SetSpriteColor(ThisNote,255,0,0,255)
If ThisY > 330
DeleteSprite(ThisNote)
Notes.Remove(x)
Endif
Next x
EndFunction
Function SetRow(Row)
ThisRow$ = Song$[Row]
For x = 1 to 8
If MID(ThisRow$,x,1) <> "0"
ThisSprite = CreateSprite(0)
SetSpriteColor(ThisSprite,0,0,255,255)
SetSpriteSize(Thissprite,30,30)
SetSpritePosition(ThisSprite,x*30,-30)
Notes.Insert(ThisSprite)
Endif
Next x
EndFunction
Function MakeSong(Length)
For x = 1 to Length
This = Random(1,8)
Row$ = ""
For y = 1 to 8
If y = This then Row$ = Row$ + STR(This) else Row$ = Row$ + "0"
Next y
Song$.Insert(Row$)
Next x
EndFunction
i'm "creating" a "song" which consists of 20 rows of strings 8 characters long. Ie, MakeSong(20).
for this, only 1 note is played at a time but later code accounts for multiple notes being played at once.
then initializing the current row of notes to 0, the corresponding Note/Sprite is generated and placed just above the visible area in its corresponding column (1-8) and added to an array (Notes) for later handling.
the sprite begins falling and then the new row/note/sprite is generated and placed once per second. IE, SetRow(CurrentRow), over and over (the "song" will loop).
as the notes fall (via the PlaySong() function which references the Notes array), i check the y position and corresponding keypress (1-8) as it passes over the line.
if "success", i turn the sprite green. if it passes without being "pressed", turn it red.
when it passes a final threshold, it's deleted and removed from Notes.
note the # in the top left (GetManagedSpriteCount()):
you could have thousands of rows/notes but only those that are visible matter if "handled" similarly.
hope that helps?
fixed 1 flaw. note, to remove "more than 1 note" from the array, you'll need to handle the Notes array better than i have here.
@ NextTime# = ThisTime# + 0.8 and my fingers knot up