c# - 在 Monogame 中制作 Kitty Cannon,我如何将炮弹与其大炮对齐?
问题描述
正如标题所说,我正在尝试制作一个类似于 Monogame 中的 Kitty Cannon 的简单 2D 游戏。但是,我无法将炮弹与管道对齐,因为它是可旋转的。如何将炮弹的生成点与正确的角度和位置连接起来?我在下面发布我目前拥有的代码,希望它可以理解!
class CannonBallSprite
{
private Texture2D texture;public bool shootingActive = false;
public bool shootCannon = false;
public bool keyPressed = false;
public Vector2 position;
public Vector2 origin;
public Vector2 speed = new Vector2(0, 0.1f);
public Vector2 originalSpeed = new Vector2(0, 0.1f);
public Vector2 angle; //Trajectory
public float scale;
public float minPower = 10;
public float maxPower = 15;
public float power = 10;
public CannonBallSprite(Texture2D texture)
{
this.texture = texture;
}
public void Update(float rotation, Sprite sprite)
{
if (Keyboard.GetState().IsKeyDown(Keys.Left) && power > minPower && !keyPressed)
{
power -= 1;
keyPressed = true;
}
else if (Keyboard.GetState().IsKeyDown(Keys.Right) && power < maxPower && !keyPressed)
{
power += 1;
keyPressed = true;
}
if (Keyboard.GetState().IsKeyUp(Keys.Left) && keyPressed)
{
System.Threading.Thread.Sleep(300);
keyPressed = false;
}
else if(Keyboard.GetState().IsKeyUp(Keys.Right) && keyPressed)
{
System.Threading.Thread.Sleep(300);
keyPressed = false;
}
if (Keyboard.GetState().IsKeyDown(Keys.Space) && !shootingActive)
{
position = new Vector2(107, 365); // here maybe?
sprite.hasHit = false;
shootCannon = true;
}
if(shootCannon)
{
Move(angle, power);
speed += new Vector2(0, 0.1f); //standard gravitation
angle = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
Debug.Write("test");
position += speed; //Definiera marken
}
else
{
speed = originalSpeed;
}
}
public void Move(Vector2 rot, float shootPower)
{
position.X += rot.X * shootPower;
position.Y += rot.Y * shootPower;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, null, Color.White, 0, origin, scale, SpriteEffects.None, 0f);
}
}
游戏1类:
namespace CannonShoot
{
public class Game1 : Game
{
private GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
private Texture2D cannon;
private Texture2D cannonball;
private Texture2D man;
private SpriteFont font;
private Sprite spriteCannon;
private Sprite manSprite;
private CannonBallSprite cannonBallSprite;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
font = Content.Load<SpriteFont>("fontfile");
cannon = Content.Load<Texture2D>("cannon");
cannonball = Content.Load<Texture2D>("cannonball");
man = Content.Load<Texture2D>("man");
spriteCannon = new Sprite(cannon)
{
position = new Vector2(100, 400),
origin = new Vector2(cannon.Width / 2, cannon.Height / 2),
scale = 0.12f
};
cannonBallSprite = new CannonBallSprite(cannonball)
{
position = new Vector2(1150, 3750),
scale = 0.2f
};
manSprite = new Sprite(man)
{
position = new Vector2(700, 250),
origin = new Vector2(man.Width / 2, man.Height / 2),
scale = 0.4f
};
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if(!cannonBallSprite.shootCannon)
{
spriteCannon.Update();
}
//cannonBallSprite = (spriteCannon.position.X, spriteCannon.position.Y);
cannonBallSprite.Update(spriteCannon.rotation, manSprite);
manSprite.UpdateHitbox(cannonBallSprite);
if(cannonBallSprite.position.X >= 1000 || cannonBallSprite.position.Y >= 600) //respawn
{
cannonBallSprite.shootCannon = false;
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteCannon.Draw(spriteBatch);
manSprite.Draw(spriteBatch);
cannonBallSprite.Draw(spriteBatch);
spriteBatch.DrawString(font, "Power: " + cannonBallSprite.power, new Vector2(16, 16), Color.Black);
spriteBatch.DrawString(font, "Hits: " + manSprite.hit, new Vector2(16, 62), Color.Black);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
精灵类:
namespace CannonShoot
{
class Sprite
{
private Texture2D texture;
public Vector2 position;
public Vector2 origin;
public float scale;
public float rotationVelocity = 3f;
public float linearVelocity = 4f;
public float minRot = -1f;
public float maxRot = 0f;
public float rotation;
public float hit = 0;
public bool hasHit = false;
public Sprite(Texture2D texture)
{
this.texture = texture;
}
public void Update()
{
if (rotation <= maxRot && rotation >= minRot)
{
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
rotation -= MathHelper.ToRadians(rotationVelocity);
}
else if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
rotation += MathHelper.ToRadians(rotationVelocity);
}
if(rotation < minRot)
{
rotation = minRot;
}
if (rotation > maxRot)
{
rotation = maxRot;
}
}
}
public void UpdateHitbox(CannonBallSprite cbSprite) //hitbox och
{
if(cbSprite.position.X >= 700 && cbSprite.position.Y <= 350 && cbSprite.position.Y >= 150 && !hasHit)
{
hit++;
hasHit = true;
cbSprite.shootCannon = false;
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, null, Color.White, rotation, origin, scale, SpriteEffects.None, 0f);
}
}
}
解决方案
获取旋转物体的桶位置的代码:
angle = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
SpawnPosition = position + angle * TextureWidth * scale; // + .5f * TextureHeight * scale; if origin is at 0,0.
宽度和高度基于指向右侧的大炮纹理。
推荐阅读
- c# - Include 中使用的 Lambda 表达式在 Entity Framework Core 中无效
- elixir - 如何使用 Elixir/Nerves 获取当前设备 IP
- python - 将日期时间转换为序数
- javascript - hls.js hls.subtitleTracks 返回空数组
- image - 未能呈现 B64 编码的 Thymeleaf
- regex - 正则表达式 - 在字符的出现数 N 后开始匹配
- flutter - Flutter/Dart 使用 ListView.builder 为每个 x 项目构建一个不同的小部件
- sql - 根据前一行和相同的计算列计算列值
- java - 使用日期错误打印月份中的日期?
- c++ - 如何创建派生对象的向量?