protected override void ExecuteCopyToDevice()
            {
                base.ExecuteCopyToDevice();

                MyTwoPlayerPongWorld Owner = GetTwoPlayerOwner();

                Owner.PaddleBPosX.SafeCopyToDevice();
                Owner.PaddleBPosY.SafeCopyToDevice();

                Owner.EventB.SafeCopyToDevice();
                Owner.BinaryEventB.SafeCopyToDevice();
            }
            protected override void ExecutePrepareHost()
            {
                base.ExecutePrepareHost();

                MyTwoPlayerPongWorld Owner = GetTwoPlayerOwner();

                Owner.BinaryEventB.Host[LOST_LIFE_I]          = 0;
                Owner.BinaryEventB.Host[BOUNCE_BALL_I]        = 0;
                Owner.BinaryEventB.Host[OPPONENT_LOST_LIFE_I] = 0;
                Owner.EventB.Host[0] = 0.0f;

                Owner.ControlsB.SafeCopyToHost();
            }
            private void AddPaddleBToGameObjects()
            {
                MyTwoPlayerPongWorld Owner = (MyTwoPlayerPongWorld)this.Owner;

                if (Owner.m_gameObjects.Count < 3)
                {
                    MyGameObject paddleA = Owner.m_gameObjects[1];
                    MyGameObject paddleB = new MyGameObject()
                    {
                        pixelSize = new int2(paddleA.pixelSize.x, paddleA.pixelSize.y),
                        bitmap    = paddleA.bitmap
                    };
                    Owner.m_gameObjects.Add(paddleB);
                }
            }
            protected override void ResetBallAndPaddle()
            {
                base.ResetBallAndPaddle(); // moves the ball on the paddle of player A

                MyTwoPlayerPongWorld Owner = GetTwoPlayerOwner();

                MyGameObject ball    = Owner.m_gameObjects[0];
                MyGameObject paddleB = Owner.m_gameObjects[2];

                if (m_lastLost == PLAYER_A) // moves the ball on the paddle of player B
                {
                    ball.position.y = 22 - ball.pixelSize.y;
                    ball.velocity.y = 1f;
                }

                paddleB.position.x = (Owner.Scene.Width - paddleB.pixelSize.x) * 0.5f;
                paddleB.position.y = 14 - paddleB.pixelSize.y;

                paddleB.velocity.x = 0;
                paddleB.velocity.y = 0;

                m_controlB = m_controlBCoolDown = 0;
            }
            protected override void ExecuteResolveEvents()
            {
                MyTwoPlayerPongWorld Owner = GetTwoPlayerOwner();

                MyGameObject ball    = Owner.m_gameObjects[0];
                MyGameObject paddle  = Owner.m_gameObjects[1];
                MyGameObject paddleB = Owner.m_gameObjects[2];

                ResolveBallEvents(ball, paddle, paddleB);

                UpdateControl(ref m_control, ref m_controlCoolDown, Owner.Controls.Host);
                UpdateControl(ref m_controlB, ref m_controlBCoolDown, Owner.ControlsB.Host);
                ResolvePaddleEvents(paddle, m_control);
                ResolvePaddleEvents(paddleB, m_controlB);

                Owner.BallPosX.Host[0] = ball.position.x + ball.pixelSize.x * 0.5f;
                Owner.BallPosY.Host[0] = ball.position.y + ball.pixelSize.y * 0.5f;

                Owner.PaddlePosX.Host[0] = paddle.position.x + paddle.pixelSize.x * 0.5f;
                Owner.PaddlePosY.Host[0] = paddle.position.y + paddle.pixelSize.y * 0.5f;

                Owner.PaddleBPosX.Host[0] = paddleB.position.x + paddleB.pixelSize.x * 0.5f;
                Owner.PaddleBPosY.Host[0] = paddleB.position.y + paddleB.pixelSize.y * 0.5f;
            }
            protected void ResolveBallEvents(MyGameObject ball, MyGameObject paddle, MyGameObject paddleB)
            {
                MyTwoPlayerPongWorld Owner = GetTwoPlayerOwner();

                float2 futurePos = ball.position + ball.velocity;

                //leftSide
                if (futurePos.x < 0 && ball.velocity.x < 0)
                {
                    ball.velocity.x = -ball.velocity.x;
                }
                //rightSide
                if (futurePos.x + ball.pixelSize.x > Owner.Scene.Width && ball.velocity.x > 0)
                {
                    ball.velocity.x = -ball.velocity.x;
                }

                //bottom side
                if (futurePos.y + ball.pixelSize.y > Owner.Scene.Height && ball.velocity.y > 0)
                {
                    if (stepsFrozen == 0)
                    {
                        Owner.Event.Host[0]  += LOST_LIFE;          // take the life at the first freeze frame
                        Owner.EventB.Host[0] += OPPONENT_LOST_LIFE; // reward for the other player
                        Owner.BinaryEvent.Host[LOST_LIFE_I]           = 1;
                        Owner.BinaryEventB.Host[OPPONENT_LOST_LIFE_I] = 1;
                        m_lastLost = PLAYER_A;
                    }
                    if (stepsFrozen == this.FreezeAfterFail)
                    {
                        stepsFrozen = 0;
                        ResetGame();
                    }
                    else
                    {
                        stepsFrozen++;
                        return;
                    }
                }

                //top side
                if (futurePos.y < 0 && ball.velocity.y < 0)
                {
                    if (stepsFrozen == 0)
                    {
                        Owner.EventB.Host[0] += LOST_LIFE;          // take the life at the first freeze frame
                        Owner.Event.Host[0]  += OPPONENT_LOST_LIFE; // reward for the other player
                        Owner.BinaryEventB.Host[LOST_LIFE_I]         = 1;
                        Owner.BinaryEvent.Host[OPPONENT_LOST_LIFE_I] = 1;
                        m_lastLost = PLAYER_B;
                    }
                    if (stepsFrozen == this.FreezeAfterFail)
                    {
                        stepsFrozen = 0;
                        ResetGame();
                    }
                    else
                    {
                        stepsFrozen++;
                        return;
                    }
                }

                //paddle A
                if (futurePos.y + ball.pixelSize.y > paddle.position.y &&
                    futurePos.y + ball.pixelSize.y < paddle.position.y + paddle.pixelSize.y &&
                    futurePos.x + 10 > paddle.position.x &&
                    futurePos.x + ball.pixelSize.x < paddle.position.x + paddle.pixelSize.x + 10 &&
                    ball.velocity.y > 0)
                {
                    ball.velocity.y  = -ball.velocity.y;
                    ball.velocity.x += paddle.velocity.x * 0.2f;

                    Owner.Event.Host[0] += BOUNCE_BALL;
                    Owner.BinaryEvent.Host[BOUNCE_BALL_I] = 1;
                }

                // paddle B
                if (futurePos.y < paddleB.position.y + paddleB.pixelSize.y &&
                    futurePos.y > paddleB.position.y &&
                    futurePos.x + 10 > paddleB.position.x &&
                    futurePos.x + ball.pixelSize.x < paddleB.position.x + paddleB.pixelSize.x + 10 &&
                    ball.velocity.y < 0)
                {
                    ball.velocity.y  = -ball.velocity.y;
                    ball.velocity.x += paddleB.velocity.x * 0.2f;

                    Owner.EventB.Host[0] += BOUNCE_BALL;
                    Owner.BinaryEventB.Host[BOUNCE_BALL_I] = 1;
                }

                ball.position += ball.velocity * DELTA_T;
            }