private void button1_Click(object sender, EventArgs e) { PictureBox usebox = Pictestellipse; cBall ballhit = new cBall(new PointF(100, 100), new PointF(2, 7)); EllipseBlock eb = new EllipseBlock(new RectangleF(90, 105, 32, 16)); var Ballpoly = ballhit.GetBallPoly(); var EllipsePoly = eb.GetPoly(); /* Polygon ballpoly = ballhit.GetBallPoly(); Vector Adjustment = new Vector(); GeometryHelper.PolygonCollisionResult pcr = GeometryHelper.PolygonCollision(EllipsePoly, ballpoly, new Vector(ballhit.Velocity.X,ballhit.Velocity.Y)); //minimumtranslationvector will be the normal we want to mirror the ball speed through. ballhit.Velocity = ballhit.Velocity.Mirror(pcr.MinimumTranslationVector); ballhit.Velocity = new PointF(-ballhit.Velocity.X, -ballhit.Velocity.Y); ballhit.Location = new PointF(ballhit.Location.X + Adjustment.X, ballhit.Location.Y + Adjustment.Y); * */ GeometryHelper.PolygonCollisionResult pcr = GeometryHelper.PolygonCollision(EllipsePoly, Ballpoly, new Vector(ballhit.Velocity.X, ballhit.Velocity.Y)); PointF reflectedVelocity = ballhit.Velocity; //only if an intersection occurs or will occur. if (pcr.Intersect || pcr.WillIntersect) { //minimumtranslationvector should work to be used as the normal to reflect across. } //calculate Normal of ellipse at that position. var addevent = new PaintEventHandler((g, pea) => { ballhit.Draw(pea.Graphics); eb.Draw(pea.Graphics); }); usebox.Paint += addevent; //force update. usebox.Invalidate(); usebox.Update(); }
public override bool HitBlock(BCBlockGameState currentstate,cBall ballobject, Block blockhit) { return !(blockhit.MustDestroy()); }
/// <summary> /// /// </summary> /// <param name="Origin">cBall object to be used as the origin location for rotary calculations.</param> /// <param name="Derived"></param> public SpinShotsubBallInfo(cBall pOrigin, cBall pDerived, double pAngle, double pAngleSpeed, double pRadius) { OriginBall = pOrigin; BallObject = pDerived; Angle = pAngle; AngleSpeed = pAngleSpeed; Radius = pRadius; //hook our ball's BallImpact Event... BallObject.BallImpact += new cBall.ballimpactproc(BallObject_BallImpact); //the "owner" class should be hooking it as well so that we (as a SpinShotsubballinfo) are removed from any relevant future calculations, //allowing the ball to "fly off". }
public void SparkleEmitter(cBall ballobj, BCBlockGameState gamestate) { PointF VelocityUse = new PointF((float)(ballobj.Velocity.X * 0.1 + (BCBlockGameState.rgen.NextDouble() - 0.5) * 2), (float)(ballobj.Velocity.Y * 0.1 + (BCBlockGameState.rgen.NextDouble() - 0.5) * 2)); Color usesparklecolor = BCBlockGameState.Choose(new Color[] { Color.Red, Color.Yellow, Color.LimeGreen, Color.Pink, Color.Magenta, Color.Chartreuse }); if (BCBlockGameState.rgen.NextDouble() > 0.8) return; //don't add a particle. if (BCBlockGameState.rgen.NextDouble() > 0.5) { VelocityUse = new PointF(0, 0); } gamestate.Particles.Add(new Sparkle(ballobj.Location, VelocityUse, usesparklecolor)); }
public List<Block> proxyperformframe(cBall ballobject, BCBlockGameState ParentGameState, ref List<cBall> ballsadded, ref List<cBall> ballsremove, out bool removethis) { removethis = false; if (proxylife.ContainsKey(ballobject)) { proxylife[ballobject]++; } else { proxylife.Add(ballobject, 0); } if (proxylife[ballobject] > 0) { Debug.Print("force removing a ball"); removethis = true; } return null; }
public BallBehave(cBall ballBehavioursEdit) { _ballEdit = ballBehavioursEdit; InitializeComponent(); }
public PolygonObstacleBaseEventArgs(BCBlockGameState pgstate, cBall pBall, PolygonObstacle pObstacle) { _gameState = pgstate; _Ball = pBall; _Obstacle = pObstacle; }
public abstract List<Block> FrameTick(cBall ballobject, BCBlockGameState ParentGameState, ref List<cBall> ballsadded, ref List<cBall> ballsremove, out bool removethis);
public override sealed List<Block> PerformFrame(cBall ballobject, BCBlockGameState ParentGameState, ref List<cBall> ballsadded, ref List<cBall> ballsremove, out bool removethis) { List<Block> result = FrameTick(ballobject, ParentGameState, ref ballsadded, ref ballsremove, out removethis); removethis = Destroyself || removethis; return result; }
public virtual void BehaviourRemoved(cBall onBall, BCBlockGameState currstate) { }
public override void BehaviourAdded(cBall onBall, BCBlockGameState currstate) { base.BehaviourAdded(onBall, currstate); //start timer... currstate.DelayInvoke(_TimeLength, DelayRoutine, null); }
public override List<Block> PerformFrame(cBall ballobject, BCBlockGameState ParentGameState, ref List<cBall> ballsadded, ref List<cBall> ballsremove, out bool removethis) { //if (ballobject.Behaviours.Count <= 2) //{ //only if we are the only behaviour... for (int i = 0; i < (int) (7*BCBlockGameState.ParticleGenerationFactor); i++) { ParentGameState.Particles.Add(new FireParticle(ballobject)); } //} return base.PerformFrame(ballobject, ParentGameState, ref ballsadded, ref ballsremove,out removethis); }
public override HitWallReturnConstants HitWall(BCBlockGameState currentstate, cBall ballobject) { _NumBounces--; if(_NumBounces <= 0) return HitWallReturnConstants.HitBall_Destroy; //is destroyed regardless. return HitWallReturnConstants.HitBall_Default; }
public override bool HitBlock(BCBlockGameState currentstate, cBall ballobject, Block blockhit) { //currentstate.Balls.Remove(ballobject); return true; }
public void invokeballimpact(cBall withball) { bool doignore = false; ballimpactproc tempcopy = BallImpact; if (tempcopy != null) tempcopy.Invoke(withball); }
public override void BehaviourAdded(cBall onBall, BCBlockGameState currstate) { base.BehaviourAdded(onBall, currstate); BaseBehaviour AddedBehaviour = (BaseBehaviour)Activator.CreateInstance(useBehaviour); currstate.NextFrameCalls.Enqueue(new BCBlockGameState.NextFrameStartup(() => onBall.Behaviours.Add(AddedBehaviour))); currstate.DelayInvoke(_Span,delayroutine,new object[]{onBall,AddedBehaviour}); }
public void invokebeforeblockimpact(cBall withball) { ballimpactproc tempcopy = BeforeBallImpact; if (tempcopy != null) tempcopy.Invoke(withball); }
public virtual bool HitBlock(BCBlockGameState currentstate, cBall ballobject, Block blockhit) { //throw new NotImplementedException(); return true; }
protected bool InvokeObstacleHit(BCBlockGameState gstate,cBall Source,PolygonObstacle obstacle) { var copied = ObstacleHit; if (copied != null) { var created = new PolygonObstacleHitEventArgs(gstate, Source, obstacle); copied(this, created); return created.Cancel; } return false; }
public override List<Block> PerformFrame(cBall ballobject, BCBlockGameState ParentGameState, ref List<cBall> ballsadded, ref List<cBall> ballsremove, out bool removethis) { //spew out 3 waterparticles at random velocities (<=2) const int WaterBallSpewCount = 1; for (int i = 1; i < WaterBallSpewCount; i++) { //calculate the random velocities. float xvel = ((float)BCBlockGameState.rgen.NextDouble() * 2) - 1f; float yvel = ((float)BCBlockGameState.rgen.NextDouble() * 2) - 1f; //add current ball speeds by a factor of .3. xvel+= (ballobject.Velocity.X/3); yvel+=(ballobject.Velocity.Y/3); PointF pointvelocity = new PointF(xvel,yvel); //create and add the new particle. // ParentGameState.Particles.Add(new WaterParticle(ballobject.Location, pointvelocity)); } return base.PerformFrame(ballobject, ParentGameState, ref ballsadded, ref ballsremove,out removethis); }
public PolygonObstacleHitEventArgs(BCBlockGameState pgstate, cBall pBall, PolygonObstacle pObstacle) : base(pgstate, pBall, pObstacle) { }
public virtual HitWallReturnConstants HitWall(BCBlockGameState currentstate, cBall ballobject) { // throw new NotImplementedException(); return HitWallReturnConstants.HitBall_Default; }
public override bool PerformFrame(BCBlockGameState gamestate) { bool retval = base.PerformFrame(gamestate); //add some particles around the edges of the explosion, moving outward... if (gamestate.Particles.Count((w)=>!w.Important) < BCBlockGameState.MaxParticles) { for (int i = 0; i < (int)(25f * BCBlockGameState.ParticleGenerationFactor); i++) { const float speedmult = 1; //choose a random Angle... double randomangle = Math.PI * 2 * BCBlockGameState.rgen.NextDouble(); //create the appropriate speed vector, based on our radius... double usespeed = (_CurrentRadius / _MaxRadius) * speedmult; //should be proportional to how close we are to the maximum radius; max radius will have particles move 1... usespeed += ((BCBlockGameState.rgen.NextDouble() * 0.6) - 0.3); PointF addpointLocation = new PointF(Location.X + (float)Math.Cos(randomangle) * _CurrentRadius, Location.Y + (float)Math.Sin(randomangle) * _CurrentRadius); //create a dustparticle... PointF PointSpeed = new PointF((float)(Math.Cos(randomangle) * usespeed), (float)(Math.Sin(randomangle) * usespeed)); Particle addparticle = null; if (i % 5 != 0) { addparticle = new DustParticle(addpointLocation, PointSpeed); } else if (_ShowOrbs) { //LightOrb... LightOrb lo = new LightOrb(addpointLocation, ExplosionColor, (float)BCBlockGameState.rgen.NextDouble() * 10 + 5); lo.Velocity = PointSpeed; addparticle = lo; } if (addparticle != null) gamestate.Particles.Add(addparticle); } } //each frame, check for blocks that are within the given radius. Hell with it, we'll check their centerpoints... if (gamestate.PlayerPaddle != null) { //if( if (DamagePaddle && BCBlockGameState.RectangleIntersectsCircle(gamestate.PlayerPaddle.Getrect(), Location, _CurrentRadius)) { gamestate.PlayerPaddle.HP -= 1f; } } if (_EffectObjects) { //find all GameObjects that implement IExplodable. //we might be bothered to do the same for Balls, I suppose. No promises. IEnumerable<IExplodable> result = BCBlockGameState.Join<IExplodable>( (from ball in gamestate.Balls where ball is IExplodable && (BCBlockGameState.Distance(Location,ball.Location) < _CurrentRadius) select ball as IExplodable), (from obj in gamestate.GameObjects where obj is IExplodable select obj as IExplodable)); //in order to prevent contention issues, we will defer the loop that "effects" each item until the next gametick iteration starts. gamestate.NextFrameCalls.Enqueue(new BCBlockGameState.NextFrameStartup(() => { foreach (var iterateresult in result) { PointF useVelocityEffect = new PointF(Math.Max(1,Velocity.X),Math.Max(1,Velocity.Y)); iterateresult.ExplosionInteract(this, Location, useVelocityEffect); } })); } List<Block> removethese = new List<Block>(); if (_DamageBlocks) { var blowemup = from p in gamestate.Blocks where BCBlockGameState.Distance(Location.X, Location.Y, p.CenterPoint().X, p.CenterPoint().Y) < _CurrentRadius select p; if (blowemup.Any()) { foreach (var loopblock in blowemup) { //destroy it. if (loopblock is DestructionBlock) { //special handling for combos Debug.Print("DestructionBlock detected in ExplosionEffect..."); (loopblock as DestructionBlock).ComboCount = this.ComboCount + 1; } if (DestroyAll || loopblock.MustDestroy()) { loopblock.StandardSpray(gamestate); removethese.Add(loopblock); } } lock (gamestate.Blocks) { foreach (Block removeit in removethese) { //get angle between the center of the explosion and the block's center. double Angle = BCBlockGameState.GetAngle(CenterPoint(), removeit.CenterPoint()); int useSpeed = BCBlockGameState.ClampValue((int)_MaxRadius / 2, 1, 5); PointF useVelocity = BCBlockGameState.GetVelocity(useSpeed, Angle); cBall tempball = new cBall(new PointF(removeit.CenterPoint().X-useVelocity.X,removeit.CenterPoint().Y-useVelocity.Y), useVelocity); tempball.PreviousVelocity = useVelocity; tempball.Behaviours.Add(new TempBallBehaviour()); //add a proxy behaviour to remove it as well. //tempball.Behaviours.Add(new ProxyBallBehaviour("ExplosionEffect", null, proxyperformframe, null, null, null, null, null, null)); //gamestate.Balls.AddLast(tempball); List<cBall> discardlist = new List<cBall>(); try { //this is... well, cheating... //we cannot add GameObjects to the List, except by plopping them in the ref AddedObject parameter. //however, we cannot "force" the PerformBlockHit of a block (say a destruction block) to add a GameObject (another ExplosionEffect, in that case) //we cheat. we swap out the entire gamestate.GameObject LinkedList with a new one, call the routine, and then //we add any added GameObjects to our ref parameter, and swap the old list back in, hoping nobody notices our //audacity to fiddle with core game state objects... var copiedref = gamestate.GameObjects; gamestate.GameObjects = new LinkedList<GameObject>(); removeit.PerformBlockHit(gamestate, tempball); gamestate.Blocks.Remove(removeit); var tempadded = gamestate.GameObjects; gamestate.GameObjects = copiedref; //now we add the ones we need to add to our ref array. I feel dirty. gamestate.Defer(() => { foreach (var iterate in tempadded) { gamestate.GameObjects.AddLast(iterate); } }); } catch { } //we don't add the ball to our GameState, so we don't have to worry about it persisting :D //the idea is that we want to invoke the actions of the block (which for many blocks will simply be destroyed). //at the same time, some blocks might react weirdly to having temporary balls tossed into their centers, so we make it so the ball will only live for //two frames by adding a proxyballbehaviour that ensure that. //gamestate.Blocks.Remove(removeit); gamestate.Forcerefresh = true; } //changed: instead of removing them, create a temporary ball at their center point. } } } return retval; }
public virtual List<Block> PerformFrame(cBall ballobject, BCBlockGameState ParentGameState, ref List<cBall> ballsadded, ref List<cBall> ballsremove,out bool removethis) { removethis=false; if(!mInitialized) { useball = ballobject; prevstate = ParentGameState; BehaviourAdded(ballobject, ParentGameState); mInitialized=true; } //throw new NotImplementedException(); return null; }
/// <summary> /// Creates the Spinshot, using the given ball as the origin /// </summary> /// <param name="gamestate"></param> /// <param name="useorigin"></param> /// <param name="pLocation"></param> /// <param name="Numorbit"></param> /// <param name="radius"></param> /// <param name="rotationspeed"></param> /// <param name="pVelocity"></param> public SpinShot(BCBlockGameState gamestate, cBall useorigin, PointF pLocation, int Numorbit, float radius, float rotationspeed) : base(pLocation, useorigin.Velocity) { SubObjects = new List<SpinShotsubBallInfo>(); OurBall = useorigin; OurBall.BallImpact += new cBall.ballimpactproc(OurBall_BallImpact); gamestate.Balls.AddLast(OurBall); //we let the game logic handle the ball, but our performframe will "update" the position of the sub-balls. //speaking of which- we need to create those. float Angleuse = (float)((Math.PI * 2) / Numorbit); float useangle = 0; for (int i = 0; i < Numorbit; i++) { useangle = ((float)i) * Angleuse; PointF useposition = new PointF((float)(Math.Cos(useangle) * radius) + pLocation.X, (float)(Math.Sin(useangle) * radius) + pLocation.Y); cBall derivedball = new cBall(useposition, new PointF(0.1f, 0.1f)); //derivedball.Behaviours.Add(new TempBallBehaviour()); derivedball.Behaviours.Add(new NonReboundableBallBehaviour()); derivedball.Behaviours.Add(new ParticleEmitterBehaviour(SparkleEmitter)); derivedball.DrawPen = new Pen(Color.Transparent); derivedball.DrawBrush = spinshotbrush; SpinShotsubBallInfo subinfo = new SpinShotsubBallInfo(OurBall, derivedball, useangle, rotationspeed, radius); SubObjects.Add(subinfo); gamestate.Balls.AddLast(derivedball); } }
public cBall(cBall clonethis) { Radius = clonethis.Radius; Location = clonethis.Location; Velocity = clonethis.Velocity; DrawBrush = (Brush)clonethis.DrawBrush.Clone(); DrawPen = (Pen)clonethis.DrawPen.Clone(); //Behaviours = clonethis.Behaviours; //Don't Set Behaviours directly. go through each. foreach (var loopbehave in clonethis.Behaviours) { Behaviours.Add(loopbehave); } DrawColor = clonethis.DrawColor; }
void OurBall_BallImpact(cBall ballimpact) { //throw new NotImplementedException(); hasbeendestroyed = true; //release All the balls in our subobjects. foreach (var subobj in SubObjects) { subobj.ReleaseBall(); } SubObjects = new List<SpinShotsubBallInfo>(); }
public static void CollideBalls(cBall BallA, cBall BallB) { double RatioA = BallB.Mass / (BallA.Mass + BallB.Mass); double RatioB = BallA.Mass / (BallA.Mass + BallB.Mass); //Get the velocities of each ball. PointF VelR = new PointF(BallB.Velocity.X-BallA.Velocity.X,BallB.Velocity.Y-BallA.Velocity.Y); //I = (1+e)*N*(Vr • N) //Va = -I*(Mb / (Ma+Mb)) //Vb = +I*(Ma / (Ma+Mb)) //angle between the two balls. double angle = BCBlockGameState.GetAngle(BallA.Location,BallB.Location); //create a vector of magnitude 1 of that angle. PointF N = new PointF((float)Math.Cos(angle),(float)Math.Sin(angle)); }
void BallObject_BallImpact(cBall ballimpact) { //release the ball... Set it's Speed to getSpeedVector. ballimpact.Velocity = getSpeedVector(); //"owner" SpinShot will properly 'release' the ball by removing us from the collection. }
public override List<Block> PerformFrame(cBall ballobject, BCBlockGameState ParentGameState, ref List<cBall> ballsadded, ref List<cBall> ballsremove, out bool removethis) { List<Block> returnval = base.PerformFrame(ballobject, ParentGameState, ref ballsadded, ref ballsremove, out removethis); if (!Waiting) { //if we aren't "waiting", then set waiting to true, cache the current speed of the ball, and initialize startWaitTime. cachedSpeed = ballobject.Velocity; ballobject.Velocity = PointF.Empty; //set speed to 0 Waiting=true; startWaitTime=DateTime.Now; prevbehaviours=ballobject.Behaviours; ballobject.Behaviours = new List<iBallBehaviour>(); ballobject.Behaviours.Add(this); } else if(Waiting) { //if we <ARE> waiting, then check the times. if (TimeElapsed > waitTime) { //waiting is over! ballobject.Velocity=cachedSpeed; ballobject.Behaviours = prevbehaviours; //and remove ourselves.. removethis=true; } } return returnval; }