home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-04 | 5.9 KB | 215 lines | [TEXT/MWPS] |
- program SpriteEngine;
-
- uses
- {$IFC UNDEFINED THINK_PASCAL}
- Types, QuickDraw, Fonts, Events, Packages, Menus, Dialogs, Windows,{}
- OSUtils, ToolUtils, OSEvents, Resources,
- {$ENDC}
- QDOffScreen, SpriteStructure, SpriteTools, SpriteHandlers;
-
- {SpriteEngine}
- {============}
-
- {This demo sprite engine is designed for the following structure:}
- {(Lower units use the higher ones.)}
- {}
- {SpriteTools.c: Utilities for loading and drawing}
- {|}
- {SpriteHanders.c: All custom code: Sprite init, movement, collisions}
- {|}
- {SpriteEngine.c: Main program, sprite engine}
-
- {The only files you need to edit in order to change the sprite behavior are}
- {the files SpriteHandlers.c and SpriteHandlers.h.}
-
-
- (* The actual sprite engine *)
-
-
- procedure InitSpriteEngine (var offBounds: Rect; backgroundPictureID: Integer);
-
- var
- backgroundPicture: PicHandle;
- saveGD: GDHandle;
- savePort: GWorldPtr;
-
- begin
- MyNewGWorld(gOffScreen, offBounds);
- MyNewGWorld(gBackScreen, offBounds);
-
- GetGWorld(savePort, saveGD); (*Save the port/device*)
- SetGWorld(GWorldPtr(gBackScreen), nil);
-
- EraseRect(offBounds);
-
- backgroundPicture := GetPicture(backgroundPictureID);
- if (backgroundPicture <> nil) then
-
- begin
- DrawPicture(backgroundPicture, offBounds);
- ReleaseResource(Handle(backgroundPicture));
- end;
- SetGWorld(GWorldPtr(gOffScreen), nil);
- CopyBits(gBackScreen^.portBits, gOffScreen^.portBits, offBounds, offBounds, srcCopy, nil);
- SetGWorld(GWorldPtr(myWindow), GetMainDevice);
- CopyBits(gOffScreen^.portBits, myWindow^.portBits, offBounds, offBounds, srcCopy, nil);
- SetGWorld(savePort, saveGD);
- end; (*InitSpriteEngine*)
-
-
-
- procedure RunSpriteEngine;
-
- const
- kWallBounce = 7;(*1/10-ths of speed kept after wallbounce*)
- kBallDiameterSquared = (32 * 32);(*Diameter 32, squared*)
-
- var
- tmpRect: Rect;
- saveGD: GDHandle;
- savePort: GWorldPtr;
- theSprite, anotherSprite: SpritePtr;
- bounds1, bounds2: Rect;
-
- begin
- GetGWorld(savePort, saveGD); (*Save the port/device*)
- (*1: Erase all sprites from gOffScreen*)
- (*Note: We keep the rectangles for erasing on the screen, later.*)
- SetGWorld(GWorldPtr(gOffScreen), nil);
-
- theSprite := gSpriteList;
- while (theSprite <> nil) do
- begin
- theSprite^.drawingRect := theSprite^.face^.portRect;
- OffsetRect(theSprite^.drawingRect, theSprite^.position.h, theSprite^.position.v);
- CopyBits(gBackScreen^.portBits, gOffScreen^.portBits, theSprite^.drawingRect, theSprite^.drawingRect, srcCopy, nil);
-
- theSprite := theSprite^.next;
- end;
-
- (*2: Change the position and speed*)
- theSprite := gSpriteList;
- while (theSprite <> nil) do
-
- begin
- MoveSprite(theSprite);
-
- theSprite := theSprite^.next;
- end;(*position/speed loop*)
-
- (*3: Check for collisions*)
- theSprite := gSpriteList;
- while (theSprite <> nil) do (*For all sprites in the list…*)
- begin
- bounds1 := theSprite^.face^.portRect;
- OffsetRect(bounds1, theSprite^.position.h, theSprite^.position.v);
-
- anotherSprite := theSprite^.next;
- while (anotherSprite <> nil) do
- (*compare its position to all following sprites*)
- begin
- bounds2 := anotherSprite^.face^.portRect;
- OffsetRect(bounds2, anotherSprite^.position.h, anotherSprite^.position.v);
-
- if (SectRect(bounds1, bounds2, tmpRect)) then
- HitSprite(theSprite, anotherSprite);
-
- anotherSprite := anotherSprite^.next;
- end;
- theSprite := theSprite^.next;
- end; (*collision loop*)
-
- (*4: Draw sprites in gOffScreen*)
- (*Note: PlotCIcon or DrawPicture are not very fast! We can speed it up my*)
- (*pre-drawing them in some offscreen, and CopyBits them from there.*)
- theSprite := gSpriteList;
- while (theSprite <> nil) do (*For all sprites in the list…*)
- begin
- tmpRect := theSprite^.face^.portRect;
- OffsetRect(tmpRect, theSprite^.position.h, theSprite^.position.v);
- PlotFace(theSprite^.face, gOffScreen, tmpRect.topLeft);
- theSprite := theSprite^.next;
- end;
-
- (*5: Copy sprites to the screen (gWind) - both old and new position!*)
- (*Note: Depending on what limitations we have on movement, we may be able to avoid the multiple*)
- (*CopyBitsing here. E.g. if sprites always move a maximum of 2 pixels, we can copy a 2 pixels*)
- (*larger area, etc.*)
- SetGWorld(GWorldPtr(myWindow), saveGD);
- theSprite := gSpriteList;
- while (theSprite <> nil) do (*For all sprites in the list…*)
- begin
- CopyBits(gOffScreen^.portBits, myWindow^.portBits, theSprite^.drawingRect, theSprite^.drawingRect, srcCopy, nil);
- theSprite^.drawingRect := theSprite^.face^.portRect;
- OffsetRect(theSprite^.drawingRect, theSprite^.position.h, theSprite^.position.v);
- CopyBits(gOffScreen^.portBits, myWindow^.portBits, theSprite^.drawingRect, theSprite^.drawingRect, srcCopy, nil);
-
- theSprite := theSprite^.next;
- end;
- SetGWorld(savePort, saveGD);
- end; (*RunSpriteEngine*)
-
-
-
- (* Standard inits *)
-
- procedure InitToolbox;
- begin
- {$IFC UNDEFINED THINK_PASCAL}
- InitGraf(@qd.thePort);
- InitFonts;
- FlushEvents(everyEvent, 0);
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(nil);
- {$ENDC}
- InitCursor;
- end; (*InitToolbox*)
-
-
- (* Initialize - create window, load graphics *)
-
- procedure InitStuff;
- var
- windowRectangle: Rect;
-
- (*Set up the window*)
- begin
- SetRect(windowRectangle, 50, 50, 450, 350);
- myWindow := NewCWindow(nil, windowRectangle, 'Sprite test', true, documentProc, WindowPtr(-1), false, 0);
- SetPort(myWindow);
-
- {$IFC UNDEFINED THINK_PASCAL}
- qd.randSeed := TickCount; (*Seed the random number generator*)
- {$ELSEC}
- randSeed := TickCount; (*Seed the random number generator*)
- {$ENDC}
- end; (*InitStuff*)
-
- const
- kBackgroundPictureID = 128;
-
- (* Main program *)
-
- var
- startTime: LongInt;
-
- begin
- InitToolbox;
- InitStuff;
- InitSpriteEngine(myWindow^.portRect, kBackgroundPictureID);
- InitSprites;
-
- {HideCursor;}
- while not Button do
- begin
- startTime := TickCount;
- RunSpriteEngine;
- while TickCount < startTime + kFrameTime do
- ;
- end;
- {ShowCursor;}
-
- FlushEvents(mDownMask, 0);
- end. (*main*)