#!perl # "Blockhead in Love" v1.0 # by David Seay <g-s@navix.net> # # October 1999 # # To exit press cmd '.' repeatedly until the song stops. # use Mac::Events; use Mac::Windows; use Mac::QuickDraw; use Mac::Fonts; use Mac::Speech; &set_up_graphics; &set_up_music; &set_up_song; $voice = $Voice{"Princess"}; $channel = NewSpeechChannel($voice) or die $^E; SpeakText $channel, "Presenting $song[0], sung by Blockhead." or die $^E; while (SpeechBusy()) {} $voice = $Voice{"Zarvox"}; $channel = NewSpeechChannel($voice) or die $^E; for $n (1..$#song) { if ($song[$n] eq "") { next } ($word,$note,$dur) = split("\t",$song[$n]); &openMouth; SetSpeechPitch $channel, $pitch{$note}; SpeakText $channel, $word or die $^E; select(undef, undef, undef, $dur{$dur} - .1); &closeMouth; select(undef, undef, undef, .1); WaitNextEvent(); } sleep 1; while (SpeechBusy()) {} SetSpeechPitch $channel, 61; SpeakText $channel, "Thank you." or die $^E; while (SpeechBusy()) {} SetSpeechPitch $channel, 60; SpeakText $channel, "You've been a wonderful audience." or die $^E; while (SpeechBusy()) {} DisposeSpeechChannel($channel); RGBForeColor(new RGBColor(@faceColor)); PaintOval($leftEyeLoc); RGBForeColor(new RGBColor(@eyeColor)); PaintOval($leftWinkLoc); sleep 1; &DrawBlockhead; WaitNextEvent while $win->window; # until close box is clicked dispose $win; exit(0); sub DrawBlockhead { SetPort($win->window); PenPat($pat1); RGBForeColor(new RGBColor(@faceColor)); PaintRect($faceSize); RGBForeColor(new RGBColor(@eyeColor)); PaintOval($leftEyeLoc); PaintOval($rightEyeLoc); RGBForeColor(new RGBColor(@noseColor)); PaintOval($noseLoc); RGBForeColor(new RGBColor(@mouthColor)); PaintOval($mouthLoc[0]); } sub openMouth { # &DrawBlockhead; RGBForeColor(new RGBColor(@faceColor)); PaintOval($mouthLoc[0]); RGBForeColor(new RGBColor(@mouthColor)); if ($word =~ /o/) { PaintOval($mouthLoc[2]) } else { PaintOval($mouthLoc[1]) } if ($word =~ /\./) { &blink } } sub closeMouth { &DrawBlockhead; RGBForeColor(new RGBColor(@mouthColor)); PaintOval($mouthLoc[0]); } sub blink { RGBForeColor(new RGBColor(@faceColor)); PaintOval($leftEyeLoc); PaintOval($rightEyeLoc); RGBForeColor(new RGBColor(@eyeColor)); PaintOval($leftWinkLoc); PaintOval($rightWinkLoc); } sub set_up_graphics { @white = split(",","65535, 65535, 65535"); @yellow = split(",","65535, 65535, 0"); @violet = split(",","65535, 0, 65535"); @red = split(",","65535,0,0"); @cyan = split(",","0, 65535, 65535"); @green = split(",","0,65535,0"); @blue = split(",","0,0,65535"); @black = split(",","0,0,0"); $winLeft = 100; $winTop = 100; $winWidth = 150; $winHeight = 140; @faceColor = @yellow; $faceWidth = 100; $faceHeight = 100; @eyeColor = @blue; $eyeWidth = 20; $eyeHeight = 16; @noseColor = @red; $noseWidth = 14; $noseHeight = 30; @mouthColor = @black; $mouthWidth = 40; $mouthHeight = 4; $pat1 = new Pattern q{ XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX }; $winRight = $winLeft + $winWidth; $winBottom = $winTop + $winHeight; $winHorizMid = $winLeft + int($winWidth / 2); $winVertMid = $winTop + int($winHeight / 2); $faceLeft = int(($winWidth - $faceWidth)/2); $faceTop = int(($winHeight - $faceHeight)/2); $faceRight = $faceLeft + $faceWidth; $faceBottom = $faceTop + $faceHeight; $faceHorizMid = $faceLeft + int($faceWidth / 2); $faceHeight = $faceBottom - $faceTop; $faceVertMid = $faceTop + int($faceHeight / 2); $faceSize = new Rect $faceLeft, $faceTop, $faceRight, $faceBottom; $eyeLeft = $faceHorizMid - $eyeWidth - 5; $eyeTop = $faceTop + $eyeWidth; $eyeRight = $faceHorizMid + 5; $eyeBottom = $eyesTop + $eyeHeight; $eyeVertMid = $eyeTop + int($eyeHeight / 2); $leftEyeLoc = new Rect $eyeLeft, $eyeTop, $eyeLeft + $eyeWidth, $eyeTop + $eyeHeight; $rightEyeLoc = new Rect $eyeRight, $eyeTop, $eyeRight + $eyeWidth, $eyeTop + $eyeHeight; $leftWinkLoc = new Rect $eyeLeft, $eyeVertMid, $eyeLeft + $eyeWidth, $eyeTop + $eyeHeight - int($eyeHeight / 4); $rightWinkLoc = new Rect $eyeRight, $eyeVertMid, $eyeRight + $eyeWidth, $eyeTop + $eyeHeight - int($eyeHeight / 4); $noseLeft = $faceHorizMid - int($noseWidth / 2); $noseTop = $eyeTop + $eyeHeight + 2; $noseLoc = new Rect $noseLeft, $noseTop, $noseLeft + $noseWidth, $noseTop + $noseHeight; $mouthLeft = $faceHorizMid - int($mouthWidth / 2); $mouthTop = $noseTop + $noseHeight + 8; $mouthLoc[0] = new Rect $mouthLeft, $mouthTop, $mouthLeft + $mouthWidth, $mouthTop + $mouthHeight; # mouth closed $mouthLoc[1] = new Rect $mouthLeft + 3, $mouthTop, $mouthLeft + $mouthWidth - 3, $mouthTop + $mouthHeight + 10; # mouth open wide $mouthLoc[2] = new Rect $mouthLeft + 7, $mouthTop, $mouthLeft + $mouthWidth - 7, $mouthTop + $mouthHeight + 7; # mouth open some $bounds = new Rect $winLeft, $winTop, $winRight, $winBottom; $win = new MacColorWindow $bounds, "Blockhead", 1, floatProc(), 1; $win->sethook("redraw", \&DrawBlockhead); &DrawBlockhead; sleep 1; } sub set_up_music { @noteNames = split(" ", "c d e f g a b C D E F G A B C1"); @scalePitches = split(",","48,50,52,53,55,57,59,60,62,64,65,67,69,71,72"); for $p (0..$#scalePitches) { $pitch{$noteNames[$p]} = $scalePitches[$p] } $tempo_factor = .28; # Increase if ends of words are clipped # NOTE DURATIONS $dur{e} = .50 * $tempo_factor; # eighth note $dur{de} = .75 * $tempo_factor; # dotted eighth note $dur{'q'} = 1.0 * $tempo_factor; # quarter note $dur{dq} = 1.5 * $tempo_factor; # dotted quarter note $dur{h} = 2.0 * $tempo_factor; # half note $dur{he} = 2.5 * $tempo_factor; # half note + an eighth $dur{dh} = 3.0 * $tempo_factor; # dotted half note $dur{dhe} = 3.5 * $tempo_factor; # dotted half note + an eighth $dur{w} = 4.0 * $tempo_factor; # whole note } sub set_up_song { # SONG FORMAT - items must be delimited by tabs # 1) word or syllable to be sung # 2) pitch (how high or low) # 3) duration (how long) # # Put a period after a word to make Blockhead blink. # # Hint: You can use a spreadsheet program to enter a new song. # 1) Put each note's info on a separate row. # 2) Select all of the spreadsheet cells. # 3) Paste into the '$song' variable below. # # "True Love", Copyright 1988 by David D. Seay $song = <<'EOF'; True Love, words and music copy write 1988 by David D C do g q do a q do C q do C q I've E q got E q a E q pim. E q pull C q on C q the a q end C q of a q my C q nose E h do g q do a q do C q do. C q and E q I've E q got E q poise E q son C q oak C q be a q tween C q all C q my E q toes C h do. C q do b q do a q do g q I F q all F q ways F q had F q a D q pair D q of b q not D q tee D q knees F h do g q do a q do C q do. C q I E q real E q ee E q make E q a E q mess E q when E q ev G q er G q I E q sneeze C h do g q do a q do C q do. C q I've E q got E q a E q pair E q of C q feet C q that a q real C q lee a q do C q stink E h do g q do a q do C q do C q I've E q got E q a E q point E q mints C q ev C q ree a q week C q with C q my E q shrink. C h do C q do b q do a q do g q There F q is F q still F q one D q thing D q that b q keeps D q me D q hap D q pee F h do g q do a q do C q do. C q I E q know E q my E q bay E q be E h she's E q still G q hen G q love E q with E q me C q I g q call a q that C q True E w love C h do g q do a q do. C q do E w do C h do g q do C q do E q do F w do D h do g q do a q do C q do. E w do C h do g q do a q do C q do E w do C h do g q do a q do C q do E w do C h do. g q do C q do E q do F w do D h do g q do a q do C q do E w do. C w EOF @song = split("\n",$song); } sub key_down { my($ev) = @_; $k = chr($ev->character); if (($CurrentEvent->modifiers & 256) == 256 && $k eq ".") { StopSpeech $channel or die $^E; DisposeSpeechChannel $channel; dispose $win; exit(0); } } ===== Want to unsubscribe from this list? ===== Send mail with body "unsubscribe" to macperl-request@macperl.org