Example #1
0
 public override bool collide(cCritter pcritter)
 {
     if (pcritter.IsKindOf("cCritterWank") || pcritter.IsKindOf("cCritterDragonball"))
     {
         return(false);
     }
     else
     {
         return(base.collide(pcritter));
     }
 }
Example #2
0
 public override bool collide(cCritter pother)
 {
     if (pother.IsKindOf("cCritter3DPlayer"))
     {
         return(true);
     }
     else if (pother.IsKindOf("cCritter3DPlayerBullet"))
     {
         return(true);
     }
     return(false);
 }
Example #3
0
 public override void copy(cCritter pcritter)
 {
     base.copy(pcritter);
     if (!pcritter.IsKindOf("cCritter3DBoss"))
     {
         return;
     }
     cCritter3DBoss pcritterplayer = (cCritter3DBoss)(pcritter);
 }
Example #4
0
     public override int collidesWith(cCritter pcritterother)
     {
         /* Make sure I don't ever waste time colliding walls with
 walls. I only call this the one time that I enroll the cCritterWall
  into the cGame's _pcollider. */
         if (pcritterother.IsKindOf("cCritterWall"))
             return cCollider.DONTCOLLIDE;
         return base.collidesWith(pcritterother);
     }
Example #5
0
 public override bool collide(cCritter pother)
 {
     if (pother.IsKindOf("cCritter3DPlayer"))
     {
         //move away from player
         addForce(new cForceClassEvade(0.3f, 0.3f));
         return(true);
     }
     return(false);
 }
 public override bool collide(cCritter pcritter)
 {
     if (pcritter.IsKindOf("cCritterViewer"))
     {
         return(false);
     }
     else
     {
         return(base.collide(pcritter));
     }
 }
Example #7
0
        //Checks if pcritter inside.

        public override int collidesWith(cCritter pothercritter)
        {
            if (pothercritter.IsKindOf("cCritter3DPlayer"))
            {
                return(cCollider.COLLIDEASCALLER);
            }
            else
            {
                return(cCollider.DONTCOLLIDE);
            }
        }
Example #8
0
        public override bool collide(cCritter pcritter)
        {
            bool collided = base.collide(pcritter);

            if (collided && pcritter.IsKindOf("cCritter3DPlayer"))
            {
                (( cGame3D )Game).setdoorcollision( );
                return(true);
            }
            return(false);
        }
Example #9
0
        public override bool collide(cCritter pcritter)
        {
            bool collided   = base.collide(pcritter);
            bool killedBoss = ((cGame3D)Game).IsBossDead(); //Can only enter the door if the boss is killed

            if (collided && pcritter.IsKindOf("cCritter3DPlayer") && killedBoss)
            {
                (( cGame3D )Game).setdoorcollision( );
                return(true);
            }
            return(false);
        }
Example #10
0
        /// <summary>
        /// If player has collided with a nonwall critter, and _sensitive has been set to true, this will
        /// damage the player by 1 point.
        /// </summary>
        /// <param name="pcritter"></param>
        /// <returns></returns>
        public override bool collide(cCritter pcritter)
        {
            if (_baseAccessControl == 1)
            {
                return(base.collide(pcritter));
            }
            bool collided = base.collide(pcritter);  // will call cCritter collide

            if (collided && _sensitive && !pcritter.IsKindOf("cCritterWall"))
            {
                damage(1);
            }
            return(collided);
        }
Example #11
0
 public override bool collide(cCritter pother)
 {
     if (base.collide(pother))
     {
         if (pother.IsKindOf("cCritter3DPlayer"))
         {
             Framework.snd.play(Sound.GlassBreaking);
             pother.addScore(12);
             pother.addVelocity(new cVector3(0, 0, -5));
         }
         return(true);
     }
     return(false);
 }
Example #12
0
 /// <summary>
 /// The purpose of this function is to ignore colliding with bullets from the same shooter.  If the shooter
 /// is dead (null), it will also ignore bullet collisions from other dead shooters.  Also, will not let a bullet from
 /// a shooter bump into the shooter.
 /// </summary>
 /// <param name="pcritter">The critter this bullet is bumping into.</param>
 /// <returns></returns>
 public override int collidesWith(cCritter pcritter)
 {
     if (pcritter.IsKindOf("cCritterBullet") &&
         ((cCritterBullet)pcritter).Shooter == _pshooter) // Can be NULL
     {
         return(cCollider.DONTCOLLIDE);
     }
     //Don't bump into your shooter.
     if (pcritter == _pshooter)
     {
         return(cCollider.DONTCOLLIDE);
     }
     return(base.collidesWith(pcritter));
 }
Example #13
0
        public override bool collide(cCritter pcritter)
        {
            if (pcritter.IsKindOf("KnockbackBullet"))
            {
                return(false);
            }

            bool collided = base.collide(pcritter);

            if (Player.Shield)
            {
                pcritter.damage(5);
            }
            return(collided);
        }
        public override bool collide(cCritter pcritter)
        {
            bool collided = base.collide(pcritter);

            if (collided && pcritter.IsKindOf("cCritter3DPlayer"))
            {
                count++;
                cCritter3DPlayer player = (cCritter3DPlayer)pcritter;
                if (count >= DELAY)
                {
                    player.damage(DAMAGE);
                    count = 0;
                }
            }

            return(collided);
        }
Example #15
0
        public override void copy(cCritter pcritter)
        {
            /*We need to overload the cCritter copy because if I have cCritterArmedRobot which is
             * a cCritterArmed, and it gets split in two by a replicate call, then I want the new
             * copy to have all the same shooting behavior as the old one.  In general, I should
             * overload copy for each of my critter child classes, but for now this one is the
             * most important.  The overload does the regular copy, then looks if the thing
             * being copied is a cCritterArmed, and if it is then it copies the additional fields. */
            base.copy(pcritter);
            if (!pcritter.IsKindOf("cCritterArmedPlayer"))
            {
                return;                                                           //You're done if pcritter isn't a cCritterArmed*.
            }
            cCritterArmedPlayer pcritterplayer = (cCritterArmedPlayer)(pcritter); /* I know it is a
                                                                                   * cCritterArmed at this point, but I need to do a cast, so the compiler will let me
                                                                                   * call a bunch of cCritterArmed methods. */

            _sensitive = pcritterplayer._sensitive;
        }
Example #16
0
        public override bool collide(cCritter pcritter)
        {
            if (pcritter.IsKindOf("cCritterBoss"))
            {
                //_health--;
                //moveTo(new cVector3(pcritter.Position.X, pcritter.Position.Y, pcritter.Position.Z + 50));
                //Framework.snd.play(Sound.GlassBreaking);
                return(true);
            }
            else
            {
                bool playerhigherthancritter = Position.Y - Radius > pcritter.Position.Y;

                /* If you are "higher" than the pcritter, as in jumping on it, you get a point
                 * and the critter dies.  If you are lower than it, you lose health and the
                 * critter also dies. To be higher, let's say your low point has to higher
                 * than the critter's center. We compute playerhigherthancritter before the collide,
                 * as collide can change the positions. */
                _baseAccessControl = 1;
                bool collided = base.collide(pcritter);
                _baseAccessControl = 0;
                if (!collided)
                {
                    return(false);
                }

                /* If you're here, you collided.  We'll treat all the guys the same -- the collision
                 * with a Treasure is different, but we let the Treasure contol that collision. */
                if (playerhigherthancritter)
                {
                    Framework.snd.play(Sound.Dissolve2);
                    addScore(10);
                }
                else
                {
                    damage(1);
                    Framework.snd.play(Sound.Dissolve);
                }
                pcritter.die();
                return(true);
            }
        }
Example #17
0
        public override bool collide(cCritter pcritter)
        {
            bool playerhigherthancritter = Position.Y - Radius > pcritter.Position.Y;

            /* If you are "higher" than the pcritter, as in jumping on it, you get a point
             * and the critter dies.  If you are lower than it, you lose health and the
             * critter also dies. To be higher, let's say your low point has to higher
             * than the critter's center. We compute playerhigherthancritter before the collide,
             * as collide can change the positions. */
            _baseAccessControl = 1;
            bool collided = base.collide(pcritter);

            _baseAccessControl = 0;
            if (!collided)
            {
                return(false);
            }

            /* If you're here, you collided.  We'll treat all the guys the same -- the collision
             * with a Treasure is different, but we let the Treasure contol that collision. */
            if (playerhigherthancritter)
            {
                Framework.snd.play(Sound.Goopy);
                //addScore( 10 );
            }
            else
            {
                if (!Shield)
                {
                    damage(1);
                    Framework.snd.play(Sound.HammerOnce);
                }
            }
            if (pcritter.IsKindOf("KnockbackBullet"))
            {
                KnockbackBullet bullet = (KnockbackBullet)pcritter;
                pcritter.collide(this);
            }
            return(true);
        }
Example #18
0
 public override void copy(cCritter pcritter)
 {
     /*We need to overload the cCritter copy because if I have 
 cCritterWallRobot which is a cCritterWall, and it gets split in two 
 by a replicate call, then I want the new copy to have all the same 
 shooting behavior as the old one.  In general, I should
 overload copy for each of my critter child classes, but for now this 
 one is the most important.  The overload does the regular copy, then 
 looks if the thing being copied is a cCritterWall, and if it is then 
 it copies the additional fields. */
     base.copy(pcritter);
     if (!pcritter.IsKindOf("cCritterWall"))
         return; //You're done if pcritter isn't a cCritterWall*.
     cCritterWall pcritterwall = (cCritterWall)(pcritter);
     /* I know it is a cCritterWall at this point, but I need
 to do a cast, so the compiler will let me
 access cCritterWall methods and fields. */
     cRealBox3 r = new cRealBox3();
     r.copy(pcritterwall.Skeleton);
     Skeleton = r;
     _defaultfillcolor = pcritterwall._defaultfillcolor;
 }
Example #19
0
        public override bool collide(cCritter pcritter)
        {
            bool playerhigherthancritter = Position.Y - Radius > pcritter.Position.Y;

            /* If you are "higher" than the pcritter, as in jumping on it, you get a point
             * and the critter dies.  If you are lower than it, you lose health and the
             * critter also dies. To be higher, let's say your low point has to higher
             * than the critter's center. We compute playerhigherthancritter before the collide,
             * as collide can change the positions. */
            _baseAccessControl = 1;
            bool collided = base.collide(pcritter);

            _baseAccessControl = 0;
            if (!collided)
            {
                return(false);
            }

            /* If you're here, you collided.  We'll treat all the guys the same -- the collision
             * with a Treasure is different, but we let the Treasure contol that collision. */
            if (playerhigherthancritter)
            {
                Framework.snd.play(Sound.Goopy);
                addScore(10);
            }
            else if (pcritter.IsKindOf("cCritter3DBoss"))
            {
                damage(2);
            }
            else if (pcritter.IsKindOf("cCritterWank"))
            {
                if (gohanSpawned)
                {
                    return(false);
                }
                else
                {
                    //spawn little goku
                    cCritterGohan gohan = new cCritterGohan(owner);
                    gohan.moveTo(new cVector3(20.0f, 0.0f, -22.0f));
                    gohanSpawned = true;
                    MessageBox.Show("Your son, Gohan, has been born.");
                    return(true);
                }
            }
            else if (pcritter.IsKindOf("cCritterGohan"))
            {
                //play gohan sound
                return(true);
            }
            else if (pcritter.IsKindOf("cCritterDragonball"))
            {
                int rand = (int)Framework.randomOb.random(3);
                switch (rand)
                {
                case 0:
                    Framework.snd.play(Sound.Samurai);
                    break;

                case 1:
                    Framework.snd.play(Sound.Shout);
                    break;

                case 2:
                    Framework.snd.play(Sound.WorkHard);
                    break;
                }
                addScore(100);
                addHealth(5);
                numDragBallsCollected++;
                pcritter.die();
                return(true);
            }
            else
            {
                damage(1);
                Framework.snd.play(Sound.Crunch);
                pcritter.die();
            }
            return(true);
        }
Example #20
0
        /* Overload this so as not to change
            velocity as I normally want my walls to be stable and not drift after being dragged. */

        public override bool collide(cCritter pcritter)
        {
            cVector3 oldlocalpos, newlocalpos;
            float newdistance;
            int oldoutcode, newoutcode;
            bool crossedwall;

            oldlocalpos = globalToLocalPosition(pcritter.OldPosition);
            oldoutcode = _pskeleton.outcode(oldlocalpos);
            newlocalpos = globalToLocalPosition(pcritter.Position);
            newdistance = _pskeleton.distanceToOutcode(newlocalpos,
                out newoutcode); //Sets the newoutcode as well.
            crossedwall = crossed(oldoutcode, newoutcode);

            if (newdistance >= pcritter.Radius && !crossedwall) //No collision 
                return false; /*See if there's a collision at all. We
		say there's a collision if crossedwall or if the
		cCritterWall.distance is less than radius.  Remember that
		cCritterWall.distance measures the distance to the OUTSIDE 
		PERIMETER of the box, not the distance to the box's center. */

            /* I collided, so I need to move back further into the last good
            zone I was in outside the wall.  I want to set newlocalpos so 
            the rim of its critter is touching the wall. The idea is to back
            up in the direction of oldlocalpos.  To allow the possibility
            of skidding along the wall, we plan to back up from the
            the face (or edge or corner) facing oldlocalpos.  This works
            only if oldlocalpos was a good one, not inside the box.  In 
            principle this should always be true, but some rare weird circumstance
            (like a triple collsion) might mess this up, so we check for the
            bad case before starting. */

            if (oldoutcode == cRealBox3.BOX_INSIDE) //Note that this almost never happens.
            {
                cVector3 insidepos = new cVector3();
                insidepos.copy(oldlocalpos);
                oldlocalpos.subassign(pcritter.Tangent.mult(_pskeleton.MaxSize));
                //Do a brutally large backup to get out of the box for sure.
                oldoutcode = _pskeleton.outcode(oldlocalpos);
                //Recalculate outcode at this new position.
                oldlocalpos = _pskeleton.closestSurfacePoint(oldlocalpos, oldoutcode,
                    insidepos, cRealBox3.BOX_INSIDE, false);
                //Go to the closest surface point from there.
                oldoutcode = _pskeleton.outcode(oldlocalpos);
                //Recalculate outcode one more time to be safe.
                crossedwall = crossed(oldoutcode, newoutcode);
                //Recalculate crossedwall 
            }
            /* I find that with this code, the mouse can drag things through walls,
        so I do a kludge to block it by setting crossedwall to TRUE, this
        affects the action of cRealBox.closestSurfacePoint, as modified
        in build 34_4. */
            if (pcritter.Listener.IsKindOf("cListenerCursor"))
                crossedwall = true; //Don't trust the mouse listener.
            newlocalpos = _pskeleton.closestSurfacePoint(oldlocalpos, oldoutcode,
                newlocalpos, newoutcode, crossedwall);
            /* This call to closestSurfacePoint will move the newlocal pos
        from the far new side (or inside, or overlapping) of the box back to 
        the surface, usually on the old near side, edge, or corner given by
        oldoutcode. This prevents going through the	wall.
            If oldoutcode is a corner position and you are in fact heading
        towards a face near the corner, we used to bounce off the corner
        even though visually you can see you should bounce off the
        face.  This had the effect of making a scooter player get hung up on
        a corner sometimes. As of build 34_3, I'm moving the 
        newlocalpos to the newoutocode side in the case where oldlocalpos
        is an edge or a corner, and where crossedwall isn't TRUE.  I
        have to force in a TRUE for the cCursorLIstener case.  The USEJIGGLE
        code below also helps keep non-player critters from getting stuck
        on corners. */
            //Now back away from the box.
            newoutcode = _pskeleton.outcode(newlocalpos);
            cVector3 avoidbox = _pskeleton.escapeVector(newlocalpos, newoutcode);
            newlocalpos.addassign(avoidbox.mult(pcritter.Radius));
            newoutcode = _pskeleton.outcode(newlocalpos);
            pcritter.moveTo(localToGlobalPosition(newlocalpos), true);
            //TRUE means continuous motion, means adjust tangent etc.
            //Done with position, now change the velocity 
            cVector3 localvelocity = globalToLocalDirection(pcritter.Velocity);
            cVector3 oldlocalvelocity = new cVector3();
            oldlocalvelocity.copy(localvelocity);
            _pskeleton.reflect(localvelocity, newoutcode);
            /* I rewrote the reflect code on Feb 22, 2004 for VErsion 34_3, changing
        it so that when you reflect off an edge or corner, you only bounce
        the smallest of your three velocity components. Balls stll seem to
        get hung up on the corner once is awhile. */
            /* Now decide, depending on the pcritter's absorberflag and bounciness,
        how much you want to use the new localvelocity vs. the 
        oldlocalvelocity. We decompose the new localvelocity into the
        tangentvelocity parallel to the wall and the normalvelocity
        away from the wall. Some pencil and paper drawings convince
        me that the tangent is half the sum of the oldlocalvelocity
        and the reflected new localvelocity. */
            cVector3 tangentvelocity = localvelocity.add(oldlocalvelocity).mult(0.5f);
            cVector3 normalvelocity = localvelocity.sub(tangentvelocity);
            float bouncefactor = 1.0f;
            if (pcritter.AbsorberFlag)
                bouncefactor = 0.0f;
            else
                bouncefactor = pcritter.Bounciness;
            localvelocity = tangentvelocity.add(normalvelocity.mult(bouncefactor));
            /* Maybe the rotation should depend on the kind of edge or corner.
            Right now let's just use critter's binormal. Don't to it 
            to the player or viewer as it's confusing.  */
            if (!(cRealBox3.isFaceOutcode(newoutcode)) && //edge or corner 
                !(pcritter.IsKindOf("cCritterViewer")) && //not viewer 
                !(pcritter.IsKindOf("cCritterArmedPlayer")))
            //Not player.  Note that cPlayer inherits from cCritterArmedPlayer, 
            //so don't use cCritterPlayer as the base class here.
            {
                localvelocity.rotate(new cSpin(
                    Framework.randomOb.randomReal(
                        -cCritterWall.CORNERJIGGLETURN,
                        cCritterWall.CORNERJIGGLETURN), //A random turn 
                        pcritter.Binormal)); //Around the critter's binormal 
                localvelocity.multassign(cCritterWall.CORNERJIGGLEKICK); //Goose it a little 
            }
            pcritter.Velocity = localToGlobalDirection(localvelocity);
            return true;
        }
Example #21
0
        /* Uses _foveaproportion which lies between 0.0 and 1.0. We say something is visible if it
         *  appears on the inner _foveaproportion central box of the viewer's image screen,
         *  which is what you see in the view window. */
        //overloads

        //Use _pownerview to get the CpopDoc and get the cGame from that.

        public override void update(ACView pactiveview, float dt)
        {
            base.update(pactiveview, dt);
            ZClipPlanes = Game.Border.outerBox(cSprite.MAXPRISMDZ);
            if (_trackplayer &&
                !((Listener != null) && Listener.RuntimeClass == "cListenerViewerRide"))

            /* The meaning of the visibleplayer() condition is that it doesn't make sense
             * to track the player if it's not an onscreen player. The reason for the
             * listener condition is that you don't want to stare at the player when
             * riding it. */
            /*  I should  explain that the goal here is to not bother turning when the player
             * is  moving around in the middle of the veiw area, and only to turn when he's near
             * the edge, but to have the turning when he's near the edge be smoooth.
             * The use of the 0.85 foveaproportion parameter means that you react before the player
             * gets right up to the edge.  The reactproportion factor in lookAtProportional and
             * moveToProportional is delicate and should probably be adjusted according to the
             * current player speed relative to the visible window.  The issue is that (a) if I make
             * reactproportion too small, like 0.01, then the viewer doesn't turn (or move) fast
             * enough to catch up with the player and keep it in view, but (b) if I make reactpropotion
             * too big, like 0.5, then the turning or moving is such an abrupt jump that the visual
             * effect is jerky.  The goal is to do turns that are just big enough to not look jerky,
             * but to have the turns be big enough so you aren't turning more often than you really
             * have to.  Another downside of a toosmall reactproportion, by the way, is that it can be
             * computationally expensive to react.
             * The way we finally solved this is to do a while loop to turn just
             * far enough, moving just a little at a time so as to not overshoot. */
            {
                if (isVisible(Game.Player.Position)) // Uses _foveaproportion
                {
                    _lastgoodplayeroffset = Position.sub(Game.Player.Position);
                }

                /*I'm not sure about constantly changing _lastgoodplayeroffset.  On the
                 * one hand, the offset I set in setViewpoint was a standard good one, so why
                 * not keep it.  On the other, if I want to move my viewpoint around then I
                 * do want to be able to get a new value here. It seems ok for now.*/
                else //not visible, so do somehting about it.
                {
                    int loopcount      = 0; /* Never have a while loop without a loopcount
                                             * to make sure you don't spin inside the while forever under some
                                             * unexpected situation like at startup. */
                    cVector3 lookat    = Game.Player.Position;
                    cVector3 viewerpos = lookat.add(_lastgoodplayeroffset);
                    if (Game.worldShape() == cGame.SHAPE_XSCROLLER)
                    {
                        lookat = new cVector3(Game.Player.Position.X,
                                              Game.Border.Midy, Game.Player.Position.Z);
                        viewerpos = new cVector3(lookat.X, Position.Y, Position.Z);
                    }
                    if (Game.worldShape() == cGame.SHAPE_YSCROLLER)
                    {
                        lookat = new cVector3(Game.Border.Midx,
                                              Game.Player.Position.Y, Game.Player.Position.Z);
                        viewerpos = new cVector3(Position.X, lookat.Y, Position.Z);
                    }
                    if (_perspective)
                    {
                        while (!isVisible(lookat) && loopcount < 100) // Uses _foveaproportion
                        {
                            moveToProportional(viewerpos, cCritterViewer.TURNPROPORTION);
                            loopcount++;
                        }
                    }
                    else //ortho case
                    {
                        while (!isVisible(lookat) && loopcount < 100) // Uses _foveaproportion
                        {
                            moveToProportional(lookat.add(Game.Player.Binormal.mult(10.0f)),
                                               cCritterViewer.TURNPROPORTION);
                            loopcount++;
                        }
                    }
                }
            }
            //Possibly ride the player.
            if (Listener.IsKindOf("cListenerViewerRide"))
            {
                cCritter pplayer = Game.Player;
                cVector3 offset  = ((cListenerViewerRide)Listener).Offset;
                moveTo(pplayer.Position.add(
                           pplayer.AttitudeTangent.mult(offset.X).add(
                               pplayer.AttitudeNormal.mult(offset.Y).add(
                                   pplayer.AttitudeBinormal.mult(offset.Z)))));
                cRealBox3 skeleton = pplayer.MoveBox;
                if (skeleton.ZSize < 0.5f)
                {
                    skeleton.setZRange(0.0f, offset.Z);
                }
                if (skeleton.YSize < 0.5f)
                {
                    skeleton.setYRange(0.0f, offset.Z);
                }
                skeleton.clamp(_position);
                for (int i = 0; i < Game.Biota.count(); i++)
                {
                    cCritter pother = Game.Biota.GetAt(i);
                    if (pother.IsKindOf("cCritterWall"))
                    {
                        pother.collide(this);
                    }
                }

                /* colliding with the wall may have twisted the viwer's orientation,
                 * so align it once again. */
                Attitude = pplayer.Attitude; /* Before we call lookAt,
                                              * make sure your attitude matches the player.  For one thing,
                                              * you may have gotten twisted around in the COLLIDEVIEWER code. */
                lookAt(pplayer.Position.add(
                           pplayer.AttitudeTangent.mult(cListenerViewerRide.PLAYERLOOKAHEAD * pplayer.Radius))
                       );

                /* This has the effect that as offset gets large you change your
                 * looking direction see right in front of the player. The multiplier
                 * cCritterViewer.PLAYERLOOKAHEAD is tweaked to work well
                 * with the default cCritterViewer.OFFSET. */
            }
        }
        public override void listen(float dt, cCritter pcritter)
        {
            pcritter.Acceleration = new cVector3(0.0f, pcritter.Acceleration.Y, 0.0f);

            bool left     = Framework.Keydev[vk.A];
            bool right    = Framework.Keydev[vk.D];
            bool up       = Framework.Keydev[vk.W];
            bool down     = Framework.Keydev[vk.S];
            bool space    = Framework.Keydev[vk.Space];
            bool pagedown = Framework.Keydev[vk.PageDown];
            bool lControl = Framework.Keydev[vk.ControlLeft];

            cCritter3DPlayer playerCritter = (cCritter3DPlayer)pcritter;

            if (!left && !right && !down && !up && !pagedown && !space && !lControl && !playerCritter.CountingFrames)
            {
                pcritter.Velocity          = new cVector3(0.0f, pcritter.Velocity.Y, 0.0f);
                pcritter.Acceleration      = new cVector3(0.0f, pcritter.Acceleration.Y, 0.0f);
                pcritter.Sprite.ModelState = State.Idle;
                return;
            }

            if ((up || down || right || left) && !_hopping && !playerCritter.CountingFrames)
            {
                pcritter.Sprite.ModelState = State.Run;
            }


            if (up)
            {
                pcritter.Velocity = new cVector3(-pcritter.MaxSpeed / 4, pcritter.Velocity.Y, pcritter.Velocity.Z);
            }

            else if (down)
            {
                pcritter.Velocity = new cVector3(pcritter.MaxSpeed / 4, pcritter.Velocity.Y, pcritter.Velocity.Z);
            }
            else
            {
                pcritter.Velocity = new cVector3(0, pcritter.Velocity.Y, pcritter.Velocity.Z);
            }
            if (space && !_hopping)
            {
                pcritter.Acceleration      = new cVector3(0.0f, _hopStrength, 0.0f);
                pcritter.Sprite.ModelState = State.Jump;
                Framework.snd.play(Sound.Blink);
                _hopping = true;
            }

            //   if (pagedown)
            //     pcritter.Velocity = new cVector3(0.0f, pcritter.MaxSpeed, 0.0f);
            if (right)
            {
                pcritter.Velocity = new cVector3(pcritter.Velocity.X, pcritter.Velocity.Y, -pcritter.MaxSpeed / 4);
            }
            else if (left)
            {
                pcritter.Velocity = new cVector3(pcritter.Velocity.X, pcritter.Velocity.Y, pcritter.MaxSpeed / 4);
            }
            else
            {
                pcritter.Velocity = new cVector3(pcritter.Velocity.X, pcritter.Velocity.Y, 0);
            }

            //Now match the attitude.
            if (pcritter.AttitudeToMotionLock)
            {
                /* Need this condition if you want
                 * to have a "spaceinvaders" type shooter that always points up as in
                 * the textbook problem 3.11 */
                pcritter.copyMotionMatrixToAttitudeMatrix();
            }
            //Note that if pcritter is cCritterArmed*, then the cCritterArmed.listen does more stuff.

            if (pcritter.Position.Y <= pcritter.Game.Border.Loy + 2)
            {
                _hopping = false;
            }

            if (lControl)
            {
                if (pcritter.IsKindOf("cCritter3DPlayer"))
                {
                    _meleeAttacking = true;
                    cCritter3DPlayer player = (cCritter3DPlayer)pcritter;
                    player.MeleeAttack();
                    _meleeAttacking = false;
                }
            }
        }