//Used by the two constructors. protected void _fixConvex() { // I rewrote this to make it efficient for a linked list // First, test a bunch using a foreach -- JC bool first = true; bool second = true; cVector3 v1 = new cVector3(); cVector3 v2 = new cVector3(); float test; foreach (cVector3 v3 in _vectorvert) { if (!first && !second) { test = ((v2 - v1).mult((v3 - v1))).Z; /* Take the cross product and look at the z component. * If it is positive, the cross product points up, so this is * counterclockwise rotation and you aren't convex. */ if (test < 0) { _convex = false; break; } v1.copy(v2); v2.copy(v3); } else if (first) { v1.copy(v3); first = false; } else // second { v2.copy(v3); second = false; } } // finally, do two special tests -- JC cVector3 last = _vectorvert[0]; test = ((v2 - v1).mult((last - v1))).Z; if (test < 0) { _convex = false; return; } v1.copy(v2); v2.copy(last); last = _vectorvert[1]; test = ((v2 - v1).mult((last - v1))).Z; if (test < 0) { _convex = false; } }
protected float _realdotradiusweight; //Ratio of vertex marker dot size to _Shaperadius. /* DON'T put in a Real _radius or Real _angle! C++ will let you do * this even though these fields exist in cSprite, but what a mistake. If you * put a second _radius in here, then the cShape methods change the * cShape _radius, but the cSprite::radius() accessor returns the cSprite * _radius, which will still be 0.0 */ //Private helper functions protected void _initializer() //used by the constructors { //The two CArrays are set to size 0 by their default constructors //Nine decoration fields _dotted = false; _pdotcolorstyle = new cColorStyle(); _pdotcolorstyle.FillColor = Color.Yellow; _realdotradiusweight = 0.05f; // helper fields _convex = true; _vectorvert = new LinkedList <cVector3>( delegate(out cVector3 v1, cVector3 v2) { v1 = new cVector3(); v1.copy(v2); } ); _transformedvert = new LinkedList <cVector3>( delegate(out cVector3 v1, cVector3 v2) { v1 = new cVector3(); v1.copy(v2); } ); }
public cForceVortex(float friction, float spiralangle, cVector3 eyeposition) : base(friction) { _eyeposition = new cVector3(); _spiralangle = spiralangle; _eyeposition.copy(eyeposition); }
public override int clamp(cRealBox3 border) { /* We don't change _pskeleton as it has the geometric info. We * just change _position. */ if (_baseAccessControl == 1) { return(base.clamp(border)); } cRealBox3 effectivebox = border; cVector3 oldcorner; cVector3 newcorner = new cVector3(); int outcode = 0; int totaloutcode = 0; for (int i = 0; i < 8; i++) //Step through the wall's corners { oldcorner = _pskeleton.corner(i) + _position; newcorner.copy(oldcorner); outcode = effectivebox.clamp(newcorner); if (outcode != cRealBox3.BOX_INSIDE) //corner was moved { _position += newcorner - oldcorner; /* As long at the wall is small enough to * fit inside the border, the successive * corrections won't cancel each other out. */ totaloutcode |= outcode; } } _wrapposition1.copy(_position); _wrapposition2.copy(_position); _wrapposition3.copy(_position); /* So it won't think it wrapped. */ return(outcode); }
public override void copy(cForce pforce) { base.copy(pforce); if (!(pforce is cForceVortex)) { return; } cForceVortex pforcechild = ( cForceVortex )(pforce); // Cast so next lines work. _eyeposition.copy(pforcechild._eyeposition); _spiralangle = pforcechild._spiralangle; }
public override void copy(cForce pforce) { base.copy(pforce); if (!pforce.IsKindOf("KnockbackForce")) { return; } KnockbackForce pforcechild = (KnockbackForce)pforce; //copy fields here forceVector.copy(pforcechild.forceVector); count = pforcechild.count; }
public override cVector3 force(cCritter pcritter) { if (_pnode == null) { return(new cVector3(0.0f, 0.0f, 0.0f)); } cVector3 pursueforcevector = (pcritter.directionTo(_pnode) * pcritter.MaxSpeed) - pcritter.Velocity; pursueforcevector.Magnitude = _intensity; pursueforcevector *= pcritter.Mass; cVector3 p = new cVector3(); p.copy(pursueforcevector); return(p); }
public override cVector3 force(cCritter pcritter) { if (_pnode == null) { return(new cVector3(0.0f, 0.0f, 0.0f)); } cVector3 pursueforcevector = (pcritter.directionTo(_pnode).mult(pcritter.MaxSpeed)).sub(pcritter.Velocity); pursueforcevector.Magnitude = _intensity + 2; //increase the intensity, stronger the 'seek' force pursueforcevector.multassign(pcritter.Mass); cVector3 p = new cVector3(); p.copy(pursueforcevector); return(p); }
public override cVector3 force(cCritter pcritter) { count++; //if the count length hasn't yet been reached, just return the upward force if (count != COUNT_LENGTH) { cVector3 frc = new cVector3(); frc.copy(forceVector); return(frc); } //once the count length is reached, remove the upward force by setting forceVector to the zero vector. //TODO: remove the force from the list altogether. else { forceVector = new cVector3(0, 0, 0); cVector3 v = new cVector3(); v.copy(forceVector); return(v); } }
public void setViewpoint(cVector3 toViewer, cVector3 lookatPoint, bool trytoseewholeworld = true) { //First do some default setup stuff cVector3 toviewer = new cVector3(); toviewer.copy(toViewer); cVector3 lookatpoint = new cVector3(); lookatpoint.copy(lookatPoint); _fieldofviewangle = cCritterViewer.STARTFIELDOFVIEWANGLE; Speed = 0.0f; _attitude = new cMatrix3(new cVector3(0.0f, 0.0f, -1.0f), new cVector3(-1.0f, 0.0f, 0.0f), new cVector3(0.0f, 1.0f, 0.0f), new cVector3(0.0f, 0.0f, 0.0f)); /* To get a reasonable default orientation, we arrange the viewer axes so that: * viewer x axis = world -z axis, viewer y axis = world -x axis, viewer z axis = world y axis. * We pick this orientation so that if the viewer moves "forward" (along its tangent vector) * it moves towards the world. (We correct the mismatch between the coordinate systems in the * cCritterViewer.loadViewMatrix method, which has a long comment about this.) * Note that we will adjust _position (fourth column) later in this call * with a moveTo, also we may rotate the _attitude a bit. */ if (!_perspective) //Ortho view, simply move up. { _proportionofworldtoshow = 1.0f; //Show all of a flat world. moveTo(lookatpoint + (new cVector3(0.0f, 0.0f, 1.0f)) * cCritterViewer.ORTHOZOFFSET); // Get above the world _maxspeed = _maxspeedstandard = 0.5f * cCritterViewer.ORTHOZOFFSET; //Mimic perspective case. } else //_perspective { if (toviewer.IsPracticallyZero) //Not usable, so pick a real direction. { toviewer.copy(new cVector3(0.0f, 0.0f, 1.0f)); //Default is straight up. } if (trytoseewholeworld) /* Treat toviewer as a direction, and back off in that direction * enough to see the whole world */ { toviewer.normalize(); //Make it a unit vector. _proportionofworldtoshow = cCritterViewer.PROPORTIONOFWORLDTOSHOW; //Trying to show all of a world when flying around it, often leaves too big a space around it. float furthestcornerdistance = Game.Border.maxDistanceToCorner(lookatpoint); float tanangle = (float)Math.Tan(_fieldofviewangle / 2.0f); /* We work with half the fov in this calculation, * the tanangle will be the ratio of visible distance to distance above the world, * that is, tanangle = dr/dz, where * Our dr is _proportionofworldtoshow * furthestcornerdistance, and * our dz is the unknown seeallz height we need to back off to. * Swap tangangle and dz to get the next formula. */ float seeallz = _proportionofworldtoshow * furthestcornerdistance / tanangle; moveTo(lookatpoint + toviewer * seeallz); } else /*Not trytoseewholeworld. In this case we don't normalize toviewer, instead * we treat it as a displacment from the lookatpoint. */ { moveTo(lookatpoint + toviewer); } lookAt(lookatpoint); _maxspeed = _maxspeedstandard = 0.5f * (Position - lookatpoint).Magnitude; /* Define the speed like this so it typically takes two seconds (1/0.5) * to fly in to lookatpoint. */ _lastgoodplayeroffset = Position - Game.Player.Position; } }
/* Overload this so as not to change * velocity as I normally want my walls to be stable and not drift after being dragged. */ /// <summary> /// There's a collision if pcritter has crossed the wall or if the radius of pcritter is more than /// the pcritter's distance to the wall. Has code to prevent the pcritter from going through the wall. /// Returns true if a collision was detected and false otherwise. /// </summary> /// <param name="pcritter">The critter to test for a collision with the wall.</param> /// <returns></returns> 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 -= pcritter.Tangent * _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 is 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 += avoidbox * 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 + oldlocalvelocity) * 0.5f; cVector3 normalvelocity = localvelocity - tangentvelocity; float bouncefactor = 1.0f; if (pcritter.AbsorberFlag) { bouncefactor = 0.0f; } else { bouncefactor = pcritter.Bounciness; } localvelocity = tangentvelocity + normalvelocity * 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 is cCritterViewer) && //not viewer !(pcritter is 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 *= cCritterWall.CORNERJIGGLEKICK; //Goose it a little } pcritter.Velocity = localToGlobalDirection(localvelocity); return(true); }
public cForceDrag(float friction, cVector3 windvector) { _windvector = new cVector3(); _windvector.copy(windvector); _intensity = friction; }
public cForceGravity(float gravity, cVector3 pulldirection) { _pulldirection = new cVector3(); _pulldirection.copy(pulldirection); _intensity = gravity; }
public void copy(cDistanceAndDirection dd) { _distance = dd._distance; _direction.copy(dd._direction); }
public cDistanceAndDirection(float dist, cVector3 dir) { _distance = dist; _direction = new cVector3(); _direction.copy(dir); }
public void setRoom2() { Biota.purgeCritters("cCritterWall"); Biota.purgeCritters("cCritter3Dcharacter"); Biota.purgeCritters("cCritterBoss"); setBorder(50.0f, 40.0f, 50.0f); cRealBox3 skeleton = new cRealBox3(); skeleton.copy(_border); setSkyBox(skeleton); SkyBox.setAllSidesTexture(BitmapRes.Graphics1, 2); SkyBox.setSideTexture(cRealBox3.LOY, BitmapRes.Concrete); SkyBox.setSideSolidColor(cRealBox3.HIY, Color.Blue); _seedcount = 0; Player.setMoveBox(new cRealBox3(50.0f, 40.0f, 50.0f)); wentThrough = true; startNewRoom = Age; //add door cCritterDoor pdwall = new cCritterDoor(new cVector3(_border.Midx, _border.Loy + 4, _border.Loz), new cVector3(_border.Midx, _border.Loy + 10, _border.Loz), 2.0f, 3.0f, this); cSpriteTextureBox pspritedoor = new cSpriteTextureBox(pdwall.Skeleton, BitmapRes.Door); pdwall.Sprite = pspritedoor; float wallThickness = 5.0f, wallHeight = 10.0f; //starting block cVector3 enda = new cVector3(Border.Midx, Border.Loy + 1, Border.Hiz); cVector3 endb = new cVector3(Border.Midx, Border.Loy + 1, Border.Hiz - 5); cCritterWall startingBlock = new cCritterWall(enda, endb, wallThickness, wallHeight, this); cSpriteTextureBox pspritebox = new cSpriteTextureBox(startingBlock.Skeleton, BitmapRes.Wood2, 16); //Sets all sides startingBlock.Sprite = pspritebox; //ending block cVector3 enda2 = new cVector3(Border.Midx, Border.Loy + 1, Border.Loz + 7); cVector3 endb2 = new cVector3(Border.Midx, Border.Loy + 1, Border.Loz); cCritterWall endBlock = new cCritterWall(enda2, endb2, wallThickness, 8.0f, this); cSpriteTextureBox pspritebox2 = new cSpriteTextureBox(endBlock.Skeleton, BitmapRes.Wood2, 16); //Sets all sides endBlock.Sprite = pspritebox2; //floor cVector3 enda3 = new cVector3(Border.Midx, Border.Loy, Border.Loz); cVector3 endb3 = new cVector3(Border.Midx, Border.Loy, Border.Hiz); DamagingWall floor = new DamagingWall(enda3, endb3, 0.5f, 0.5f, this); //med pack _ptreasure = new cCritterMedpack(this, new cVector3(Border.Midx, Border.Loy + 7, Border.Hiz - 4)); //sliding walls (spawned based on pos of starting block) cVector3 leftEnd = new cVector3(); leftEnd.addassign(startingBlock.Position.add(new cVector3(0, 4.0f, -0.5f))); cVector3 rightEnd = new cVector3(); rightEnd.copy(leftEnd); rightEnd.addassign(new cVector3(0, 0, -5.0f)); float thickness = 0.1f, height = 0.3f; cVector3 moveAxisandDirection = new cVector3(0, 0, -0.005f); cVector3 startPos = new cVector3(); startPos.copy(rightEnd); cVector3 endPos = new cVector3(); endPos.copy(startPos); endPos.Z = Border.Loz + 9.5f; //spawn sliding walls in a separate thread new Thread(() => spawnWall(leftEnd, rightEnd, thickness, height, this, cCritterSlideWall.TYPE.PLATFORM, moveAxisandDirection, false, startPos, endPos)).Start(); seedCritters(); Player.moveTo(startingBlock.Position.add(new cVector3(0, 10.0f, 0))); new cCritterBossDrFreak(this, endBlock.Position.add(new cVector3(0, 10.0f, 0)), new KnockbackBullet(), 5); }