作为一个新程序员,我没有进行实际的AI实现,而是使用了以下解决方案来使右侧的球拍跟随球移动:
if(ball.position.Y > p2.position.Y){ p2.position.Y += ball.position.Y;}else if (ball.position.Y < p2.position.Y){ p2.position.Y -= ball.position.Y;}
然而,实际情况是这样的(我尝试使用PrtScn截屏,结果似乎暂停了游戏一微秒,只捕捉到了一个球拍而不是两个闪烁的球拍)。那么,我该怎么做才能让第二个球拍看起来像一个呢?
程序的完整代码:
Game1.cs
namespace Pong{ public class Game1 : Game { //变量 GraphicsDeviceManager graphics; SpriteBatch spriteBatch; //边界 Texture2D borders; //球拍 Paddle p1 = new Paddle(); Paddle p2 = new Paddle(); //球 Ball ball = new Ball(); //位置 Vector2 bordersPos; //构造函数 public Game1() : base() { graphics = new GraphicsDeviceManager(this); graphics.IsFullScreen = false; graphics.PreferredBackBufferHeight = 800; graphics.PreferredBackBufferWidth = 800; //内容加载器 Content.RootDirectory = "Content"; } //初始化 protected override void Initialize() { base.Initialize(); } //加载内容 protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); //分配纹理 p1.texture = Content.Load<Texture2D>("paddle1"); p2.texture = Content.Load<Texture2D>("paddle1"); borders = Content.Load<Texture2D>("borders"); ball.texture = Content.Load<Texture2D>("ball"); //位置 p1.position.X = 50; p1.position.Y = graphics.GraphicsDevice.Viewport.Height / 2 - (p1.height / 2); p2.position.X = graphics.GraphicsDevice.Viewport.Width - 50 - p2.width; p2.position.Y = graphics.GraphicsDevice.Viewport.Height / 2 - (p2.height / 2); bordersPos.Y = 0; bordersPos.X = 0; ball.position.X = 800 / 2 - ball.width / 2; ball.position.Y = 800 / 2 - ball.height / 2; } protected override void UnloadContent() { } //更新 protected override void Update(GameTime gameTime) { //退出 if (Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); //更新玩家控制 PlayerInput(); p1.Update(); p2.Update(); ball.Update(); //球拍碰撞 if (padCol1()) { if (ball.movingDownLeft) { ball.movingDownRight = true; ball.movingDownLeft = false; } else if (ball.movingUpLeft) { ball.movingUpRight = true; ball.movingUpLeft = false; } } if (padCol2()) { if (ball.movingDownRight) { ball.movingDownLeft = true; ball.movingDownRight = false; } else if (ball.movingUpRight) { ball.movingUpLeft = true; ball.movingUpRight = false; } } //AI if(ball.position.Y > p2.position.Y){ p2.position.Y += ball.position.Y; } else if (ball.position.Y < p2.position.Y) { p2.position.Y -= ball.position.Y; } base.Update(gameTime); } //绘制 protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.Black); spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend); //球拍 p1.Draw(spriteBatch); p2.Draw(spriteBatch); //边界 spriteBatch.Draw(borders, bordersPos, Color.White); //球 ball.Draw(spriteBatch); spriteBatch.End(); base.Draw(gameTime); } //玩家输入 public void PlayerInput() { //玩家1 if (Keyboard.GetState(p1.pNumber).IsKeyDown(Keys.W)) { p1.position.Y -= p1.speed; } else if (Keyboard.GetState(p1.pNumber).IsKeyDown(Keys.S)) { p1.position.Y += p1.speed; } } //球拍碰撞 public bool padCol1() { if (ball.position.Y >= p1.position.Y && ball.position.X > p1.position.X && ball.position.X < (p1.position.X + p1.width) && ball.position.Y < (p1.position.Y + p1.height)) { return true; } else return false; } public bool padCol2() { if (ball.position.Y >= p2.position.Y && ball.position.X > p2.position.X && ball.position.X < (p2.position.X + p2.width) && ball.position.Y < (p2.position.Y + p2.height)) { return true; } else return false; }}}
Paddle.cs
namespace Pong{class Paddle : Game{ //变量 public Texture2D texture; public Vector2 position; public PlayerIndex pNumber; public int width, height; public float speed; //构造函数 public Paddle() { texture = null; position = Vector2.Zero; pNumber = PlayerIndex.One; width = 64; height = 187; speed = 10.0f; } //更新 public void Update() { //设置边界 if (position.Y <= 30) position.Y = 30; if (position.Y >= 800 - 217) position.Y = 800 - 217; } //绘制 public void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(texture, position, Color.White); }}
Ball.cs
namespace Pong{class Ball : Game{ //变量 public Vector2 position; public Texture2D texture; public int width, height; public float speed; public bool movingDownLeft, movingUpLeft, movingDownRight, movingUpRight; //构造函数 public Ball() { Content.RootDirectory = ("Content"); speed = 6.0f; width = 20; height = 20; movingDownLeft = true; movingUpRight = false; movingUpLeft = false; movingDownRight = false; position = Vector2.Zero; } //绘制 public void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(texture, position, Color.White); } //更新 public void Update() { //方向 if(movingUpLeft){ position.Y -= speed; position.X -= speed; } if (movingDownLeft) { position.Y += speed; position.X -= speed; } if (movingUpRight) { position.Y -= speed; position.X += speed; } if (movingDownRight) { position.Y += speed; position.X += speed; } //球与墙的碰撞 if(movingUpLeft && position.Y <= 30) { movingDownLeft = true; movingUpLeft = false; } //1 else if (movingDownLeft && position.X <= 0) { movingDownRight = true; movingDownLeft = false; } //2 else if (movingUpLeft && position.X <= 0) { movingUpRight = true; movingUpLeft = false; } //3 else if (movingDownLeft && position.Y >= 800 - 45) { movingUpLeft = true; movingDownLeft = false; } //4 else if (movingDownRight && position.X >= 800 - width) { movingDownLeft = true; movingDownRight = false; } //5 else if (movingUpRight && position.Y <= 30) { movingDownRight = true; movingUpRight = false; } //6 else if (movingDownRight && position.Y >= 800 - 45) { movingUpRight = true; movingDownRight = false; } //7 else if (movingUpRight && position.X >= 800 - width) { movingUpLeft = true; movingUpRight = false; } }}}
回答:
我从未使用过MonoGame,但这段代码:
if(ball.position.Y > p2.position.Y){ p2.position.Y += ball.position.Y;}else if (ball.position.Y < p2.position.Y){ p2.position.Y -= ball.position.Y;}
总是会超调,然后触发下一次更新。
你为什么不直接这样做呢:
p2.position.Y = ball.position.Y;
编辑:你可能还应该使你的输入帧率独立(除非MonoGame已经为你做了这件事)。现在看起来你的球拍移动速度会根据你的帧率而变化。