home *** CD-ROM | disk | FTP | other *** search
-
- // Handles moving and rendering various moving objects.
-
- #import <gamekit/gamekit.h>
- #import <stdio.h>
-
- @implementation GKActor
-
- - init // initialize the new instance vars
- { // You need to override this to set state and maxFrames at the very least
- [super init];
- NX_X(&boundingBox) = 0;
- NX_Y(&boundingBox) = 0;
- NX_HEIGHT(&boundingBox) = GK_DEFAULT_ACTOR_WIDTH;
- NX_WIDTH(&boundingBox) = GK_DEFAULT_ACTOR_HEIGHT;
- GK_CLEAR_VECTOR(&nextLocation);
- GK_CLEAR_VECTOR(&lastLocation);
- GK_CLEAR_VECTOR(&lastDrawnLocation);
- maxFrames = (int *)malloc(sizeof(int));
- maxFrames[0] = 0; maxSeries = 1; series = 0;
- frame = 0; cycles = 0; state = GK_DEAD_ACTOR;
- renderedImage = nil; drawingLevel = GK_DYNAMIC_ACTOR;
- return self;
- }
-
- - (int)drawingLevel { return drawingLevel; }
- - setDrawingLevel:(int)aLevel { drawingLevel = aLevel; return self; }
- - stage { return stage; }
-
- - setStage:aStage { // ***** probably ought to make sure we're not on any other stage!
- stage = aStage;
- return self;
- }
-
- - leaveTheStage
- {
- [stage removeActor:self ofType:drawingLevel];
- return self;
- }
-
- - setSize:(const NXSize *)aSize
- // set the actor's size (enclosing frame in image)
- {
- GK_COPY_SIZES(&(boundingBox.size), aSize);
- return self;
- }
-
- - setRenderedImage:anImage // set the bitmap image used to render
- { // we don't free an old image, if it exists. This is because others
- // might also be using the image. What I should do is a reference
- // counting image *****
- renderedImage = anImage;
- return self;
- }
-
- - setSeries:(int)anInt // set the animation series (row) to use in bitmap
- {
- if (anInt >= maxSeries) return nil; // only change to a valid series number
- series = anInt;
- return self;
- }
-
- - setMaxFrames:(const int *)anIntArray count:(int)anInt // array indexed by
- // series number; gives the number of frames in the series
- { // This could possibly be incorporated into an "Array" object, perhaps
- // one which does reference counting. *****
- int i;
- free(maxFrames); maxFrames = (int *)malloc(sizeof(int) * anInt);
- for (i=0; i<anInt; i++) maxFrames[i] = anIntArray[i];
- maxSeries = anInt;
- return self;
- }
-
- - move:sender // Move the Actor one animation frame
- { // you must override this and put something here
- // alter the nextLocation vector to move the actor.
- return self;
- }
-
- - (int)collisionType // called to determine which type of collision
- // detection to use with this actor
- { // override to change type... default is the bounding box
- return GK_RECTANGLE_SHAPE;
- }
-
- - (void *)shapeStruct // if you change the collision type, you must
- { // return a pointer to an appropriate structure defining the shape
- return (&boundingBox); // Note that if you call this method, do NOT
- // alter the boundingBox returned! It will cause all sorts of havoc!
- }
-
- - collidedWith:anActor // called when it is detected that we hit something
- { // you should override to do something about the hit, if necessary
- return self;
- }
-
- - lastAt:(NXPoint *)aPoint // called to find out where actor was
- {
- GK_COPY_VECTORS(aPoint, &lastLocation);
- return self;
- }
-
- - lastDrawnAt:(NXPoint *)aPoint // called to find out where actor was
- {
- GK_COPY_VECTORS(aPoint, &lastDrawnLocation);
- return self;
- }
-
- - at:(NXPoint *)aPoint // called to find out where actor was
- {
- GK_COPY_VECTORS(aPoint, &GK_location);
- return self;
- }
-
- - getBoundingBox:(NXRect *)box
- {
- GK_COPY_RECT(box, &boundingBox);
- return self;
- }
-
- - (int)series { return series; } // the series we're currently using
- - (int)frame { return frame; } // the next frame that will be drawn
-
- - moveOneFrame // moves the actor along; accessed via renderAt::move:
- {
- // flag movement; we won't redraw if no movement...
- if ((GK_VECTOR_X(&GK_location) != GK_VECTOR_X(&nextLocation)) ||
- (GK_VECTOR_Y(&GK_location) != GK_VECTOR_Y(&nextLocation)))
- movedThisFrame = YES;
- GK_COPY_VECTORS(&GK_location, &nextLocation);
- GK_COPY_VECTORS(&lastLocation, &GK_location);
- return self;
- }
-
- - eraseInDirtPile:dirtPile
- { // pass our most recent dirty rect to the DirtPile...
- [dirtPile addRegion:GK_VECTOR_X(&lastDrawnLocation)
- :GK_VECTOR_Y(&lastDrawnLocation)
- :boundingBox.size.width
- :boundingBox.size.height];
- return self;
- }
-
- - markInDirtPile:dirtPile // same as above but called at different times
- { // pass our most recent dirty rect to the DirtPile...
- [dirtPile addRegion:GK_VECTOR_X(&lastDrawnLocation)
- :GK_VECTOR_Y(&lastDrawnLocation)
- :boundingBox.size.width
- :boundingBox.size.height];
- return self;
- }
-
- - renderAt:(NXPoint *)offset move:(BOOL)moveOk withDirtPile:dirtPile
- // draw actor; lock focus on view that gets the actor before call
- { // this should be overridden by the actor subclass
- NXPoint zero = { 0.0, 0.0 };
- if (state == GK_DEAD_ACTOR) return self; // we're dead, nothing to do
- if (moveOk) [self moveOneFrame];
- GK_COPY_VECTORS(&lastDrawnLocation, &GK_location); // we need to track
- // this so we can do erase properly
- if (movedThisFrame) { // handle the drawing if need to redraw.
- if (offset) [self drawActorWithOffset:offset];
- else [self drawActorWithOffset:&zero];
- // mark the drawn area as dirty
- [self markInDirtPile:dirtPile];
- movedThisFrame = NO;
- }
- [self updateDrawingState]; // we update _even_ if no movement;
- // if you object is stationary, but changes shape a lot, then
- // you should set the movedThisFrame flag in this method!
- return self;
- }
-
- - drawActorWithOffset:(NXPoint *)offset // draw the actor
- { // 90% of the time you'll override this completely
- NXRect from = { { frame * NX_WIDTH(&boundingBox),
- series * NX_HEIGHT(&boundingBox) },
- { NX_WIDTH(&boundingBox), NX_HEIGHT(&boundingBox) } };
- NXPoint pos = { NX_X(&boundingBox) + GK_VECTOR_X(offset),
- NX_Y(&boundingBox) + GK_VECTOR_Y(offset) };
- [renderedImage composite:NX_SOVER fromRect:&from toPoint:&pos];
- return self;
- }
-
- - updateDrawingState // change the internal state machine (ie. advance
- { // frames, etc. This will also
- cycles++;
- frame++; if (frame >= maxFrames[series]) frame = 0;
- return self;
- }
-
- @end
-