If the sinescroll code ran at 60 fps with the basic canvas? 
It depends on monitor Hz and used code so there can't be a generic "Yes" answer.
Like TRon already mentioned, take advantage from buffering and just render whats needed to be rendered.
My suggestion, change your "Draw" method that it output a TBitmap instead of accessing the destination canvas, that way you can pump one finished rendering and straight work on the next while the LCL cares about to paint your bitmap on whatever canvas. (simple doublebuffer)
And if you want to make it simple for the interested beginners, that is first of all a really nice doing from your side but I can't say it often enough, name your variables/methods logical for others not for your own doings, make code readable.
Or would you know what that header arguments mean if you have not coded it?
constructor Create(font_name: string; offset: Char; w, py, fw, fh, sh: Integer;s_speed: integer; text: string);
a beginner read:
font_name: cool I enter "Arial"... sad it does not work but why? I entered a font name....
offset: what the heck does that mean? lets find out and try
w, py, fw, fh, sh: cool, a collection of integers
s_speed: okay, this might be something about speed, maybe...
text: hey I remember, that is a property of a TControl, but what does it do here?
if "font_name" mean, tell me a fontfilename, why not call the variable "AFontFilename"?
if "w" means "Width", first rename to "AWidth" and second, the width of what?
and so on, this problematic is like a red line thru all your sources, no offend, just saying.