first commit

This commit is contained in:
pete gamache 2016-10-15 10:52:32 -04:00
commit c064619e4d
106 changed files with 9112 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.DS_Store

BIN
Duane Blehm's Code.zip Normal file

Binary file not shown.

View File

@ -0,0 +1,24 @@
About the Animation Demo files:
{note: TML is now shipping version 2.5 of their Pascal, believe it is
free to version 2.0 owners. Fixes some stuff for the new System. We
didn't have any trouble with 2.0 until we moved up to System 4.1. The
package includes 'Edit' version 2.1. 'Edit' is also available from APDA..see
the MoreInfo.sit files.
**note: Watch out for the new print stuff and systems before 4.1!}
'Animation Steps' is a 'FullPaint' document that illustrates the steps
in getting graphics from a Paint program to animation on the screen...
document can be opened from most Paint type programs.
'Animation.Pas' is an 'Edit' text file containing pascal source
code to be compiled by the Pascal compiler.
'Anim.R' is an 'Edit' text file containing RMaker source code to
be compiled by RMaker.
'Anim/Rsrc' is a resource document containing resources built with
ResEdit, the resource editor. These resources are 'included' when
Anim.R is compiled by RMaker.
'Animation' is our application... the result of Link.

View File

@ -0,0 +1,16 @@
* Anim.R
Anim.rsrc
TYPE MENU
,1
\14
,256
File
OffScreen..
Quit
* will include Pict resource file built with ResEdit and ScrapBook
INCLUDE Anim/rsrc

View File

View File

Binary file not shown.

View File

@ -0,0 +1,534 @@
Program Anim;
{this is a simple animation program.. in CreatePictures we load several
pictures. These pictures can be created in any Paint or Drawing type
program.. then copied to Scrapbook DA. Using ResEdit, the resource editor,
these Pictures can be copied from the Scrapbook into 'PICT' type resources.
Note that in our Anim.R source file we have an INCLUDE Anim.rsrc... when
RMaker compiles the Anim.R file it 'includes' any resources in the file
Anim.rsrc. That's how our Paint pictures get into the SimpleAnimation
resources.
Once we have them loaded into our various picHandles we then
CreateOffScreenBitMap so we have a place to DrawPicture() them. The
OffScreen bitmap is a section of memory just like the memory being
displayed on the screen... we just can't see it! at least not until we
CopyBits() some of it over to the visible screen Bitmap. We 'Draw' into
the OffScreen by setting our window^.portbits to our OffScreen bitmap..
watch out for 'clipping' if your OffScreen is bigger than your window.
Now for the fun! We have everything we need for the CopyBits() ROM call.
We have two Rectangles... one (sRect) that frames the shape to be copied
from OffScreen, the other (dRect) frames the location in our window where
we want the shape to be drawn. If dRect is not same size as sRect then
CopyBits will scale the shape to fit. This program uses the srcCopy mode
to 'erase' any previous stuff in the dRect... by using a 3 pixel white
border on the left side of our wagon we can offset it by 3 pixels per
animation loop and still 'erase' the previous wagon just by drawing over it.
Internal Animation (wheels turning, horse running,etc.) is achieved by
alternately drawing 3 different shapes in sequence as the dRect moves across
the screen... this is easily done by having an array of offscreen sRect's
and an index to step thru the array...}
{note: to move a given rectangle 'myRect' from its present location
(Current) to another location (Destination) the following can be used...
OffsetRect(myRect,Destination.h - Current.h,Destination.v - Current.v);
or...
OffsetRect(myRect,DestRect.left - myRect.left,DestRect.top - myRect.top);}
USES MacIntf;
{$L Anim.rsrc}{link resources...just our menu stuff}
CONST
lastMenu = 2; {Number of Menus}
appleMenu = 1;
fileMenu = 256;
WagonOne = 128;{Three wagon shapes loaded from resource file}
WagonTwo = 129;
WagonThree = 130;
{Resource Picts pasted from Scrapbook into Resource file using ResEdit}
VAR {global program stuff}
myDialog: DialogPtr;
myMenus: Array[1..lastMenu] of MenuHandle;
refNum,theMenu,
theItem: integer;
Finished: Boolean;{used to terminate the program}
ClockCursor: CursHandle; {handle to watch cursor}
myWindow: WindowPtr;
Screen,DragArea,
GrowArea: Rect;
HomeTown: PicHandle;{handle for our Logo pic}
HomeRect: Rect;{destination rect for our Logo}
Wagon: Array[1..3] of PicHandle;{we got three wagon pics}
WagonRect: Rect;{size of one wagon, onScreen destination for Copybits}
OffWagonRect: Array[1..3] of Rect;{wagon shape rects in offScreen}
WagonNdx: integer;{which of 3 wagon shapes is to be drawn}
{here's all the fly/regions stuff}
Fly: array[1..2] of PicHandle;{for loading 2 fly pictures}
FlyRect: Rect;{destination rect for drawing fly}
OffFly: array[1..2] of Rect;{source rects in offscreen}
FlyNdx: integer;{which offFly to draw}
Flower: PicHandle;{load picture from resource}
FlowerRect: Rect;{for locating the flower}
FlowerRgn: RgnHandle;{For 'clipping' fly and flower}
FlyLimits: Rect;{for fly border}
FlightRect: Rect;{For limiting fly flight}
CursorIsOn: Boolean;
MouseRect: Rect;{size of FlightRect, slides with mouse to smooth movement}
OffScreen,OldBits: BitMap; {for drawing into offscreen}
SizeOfOff: Size; {Size offscreen bitmap}
OffRowBytes: Integer;
{----------------------------------------------}
procedure CreatePictures; {get 3 Wagon PICT's from resource file}
var
i:integer;
Begin
HomeTown := GetPicture(131);{HomeTown logo}
HomeRect := HomeTown^^.picFrame;{size dest.Rest for drawing pic}
{we'll draw logo into upper right corner of window so relocate}
OffSetRect(HomeRect,myWindow^.portRect.right - 20 -
HomeRect.right,20 - HomeRect.top);
Wagon[1] := GetPicture(WagonOne); {load Wagon shapes from resources}
Wagon[2] := GetPicture(WagonTwo);
Wagon[3] := GetPicture(WagonThree);
WagonRect := Wagon[1]^^.picFrame; { i-159, size our WagonRect }
{Size Rects for OffScreen shapes...will locate them later}
For i := 1 to 3 do OffWagonRect[i] := WagonRect;
{load flystuff to demonstrate regions}
Fly[1] := GetPicture(132);
Fly[2] := GetPicture(133);
{size the fly rectangles}
For i := 1 to 2 do OffFly[i] := Fly[i]^^.picFrame;{they're both same size}
FlyRect := OffFly[1];
Flower := GetPicture(134);
FlowerRect := Flower^^.picFrame;
{load the region resource and coerce it to RgnHandle}
FlowerRgn := RgnHandle(GetResource('RGN ',128));{flower region... outline}
{note this region created with our 'Regions' utility}
end;
procedure CreateOffScreenBitMap; {see CopyBits stuff,also tech.note 41}
const
OffLeft = 0;
OffTop = 0;
OffRight = 115;
OffBottom = 95; {size bitmap to contain three wagon Picts}
var
bRect: Rect;
Begin
{find size/rows/bounds of bitimage}
SetRect(bRect,Offleft,OffTop,OffRight,OffBottom); { drawing area }
with bRect do begin
OffRowBytes := (((right - left -1) div 16) +1) * 2;{has to be even!}
SizeOfOff := (bottom - top) * OffRowBytes;
OffSetRect(bRect,-left,-top); {local coordinates...0,0 = topleft }
end; { of with }
with OffScreen do begin; { create new BitMap record }
{create new bitimage and make baseAddr point to it}
baseAddr := QDPtr(NewPtr(SizeOfOff));
rowbytes := OffRowBytes;{number of bytes/row,can extend beyond bounds}
bounds := bRect;{limits of bitimage drawing?}
end; { of with OffScreen }
End;
procedure DrawPicsIntoOffScreen;
var
i: integer;
Begin
OldBits := myWindow^.portBits; {preserve old myWindow BitMap}
SetPortBits(OffScreen); {our new myWindow BitMap }
{note: If offscreen bitmap is bigger than myWindow bitmap watchout for
clipping caused by ClipRgn and VisRgn fields of grafport record, you
can set cliprgn with ClipRect procedure and use CopyRgn procedure
to store old visrgn in temporary rgn... etc.}
FillRect(myWindow^.PortRect,white); {erase our new BitMap to white}
{locate wagon shape Rectangles in OffScreen Bitmap}
OffSetRect(OffWagonRect[1],-OffWagonRect[1].left,
-OffWagonRect[1].top);{topleft corner..0,0}
OffSetRect(OffWagonRect[2],-OffWagonRect[2].left,
OffWagonRect[1].bottom - OffWagonRect[2].top);{below 1}
OffSetRect(OffWagonRect[3],-OffWagonRect[3].left,
OffWagonRect[2].bottom - OffWagonRect[3].top);{below 2}
{draw the wagons into the offscreen bitmap}
For i := 1 to 3 do DrawPicture(Wagon[i],OffWagonRect[i]);
{locate the flys in the offscreen bitmap}
OffSetRect(OffFly[1],OffWagonRect[1].right - OffFly[1].left,
-OffFly[1].top); {right of wagons, at top}
OffSetRect(OffFly[2],OffWagonRect[1].right - OffFly[2].left,
OffFly[1].bottom-OffFly[2].top); {right of wagons, below fly[1]}
{draw the flys into offscreen}
For i := 1 to 2 do DrawPicture(Fly[i],OffFly[i]);
{could do a 'ReleaseResource' here if you're done with the Pictures}
SetPortBits(OldBits); {restore old bitmap}
end;
procedure DrawWindowContents(WhichWindow:WindowPtr);{response to Update event}
var
trect:Rect;
i:integer;
Begin
DrawPicture(HomeTown,HomeRect);{draw our logo}
{draw groundline under wagon}
MoveTo(myWindow^.portRect.left,WagonRect.bottom);
LineTo(myWindow^.portRect.right,WagonRect.bottom);
{copy offScreen Wagons & flys into Window..upperleft corner,as in bitmap}
CopyBits(OffScreen,myWindow^.portBits,OffScreen.bounds,
OffScreen.bounds,srcCopy,nil);
{draw current wagon Shape being animated into WagonRect}
CopyBits(OffScreen,myWindow^.portBits,OffWagonRect[WagonNdx],
WagonRect,srcCopy,nil);
{all the fly stuff}
DrawPicture(Flower,FlowerRect);
CopyBits(OffScreen,myWindow^.portBits,OffFly[FlyNdx],
FlyRect,srcCopy,FlowerRgn);
FrameRoundRect(FlyLimits,48,32);{border around the fly area}
End;
Procedure InitialAnimation;{locate everything to begin animation}
var
tRgn:RgnHandle;
Begin
{locate first WagonRect,left side of window on groundline (250)}
OffSetRect(WagonRect,-WagonRect.left,250-WagonRect.bottom);
WagonNdx := 1;{set to first Wagon shape}
{locate the flower}
OffSetRect(FlowerRect,160-FlowerRect.left,90-FlowerRect.top);
{locate the FlowerRgn in sync with Flower}
OffSetRgn(FlowerRgn,FlowerRect.left-FlowerRgn^^.rgnBBox.left,
FlowerRect.top-FlowerRgn^^.rgnBBox.top);
{size the FlyLimits}
FlyLimits := FlowerRect;
InsetRect(FlyLimits,-18,0);{expand left/right for border}
FlyLimits.top := FlyLimits.top - 18;{also top.. leave bottom for stem}
{create the region to exclude drawing in the flower}
tRgn := NewRgn;
OpenRgn;
FrameRoundRect(FlyLimits,48,32);
CloseRgn(tRgn);{region of limits rectangle}
DiffRgn(tRgn,FlowerRgn,FlowerRgn);{take out flower,put result in FlowerRgn}
{expand limits by 1 so we can have a frame border}
InSetRect(FlyLimits,-1,-1);
FlightRect := FlyLimits;{FlightRect will compensate for using fly.topleft}
InSetRect(FlightRect,-20,-20);{expand it so fly will be outside border}
OffSetRect(FlightRect,-20,-20);{compensate for using flyRect.topleft}
MouseRect := FlightRect;{MouseRect moves with cursor,& map into FlightRect}
{locate fly in upperleft of FlightRect}
OffSetRect(FlyRect,FlightRect.left-FlyRect.left,
FlightRect.top-FlyRect.top);
FlyNdx := 1;{set to first Fly shape}
end;
procedure AnimateWagon;
var tPoint:Point;
tRect:Rect;
Begin
{locate next WagonRect for wagon shape}
If WagonRect.left > myWindow^.portRect.right then
OffSetRect(WagonRect,-WagonRect.right,0) {back to left side}
else OffSetRect(WagonRect,1,0); {move one pixel to right}
{draw Current WagonNdx shape into WagonRect}
CopyBits(OffScreen,myWindow^.portBits,OffWagonRect[WagonNdx],
WagonRect,srcCopy,nil);
{next wagon shape to be drawn}
If WagonNdx < 3 then inc(WagonNdx) {next shape}
else WagonNdx := 1; {back to first shape}
{now animate the fly}
GetMouse(tPoint);{get current mouse coordinates}
{hide cursor if its over the fly area}
If PtInRect(tPoint,FlyLimits) then begin
If CursorIsOn then begin {hide cursor if its on}
HideCursor;
CursorIsOn := False;
end;
end
else If not(CursorIsOn) then begin {show cursor if its off}
ShowCursor;
CursorIsOn := True;
end;
{limit fly image (FlyRect) to FlightRect extremes..}
{to keep fly from wondering off visible area}
{mouseRect moves with the cursor and tPoint is mapped into FlightRect}
If not(PtInRect(tPoint,MouseRect)) then begin
{a coordinate is outside mouseRect so slide mouseRect to tPoint}
If tPoint.h < MouseRect.left then begin {slide MouseRect to left}
MouseRect.right := MouseRect.right -
(MouseRect.left - tPoint.h);
MouseRect.left := tPoint.h;
end
else If tPoint.h > MouseRect.right then begin
MouseRect.left := MouseRect.left + tPoint.h - MouseRect.right;
MouseRect.right := tPoint.h;
end;
If tPoint.v < MouseRect.top then begin
MouseRect.bottom := MouseRect.bottom -
(MouseRect.top - tPoint.v);
MouseRect.top := tPoint.v;
end
else If tPoint.v > MouseRect.bottom then begin
MouseRect.top := MouseRect.top + tPoint.v - MouseRect.bottom;
MouseRect.bottom := tPoint.v;
end;
end;{if not(ptinRect)}
{tPoint is to Mouse as FlyRect.topleft is to FlightRect}
MapPt(tPoint,MouseRect,FlightRect);
{determine horizontal offset if needed}
If tPoint.h > FlyRect.left + 2 then begin
FlyRect.left := FlyRect.left + 3;{offsetRect to right}
FlyRect.right := FlyRect.right + 3;
end
else if tPoint.h < FlyRect.left - 2 then begin
FlyRect.left := FlyRect.left - 3;{offsetRect to left}
FlyRect.right := FlyRect.right - 3;
end;
{vertical offset?}
If tPoint.v > FlyRect.top + 2 then begin
FlyRect.top := FlyRect.top + 3;
FlyRect.bottom := FlyRect.bottom + 3;
end
else if tPoint.v < FlyRect.top - 2 then begin
FlyRect.top := FlyRect.top - 3;
FlyRect.bottom := FlyRect.bottom - 3;
end;
CopyBits(OffScreen,myWindow^.portBits,OffFly[FlyNdx],
FlyRect,srcCopy,FlowerRgn);
If FlyNdx = 1 then inc(FlyNdx) {next shape, there are 2}
else FlyNdx := 1; {back to first shape}
end;
PROCEDURE InitThings;
Begin
InitGraf(@thePort); {create a grafport for the screen}
MoreMasters; {extra pointer blocks at the bottom of the heap}
MoreMasters; {this is 5 X 64 master pointers}
MoreMasters;
MoreMasters;
MoreMasters;
{get the cursors we use and lock them down - no clutter}
ClockCursor := GetCursor(watchCursor);
HLock(Handle(ClockCursor));
{show the watch while we wait for inits & setups to finish}
SetCursor(ClockCursor^^);
{init everything in case the app is the Startup App}
InitFonts; {startup the fonts manager}
InitWindows; {startup the window manager}
InitMenus; {startup the menu manager}
TEInit; {startup the text edit manager}
InitDialogs(Nil); {startup the dialog manager}
Finished := False; {set program terminator to false}
FlushEvents(everyEvent,0); {clear events from previous program}
{ set up screen size stuff }
Screen := ScreenBits.Bounds; { Get screen dimensions from thePort }
with Screen do { Screen.Left, etc. }
Begin
SetRect(DragArea,Left+4,Top+24,Right-4,Bottom-4);
SetRect(GrowArea,Left,Top+24,Right,Bottom);
End;
End;
procedure CreateWindow;
var
Wrect: Rect;
TypeWind: Integer;
Visible: Boolean;
GoAway: Boolean;
RefVal: Longint;
Begin
SetRect(Wrect,10,40,500,300);
TypeWind := 0;
Visible := True;
GoAway := True;
myWindow := NewWindow(Nil,Wrect,'Simple Animation',Visible,
TypeWind,Nil,GoAway,RefVal);
SetPort(myWindow);
ClipRect(myWindow^.portRect);{set clipping area as per Inside Mac}
End;
procedure DoMenuCommand(mResult:LongInt);
var
name: Str255;
tPort: GrafPtr;
Begin
theMenu := HiWord(mResult);
theItem := LoWord(mResult);
Case theMenu of
appleMenu:
Begin
GetItem(myMenus[1],theItem,name);
refNum := OpenDeskAcc(name);
End;
fileMenu:
Case theItem of
1:{display offScreen bitmap in dialog}
Begin
myDialog := GetNewDialog(128,nil,myWindow);{from resource}
GetPort(tPort);
ShowWindow(myDialog);{invisible in resource}
SelectWindow(myDialog);
SetPort(myDialog); {so we can draw into our window}
CopyBits(OffScreen,myDialog^.portBits,OffScreen.bounds,
OffScreen.bounds,srcOr,Nil);{the whole thing}
FrameRect(OffScreen.bounds);{frame it }
MoveTo(OffScreen.bounds.left + 10,OffScreen.bounds.bottom + 20);
DrawString('^ copy of OffScreen Bitmap');
ModalDialog(Nil,theItem);{we'll close no matter what hit}
HideWindow(myDialog);
SelectWindow(myWindow);{restore our game window}
SetPort(tPort);
end;{1:}
2:Finished := True;
end;{case theItem}
End;
HiliteMenu(0);
End;
procedure TakeCareMouseDown(myEvent:EventRecord);
var
Location: integer;
WhichWindow: WindowPtr;
MouseLoc: Point;
WindowLoc: integer;
Begin
MouseLoc := myEvent.Where; {Global coordinates}
WindowLoc := FindWindow(MouseLoc,WhichWindow); {I-287}
case WindowLoc of
inMenuBar:
DoMenuCommand(MenuSelect(MouseLoc));
inSysWindow:
SystemClick(myEvent,WhichWindow); {I-441}
inContent:
If WhichWindow <> FrontWindow then
SelectWindow (WhichWindow);
inGoAway:
If TrackGoAway(WhichWindow,MouseLoc) then
Finished := True;{end the game}
end; {case of}
end; { TakeCareMouseDown }
procedure TakeCareActivates(myEvent:EventRecord);
var
WhichWindow: WindowPtr;
Begin
WhichWindow := WindowPtr(myEvent.message);
SetPort(WhichWindow);
End;
procedure TakeCareUpdates(Event:EventRecord);
var
UpDateWindow,TempPort: WindowPtr;
Begin
UpDateWindow := WindowPtr(Event.message);
GetPort(TempPort);
SetPort(UpDateWindow);
BeginUpDate(UpDateWindow);
EraseRect(UpDateWindow^.portRect);{ or UpdateWindow^.VisRgn^^.rgnBBox }
DrawWindowContents(UpDateWindow);
EndUpDate(UpDateWindow);
SetPort(TempPort);
End;
procedure MainEventLoop;
var
myEvent: EventRecord;
Begin
InitCursor;
CursorIsOn := True;{keep track of hide/show cursor}
Repeat
SystemTask;
If GetNextEvent(EveryEvent,myEvent) then
Case myEvent.What of
mouseDown: TakeCareMouseDown(myEvent);
KeyDown: Finished:= True;
ActivateEvt:TakeCareActivates(myEvent);
UpDateEvt: TakeCareUpdates(myEvent);
End
Else AnimateWagon;{animate one loop of our wagon shape}
Until Finished;
End;
procedure SetUpMenus;
var
i: integer;
Begin
myMenus[1] := GetMenu(appleMenu); {get menu info from resources}
AddResMenu(myMenus[1],'DRVR'); {add in all the DA's}
myMenus[2] := GetMenu(fileMenu);
For i := 1 to lastMenu do
begin
InsertMenu(myMenus[i],0);
end;
DrawMenuBar;
End;
procedure CloseStuff;
Begin
{be sure to kill any sound I/O before quitting!}
End;
{Main Program begins here}
BEGIN
InitThings;
SetUpMenus;
CreateWindow;
CreatePictures;{load picts from resource file}
CreateOffScreenBitMap;{for use with copyBits procedure}
DrawPicsIntoOffScreen;{OffScreen holds all our wagon/fly shapes}
InitialAnimation;{set up stuff for start of animation}
MainEventLoop;{will animate wagon/fly if nothing else is going on}
CloseStuff;
END.

View File

@ -0,0 +1 @@
about the Cairo files.... 'Cairo Shapes' is a 'FullPaint' document containing the shapes that are used for animation, score, etc... can be opened from MacPaint. 'Cairo Animation' is a 'FullPaint' document illustrating the way animation is done in the game. 'CairoFont.pro' is an 'Edit' text file containing source code for procedure used to access the Cairo FontRecord. 'CairoShootOut.Pas' is an 'Edit' text file containing pascal source code to be compiled by the Pascal compiler. 'aCairo.R' is an 'Edit' text file containing RMaker source code to be compiled by RMaker. 'aCairo.Rsrc' is a resource document containing resources built with ResEdit, the resource editor. These resources are 'included' when 'aCairo.R' is compiled by RMaker. 'CairoShootOut' is our application... the result of Link.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
{... here's how we copied the bitImage and locTable of Cairo font...} TYPE {GLOBAL types used for this procedure} FintPtr = ^FontRec; FontHandle = ^FintPtr;{FintPtr???, because FontPtr is already declared!} var {GLOBAL varibles used in this procedure} myFont: FontHandle;{so we can load resource and access FontRec} FontMap: BitMap;{will point to copy of font bitimage} RowWords: integer; RowBytes: integer; tPtr: Ptr; tLong: Longint; BitPtr: Ptr;{pointer to our Copy of BitImage} Locate: Array[0..130] of integer;{'partial' Cairo location table} LocatePtr: Ptr; procedure CreateCairoStuff; var trect:Rect; Begin {load Cairo font and make copies of Character image and locate table} myFont := FontHandle(GetResource('FONT',1426)); HLock(Handle(myFont));{lock it so it won't move... pointers!} RowWords := myFont^^.rowWords;{number of words in row} RowBytes := RowWords * 2;{number of bytes in row} {make tPtr point to start of fontRec bitimage} tPtr := @myFont^^.rowWords;{field just before the bitimage} tLong := ORD(tPtr);{coerce to longint,i-80} tLong := tLong + 2;{2 bytes to get to beginning of bit image,i-234} tPtr := Pointer(tLong);{coerce back to pointer} {create BitPtr size of the bitimage} BitPtr := NewPtr(RowBytes * myFont^^.fRectHeight); {bytes to move = bytes per row * number of rows....} BlockMove(tPtr,BitPtr,RowBytes * myFont^^.fRectHeight);{make the move!} {make tPtr point to start of fontRec locTable.. just beyond bitimage} tPtr := @myFont^^.rowWords;{find start of LocTable for font} tLong := ORD(tPtr);{coerce to longint,i-80} tLong := tLong + (RowBytes * myFont^^.fRectHeight) + 2;{bitimage + integer} tPtr := Pointer(tLong);{coerce back to pointer} {make LocatePtr point to start of our Locate table} LocatePtr := @Locate[0]; {bytes to move = (last char + 1) * 2.. in our case (130+1)*2 = 262} {or Locate[] contains 131 integers (zero based) = 262 bytes} BlockMove(tPtr,LocatePtr,262);{copy LocTable to our Locate array} {for Cairo: Locate[130] = 1656.. offset to rightside of last character, use ResEdit to look at last char of font... will give this OffSet} SetRect(tRect,0,0,Locate[130],myFont^^.fRectHeight); FontMap.baseAddr := QDPtr(BitPtr);{make FontMap point to BitPtr image} FontMap.rowbytes := RowBytes;{row width in bytes, must be even no.} FontMap.bounds := tRect; HUnlock(Handle(myFont));{unlock it, we're done with Ptr stuff} ReleaseResource(Handle(myFont));{if you're done with it} End; {once you have the FontMap ....to draw the char '33' from the BitImage:} var p,q:integer; SourceRect,DestRect:Rect; Begin SourceRect := FontMap.Bounds;{set top and bottom of Rect} SourceRect.left := Locate[33];{coordinate offset to leftside of char 33} SourceRect.right := Locate[33 + 1];{offset to rightside of char 33} DestRect := SourceRect;{size the destination rect} OffSetRect(DestRect,p,q);{locate the DestRect where you want drawn} {now do the transfer!} CopyBits(FontMap,myWindow^.portBits,SourceRect,DestRect,srcCopy,nil); End;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
* aCairo.R
aCairo.rsrc
TYPE NILE = STR
,0
Cairo ShootOut ver1.2src, by Duane Blehm, 9/15/87
TYPE MENU
,1
\14
About ShootOut...
(-
,256
Game
Begin
Quit /Q
,257
Options
Unlock..
Help..
HiScore..
! Sound
Set Speed..
,258
Works
Peek OffScreen
Source Code...
,259
(Any Key to Exit)
* will include Resource file built with ResEdit and ScrapBook
INCLUDE aCairo/rsrc

View File

Binary file not shown.

View File

@ -0,0 +1,16 @@
* CMask.R
CMask.rsrc
TYPE MENU
,1
\14
,256
File
OffScreen..
Quit
* will include Pict resources file built with ResEdit and ScrapBook
INCLUDE CMask/rsrc

View File

View File

View File

@ -0,0 +1,533 @@
Program CopyMaskDemo;{copyright ©,1987...Duane Blehm,HomeTown Software}
{This program illustrates using the CopyMask() ROM procedure for animation.
Note: CopyMask and CalcMask are NOT available in the 64k ROMs.
We just set up everything so we could achieve the same 'effect' as we did
with CopyBits and regions in the Animation Demo. We're sure there are
some better examples of how CopyMask might be used... thought out with
its features in mind. See Inside Mac vol. 4 or Technical Note #57 for
specs. on these and other 'new' 128k ROM Quickdraw routines.}
USES MacIntf;
{$L CMask.rsrc}{link resources...just our menu stuff}
CONST
lastMenu = 2; {Number of Menus}
appleMenu = 1;
fileMenu = 256;
VAR {global program stuff}
FlowerMap, {will use FlowerMap to do our CalcMask of Flower pict}
MaskMap: BitMap;{final mask, used with CopyMask call}
imagePtr,tPtr: Ptr;{imagePtr points to temp. BitImage of FlowerMap}
tRect,
MaskRect: Rect;{MaskRect same size as FlyRect, CopyMask call}
HomeTown: PicHandle;{handle for our Logo pic}
HomeRect: Rect;{destination rect for our Logo}
{here's all the fly/regions stuff}
Fly: array[1..2] of PicHandle;{for loading 2 fly pictures}
FlyRect: Rect;{destination rect for drawing fly}
OffFly: array[1..2] of Rect;{source rects in offscreen}
FlyNdx: integer;{which offFly to draw}
Flower: PicHandle;{load picture from resource}
FlowerRect: Rect;{for locating the flower}
FlyBorder: Rect;{for fly border}
FlightRect: Rect;{For limiting fly flight}
CursorIsOn: Boolean;
MouseRect: Rect;{slides with mouse to smooth movement}
OffScreen, {will hold our 2 fly images}
OldBits: BitMap;
SizeOfOff: Size; {for Size-ing the offscreen bitmap}
OffRowBytes: Integer;
myDialog: DialogPtr;
myMenus: Array[1..lastMenu] of MenuHandle;
refNum,theMenu,
theItem: integer;
Finished: Boolean;{used to terminate the program}
ClockCursor: CursHandle; {handle to watch cursor}
myWindow: WindowPtr;
Screen,DragArea,
GrowArea: Rect;
i,x,y: integer;
{----------------------------------------------}
procedure CreatePictures;
var
i:integer;
Begin
HomeTown := GetPicture(131);{HomeTown logo}
HomeRect := HomeTown^^.picFrame;{size dest.Rest for drawing pic}
{we'll draw logo into upper right corner of window so relocate}
OffSetRect(HomeRect,myWindow^.portRect.right - 1 -
HomeRect.right,1 - HomeRect.top);
{load flystuff to demonstrate regions}
Fly[1] := GetPicture(132);
Fly[2] := GetPicture(133);
{size the fly rectangles}
For i := 1 to 2 do OffFly[i] := Fly[i]^^.picFrame;{they're both same size}
FlyRect := OffFly[1];
Flower := GetPicture(134);
FlowerRect := Flower^^.picFrame;{size the FlowerRect}
end;
procedure CreateOffScreenBitMap; {see CopyBits stuff,also tech.note 41}
var
bRect: Rect;
Begin
{find size/rows/bounds of bitimage}
SetRect(bRect,0,0,50,95); { big enough for our flys! }
with bRect do begin
OffRowBytes := (((right - left -1) div 16) +1) * 2;{has to be even!}
SizeOfOff := (bottom - top) * OffRowBytes;
OffSetRect(bRect,-left,-top); {local coordinates...0,0 = topleft }
end; { of with }
with OffScreen do begin; { create new BitMap record }
{create new bitimage and make baseAddr point to it}
baseAddr := QDPtr(NewPtr(SizeOfOff));
rowbytes := OffRowBytes;{number of bytes/row,can extend beyond bounds}
bounds := bRect;{limits of bitimage drawing?}
end; { of with OffScreen }
End;
procedure DrawPicsIntoOffScreen;
var
i: integer;
Begin
OldBits := myWindow^.portBits; {preserve old myWindow BitMap}
SetPortBits(OffScreen); {our new myWindow BitMap }
FillRect(OffScreen.bounds,white); {erase our new BitMap to white}
{locate the flys in the offscreen bitmap}
OffSetRect(OffFly[1],- OffFly[1].left,-OffFly[1].top);
OffSetRect(OffFly[2],- OffFly[2].left,OffFly[1].bottom-OffFly[2].top);
{draw the flys into offscreen}
For i := 1 to 2 do begin
DrawPicture(Fly[i],OffFly[i]);
ReleaseResource(Handle(Fly[i]));{done with pics so dump em}
end;
SetPortBits(OldBits); {restore old bitmap}
end;
procedure CreateMaskBitMap;
{first in the FlowerMap we draw the flower then we do a CalcMask of it
into an identical bitimage (imagePtr). Once we have the mask in imagePtr
we make FlowerMap.baseAddr point to it and invert it so the fly is drawn
'outside' the flower edges (the 'flower' becomes white instead black). The
MaskMap needs to be size of the area the fly will be flying over, and we
have a RoundRect border which includes the flower area. So we fill the
RoundRect area with black and copyBits the inverted Flower mask from
FlowerMap. (see Paint document for illustration of this) Now there is
black everywhere in the MaskMap we want the Fly to be drawn on the screen
except the 'coordinates' are not the same. All we need to do is start
the MaskRect over the MaskMap in sync with the flyRect in our window so
they begin in the same 'relative' position to the flower/border}
Begin
{find size/rows/bounds of bitimage}
tRect := Flower^^.picFrame;{FlowerMap size of flower picture}
with tRect do begin
OffRowBytes := (((right - left -1) div 16) +1) * 2;{has to be even!}
SizeOfOff := (bottom - top) * OffRowBytes;
OffSetRect(tRect,-left,-top); {local coordinates...0,0 = topleft }
end; { of with }
with FlowerMap do begin; { create new BitMap record }
{create new bitimage and make baseAddr point to it}
baseAddr := QDPtr(NewPtr(SizeOfOff));
rowbytes := OffRowBytes;{number of bytes/row,can extend beyond bounds}
bounds := tRect;{limits of bitimage drawing?}
end; {with}
imagePtr := QDPtr(NewPtr(SizeOfOff));{Bitimage same as FlowerMap}
OldBits := myWindow^.portBits; {preserve old myWindow BitMap}
SetPortBits(FlowerMap); {our new myWindow BitMap }
DrawPicture(Flower,tRect);{draw flower into the BitMap}
{create mask for flower picture, 128k ROMs only}
CalcMask(FlowerMap.baseAddr,imagePtr,FlowerMap.rowbytes,
FlowerMap.rowbytes,FlowerMap.bounds.bottom-FlowerMap.bounds.top,
FlowerMap.rowbytes div 2);
FlowerMap.baseAddr := imagePtr;{make FlowerMap point to mask}
SetPortBits(FlowerMap);{make our window point to new flowerMap}
InvertRect(FlowerMap.Bounds);{we want to draw outside the flower }
{create the offscreen MaskMap.....find size/rows/bounds of bitimage}
tRect := FlightRect;
InsetRect(tRect,-64,-64);{enlarge so fly can exceed border}
with tRect do begin
OffRowBytes := (((right - left -1) div 16) +1) * 2;{has to be even!}
SizeOfOff := (bottom - top) * OffRowBytes;
OffSetRect(tRect,-left,-top); {local coordinates...0,0 = topleft }
end; { of with }
with MaskMap do begin; { create new BitMap record }
{create new bitimage and make baseAddr point to it}
baseAddr := QDPtr(NewPtr(SizeOfOff));
rowbytes := OffRowBytes;{number of bytes/row,can extend beyond bounds}
bounds := tRect;{limits of bitimage drawing}
end; {with}
SetPortBits(MaskMap);{so we can draw into the MaskMap}
FillRect(MaskMap.bounds,white);{erase it to white}
InsetRect(tRect,64,64);{shrink it back to flight size to draw border}
FillRoundRect(tRect,48,32,black);{black in the flight area}
{copy the Flower mask into MaskMap}
tRect := FlowerRect;
{locate it in center of border}
OffSetRect(tRect,64+FlowerRect.left-FlightRect.left-tRect.left,
64+FlowerRect.top-FlightRect.top-tRect.top);
CopyBits(FlowerMap,MaskMap,FlowerMap.bounds,tRect,srcCopy,nil);
{note: we are done with the FlowerMap at this point.}
SetPortBits(OldBits); {restore old bitmap}
End;
procedure DrawWindowContents(WhichWindow:WindowPtr);{response to Update event}
var
trect:Rect;
i:integer;
Begin
DrawPicture(HomeTown,HomeRect);{draw our logo}
{copy offScreen flys into Window..upperleft corner,as in bitmap}
CopyBits(OffScreen,myWindow^.portBits,OffScreen.bounds,
OffScreen.bounds,srcCopy,nil);
{all the fly stuff}
DrawPicture(Flower,FlowerRect);
FrameRoundRect(FlyBorder,48,32);{border around the fly area}
CopyMask(OffScreen,MaskMap,myWindow^.portBits,OffFly[FlyNdx],
MaskRect,FlyRect);{draw the fly}
End;
Procedure InitialAnimation;{locate everything to begin animation}
Begin
{locate the flower}
OffSetRect(FlowerRect,160-FlowerRect.left,90-FlowerRect.top);
{size the FlyBorder}
FlyBorder := FlowerRect;
InsetRect(FlyBorder,-18,0);{expand left/right for border}
FlyBorder.top := FlyBorder.top - 18;{also top.. leave bottom for stem}
FlightRect := FlyBorder;{FlightRect will compensate for using fly.topleft}
CreateMaskBitMap;{create the 'mask' for use with the CopyMask call}
InsetRect(FlightRect,-16,-16);{so fly can go beyond the flyborder}
OffSetRect(FlightRect,-16,-16);{because we're using FlyRect.topleft}
MouseRect := FlightRect;{MouseRect moves with cursor,& maps into FlightRect}
{expand limits by 1 so we can have a frame border that's not erased}
InSetRect(FlyBorder,-1,-1);
MaskRect := FlyRect;
{locate fly in upperleft of FlightRect}
OffSetRect(FlyRect,FlightRect.left-FlyRect.left,
FlightRect.top-FlyRect.top);
{locate MaskRect in MaskMap relative to FlyRect and FlightRect}
OffSetRect(MaskRect,32-MaskRect.left,32-MaskRect.top);{in synch with fly}
FlyNdx := 1;{set to first Fly shape}
end;
procedure AnimateStuff;
var tPoint:Point;
tRect:Rect;
aTick:Longint;
Begin
Delay(2,aTick);{CopyMask is seems to be faster than CopyBits with Rgn..?}
{now animate the fly}
GetMouse(tPoint);{get current mouse coordinates}
{hide cursor if its over the fly area}
If PtInRect(tPoint,FlyBorder) then begin
If CursorIsOn then begin {hide cursor if its on}
HideCursor;
CursorIsOn := False;
end;
end
else If not(CursorIsOn) then begin {show cursor if its off}
ShowCursor;
CursorIsOn := True;
end;
{limit fly image (FlyRect) to FlightRect extremes..}
{to keep fly from wondering off visible area}
{mouseRect moves with the cursor and tPoint is mapped into FlightRect}
If not(PtInRect(tPoint,MouseRect)) then begin
{a coordinate is outside mouseRect so slide mouseRect to tPoint}
If tPoint.h < MouseRect.left then begin {slide MouseRect to left}
MouseRect.right := MouseRect.right -
(MouseRect.left - tPoint.h);
MouseRect.left := tPoint.h;
end
else If tPoint.h > MouseRect.right then begin
MouseRect.left := MouseRect.left + tPoint.h - MouseRect.right;
MouseRect.right := tPoint.h;
end;
If tPoint.v < MouseRect.top then begin
MouseRect.bottom := MouseRect.bottom -
(MouseRect.top - tPoint.v);
MouseRect.top := tPoint.v;
end
else If tPoint.v > MouseRect.bottom then begin
MouseRect.top := MouseRect.top + tPoint.v - MouseRect.bottom;
MouseRect.bottom := tPoint.v;
end;
end;{if not(ptinRect)}
{tPoint is to MouseRect as FlyRect.topleft is to FlightRect}
MapPt(tPoint,MouseRect,FlightRect);
{determine horiz/vert. offset if needed, MaskRect moves in sync with FlyRect}
If tPoint.h > FlyRect.left + 2 then begin
FlyRect.left := FlyRect.left + 3;{offsetRect to right}
FlyRect.right := FlyRect.right + 3;
MaskRect.left := MaskRect.left + 3;{offsetRect to right}
MaskRect.right := MaskRect.right + 3;
end
else if tPoint.h < FlyRect.left - 2 then begin
FlyRect.left := FlyRect.left - 3;{offsetRect to left}
FlyRect.right := FlyRect.right - 3;
MaskRect.left := MaskRect.left - 3;{offsetRect to left}
MaskRect.right := MaskRect.right - 3;
end;
{vertical offset?}
If tPoint.v > FlyRect.top + 2 then begin
FlyRect.top := FlyRect.top + 3;
FlyRect.bottom := FlyRect.bottom + 3;
MaskRect.top := MaskRect.top + 3;
MaskRect.bottom := MaskRect.bottom + 3;
end
else if tPoint.v < FlyRect.top - 2 then begin
FlyRect.top := FlyRect.top - 3;
FlyRect.bottom := FlyRect.bottom - 3;
MaskRect.top := MaskRect.top - 3;
MaskRect.bottom := MaskRect.bottom - 3;
end;
{draw the fly from OffScreen to myWindow using MaskMap}
CopyMask(OffScreen,MaskMap,myWindow^.portBits,OffFly[FlyNdx],
MaskRect,FlyRect);
If FlyNdx = 1 then inc(FlyNdx) {next shape, there are 2}
else FlyNdx := 1; {back to first shape}
end;
PROCEDURE InitThings;
Begin
InitGraf(@thePort); {create a grafport for the screen}
MoreMasters; {extra pointer blocks at the bottom of the heap}
MoreMasters; {this is 5 X 64 master pointers}
MoreMasters;
MoreMasters;
MoreMasters;
{get the cursors we use and lock them down - no clutter}
ClockCursor := GetCursor(watchCursor);
HLock(Handle(ClockCursor));
{show the watch while we wait for inits & setups to finish}
SetCursor(ClockCursor^^);
{init everything in case the app is the Startup App}
InitFonts; {startup the fonts manager}
InitWindows; {startup the window manager}
InitMenus; {startup the menu manager}
TEInit; {startup the text edit manager}
InitDialogs(Nil); {startup the dialog manager}
Finished := False; {set program terminator to false}
FlushEvents(everyEvent,0); {clear events from previous program}
{ set up screen size stuff }
Screen := ScreenBits.Bounds; { Get screen dimensions from thePort }
with Screen do { Screen.Left, etc. }
Begin
SetRect(DragArea,Left+4,Top+24,Right-4,Bottom-4);
SetRect(GrowArea,Left,Top+24,Right,Bottom);
End;
End;
procedure CreateWindow;
var
Wrect: Rect;
TypeWind: Integer;
Visible: Boolean;
GoAway: Boolean;
RefVal: Longint;
Begin
SetRect(Wrect,8,40,504,336);
TypeWind := 0;
Visible := True;
GoAway := True;
myWindow := NewWindow(Nil,Wrect,'CopyMask Demo',Visible,
TypeWind,Nil,GoAway,RefVal);
SetPort(myWindow);
ClipRect(myWindow^.portRect);{set clipping area as per Inside Mac}
End;
procedure DoMenuCommand(mResult:LongInt);
var
name: Str255;
tPort: GrafPtr;
Begin
theMenu := HiWord(mResult);
theItem := LoWord(mResult);
Case theMenu of
appleMenu:
Begin
GetItem(myMenus[1],theItem,name);
refNum := OpenDeskAcc(name);
End;
fileMenu:
Case theItem of
1:{display offScreen bitmap in dialog}
Begin
myDialog := GetNewDialog(128,nil,myWindow);{from resource}
GetPort(tPort);
ShowWindow(myDialog);{invisible in resource}
SelectWindow(myDialog);
SetPort(myDialog); {so we can draw into our window}
CopyBits(OffScreen,myDialog^.portBits,OffScreen.bounds,
OffScreen.bounds,srcOr,Nil);{the whole thing}
FrameRect(OffScreen.bounds);{frame it }
MoveTo(OffScreen.bounds.left + 10,OffScreen.bounds.bottom + 20);
DrawString('^ copy of OffScreen Bitmap');
ModalDialog(Nil,theItem);{we'll close no matter what hit}
HideWindow(myDialog);
SelectWindow(myWindow);{restore our game window}
SetPort(tPort);
end;{1:}
2:Finished := True;
end;{case theItem}
End;
HiliteMenu(0);
End;
procedure TakeCareMouseDown(myEvent:EventRecord);
var
Location: integer;
WhichWindow: WindowPtr;
MouseLoc: Point;
WindowLoc: integer;
Begin
MouseLoc := myEvent.Where; {Global coordinates}
WindowLoc := FindWindow(MouseLoc,WhichWindow); {I-287}
case WindowLoc of
inMenuBar:
DoMenuCommand(MenuSelect(MouseLoc));
inSysWindow:
SystemClick(myEvent,WhichWindow); {I-441}
inContent:
If WhichWindow <> FrontWindow then
SelectWindow (WhichWindow);
inGoAway:
If TrackGoAway(WhichWindow,MouseLoc) then
Finished := True;{end the game}
end; {case of}
end; { TakeCareMouseDown }
procedure TakeCareActivates(myEvent:EventRecord);
var
WhichWindow: WindowPtr;
Begin
WhichWindow := WindowPtr(myEvent.message);
SetPort(WhichWindow);
End;
procedure TakeCareUpdates(Event:EventRecord);
var
UpDateWindow,TempPort: WindowPtr;
Begin
UpDateWindow := WindowPtr(Event.message);
GetPort(TempPort);
SetPort(UpDateWindow);
BeginUpDate(UpDateWindow);
EraseRect(UpDateWindow^.portRect);{ or UpdateWindow^.VisRgn^^.rgnBBox }
DrawWindowContents(UpDateWindow);
EndUpDate(UpDateWindow);
SetPort(TempPort);
End;
procedure MainEventLoop;
var
myEvent: EventRecord;
Begin
InitCursor;
CursorIsOn := True;{keep track of hide/show cursor}
Repeat
SystemTask;
If GetNextEvent(EveryEvent,myEvent) then
Case myEvent.What of
mouseDown: TakeCareMouseDown(myEvent);
KeyDown: Finished:= True;
ActivateEvt:TakeCareActivates(myEvent);
UpDateEvt: TakeCareUpdates(myEvent);
End
Else AnimateStuff;
Until Finished;
End;
procedure SetUpMenus;
var
i: integer;
Begin
myMenus[1] := GetMenu(appleMenu); {get menu info from resources}
AddResMenu(myMenus[1],'DRVR'); {add in all the DA's}
myMenus[2] := GetMenu(fileMenu);
For i := 1 to lastMenu do
begin
InsertMenu(myMenus[i],0);
end;
DrawMenuBar;
End;
procedure CloseStuff;
Begin
{be sure to kill any sound I/O before quitting!}
End;
{Main Program begins here}
BEGIN
InitThings;
{check for the 64k ROMs, abort if they're present}
Environs(x,y);
If x >= 117 then begin {64k roms aren't present,so go ahead}
SetUpMenus;
CreateWindow;
CreatePictures;{load picts from resource file}
CreateOffScreenBitMap;{for use with copyBits procedure}
DrawPicsIntoOffScreen;{OffScreen holds all our fly shapes}
InitialAnimation;{set up stuff for start of animation}
MainEventLoop;{will animate fly if nothing else is going on}
end
else begin
InitCursor;{show arrow cursor}
i := NoteAlert(128,nil); {display alert and exit}
end;{else}
CloseStuff;
END.

View File

@ -0,0 +1,14 @@
About the DragPieceDemo files....
'DragPieceDemo.pas' is an 'Edit' text file containing sourcecode for our
'almost generic' DragPiece() procedure used in a simple example program.
'aDragPiece.rsrc' is a resource file which is linked to the Demo code.
'DragPieceDemo' is the application file.
'DragPiece animation' is a paint-type file that illustrates what's happening.
We're including this Demo with 'ZeroGravity' because it illustrates the same
principle of animation over backgrounds with some improvements, refinements,
etc. We make extensive use of this procedure in our new 'PUZZ'L' application.

Binary file not shown.

View File

View File

@ -0,0 +1,392 @@
Program DragPieceDemo;{Thu Dec 17, 1987, © HomeTown Software,1987
all rights reserved, this code not for distribution}
{this program demonstrates use of our 'generic' DragPiece() procedure for
animation of a 'piece' over a background. We're still trying to make the
procedure truly independent. Currently it has some 'options' embedded
within it for initializing the PicMap and PatchMap and also for how
the piece is effected on completion... see DragPiece(). The procedure
is called from TakeCareMouseDown() in window contents. }
{also you might want to check out the MakeBitMap() procedure, this is a big
improvement over our old CreateOffScreenBitmap() stuff!}
USES MacIntf;{TML Directives}
{$L aDragPiece.rsrc}{link the resource file}
CONST
lastMenu = 2; {Number of Menus}
appleMenu = 1;
fileMenu = 256;
VAR {global program stuff}
myMenus: Array[1..lastMenu] of MenuHandle;
refNum,theMenu,theItem: integer;
Finished: Boolean;{used to terminate the program}
ClockCursor: CursHandle; {handle to watch cursor}
myWindow: WindowPtr;
Screen,DragArea,GrowArea: Rect;
tRect:Rect;
tPt:Point;
DragRgn:RgnHandle;
LogoLoc:Point;
{----------------------------------------------}
procedure DrawWindowContents(WhichWindow:WindowPtr);
var
trect:Rect;
tStr:Str255;
myPic:PicHandle;
Begin
FillRect(whichWindow^.portRect,ltGray);
tStr := 'Click to create a spot and then DRAG it!';
SetRect(tRect,0,80,StringWidth(tStr) + 20,105);
EraseRect(tRect);
moveTo(10,100);
DrawString(tStr);
myPic := GetPicture(128);{logo}
tRect := myPic^^.picFrame;
{watchout! the window^.portRect is offset by a SetOrigin() call!}
OffSetRect(tRect,LogoLoc.h-tRect.right,LogoLoc.v-tRect.bottom);
DrawPicture(myPic,tRect);
End;
procedure DragPiece(aWindow:WindowPtr;var theMouse:Point;
DragRect:Rect;PieceRgn:RgnHandle);
{aWindow is window the piece is to be dragged in, theMouse is location of
mouseDown, DragRect limits the area the piece can be dragged within the
window, PieceRgn is destination Region in aWindow for the piece. PieceRgn
defines the size of the piece by its .rgnBBox and shape by the shape of
the region... the Piece drawn into the PicMap is masked into the ComboMap
by a copy of the PieceRgn. If no Mask is desired just pass a new Rgn set
to the Rect in the window with a RectRgn() call. This procedure does NO
error checking for memory available, etc., beware!}
var
tRgn:RgnHandle;{temp copy of PieceRgn for animation}
PatchMap,ComboMap,PicMap,OldBits:Bitmap;
sRect,sUnionRect,LastsRect,
cRect,cUnionRect,LastcRect:Rect;
MouseLoc,LastMouseLoc,tPt:Point;
ExitToAnimate:boolean;
MaxMove:Point;
procedure MakeBitMap(var theMap:Bitmap);{create a bitmap record}
{assumes that 'theMap.bounds' is predefined rect for size and
does NO error checking for available memory or MemErr..}
Begin
{following same as OffsetRect(theMap.bounds,-left,-top)}
theMap.bounds.right := theMap.bounds.right-theMap.bounds.left;
theMap.bounds.left := 0;
theMap.bounds.bottom := theMap.bounds.bottom-theMap.bounds.top;
theMap.bounds.top := 0;
{now with 0,0 origin.. '.right' is width, and '.bottom' is height}
theMap.rowbytes := (((theMap.bounds.right - 1) DIV 16) + 1) * 2;
{size of bitimage is bottom times rowBytes, potential MemError here}
theMap.baseAddr := NewPtr(theMap.bounds.bottom * theMap.rowbytes);
End;
Begin {procedure dragPiece}
SetPt(MaxMove,20,20);{piece will move max. of 20 pixels per loop}
{create temp. bitmaps, size Combo for MaxMove}
PicMap.bounds := PieceRgn^^.rgnBBox;{size to contain the region}
MakeBitMap(PicMap);{create the bitmap record.. must define .bounds first}
PatchMap.bounds := PicMap.bounds;{same size}
MakeBitMap(PatchMap);
ComboMap.bounds := PatchMap.bounds;
{increase size to accomodate extra for drawing background/union }
ComboMap.bounds.right := ComboMap.bounds.right + MaxMove.h;
ComboMap.bounds.bottom := ComboMap.bounds.bottom + MaxMove.v;
MakeBitMap(ComboMap);
tRgn := NewRgn;
CopyRgn(PieceRgn,tRgn);{make a temp. copy for use in drawing}
{_________ PicMap must contain image to be 'dragged' ______}
{we're just going to 'fill' the PieceRgn for this example, this bitmap
could be passed as a parameter.}
OldBits := aWindow^.portBits;
SetPortBits(PicMap);{so we can quickdraw 'piece' into the PicMap}
tRect := aWindow^.portRect;
InsetRect(tRect,-50,-50);{in case mouse is near edge of window,clipping}
ClipRect(tRect);
SetOrigin(tRgn^^.rgnBBox.left,tRgn^^.rgnBBox.top);
EraseRect(tRgn^^.rgnBBox);{erase to white first}
FillRgn(tRgn,gray);
FrameRgn(tRgn);
SetOrigin(0,0);
SetPortBits(OldBits);
{__________________________}
{____ initialize PatchMap, will be background under piece _____}
{restore, erase or draw initial BackGround under piece to PatchMap}
SetPortBits(PatchMap);{so we can quickdraw into the PatchMap}
{make the PatchMap topleft = to PieceRgn topleft for drawing, so
that the correct stuff is drawn into PatchMap for Piece location
in aWindow!}
SetOrigin(PieceRgn^^.rgnBBox.left,PieceRgn^^.rgnBBox.top);
EraseRect(PieceRgn^^.rgnBBox);{erase whole thing to white first}
{note: SetOrigin effects the aWindow^.portRect!!}
DrawWindowContents(aWindow);{draw window just like update event...}
SetOrigin(0,0);{restore normal origin}
SetPortBits(OldBits);
{___________________________}
LastsRect := tRgn^^.rgnBBox;{last location in aWindow!}
sRect := LastsRect;{initialize sRect for size}
cRect := sRect;
LastMouseLoc := theMouse;{this is where user clicked}
MouseLoc := LastMouseLoc;
MouseLoc.h := MouseLoc.h + 1;{this will force redraw thru first loop}
Repeat { the entire process Until a MouseUp}
{determine If the mouse has moved and how much}
ExitToAnimate := false;{will flag mouse movement, need to draw stuff}
Repeat {wait for mouse move or mouse up}
{keep the piece on screen}
If not (PtInRect(MouseLoc,DragRect)) then Begin {move it back in}
If MouseLoc.h > DragRect.right then
MouseLoc.h := DragRect.right
Else If MouseLoc.h < DragRect.left then
MouseLoc.h := DragRect.left;
If MouseLoc.v > DragRect.bottom then
MouseLoc.v := DragRect.bottom
Else If MouseLoc.v < DragRect.top then
MouseLoc.v := DragRect.top;
End;
tPt.h := MouseLoc.h - LastMouseLoc.h;{tPt is offset requested}
tPt.v := MouseLoc.v - LastMouseLoc.v;
If (tPt.h <> 0) OR (tPt.v <> 0) then Begin {must have moved so animate}
{tPt move must be less than MaxMove}
If tPt.h > MaxMove.h then tPt.h := MaxMove.h
Else If tPt.h < -MaxMove.h then tPt.h := -MaxMove.h;
If tPt.v > MaxMove.v then tPt.v := MaxMove.v
Else If tPt.v < -MaxMove.v then tPt.v := -MaxMove.v;
{slide sRect to new location by tPt offset}
sRect.left := sRect.left + tPt.h;
sRect.right := sRect.right + tPt.h;
sRect.top := sRect.top + tPt.v;
sRect.bottom := sRect.bottom + tPt.v;
{LastMouse is moved to the 'adjusted' location}
LastMouseLoc.h := tPt.h + LastMouseLoc.h;
LastMouseLoc.v := tPt.v + LastMouseLoc.v;
ExitToAnimate := True;{TML users can do a 'Leave' here!}
End;{If (abs..}
GetMouse(MouseLoc);
Until (not(StillDown) or ExitToAnimate);
{combine/union the Last and new sRects, in the aWindow/screen}
UnionRect(LastsRect,sRect,sUnionRect);
LastcRect := LastsRect;{copy the sRects to cRects in ComboMap}
cRect := sRect;
cUnionRect := sUnionRect;
{offset/slide all the cRects (combo) rects so cUnion is topleft}
LastcRect.right := LastcRect.right-cUnionRect.left;
LastcRect.left := LastcRect.left-cUnionRect.left;
LastcRect.bottom := LastcRect.bottom-cUnionRect.top;
LastcRect.top := LastcRect.top-cUnionRect.top;
cRect.right := cRect.right-cUnionRect.left;
cRect.left := cRect.left-cUnionRect.left;
cRect.bottom := cRect.bottom-cUnionRect.top;
cRect.top := cRect.top-cUnionRect.top;
cUnionRect.right := cUnionRect.right-cUnionRect.left;
cUnionRect.left := cUnionRect.left-cUnionRect.left;
cUnionRect.bottom := cUnionRect.bottom-cUnionRect.top;
cUnionRect.top := cUnionRect.top-cUnionRect.top;
{copy current screen Union to ComboMap}
CopyBits(aWindow^.portBits,ComboMap,sUnionRect,
cUnionRect,srcCopy,NIL);
{copy patch over last in combo.. will restore previous background}
CopyBits(PatchMap,ComboMap,PatchMap.bounds,LastcRect,srcCopy,NIL);
CopyBits(ComboMap,PatchMap,cRect,PatchMap.bounds,srcCopy,NIL);
{copy the piece into new location in Combo}
{move the tRgn to cRect to mask drawing into the Combo map}
OffSetRgn(tRgn,cRect.left - tRgn^^.rgnBBox.left,
cRect.top - tRgn^^.rgnBBox.top);
Copybits(PicMap,ComboMap,PicMap.bounds,cRect,srcCopy,tRgn);
{copy Combo union to screen}
CopyBits(ComboMap,aWindow^.portBits,cUnionRect,
sUnionRect,srcCopy,NIL);
LastsRect := sRect;{remember where the last piece is drawn}
Until (not(StillDown));{Until the mouse button is released,i-259}
{________ optional to erase the piece or leave it, etc. _____}
{we'll restore the patch of background over the piece... erasing it}
CopyBits(PatchMap,aWindow^.portBits,PatchMap.bounds,sRect,srcCopy,nil);
{____________________}
theMouse := LastMouseLoc;{return last mouse location to caller}
DisposPtr(PatchMap.baseAddr);{dispose of temp stuff in heap}
DisposPtr(ComboMap.baseAddr);
DisposPtr(PicMap.baseAddr);
DisposeRgn(tRgn);
End;{DragPiece procedure}
PROCEDURE InitThings;
Begin
InitGraf(@thePort); {create a grafport for the screen}
MoreMasters; {extra pointer blocks at the bottom of the heap}
MoreMasters; {this is 5 X 64 master pointers}
MoreMasters;
MoreMasters;
MoreMasters;
{get the cursors we use and lock them down - no clutter}
ClockCursor := GetCursor(watchCursor);
HLock(Handle(ClockCursor));
{show the watch while we wait for inits & setups to finish}
SetCursor(ClockCursor^^);
{init everything in case the app is the Startup App}
InitFonts; {startup the fonts manager}
InitWindows; {startup the window manager}
InitMenus; {startup the menu manager}
TEInit; {startup the text edit manager}
InitDialogs(Nil); {startup the dialog manager}
Finished := False; {set program terminator to false}
FlushEvents(everyEvent,0); {clear events from previous program}
{ set up screen size stuff }
Screen := ScreenBits.Bounds; { Get screen dimensions from thePort }
with Screen do Begin
SetRect(DragArea,Left+4,Top+24,Right-4,Bottom-4);
SetRect(GrowArea,Left,Top+24,Right,Bottom);
End;
End;
procedure CreateWindow;
Begin
SetRect(tRect,2,40,508,40 + 290);
myWindow := NewWindow(Nil,tRect,'DragPiece Demo',True,4,Nil,True,0);
SetPort(myWindow);
ClipRect(myWindow^.portRect);
End;
procedure DoMenuCommand(mResult:LongInt);
var
name: Str255;
tPort: GrafPtr;
Begin
theMenu := HiWord(mResult);
theItem := LoWord(mResult);
Case theMenu of
appleMenu:
Begin
GetItem(myMenus[1],theItem,name);
refNum := OpenDeskAcc(name);
End;
fileMenu: Finished := True;
End;
HiliteMenu(0);
End;
procedure TakeCareMouseDown(myEvent:EventRecord);
var
Location: integer;
WhichWindow: WindowPtr;
MouseLoc: Point;
WindowLoc: integer;
Begin
MouseLoc := myEvent.Where; {Global coordinates}
WindowLoc := FindWindow(MouseLoc,WhichWindow); {I-287}
case WindowLoc of
inMenuBar:
DoMenuCommand(MenuSelect(MouseLoc));
inSysWindow:
SystemClick(myEvent,WhichWindow); {I-441}
inContent:
If WhichWindow <> FrontWindow then
SelectWindow (WhichWindow)
else Begin
GlobalToLocal(MouseLoc);
SetRect(tRect,MouseLoc.h-20,MouseLoc.v-26,
MouseLoc.h+20,MouseLoc.v+26);
DragRgn := NewRgn;
OpenRgn;
FrameOval(tRect);
CloseRgn(DragRgn);
tRect := WhichWindow^.portRect;
DragPiece(WhichWindow,MouseLoc,tRect,DragRgn);
end;
inGoAway:
Finished := True;
end; {case of}
end; { TakeCareMouseDown }
procedure TakeCareActivates(myEvent:EventRecord);
var
WhichWindow: WindowPtr;
Begin
WhichWindow := WindowPtr(myEvent.message);
SetPort(WhichWindow);
End;
procedure TakeCareUpdates(Event:EventRecord);
var
UpDateWindow,TempPort: WindowPtr;
Begin
UpDateWindow := WindowPtr(Event.message);
GetPort(TempPort);
SetPort(UpDateWindow);
BeginUpDate(UpDateWindow);
EraseRect(UpDateWindow^.portRect);{ or UpdateWindow^.VisRgn^^.rgnBBox }
DrawWindowContents(UpDateWindow);
EndUpDate(UpDateWindow);
SetPort(TempPort);
End;
procedure MainEventLoop;
var
myEvent: EventRecord;
EventAvail: Boolean;
Begin
InitCursor;
Repeat
SystemTask;
EventAvail := GetNextEvent(EveryEvent,myEvent);
If EventAvail then
Case myEvent.What of
mouseDown: TakeCareMouseDown(myEvent);
KeyDown: Finished:= True;
ActivateEvt:TakeCareActivates(myEvent);
UpDateEvt: TakeCareUpdates(myEvent);
End;
Until Finished;
End;
procedure SetUpMenus;
var
i: integer;
Begin
myMenus[1] := GetMenu(appleMenu); {get menu info from resources}
myMenus[2] := GetMenu(fileMenu);
For i := 1 to lastMenu do InsertMenu(myMenus[i],0);
DrawMenuBar;
End;
{Main Program begins here}
BEGIN
InitThings;
MaxApplZone;
SetUpMenus;
CreateWindow;
{set destination for bottom right of our logo picture}
SetPt(LogoLoc,myWindow^.portRect.right-20,myWindow^.portRect.bottom-20);
MainEventLoop;{until finished = true}
END.

Binary file not shown.

View File

@ -0,0 +1 @@
The following are TML 2.5 Standard Procedures and Functions that you may find in the sourcecode: inc(x).. increments the value of x or x := x +1. dec(x).. decrements.... etc. trunc(x).. converts a real-type value to longint value rounded down. round(x).. converts real to longint rounded to nearest whole number. odd(x).. tests whether integer is odd... true if odd. abs(x).. returns absolute value of number. sin(x).. sine of number (radians) cos(x).. cosine of number. concat(str1,str2).. merges strings. length(str).. gives number of characters in string. leave... exit the current loop immediately (For loops, Repeat... etc.)

Binary file not shown.

View File

View File

@ -0,0 +1,776 @@
Program aRegions;{Sun Aug 23, 1987 09:19:36}
{version 0.87,copyright ©,1987...Duane Blehm,HomeTown Software}
USES MacIntf;
{$T APPL RDBN set the TYPE and CREATOR}
{$B+ set the application's bundle bit }
{$L aRegions.rsrc}{link resource file stuff}
CONST
lastMenu = 4; {Number of Menus}
appleMenu = 1;
fileMenu = 256;
editMenu = 257;
optionsMenu = 258;
TYPE
{type the dialogs so we can access by name and add to list}
DialogList = (Save,Help,SizeTheRgn,About,HowTo,Source);
VAR
tRgn: RgnHandle; {temporary region,used to Invert DemoRgn}
tStr: Str255;
myPattern: Pattern; {will hold the background pattern}
DemoRgn: RgnHandle; {region to be used in demo animation}
DemoUnderWay: Boolean; {flag if demo is underway}
i: integer;
Demo,InvertDemo: ControlHandle; {Rgn Demo and Invert It! buttons}
OffScreen: BitMap; {contains our offscreen MacPic image}
MacPic: PicHandle; {for loading PICT resource}
WorkRefNum: integer; {work resource file RefNum}
alertResult: integer; {result of putting up Alert dialogs}
DisplayStatus: integer; {what's on display,0 = nothing,1 = pic,2 = rgn}
DialNdx: DialogList; {will step through our dialogs array}
myDialog: Array[Save..Source] of DialogPtr;{our 'dialogList'}
myDialogRec: Array[Save..Source] of DialogRecord;
WorkRect: Rect; {'work'ing/drawing area of myWindow,left side}
CreateRgn,SaveRgn: ControlHandle; {Create Rgn,Save Rgn buttons}
myPic: PicHandle; {Handle to Pic pasted in from Clipboard}
PicRect: Rect; {Rect for offsetting/Drawing myPic}
DemoBox: Rect; {Bounds for movement of demo animation}
myRgn: RgnHandle; {Region created by alogrithm}
RgnFrame, {Rect limits for FindRegion call...}
tRect: Rect;
length,offSet,
theErr: Longint;
myMenus: Array[1..lastMenu] of MenuHandle;
refNum,theMenu,
theItem: integer;{menustuff}
Finished: Boolean;{used to terminate the program}
ClockCursor: CursHandle; {handle to watch cursor}
myWindow: WindowPtr;
wRecord: WindowRecord;
Screen,DragArea,
GrowArea: Rect;
{----------------------------------------------}
procedure AnimateDemo;
{animate the mac image clipped to DemoRgn}
var
tPoint:Point;
dh,dv:integer;
Begin
GetMouse(tPoint);{get current mouse coordinates}
{limit mac image (PicRect) to DemoBox extremes..}
{to keep PicRect from wondering off our visual area}
If not(PtInRect(tPoint,DemoBox)) then begin {force tPoint into DemoBox}
If tPoint.h > DemoBox.right then tPoint.h := DemoBox.right
else if tPoint.h < DemoBox.left then tPoint.h := DemoBox.left;
If tPoint.v > DemoBox.bottom then tPoint.v := DemoBox.bottom
else if tPoint.v < DemoBox.top then tPoint.v := DemoBox.top;
end;
{determine horizontal offset if needed}
If tPoint.h > PicRect.left + 2 then begin
PicRect.left := PicRect.left + 3;{offsetRect to right}
PicRect.right := PicRect.right + 3;
end
else if tPoint.h < PicRect.left - 2 then begin
PicRect.left := PicRect.left - 3;{offsetRect to left}
PicRect.right := PicRect.right - 3;
end;
{vertical offset?}
If tPoint.v > PicRect.top + 1 then begin
PicRect.top := PicRect.top + 2; {only move 2 because of pattern}
PicRect.bottom := PicRect.bottom + 2;
end
else if tPoint.v < PicRect.top - 1 then begin
PicRect.top := PicRect.top - 2; {only move 2 because of pattern}
PicRect.bottom := PicRect.bottom - 2;
end;
{ok... now draw it using the DemoRgn as a mask}
CopyBits(OffScreen,myWindow^.portBits,OffScreen.bounds,
PicRect,srcCopy,DemoRgn);
end;
procedure CreateOffScreenBitMap; {see CopyBits stuff,also tech.note 41}
var
tRect: Rect;
OffRowBytes,SizeOfOff:integer;
OldBits:Bitmap;
Begin
MacPic := GetPicture(128);{load the Mac picture from resource file}
tRect := MacPic^^.picframe;{size tRect for creating offscreen}
{calculate size/dimensions of OffScreen stuff}
with tRect do begin
OffRowBytes := (((right - left -1) div 16) +1) * 2;{has to be even!}
SizeOfOff := (bottom - top) * OffRowBytes;
OffSetRect(tRect,-left,-top);{move rect to 0,0 topleft}
end; { of with }
OffScreen.baseAddr := QDPtr(NewPtr(SizeOfOff));{Create BitImage with Ptr}
OffScreen.rowbytes := OffRowBytes;{bytes / row in BitImage}
OffScreen.bounds := tRect;
{draw the Mac Picture into OffScreen}
OldBits := myWindow^.portBits; {preserve old BitMap}
SetPortBits(OffScreen); { our new BitMap }
FillRect(OffScreen.bounds,white); {erase our new BitMap to white}
DrawPicture(MacPic,OffScreen.bounds); {draw all the pictures}
ReleaseResource(handle(MacPic)); {done so dump picture from memory}
SetPortBits(OldBits); {restore old bitmap}
end;
procedure InitialDemo;{set up stuff for Demo Regions animation}
var
dh,dv,myErr:integer;
begin
myErr := noErr;{myErr will flag a resource loading error}
If DisplayStatus = 2 then begin {use the current rgn in the demo}
DemoRgn := NewRgn;{Create a fresh DemoRgn, disposed of the last}
CopyRgn(myRgn,DemoRgn);{Copy of current myRgn into DemoRgn}
end
else begin {no current myRgn so we'll load our own in from resources}
DemoRgn := RgnHandle(GetResource('RGN ',20843));
myErr := ResError;{check for loading error}
DetachResource(Handle(DemoRgn));{take control from resource Manager}
end;
If myErr = noErr then begin {continue if no errors where encountered}
DemoUnderWay := True;{flag Demo animation in MainEventLoop}
{disable menus, other controls}
HiliteControl(CreateRgn,255);{disable}
HiliteControl(SaveRgn,255);{disable}
ShowControl(InvertDemo);
DisableItem(myMenus[4],2);{size the Rgn}
For i := 1 to LastMenu do DisableItem(myMenus[i],0);{disable menus}
DrawMenuBar;
SetCTitle(Demo,'End Demo');{so user can end the demo}
EraseRect(WorkRect);{erase the work area of window}
{find offsets to relocate DemoRgn in center of work area}
with DemoRgn^^.rgnBBox do begin
dh := ((WorkRect.right-(right-left)) div 2) - left;
dv := ((WorkRect.bottom-(bottom-top)) div 2) - top;
end;
OffSetRgn(DemoRgn,dh,dv);{center the rgnBBox}
FillRgn(DemoRgn,myPattern);{pattern of horizontal lines}
FrameRgn(DemoRgn);{outline the Rgn}
InsetRgn(DemoRgn,1,1);{so the animation won't erase Frame lines}
DemoBox := DemoRgn^^.rgnBBox;{DemoBox will limit movement of PicRect}
InsetRect(DemoBox,-120,-80);{expand beyond the Rgn a little}
PicRect := OffScreen.bounds;{Size PicRect for CopyBits}
{we'll use Mouse location and PicRect.topleft to offset PicRect
so subtract width and height of PicRect from DemoBox limits}
DemoBox.right := DemoBox.right - (PicRect.right - PicRect.left);
DemoBox.bottom := DemoBox.bottom - (PicRect.bottom - PicRect.top);
If not(odd(DemoBox.top)) then inc(DemoBox.top);{force odd for pattern}
{start the PicRect in upper left of DemoBox}
OffSetRect(PicRect,DemoBox.left-PicRect.left,DemoBox.top-PicRect.top);
end
else begin
alertResult := NoteAlert(134,nil);{sorry, bad resource}
ResetAlrtStage;
end;
end;
procedure DisplayDialog(WhichDialog:DialogList);
var
tRect,fRect: Rect;
itemHit,i,j,tIDNum,RepeatID,count: integer;
tPort: GrafPtr;
tHandle,nameHand,tbuf:Handle;
tStr,nameStr:Str255;
aLong:Longint;
tFlag:boolean;
theType:ResType;
Begin
GetPort(tPort);{save the current port}
ShowWindow(myDialog[WhichDialog]);
SelectWindow(myDialog[WhichDialog]);
SetPort(myDialog[WhichDialog]); {we may draw into our dialog window}
Case WhichDialog of
HowTo:begin {text for how to use a 'RGN ' resource}
TextFont(geneva);
Textsize(10);
tbuf := GetResource('TBUF',128);{text created with our TransText utility}
HLock(tbuf);{lock it we'll be using ptr's}
TextBox(tbuf^,GetHandleSize(tBuf),myDialog[HowTo]^.portRect,teJustLeft);
HUnLock(tBuf);{done}
ModalDialog(Nil,itemHit);
end;
Source:begin {text for Source code offer}
TextFont(geneva);
Textsize(10);
tbuf := GetResource('TBUF',129);
HLock(tbuf);
TextBox(tbuf^,GetHandleSize(tBuf),myDialog[Source]^.portRect,teJustLeft);
HUnLock(tBuf);{done}
ModalDialog(Nil,itemHit);
end;
About:ModalDialog(nil,itemHit); {put up our about Regions dialog}
SizeTheRgn:{user input data for doing an InsetRgn call}
Repeat
SelIText(myDialog[SizetheRgn],5,0,32767);{select horiz.size text}
ModalDialog(nil,itemHit);
If itemHit = 1 then Begin {size the rgn}
GetDItem(myDialog[SizetheRgn],5,i,tHandle,tRect);{Handle textitem}
GetIText(tHandle,tStr);{get the horiz. size text}
StringToNum(tStr,aLong);{convert to Number,error check?}
i := aLong;{horiz.size}
GetDItem(myDialog[SizetheRgn],6,j,tHandle,tRect);{vertical size}
GetIText(tHandle,tStr);
StringToNum(tStr,aLong);
j := aLong;
InsetRgn(myRgn,i,j);
DisplayStatus := 2;{so InvalRect 'update' will draw the region}
end;
Until((itemHit = 1) or (itemhit = 7));{size or cancel}
Help:ModalDialog(nil,itemHit);{help dialog box}
Save: Begin {save myRgn into our work resource file}
nameStr := 'myRegion';{set default Res. name}
Repeat
{get a 'unique' resID number > 128}
Repeat
tIDNum := UniqueID('RGN ');
Until(tIDNum > 127);
{install resID in item 4, name in item 3}
NumToString(tIDNum,tStr);
GetDItem(myDialog[Save],4,i,tHandle,tRect);
SetIText(tHandle,tStr);{set res Id to unique ID}
SelIText(myDialog[Save],4,0,32767);{select the res Id text}
GetDItem(myDialog[Save],3,i,nameHand,tRect);
SetIText(nameHand,NameStr);
ModalDialog(Nil,itemHit); {close it no matter what was hit}
Case itemHit of
1:{add it} begin
{get,check name and id, watch out for duplicates}
GetIText(nameHand,nameStr);{nameString}
GetIText(tHandle,tStr);
StringtoNum(tStr,aLong);
tIdNum := aLong;
{check for resource using tIDNum as ID#}
count := CountResources('RGN ');{how many rgns}
tFlag := True;{initial flag for duplicate Id numbers}
If Count > 0 then {if there any RGN'S}
For i := 1 to count do begin {step thru 'RGN ' resources}
tHandle := GetIndResource('RGN ',i);
GetResInfo(tHandle,j,theType,tStr);
If j = tIdNum then tFlag := false;{id already exists!}
end;
If tFlag then begin {unique id, so save it}
UseResFile(WorkRefNum);
AddResource(Handle(myRgn),'RGN ',tIdNum,nameStr);
UpdateResFile(WorkRefNum);
end
Else begin {id alreay used, alert user, Replace it?}
alertResult := CautionAlert(128,nil);
ResetAlrtStage;
If alertResult = 1 then begin {replace old with new}
{tIDNum is the repeated ID no.!}
tHandle := GetResource('RGN ',tIdNum);{handle to old}
RmveResource(tHandle);{remove the old}
UseResFile(WorkRefNum);{our Work file}
AddResource(Handle(myRgn),'RGN ',tIdNum,nameStr);
UpDateResFile(WorkRefNum);{force write of new}
end
else itemHit := 0;{Cancel,reset itemhit so won't exit Save:}
end;{else}
end;{1:}
end;{case itemhit}
Until((itemHit = 1) or (itemHit = 2));
end;{Save:}
end;{Case WhichDialog}
HideWindow(myDialog[WhichDialog]); {put away dialog window}
SelectWindow(myWindow);{restore our game window}
SetPort(tPort);{restore port}
InvalRect(WorkRect);{force redraw of 'whole' work area.. new Rgn?}
end;
procedure FindRegion(tRect:Rect;var theRgn:RgnHandle);
{be sure that tRect is in visible window on screen before executing this
procedure to avoid system crash}
var
x,y:integer;
ExitNoBlack: Boolean;
Vector,LineVector,ExitStatus:integer;
Original:Point;
SizeCount:integer;
Begin
SetEmptyRgn(theRgn);{in case we have to abort, will return empty}
{scanning by 'pixels' with GetPixel() ... 'pixel' is right and left
of the 'Coordinate' so move inside 1 coordinate}
dec(tRect.right);
dec(tRect.bottom);
x := tRect.left;{we'll begin in topleft, looking for topleftmost black pixel}
y := tRect.top;
{find upper left black pixel}
ExitNoBlack := false;
While ((not GetPixel(x,y)) and (not ExitNoBlack)) do
Begin
If x < tRect.right then inc(x) {move right on line}
else begin {move down to next line}
x := tRect.left;{reset x to left side of line}
If y < tRect.bottom then inc(y)
else ExitNoBlack := true; {exit!,didn't find any black pixels}
end;{else}
end;{while}
If not(ExitNoBlack) then begin {have a Black pixel..x,y so start region}
OpenRgn;
SetPt(Original,x,y); {keep track of starting point}
MoveTo(x,y);
LineVector := 1;{track direction of line, won't LineTo() until it changes}
Vector := 1; {first vector is down (1)}
inc(y);{move coordinates to next}
ExitStatus := 0;{1 = 'Original' found, rgn complete, 2 = rgn too large}
SizeCount := 0;{count LineTo's for size of region,avoid overflow}
{from Original begin 'counterclockwise' circuit around Black pixel border}
Repeat
Case Vector of {case 'last vector move' of.. get next vector}
1: Begin {last vector move was down}
{if pixel left and below is black then move left}
If GetPixel(x-1,y) then Vector := 4
{if not, then check pixel right and below... move down}
else If GetPixel(x,y) then Vector := 1
{if not, then must be pixel right and above... move right}
else Vector := 2;
end;
2: Begin {last was right}
If GetPixel(x,y) then Vector := 1
else If GetPixel(x,y-1) then Vector := 2
else Vector := 3;
end;
3: Begin {last was move up}
If GetPixel(x,y-1) then Vector := 2
else If GetPixel(x-1,y-1) then Vector := 3
else Vector := 4;
end;
4: Begin {last was move left}
If GetPixel(x-1,y-1) then Vector := 3
else If GetPixel(x-1,y) then Vector := 4
else Vector := 1;
end;{of case 4:}
End; {of case vector}
If Vector <> LineVector then begin{new direction,end of current 'line'}
SystemTask;{keep system happy?}
LineTo(x,y);{include line into region}
{sizeCount limits number of LineTo()'s, to avoid Stack crashes}
If SizeCount < 4000 then inc(SizeCount) {we'll get another line}
else begin {too much!, getting too big!.. abort the region}
ExitStatus := 2;{force exit of loop}
LineTo(Original.h,Original.v);{we'll show the Region}
end;
LineVector := Vector;{start a new line}
end;
Case Vector of {we checked for new 'line',etc. so move coordinates}
1:inc(y);{vector moves down}
2:inc(x);{vector moves right}
3:dec(y);{moves up}
4:dec(x);{moves left}
end;{case vector}
If x = Original.h then {is the new Coordinate our 'Original'}
If y = Original.v then begin
ExitStatus := 1;{finished if it is!,will force exit}
LineTo(x,y);{last line}
end;
Until (ExitStatus <> 0);{until we get back to start or too large}
CloseRgn(theRgn);{we're done so close the rgn}
InitCursor;{in case of alerts}
If ExitStatus = 2 then begin {display the abort rgn alert}
alertResult := NoteAlert(136,nil);{rgn aborted too big}
ResetAlrtStage;
end;
end {if not(Done)}
else begin {display no black pix alert}
InitCursor;{show arrow cursor for alert}
alertResult := NoteAlert(135,nil);{no black pixels}
ResetAlrtStage;
end;
End;
procedure DrawWindowContents(WhichWindow:WindowPtr);
{Remember to SetPort first, response to update event}
var
trect:Rect;
i:integer;
tRgn:RgnHandle;
tStr:Str255;
Begin
ClipRect(WorkRect);{limit drawing to WorkRect}
Case DisplayStatus of
1:Begin {picture on display}
DrawPicture(myPic,PicRect);{draw clipboard picture}
end;
2:Begin {region on display}
OffSetRgn(myRgn,5-myRgn^^.rgnBBox.left,5-myRgn^^.rgnBBox.top);
FillRgn(myRgn,ltGray);
FrameRgn(myRgn);{will appear same coords as pict}
end;
end;{case displayStatus}
ClipRect(myWindow^.portRect);{set clip to window borders.. controls}
MoveTo(WorkRect.right,WorkRect.top);{draw right work border line}
LineTo(WorkRect.right,WorkRect.bottom);
DrawControls(WhichWindow);
End;
PROCEDURE InitThings;
Begin
InitGraf(@thePort); {create a grafport for the screen}
MoreMasters; {extra pointer blocks at the bottom of the heap}
MoreMasters; {this is 5 X 64 master pointers}
MoreMasters;
MoreMasters;
MoreMasters;
{get the cursors we use and lock them down - no clutter}
ClockCursor := GetCursor(watchCursor);
HLock(Handle(ClockCursor));
{show the watch while we wait for inits & setups to finish}
SetCursor(ClockCursor^^);
{init everything in case the app is the Startup App}
InitFonts; {startup the fonts manager}
InitWindows; {startup the window manager}
InitMenus; {startup the menu manager}
TEInit; {startup the text edit manager}
InitDialogs(Nil); {startup the dialog manager}
Finished := False; {set program terminator to false}
FlushEvents(everyEvent,0); {clear events from previous program}
{ set up screen size stuff }
Screen := ScreenBits.Bounds; { Get screen dimensions from thePort }
with Screen do { Screen.Left, etc. }
Begin
SetRect(DragArea,Left+4,Top+24,Right-4,Bottom-4);
SetRect(GrowArea,Left,Top+24,Right,Bottom);
End;
End;
procedure CreateWindow;
var
tRect: Rect;
Begin
SetRect(tRect,2,24,508,338);{size the window}
myWindow := NewWindow(@wRecord,tRect,'',True,2,Nil,True,0);
SetRect(tRect,0,0,520,340);{size of clip rgn}
For DialNdx := Save to Source do begin {read all the dialogs into array}
myDialog[DialNdx] :=
GetNewDialog(ord(DialNdx)+128,@myDialogRec[DialNdx],myWindow);
SetPort(myDialog[DialNdx]);
ClipRect(tRect);{set clip to smaller size..}
end;
SetPort(myWindow);
ClipRect(tRect);
SetRect(tRect,416,35,502,59);{size/location of 1st control button}
CreateRgn := NewControl(myWindow,tRect,'Create Rgn',True,0,0,0,0,0);
OffSetRect(tRect,0,36);
SaveRgn := NewControl(myWindow,tRect,'Save Rgn',True,0,0,0,0,0);
OffSetRect(tRect,0,36);
Demo := NewControl(myWindow,tRect,'Rgn Demo',True,0,0,0,0,0);
OffSetRect(tRect,0,36);
InvertDemo := NewControl(myWindow,tRect,'Invert It!',False,0,0,0,0,0);
End;
procedure DoMenuCommand(mResult:LongInt);
var
name: Str255;
tPort: GrafPtr;
Begin
theMenu := HiWord(mResult);
theItem := LoWord(mResult);
Case theMenu of
appleMenu: Begin
If theItem = 1 then DisplayDialog(About)
Else begin
GetPort(tPort);
GetItem(myMenus[1],theItem,name);{must be a desk acc.}
refNum := OpenDeskAcc(name);
SetPort(tPort);
end;
End;
fileMenu: Finished := True;
editMenu:
{if systemEdit returns false then process click at our end}
If not(SystemEdit(theItem - 1)) then
Case theItem of
5:begin {paste}
{call GetScrap and draw picture into window}
length := GetScrap(Handle(myPic),'PICT',offset);
If length < 0 then begin {no PICT type scrap available!}
alertResult := NoteAlert(129,nil);{sorry no picture}
ResetAlrtStage;
end
else begin {we've got a picture waiting, 'paste' it}
PicRect := myPic^^.picframe;
OffSetRect(PicRect,5 - PicRect.left,5 - PicRect.top);
{check to see it picture is too large for work area}
If (PicRect.right > (WorkRect.right-6)) or
(PicRect.bottom > (WorkRect.bottom-6)) then Begin
{alert user... pic too large!}
alertResult := NoteAlert(130,nil);
ResetAlrtStage;
DisplayStatus := 0;{display nothing}
InvalRect(WorkRect);{force update redraw of work}
end
else begin {draw the scrap picture!}
EraseRect(WorkRect);
ClipRect(WorkRect);
DrawPicture(myPic,PicRect);
ClipRect(myWindow^.portRect);
RgnFrame := PicRect;
{enlarge by one pixel,to ensure white pixel border!}
InsetRect(RgnFrame,-1,-1);
DisplayStatus := 1;{flag picture on display}
HiliteControl(CreateRgn,0);{enable create a rgn}
HiliteControl(SaveRgn,255);{disable}
DisableItem(myMenus[4],2);{size}
end;{else}
end;{else}
end;{5:}
6:begin {clear to original start up status}
DisplayStatus := 0;
InvalRect(myWindow^.portRect);
HiliteControl(CreateRgn,255);
HiliteControl(SaveRgn,255);{disable}
DisableItem(myMenus[4],2);{size}
end;{6:}
end;{case theitem}
optionsMenu:
Case theItem of
1:DisplayDialog(Help);
2:DisplayDialog(SizeTheRgn);
3:DisplayDialog(HowTo);
4:DisplayDialog(Source);
end;{case theItem}
End;
HiliteMenu(0);{take hilite off menubar}
End;
procedure TakeCareControls(whichControl:ControlHandle;localMouse:point);
var
ControlHit,i: integer;
refnum:integer;
Begin
ControlHit := TrackControl(whichControl,localMouse,nil); { Find out which}
If ControlHit > 0 then {i-417}
Begin
If whichControl = CreateRgn then Begin
{handle a hit in the Create region button}
SetCursor(ClockCursor^^);{while we work on the region}
myRgn := NewRgn;
FindRegion(RgnFrame,myRgn);
DisplayStatus := 2;
InvalRect(workRect);
HiliteControl(CreateRgn,255);{disable}
HiliteControl(SaveRgn,0);
EnableItem(myMenus[4],2);{size rgn}
End;
If whichControl = SaveRgn then Begin
DisplayDialog(Save);{will handle all the save stuff}
end;
If whichControl = Demo then begin {could be begin or end of demo!}
If DemoUnderWay then begin {then end it}
DemoUnderWay := False;{stop the animation}
{enable menus, other controls}
SetCTitle(Demo,'Rgn Demo');
HideControl(InvertDemo);
InvalRect(WorkRect);
For i := 1 to LastMenu do EnableItem(myMenus[i],0);
DrawMenuBar;
DisposHandle(Handle(DemoRgn));{dump DemoRgn from memory}
If DisplayStatus = 2 then begin {still have a valid myRgn}
HiliteControl(SaveRgn,0);
EnableItem(myMenus[4],2);{size rgn}
end
else DisplayStatus := 0;{won't preserve picture?}
end {if demoUnderway begin}
else InitialDemo; {start the demo}
end;{if whichcontrol}
If whichControl = InvertDemo then Begin {invert the region}
FillRgn(DemoRgn,white);{fill with white, will erase pattern,etc.}
FrameRgn(DemoRgn);{frame is just 'inside' the rgn}
RectRgn(tRgn,WorkRect);{tRgn of WorkRect}
DiffRgn(tRgn,DemoRgn,DemoRgn);{DemoRgn out of tRgn,new in DemoRgn}
FillRgn(DemoRgn,myPattern);{Fill new DemoRgn with horz.lines}
HideControl(InvertDemo);{we can't invert it again.. so hide button}
end;
End; {of If ControlHit}
End; { of procedure}
procedure TakeCareMouseDown(myEvent:EventRecord);
var
Location: integer;
WhichWindow: WindowPtr;
MouseLoc: Point;
WindowLoc: integer;
ControlHit: integer;
WhichControl:ControlHandle;
Begin
MouseLoc := myEvent.Where; {Global coordinates}
WindowLoc := FindWindow(MouseLoc,WhichWindow); {I-287}
case WindowLoc of
inMenuBar:
DoMenuCommand(MenuSelect(MouseLoc));
inSysWindow:
SystemClick(myEvent,WhichWindow); {I-441,scrapbook,etc.}
inContent:
If WhichWindow <> FrontWindow then
SelectWindow(WhichWindow) {bring window to front}
else Begin {check for hit in control buttons}
GlobaltoLocal(MouseLoc);
ControlHit := FindControl(MouseLoc,whichWindow,whichControl);
If ControlHit > 0 then TakeCareControls(whichControl,Mouseloc);
end;
end; {case of}
end; { TakeCareMouseDown }
procedure TakeCareActivates(myEvent:EventRecord);
var
WhichWindow: WindowPtr;
Begin
WhichWindow := WindowPtr(myEvent.message);
If odd(myEvent.modifiers) then begin {becoming active}
SetPort(WhichWindow);
{disable undo,cut,copy}
DisableItem(myMenus[3],1);
DisableItem(myMenus[3],3);
DisableItem(myMenus[3],4);
end
else begin {deactivated must be desk accessory}
{enable all the Edit stuff}
For i := 1 to 6 do EnableItem(myMenus[3],i);{for DA's}
end;
End;
procedure TakeCareUpdates(Event:EventRecord);
var
UpDateWindow,TempPort: WindowPtr;
Begin
UpDateWindow := WindowPtr(Event.message);
GetPort(TempPort);
SetPort(UpDateWindow);
BeginUpDate(UpDateWindow);
EraseRect(UpDateWindow^.portRect);
DrawWindowContents(UpDateWindow);
EndUpDate(UpDateWindow);
SetPort(TempPort);
End;
procedure TakeCareKeyDown(Event:EventRecord);
Var
KeyCode,i: integer;
CharCode: char;
Begin
{ KeyCode := LoWord(BitAnd(Event.message,keyCodeMask)) div 256; not used }
CharCode := chr(LoWord(BitAnd(Event.message,CharCodeMask)));
If BitAnd(Event.modifiers,CmdKey) = CmdKey then begin
{key board command - probably a menu command}
DoMenuCommand(MenuKey(CharCode));
end;
End;
procedure MainEventLoop;
var
myEvent: EventRecord;
EventAvail: Boolean;
Begin
InitCursor;
Repeat
SystemTask;
If GetNextEvent(EveryEvent,myEvent) then
Case myEvent.What of
mouseDown: TakeCareMouseDown(myEvent);
KeyDown: TakeCareKeyDown(myEvent);
ActivateEvt: TakeCareActivates(myEvent);
UpDateEvt: TakeCareUpdates(myEvent);
End
else If DemoUnderWay then AnimateDemo;{animate one step of demo}
Until Finished;
End;
procedure SetUpMenus;
var
i: integer;
Begin
myMenus[1] := GetMenu(appleMenu); {get menu info from resources}
AddResMenu(myMenus[1],'DRVR'); {add in all the DA's}
myMenus[2] := GetMenu(fileMenu);
myMenus[3] := GetMenu(editMenu);
myMenus[4] := GetMenu(optionsMenu);
DisableItem(myMenus[4],2);{size region}
For i := 1 to lastMenu do
begin
InsertMenu(myMenus[i],0);
end;
DrawMenuBar;
End;
procedure CloseStuff;
Begin
{always kill sound i/o before quit}
CloseResFile(WorkRefNum);{close work resource file}
End;
{Main Program begins here}
BEGIN
InitThings;
MaxApplZone;{grow application zone to max... Scrapbook uses appl.heap}
theErr := ZeroScrap;{initialize the Scrap, erases any existing scrap, i-458}
SetUpMenus;
CreateWindow;
CreateOffScreenBitMap;
myPic := picHandle(NewHandle(0));{create valid handle for GetScrap call}
myRgn := NewRgn;{create the rgns}
tRgn := NewRgn;
WorkRect := myWindow^.portRect;{size the work area of window}
WorkRect.right := 410;
DisplayStatus := 0;{nothing is on display}
HiliteControl(CreateRgn,255);{disable}
HiliteControl(SaveRgn,255);{disable}
CreateResFile('RgnWork.rsrc');{no action if it already exists}
{will be created in same folder as Regions application?}
WorkRefNum := OpenResFile('RgnWork.rsrc');{open for action.. save}
DemoUnderWay := false;{no demo to start}
GetIndPattern(myPattern,sysPatListID,25);{horiz.line pattern in systemfile}
MainEventLoop;
CloseStuff;
END.

View File

View File

@ -0,0 +1,35 @@
* aRegions.R
aRegions.rsrc
TYPE RDBN = STR
,0
Regions ver0.87, Duane Blehm, 8/87
TYPE MENU
,1
\14
About Regions..
(-
,256
File
Quit /Q
,257
Edit
Undo /Z
(-
Cut /X
Copy /C
Paste /V
Clear
,258
Options
Help
Size Region..
Using Rgns..
Source offer..
INCLUDE aRegions/Rsrc

View File

View File

@ -0,0 +1 @@
About the StuntCopter files: 'StuntCopter.shapes' is a 'FullPaint' document containing the shapes that are used for animation, score, etc... can be opened from MacPaint. 'StuntCopter.Pas' is an 'Edit' text file containing pascal source code to be compiled by the Pascal compiler. 'StuntCopter.R' is an 'Edit' text file containing RMaker source code to be compiled by RMaker. 'StuntCopter.Rsrc' is a resource document containing resources built with ResEdit, the resource editor. These resources are 'included' when StuntCopter.R is compiled by RMaker. 'StuntCopter' is our application... the result of Link.

View File

@ -0,0 +1,16 @@
* Anim.R
Anim.rsrc
TYPE MENU
,1
\14
,256
File
OffScreen..
Quit
* will include Pict resource file built with ResEdit and ScrapBook
INCLUDE Anim/rsrc

View File

@ -0,0 +1,33 @@
* StuntCopter.R
aSCopt.rsrc
TYPE COPT = STR
,0
StuntCopter 1.5.. by Duane Blehm, 7/87
TYPE MENU
,1
\14
About Stunt...
(-
,256
File
Quit /Q
,257
Options
! Sound
Reset HiScore
Help..
Set Speed..
Source Code..
OffScreen..
,258
(Backspace to Exit)
Hi!
* the rest of the resources where built with ResEdit in StuntCopter.Rsrc
INCLUDE StuntCopter/Rsrc

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
About the ZeroGravity files: 'Game Animation' is a 'FullPaint' document illustrating the way animation is done in the ZeroGravity Chamber. 'About Zero Animation' is a MacWrite document that describes ZeroGravity animation. 'ZeroGravity.Pas' is an 'Edit' text file containing pascal source code to be compiled by the Pascal compiler. 'ZeroGravity.R' is an 'Edit' text file containing RMaker source code to be compiled by RMaker. 'ZeroGravity/Rsrc' is a resource document containing resources built with ResEdit, the resource editor. These resources are 'included' when ZeroGravity.R is compiled by RMaker. 'ZeroGravity' is our application... the result of Link.

Binary file not shown.

View File

View File

@ -0,0 +1,35 @@
* ZeroGravity.R
ZeroGravity.rsrc
TYPE ZGRV = STR
,0
ZeroGravity ver1.0, by Duane Blehm, 2/12/87
TYPE MENU
,1
\14
About Zero...
(-
,256
File
Quit /Q
,257
Options
Help...
LoScore...
! Sound
,258
Works
Peek OffScreen
Source Code...
,259
(Any Key to Exit)
Hi!
* the rest of the resources where built with ResEdit
INCLUDE ZeroGravity/Rsrc

File diff suppressed because it is too large Load Diff

16
Makefile Normal file
View File

@ -0,0 +1,16 @@
# Tested only on Mac OS X, YMMV, etc
all: unzip detab
unzip:
unzip -o Duane\ Blehm\'s\ Code.zip >/dev/null
detab: unzip
cp -Rp Duane\ Blehm\'s\ Code Duane\ Blehm\'s\ Code.bak
( cd Duane\ Blehm\'s\ Code && find . -name '*.[pP]as' -exec tab2space -lf -t3 {} {} \; )
( cd Duane\ Blehm\'s\ Code && find . -name '*.[pP]as' -exec perl -i -p -e "s/ +\Z//" {} \; )
( cd Duane\ Blehm\'s\ Code && find . -name '*.[rR]' -exec tab2space -lf {} {} \; )
( cd Duane\ Blehm\'s\ Code && find . -name '*.txt' -exec tab2space -lf {} {} \; )
( cd Duane\ Blehm\'s\ Code && find . -exec touch -r ../Duane\ Blehm\'s\ Code.bak/{} {} \; )
rm -r Duane\ Blehm\'s\ Code.bak

87
README.md Normal file
View File

@ -0,0 +1,87 @@
# Duane Blehm's Code
This is an archive of the Duane Blehm's source code. Duane Blehm was an
early game developer for the Macintosh. He released three games in the
1980's:
[Zero Gravity](http://www.macintoshrepository.org/4249-zero-gravity-),
[StuntCopter](http://www.macintoshrepository.org/5314-stuntcopter), and
[Cairo ShootOut!](http://www.macintoshrepository.org/4856-cairo-shootout-).
As a preteen computer nerd and budding developer, I not only loved the
games, but also had an interest in how a real application was made.
The About screens for the games offered source code printouts and unlock
codes for a small fee, so I saved up my allowance for a month or two,
stuffed a few bills and a note into an envelope, and mailed it off.
I received a reply about a year later. It was from Blehm's parents,
gently explaining that their son had passed away and they couldn't offer
the unlock codes. They returned my money. I was too young and lucky to
have much experience with death. When I read the news, I remember
feeling a pang of... something. I never forgot this feeling, and I
never forgot about the source code.
Some years later (a little over fifteen of them), Apple released a
Newton that ran NeXTSTEP and had cell phone radio. I was done becoming
a programmer and on to becoming a better one. I thought that porting
Zero Gravity to the iPhone would be a fun project, and began looking for
the source code again so that I could get the physics exactly right.
Despite the best efforts of a small LiveJournal community, I came up
empty. I had enough other projects that I lost interest in that one
for the time being.
But, just like before, I never stopped thinking about the code.
I decided earlier this year that it had been long enough since my last
try, and in 2016 the venue of choice was Twitter. I pecked out a short
plea for help, and in a hail-mary attempt to reach someone who had some
idea of how to help, I cc'ed Avadis Tevanian, Jr., who most people know
as a longtime VP at Apple but I remember primarily as the developer of
a beloved Missile Command port called MacCommand, and John Calhoun, who
wrote the fantastic paper-airplane game Glider.
Avi Tevanian doesn't tweet, really. But John Calhoun did. Suddenly I
had the source code.
So here it is, offered without license or warranty, the code for all
three of Duane Blehm's releases. I've converted line endings to LF and
detabbed the files according to Blehm's preference for three-space tab
stops, and I wrote this README and a top-level Makefile, but the rest was
his and now it's ours.
Rest in peace, Duane Blehm. Thanks for the games.
## Contents
├── Duane Blehm's Code Data forks
│   ├── Animation ƒ
│   ├── Cairo ƒ
│   ├── Copy Mask ƒ
│   ├── Drag Piece ƒ
│   ├── More Info*
│   ├── Regions ƒ
│   ├── StuntCopter ƒ
│   └── Zero Gravityƒ
├── __MACOSX Resource forks
│   └── Duane Blehm's Code
│   ├── Animation ƒ
│   ├── Cairo ƒ
│   ├── Copy Mask ƒ
│   ├── Drag Piece ƒ
│   ├── More Info*
│   ├── Regions ƒ
│   ├── StuntCopter ƒ
│   └── Zero Gravityƒ
├── Duane Blehm's Code.zip Original source dump
├── Makefile Run `make` to rebuild this archive
└── README.md This file
## Maintainer
Pete Gamache, [pete@gamache.org](mailto:pete@gamache.org).

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More