当前位置: 首页>>代码示例>>C#>>正文


C# BCBlockGameState.Defer方法代码示例

本文整理汇总了C#中BCBlockGameState.Defer方法的典型用法代码示例。如果您正苦于以下问题:C# BCBlockGameState.Defer方法的具体用法?C# BCBlockGameState.Defer怎么用?C# BCBlockGameState.Defer使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在BCBlockGameState的用法示例。


在下文中一共展示了BCBlockGameState.Defer方法的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。

示例1: GivePowerTo

        public override bool GivePowerTo(BCBlockGameState gamestate, GameCharacter gamechar)
        {
            BCBlockGameState.Soundman.PlaySound("1up");
            BasicFadingText bft = new BasicFadingText("1-Up", Location, new PointF(0, -2), new Font(BCBlockGameState.GetMonospaceFont(), 14), new Pen(Color.Black,2), new SolidBrush(Color.Green), 500);

            gamestate.playerLives++;
            gamestate.Forcerefresh = true;
            gamestate.Defer(() => gamestate.GameObjects.AddLast(bft));

            return true;
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:11,代码来源:GameCharacter.cs

示例2: BehaviourAdded

        public override void BehaviourAdded(Paddle toPaddle, BCBlockGameState gamestate)
        {
            base.BehaviourAdded(toPaddle, gamestate);
            gamestate.Defer(()=>{
                                    addedobject = new ProxyObject((po, gs) =>
                                                                      {

                                                                          PerformFrame(toPaddle, gamestate);
                                                                          return false;

                                                                      }, null);
                                    gamestate.GameObjects.AddLast(addedobject);
            });
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:14,代码来源:DeflectorBehaviour.cs

示例3: PowerUpCallback

        public bool PowerUpCallback(BCBlockGameState gamestate)
        {
            float randgen = (float)BCBlockGameState.rgen.NextDouble() * Spawnchancesum;
            int useindex = RandomValueToIndex(randgen, spawnchance);
            Type grabtype = spawntypes[useindex];

            SizeF useSize = new SizeF(16, 16);
            PointF useposition =
                new PointF(gamestate.GameArea.Width * (float)BCBlockGameState.rgen.NextDouble(), (gamestate.GameArea.Height - 72) * (float)BCBlockGameState.rgen.NextDouble());

            GameEnemy genenemy = (GameEnemy)Activator.CreateInstance(grabtype, useposition, useSize);
            gamestate.Defer(() =>
                                {
                                    gamestate.GameObjects.AddLast(genenemy);

                                    AddScore(gamestate, 10);
                                });
            return true;
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:19,代码来源:EnemySpawnerPowerUp.cs

示例4: PerformFrame

        public override bool PerformFrame(BCBlockGameState gamestate)
        {
            BCBlockGameState.IncrementLocation(gamestate, ref _Location, Velocity);
                framecounter++;
                if (framecounter >= NextDeployment)
                {
                    framecounter = 0;
                    NextDeployment = BCBlockGameState.rgen.Next(10, 30);

                    ExplosionEffect ee = new ExplosionEffect(Location, 10 + (float)(BCBlockGameState.rgen.NextDouble() * 20));
                    ee.DamageBlocks = false; //doesn't hurt blocks...
                    ee.ShowOrbs = false;

                    gamestate.Defer(() =>
                    {
                        gamestate.GameObjects.AddLast(ee);
                        BCBlockGameState.Soundman.PlaySound("explode");
                    });

                }
                return !gamestate.GameArea.Contains(new Point((int)Location.X, (int)Location.Y));
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:22,代码来源:cGameObject.cs

示例5: PerformBlockHit

        public override bool PerformBlockHit(BCBlockGameState parentstate, cBall ballhit)
        {
            if (CurrentMode == PowerupBlockMode.BlockMode_Filled)
            {
                if (isEmergePower())
                {
                    try
                    {
                        TransitoryBlockObject tbo = new TransitoryBlockObject(this);
                        parentstate.Defer(()=>parentstate.GameObjects.AddLast(tbo));
                        tbo.TransitionComplete = TransitFunc;
                        CurrentMode = PowerupBlockMode.BlockMode_Transitory;

                        BumpObjects(parentstate);
                    }
                    catch (Exception err)
                    {
                        Debug.Print(err.ToString());

                    }
                }
                else
                {
                    //call transitfunc directly.
                    TransitFunc(parentstate, null);

                }
            }
            base.PerformBlockHit(parentstate, ballhit);
            BCBlockGameState.Soundman.PlaySound("bump");
            return false;
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:32,代码来源:PowerupBlock.cs

示例6: PerformFrame

        public override bool PerformFrame(BCBlockGameState gamestate)
        {
            if (Frozen) return false;
            PointF usedoffset=PointF.Empty;
            BCBlockGameState.IncrementLocation(gamestate, ref _Location, _Velocity,ref usedoffset);
            _Poly.Offset(usedoffset);
            if (!(new Polygon(gamestate.GameArea).Contains(_Poly)))
            {
                //reflect
                var result = GeometryHelper.PolygonCollision(new Polygon(gamestate.GameArea), _Poly, Velocity);
                var copied = new PointF(-result.MinimumTranslationVector.X, -result.MinimumTranslationVector.Y);
                if (Math.Abs(result.MinimumTranslationVector.X) > Math.Abs(result.MinimumTranslationVector.Y))
                {
                    //mirror X speed.
                    Velocity = new PointF(-Velocity.X, Velocity.Y);
                }
                else
                {
                    Velocity = new PointF(Velocity.X, -Velocity.Y);
                }

            }
            _Velocity = _VelocityDecayFunction(this, _Velocity);
            CurrAngle += AngleSpeed;
            _AngleSpeed = _AngleSpeedDecayFunction(this, _AngleSpeed);

            //check for ball collisions.
            foreach (cBall checkball in gamestate.Balls)
            {
                Polygon ballpoly = checkball.GetBallPoly();

                if (_Poly.IntersectsWith(ballpoly) && !InvokeBeforeObstacleHit(gamestate,checkball,this))
                {
                    //only if it intersects.
                    Vector Adjustment;
                    GeometryHelper.PolygonCollisionResult pcr = GeometryHelper.PolygonCollision(_Poly,
                                                                                                ballpoly, new Vector(checkball.Velocity.X+Velocity.X, checkball.Velocity.Y+Velocity.Y));

                    Adjustment = pcr.MinimumTranslationVector;
                    checkball.Velocity = checkball.Velocity.Mirror(pcr.MinimumTranslationVector);
                    checkball.Velocity = new PointF(checkball.Velocity.X, checkball.Velocity.Y);
                    checkball.Location = new PointF(checkball.Location.X - Adjustment.X, checkball.Location.Y - Adjustment.Y);
                    BCBlockGameState.Soundman.PlaySound("bounce");
                    //determine percentage of "knockback" to us based on the ratio between the ball radius and our average radius.
                    float ourAverage = _Poly.AverageRadius();
                    float ballradii = checkball.Radius;
                    float ratio = ballradii / ourAverage;
                    PointF mCenter = GetRectangle().CenterPoint();
                    Velocity = new PointF(Velocity.X + pcr.MinimumTranslationVector.X * ratio, Velocity.Y + pcr.MinimumTranslationVector.Y * ratio);
                    //get angle between the ball's previous location (assumed from the velocity) and it's current pos,
                    //with our center point as the pivot.
                    PointF PrevPosition = checkball.PrevLocation;
                    PointF CurrLocation = checkball.Location;
                    var PrevAngle = BCBlockGameState.GetAngle(mCenter, PrevPosition);
                    var CurrentAngle = BCBlockGameState.GetAngle(mCenter, CurrLocation);
                    AngleSpeed = CurrentAngle - PrevAngle;

                    //reduce our size, as well.
                    _Poly = _Poly.Scale(0.9f);

                    if (_Poly.Area() < MinimumSize && !InvokeObstacleHit(gamestate,checkball,this))
                    {
                        //Fire the OnDestroy event
                        if(!InvokeObstacleDestroy(gamestate,checkball,this))
                            return true; //tweak: make it explode or something, too.
                    }

                }

            }

            if (_fShoot)
            {
                if (delayoffset++ == _ShootDelay)
                {
                    delayoffset = 0;
                    //shoot lightning. Because lightning is da' shit.
                    //choose a random point on this polygon.
                    PointF selectedpoint = BCBlockGameState.Choose(Poly.Points);
                    //get angle between that point and the paddle.
                    //if there is no paddle, use a random value.
                    double fireangle = gamestate.PlayerPaddle != null ?
                                           BCBlockGameState.GetAngle(selectedpoint, gamestate.PlayerPaddle.CenterPoint()) :
                                           BCBlockGameState.rgen.NextDouble() * Math.PI * 2;
                    PointF createdvel = BCBlockGameState.VaryVelocity(new PointF((float)Math.Cos(fireangle), (float)Math.Sin(fireangle)), Math.PI / 12);

                    LightningShot ls = new LightningShot(selectedpoint, createdvel)
                                           {
                                               DamageBlocks = false,
                                               DamagePaddle = true
                                           };
                    gamestate.Defer(() => gamestate.GameObjects.AddLast(ls));
                }

            }

            return !gamestate.GameArea.IntersectsWith(_Poly.GetBounds().ToRectangle());
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:98,代码来源:PolygonObstacle.cs

示例7: AttractRepulseDestructor

        public AttractRepulseDestructor(BCBlockGameState gstate, AttractionRepulsionBlock BlockA, AttractionRepulsionBlock BlockB)
        {
            //calculate the appropriate vectors.
                OriginalBlocks = new AttractionRepulsionBlock[] { BlockA, BlockB };
                PointF midpoint = BCBlockGameState.MidPoint(BlockA.CenterPoint(), BlockB.CenterPoint());
                double AtoB = BCBlockGameState.GetAngle(BlockA.CenterPoint(), midpoint);
                double BtoA = BCBlockGameState.GetAngle(BlockB.CenterPoint(), midpoint);
                double AuseAngle = BtoA; //default to "repel"
                double BuseAngle = AtoB;
                //if they are not the same colour...
                if (!(BlockA.BlockColor.R == BlockB.BlockColor.R &&
                    BlockA.BlockColor.G == BlockB.BlockColor.G &&
                    BlockA.BlockColor.B == BlockB.BlockColor.B))
                    BCBlockGameState.Swap(ref AuseAngle, ref BuseAngle);
                //swap, if the colour RGB triplets are unequal we want to "attract" rather than repel.

                //their initial speed will be zero.
                Aggregates = new BoxDestructor[] { new BoxDestructor(BlockA, PointF.Empty), new BoxDestructor(BlockB, PointF.Empty) };
                //but we will change their 'velocitydecay' 0.05 for now, in the appropriate direction.

                Aggregates[0].VelocityDecay = new PointF((float)Math.Cos(AuseAngle) * defaultinitialspeed,
                                                         (float)(Math.Sin(AuseAngle) * defaultinitialspeed));
                Aggregates[1].VelocityDecay = new PointF((float)(Math.Cos(BuseAngle) * defaultinitialspeed),
                     (float)(Math.Sin(BuseAngle) * defaultinitialspeed));

                Aggregates[0].VelocityIncrement = Aggregates[0].VelocityDecay;
                Aggregates[1].VelocityIncrement = Aggregates[1].VelocityDecay;
                Aggregates[0].VelocityDecay = new PointF(1 + Math.Abs(Aggregates[0].VelocityDecay.X), 1 + Math.Abs(Aggregates[0].VelocityDecay.Y));
                Aggregates[1].VelocityDecay = new PointF(1 + Math.Abs(Aggregates[1].VelocityDecay.X), 1 + Math.Abs(Aggregates[1].VelocityDecay.Y));

                //now we need to add the BoxDestructor to the gamestate.
                //we do not remove the Blocks, instead deferring that to the block itself to decide.
                //it is also the caller's responsibility to add this instance to the GameObjects list as well.
                gstate.Defer(() =>
                {
                    gstate.GameObjects.AddLast(Aggregates[0]);
                    gstate.GameObjects.AddLast(Aggregates[1]);
                });
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:39,代码来源:cGameObject.cs

示例8: AddScore

        protected void AddScore(BCBlockGameState ParentGame, int scoreadd, String prefixString)
        {
            //PointF MidPoint = new PointF(mBlockrect.Left + (mBlockrect.Width / 2), mBlockrect.Top + (mBlockrect.Height / 2));
            String usestring;

            PointF MidPoint = new PointF(Location.X + Size.Width / 2, Location.Y + Size.Height / 2);
            int addedscore = scoreadd + (Math.Sign(scoreadd) * ParentGame.GameObjects.Count * 10);
            if (String.IsNullOrEmpty(prefixString))
                usestring = addedscore.ToString();
            else
                usestring = prefixString + "(" + addedscore.ToString() + ")";

            ParentGame.GameScore += addedscore;
            //ParentGame.GameObjects.AddLast(new BasicFadingText(usestring, MidPoint, new PointF(((float)BCBlockGameState.rgen.NextDouble() * 0.2f) * -0.1f, ((float)BCBlockGameState.rgen.NextDouble()) * -0.7f), new Font(BCBlockGameState.GetMonospaceFont(), 16), null, null));
            ParentGame.Defer(() => ParentGame.GameScore += addedscore);
            ParentGame.GameObjects.AddLast(new BasicFadingText(usestring, MidPoint, new PointF(((float)BCBlockGameState.rgen.NextDouble() * 0.2f) * -0.1f, ((float)BCBlockGameState.rgen.NextDouble()) * -0.7f), new Font(BCBlockGameState.GetMonospaceFont(), 16), null, null));
            //ParentGame.EnqueueMessage(usestring);
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:18,代码来源:GamePowerUp.cs

示例9: PerformBlockHit

        public override bool PerformBlockHit(BCBlockGameState parentstate, cBall ballhit)
        {
            parentstate.Defer(()=>
                              parentstate.GameObjects.AddLast(new ProxyObject(proxyfunction, null)));

            return base.PerformBlockHit(parentstate, ballhit);
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:7,代码来源:ReplacerBlock.cs

示例10: PerformFrame

        public virtual List<Block> PerformFrame(BCBlockGameState ParentGameState,ref List<cBall> ballsadded,ref List<cBall> ballsremove)
        {
            PreviousVelocity = Velocity;
            //returns the blocks that were affected by the frame (changed or moved).
            //PointF NextPosition = new PointF(Location.X + Velocity.X, Location.Y + Velocity.Y);
            PointF NextPosition = Location;
            BCBlockGameState.IncrementLocation(ParentGameState, ref NextPosition, Velocity);
            //RectangleF NextPositionBorders = new RectangleF(NextPosition.X - Radius, NextPosition.Y - Radius, Radius, Radius);
            NormalizeSpeed();
            if(ballsadded==null)            ballsadded = new List<cBall>();
            RectangleF rectangleborders = new RectangleF(Location.X-Radius,Location.Y-Radius,Radius*2,Radius*2);
            PrevLocation=Location;
            //Location = new PointF(Location.X+Velocity.X,Location.Y+Velocity.Y);
            Location = NextPosition;

            TrailData.Enqueue(new TrailItemData(Location,Radius));
            while (TrailData.Count > _Trails)
                TrailData.Dequeue();

            BCBlockGameState wholeref = ParentGameState;

            List<Block> affectedblocks = InvokePerformFrame(this, ParentGameState, ref  ballsadded,ref ballsremove);

            if(affectedblocks==null) affectedblocks = new List<Block>();
            if (wholeref != null)
            {

                /*if (isTempBall)
                {

                    for (int i = 0; i < (int)(10 * BCBlockGameState.ParticleGenerationFactor); i++)
                    {
                        ParentGameState.Particles.Add(new FireParticle(this));

                    }

                }*/

                //check for collision with the walls...
                Rectangle clientrect = wholeref.GameArea;
                bool DoEmitSound=false;
                bool didhit=false;
                didhit = CheckWallCollision(rectangleborders, clientrect, ref DoEmitSound);

                //CheckBall.Y + CheckBall.radius >= Paddle.Y And CheckBall.Y - _
                //CheckBall.radius < Paddle.Y + Paddle.PHeight Or (((CheckBall.Y - _
                //CheckBall.Yspeed + CheckBall.radius) >= Paddle.Y And CheckBall.Y - _
                //CheckBall.Yspeed - CheckBall.radius < Paddle.Y + Paddle.PHeight) And _
                //Sgn(CheckBall.Yspeed) = 1)
                if (wholeref.PlayerPaddle != null)
                {
                    /*
                    if (rectangleborders.IntersectsWith(wholeref.PlayerPaddle.Getrect()) && Math.Sign(Velocity.Y) == 1)
                        // Paddle paddle = wholeref.PlayerPaddle;
                        //if((Location.Y + Radius >= paddle.Position.Y) && (Location.Y -
                        //    Radius < paddle.Position.X+paddle.PaddleSize.Width  ) || (((Location.Y - Velocity.Y + Radius) >= paddle.Position.Y &&
                        //    Location.Y - Velocity.Y - Radius < paddle.Position.Y+paddle.PaddleSize.Height) && Math.Sign(Velocity.Y)==1))

                        // if (Location.Y + Radius >= paddle.Position.Y && (Location.Y - Radius <= (paddle.Position.X + paddle.PaddleSize.Width)))
                    {
                        //the X coordinate checks out here...

                        {

                            wholeref.PlayerPaddle.Impact(wholeref, this);

                        }
                    }
                     * */
                    wholeref.PlayerPaddle.CheckImpact(wholeref, this, true);

                }
                bool HitBottom=false;
                if (rectangleborders.Bottom > clientrect.Bottom)
                {

                    didhit = true;
                    HitBottom=true;
                    DoEmitSound=false;

                }
                if (didhit)
                {
                    numImpacts++;
                    switch (invokeHitWall(wholeref, this))
                    {
                        case HitWallReturnConstants.HitBall_Default:
                            if (HitBottom)
                            {
                                ParentGameState.invokeballhitbottom(this);
                                ParentGameState.Defer(() => ParentGameState.Balls.Remove(this));
                            }
                            //

                            break;
                        case HitWallReturnConstants.HitBall_Destroy:

                            ParentGameState.invokeballhitbottom(this);
                            ParentGameState.Defer(() => ParentGameState.Balls.Remove(this));
                            break;
//.........这里部分代码省略.........
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:101,代码来源:cBall.cs

示例11: PerformFrame

            public override bool PerformFrame(BCBlockGameState gamestate)
            {
                bool returnvalue = base.PerformFrame(gamestate);

                switch (_ShotState)
                {
                    case BuilderShotState.BSS_Projectile:

                        List<Block> resulthittest = BCBlockGameState.Block_HitTest(gamestate.Blocks, getfullsize(),
                                                                                   false);
                        returnvalue = !returnvalue || resulthittest.Any();
                        if (returnvalue)
                        {
                            _ShotState = BuilderShotState.BSS_Expand;
                            Velocity = new PointF(0, 0.01f);
                            gamestate.Forcerefresh = true;
                        }
                        return false;

                    case BuilderShotState.BSS_Expand:
                        //if our size is the desired size of the block, create that block and return true.
                        //otherwise, change out size and location to emulate "growing".
                        if (this.ShotSize.Width >= BuildSize.Width &&
                            ShotSize.Height >= BuildSize.Height)
                        {
                            //grow phase completed.
                            //create the block in the desired location.
                            RectangleF desiredlocation = new RectangleF(Location.X, Location.Y, BuildSize.Width,
                                                                        BuildSize.Height);
                            Block builtblock = (Block) Activator.CreateInstance(this.BuildBlock, desiredlocation);
                            //add it to the game...
                            gamestate.Blocks.AddLast(builtblock);
                            //make sure to force a refresh, too.
                            gamestate.Forcerefresh = true;
                            gamestate.Defer(
                                () => gamestate.GameObjects.AddLast(new ProxyObject(forcerefresher, null)));
                            //return true to destroy outselves.
                            //todo: maybe add "effects" here, too?
                            return true;
                        }
                        else
                        {
                            //otherwise, we are in the growing phase.
                            //growincrement could be null, if so, initialize it...
                            if (Growincrement == null)
                            {
                                //initialize it to the difference between the final size and the current shot size, divided
                                //by increments.
                                Growincrement = new SizeF((BuildSize.Width - ShotSize.Width)/increments,
                                                          (BuildSize.Height - ShotSize.Height)/increments);
                            }
                            //change size by growincrement.
                            Location = new PointF(Location.X - Growincrement.Value.Width,
                                                  Location.Y - Growincrement.Value.Height);
                            ShotSize = new SizeF(ShotSize.Width + Growincrement.Value.Width*2,
                                                 ShotSize.Height + Growincrement.Value.Height*2);
                        }
                        return false;
                }
                return false;
            }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:61,代码来源:BuilderShotBehaviour.cs

示例12: getPowerup

 public override bool getPowerup(BCBlockGameState gstate,Paddle onPaddle, GamePowerUp gpower)
 {
     if(onPaddle==null) return false;
     //don't accept it.
     //reject it with great prejudice.
     //move the location temporarily.
     PointF oldposition = gpower.Location;
     SizeF oldsize = gpower.Size;
     gpower.Location = PointF.Empty;
     //draw to a temporary bitmap.
     Bitmap drawtothis = new Bitmap(16, 16);
     Graphics useg = Graphics.FromImage(drawtothis);
     useg.Clear(Color.Transparent);
     gpower.Draw(useg);
     //reset position.
     gpower.Location = oldposition;
     gpower.Size = oldsize;
     //get average.
     var averagedpixel = Color.FromArgb((int)((from p in drawtothis.getPixels() select p.ToArgb()).Average()));
     ExplosionEffect ee = new ExplosionEffect(gpower.Location, 72);
     ee.ExplosionColor = averagedpixel;
     ee.DamageBlocks = false;
     ee.DamagePaddle = false;
     gstate.Defer(() => gstate.GameObjects.AddLast(ee));
     //move  gpower to above the paddle, and invert the Y speed.
     gpower.Location = new PointF(gpower.Location.X, onPaddle.BlockRectangle.Top - gpower.getRectangle().Height - 1);
     gpower.Velocity = new PointF(gpower.Velocity.X, -Math.Abs(gpower.Velocity.Y)*1.1f);
     return true;
 }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:29,代码来源:DeflectorBehaviour.cs

示例13: TouchTop

 public override void TouchTop(BCBlockGameState gamestate, List<Block> touched, Block mainblock)
 {
     Velocity = new PointF(Velocity.X, Math.Abs(Velocity.Y * 0.5f));
     Block smackit = touched.First();
     BCBlockGameState.Block_Hit(gamestate, smackit, Velocity); //smack it with the player's velocity.
     gamestate.Forcerefresh = true;
     gamestate.Defer(() => gamestate.Forcerefresh = true);
 }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:8,代码来源:GameCharacter.cs

示例14: PerformFrame

        private void PerformFrame(Paddle toPaddle,BCBlockGameState gstate)
        {
            //add a random lightorb.
            if (offsetcall++ > 10)
            {
                offsetcall = 0;
                Color chosencolor = new HSLColor(BCBlockGameState.rgen.NextDouble() * 240, 240, 128);
                LightOrb lo = new LightOrb(toPaddle.BlockRectangle.RandomSpot(BCBlockGameState.rgen), chosencolor, 32);
                lo.Velocity = BCBlockGameState.GetRandomVelocity(0, 3);
                gstate.Defer(() => gstate.Particles.Add(lo));

            }
        }
开发者ID:BCProgramming,项目名称:BASeBlock,代码行数:13,代码来源:DeflectorBehaviour.cs


注:本文中的BCBlockGameState.Defer方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。