#!/bin/sh -u # falling object demo showing use of integer arithmetic scaling factor # # $0 [ deltay [ accel ] ] # # This version of the falling object works around the problems of # truncation that happen in integer arithmetic. By scaling all internal # program coordinate values by, say, 1000, we can have a fractional # acceleration of 100 (one tenth of 1000). Since the shell only handles # integer math, we can't store 0.1; but, we can store an acceleration # that is 100, which is one tenth of the "factor" 1000. The loop has to # go around 10 times (10*100) before the lander moves one screen line. # This produces smoother output graphics when the lander moves quickly. # # You can start the deltay at the value given on the command line. A # value of 0 lets the object fall from a standing start. A negative # value (try -1000) causes the object start with upward motion, as if it # had been thrown up in the air. (Of course you won't see the object # until it falls back into the range of the terminal screen.) # # The accel argument determines how fast the object falls (how strong # gravity is pulling it down each iteration). Default is "100" (one # tenth of "factor"). Negative acceleration causes the object to be # "pushed" up instead of falling (and the loop will never finish). Try # this command line: $0 2000 -100 # and watch the object fall down briefly, slow, stop, then go up forever. # # NOTE: This script fragment is incomplete - it does not follow all # the script guidelines set out in "script_style.txt". It also # contains many "Instructor-Style" comments that you must not use in # your own scripts. See script_style.txt for details. # # -IAN! idallen@idallen.ca PATH=/bin:/usr/bin ; export PATH LC_COLLATE=C ; export LC_COLLATE LANG=C ; export LANG umask 022 cols=$( tput cols ) lines=$( tput lines ) let xlimit=cols-1 let ylimit=lines-1 tput clear # Set X to display the output values half-way across the terminal # screen. Object's Y position starts at top of screen with y=0. Current # change in Y (Delta-Y) starts at value given on command line (default # is 0) and increases by the value of $accel on each iteration. # Acceleration can be second argument on command line (default is 100). # Acceleration is added to $deltay each loop iteration. Negative # acceleration will "push" the object up, and the loop will never end. # let factor=1000 # internal scaling factor for integer math let x=xlimit/2 let y=0 let deltay=${1-"0"} # default deltay value is 0 if argument $1 is missing let accel=${2-"100"} # default accel value is 100 if argument $2 is missing while : ; do let y=y+deltay let deltay=deltay+accel # In this script, only the X display value is the same as the # program value. The Y value is "factor" times larger than needed, # so that we can have finer control acceleration by making it less # than 1000. (An acceleration of 100 would be 1/10 of "factor".) # The display values must be non-negative and fit # on terminal screen, so we have code that limits the display values # (not the program values!) if the display values go out-of-bounds. # The "tput el" clears from cursor to end-of-line. # let dispx=x [ $dispx -lt 0 ] && let dispx=0 [ $dispx -gt $xlimit ] && let dispx=xlimit let dispy=y/factor # un-scale internal Y to be display Y [ $dispy -lt 0 ] && let dispy=0 [ $dispy -gt $ylimit ] && let dispy=ylimit tput cup $dispy $dispx tput el # clear from cursor position to end-of-line echo -n "* y=$y dispy=$dispy deltay=$deltay" # Break out of the loop when the object hits the bottom line. # If $accel is negative, this may never happen! # [ $dispy -ge $ylimit ] && break sleep 0.5 done # ASCII Art # # http://www.geocities.com/SouthBeach/Marina/4942/ascii.htm # # - I replaced all single quotes in the art with other characters to make # the quoting easier. (It's now one single-quoted string.) # - A better way to display ASCII art is to write a function that takes the # ASCII art string and displays the art one line at a time, clearing # each line (using "tput el") before displaying it. The function # could also allow the art to be shifted left or right to an # arbitrary location (but not going off the screen!). Left as an # exercise for the student (less than 20 lines of script)... # angel=' _____________ _ *** |.--- *** ---.| ( `\( ) * A Prayer to my || (`\( )/`) || `> /~\_I COMPUTER ANGELS: || > /~\ < || (_/ /\/ || (// \\) || \ \ Guide my keystrokes, ||___`| |`___|| jgs / / Keep my programs alive, |-)--|_|--(-| \/ Protect me from viruses, [=== -- o ]--. ` Back up my drive. __|---------|__ \ [::::::::::: :::] ) Amen. `""|"""""|""""`/T\ jgs \_/ ' # Put the cursor up 15 lines and display bold ASCII art. # Place cursor at start of last line before exiting. # let up=ylimit-15 tput cup $up 0 tput bold echo -n "$angel" tput sgr0 tput cup $ylimit 0