tModLoader 基础弹幕

基础弹幕


  1. 想要拥有自己的弹幕,只需要创建一个类然后继承ModProjectile其实就可以了

  2. 与基础物品一样,重写SetDefaults方法进行一些基础的设置

  3. 对于弹幕来说,SetDefaults的设置其实并不多,更多的内容是在AI还有Draw中的

字段 / 属性 说明
arrow true的话,弹幕会吃到箭的加成
friendly true的话就是友好的
false的话就是不友好的
penetrate 弹幕可穿透的数量
如果你设置为1然后又在Projectile.NewProjectile
设置弹幕穿透为无限 那么将免疫无敌帧
无限穿透是-1
ignoreWater false遇水减速
true不受影响
scale 缩放,会影响碰撞箱
timeLeft 弹幕存活时间
60是一秒
aiStyle 使用原版的AI的话可以设置这个
建议使用ProjAIStyleID设置原版AI
-1的话就是自己写AI了
tileCollide false穿墙
true不穿墙
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class TempSumeProjectile : ModProjectile
{
    public override void SetDefaults()
    {
        Projectile.friendly = true;//友好
        Projectile.aiStyle = 1;   //不建议使用神秘数字
        Projectile.timeLeft = 60;  //时间
        Projectile.penetrate = -1; //无限穿透
        Projectile.ignoreWater = true; //不受水
        Projectile.tileCollide = false;//穿墙
        Projectile.scale = 1.1f;
        base.SetDefaults();
    }
}

武器使用


​ 在物品那边,我没有给出一个属性,那就是shoot他可以设置物品射出的弹幕

以下是一个武器示例,发射出上面定义的弹幕,主要内容是最后一行。shootSpeed可以设置弹幕的速度

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TempSume : ModItem
{
    public override void SetDefaults()
    {
        Item.damage = 12;
        Item.width = 40;
        Item.height = 40;
        Item.useTurn = true;
        Item.useTime = 20;
        Item.autoReuse = true;
        Item.knockBack = 6;
        Item.useAnimation = 20;
        Item.rare = ItemRarityID.Blue;
        Item.value = Item.buyPrice(silver: 1);
        Item.UseSound = SoundID.Item1;
        Item.useStyle = ItemUseStyleID.Shoot;
        Item.DamageType = DamageClass.Summon;

        Item.shootSpeed = 10f;
        Item.shoot = ModContent.ProjectileType<TempSumeProjectile>();
    }
}

​ 这边出现了ModContent.ProjectileType<MyProjectile>(),单说ProjectileType没有太大的意义,我们从名字上来看 ModContent 模组内容。

​ 这是一个类,提供了很多静态方法,用来获取模组的内容然后使用到实际中。

​ 这边的ProjectileType就是获取模组的弹幕,返回的是该弹幕的唯一ID

现在回到游戏,使用你的武器,你应该就能看到武器发射了你自己的弹幕了

弹幕AI


​ 弹幕的AI逻辑需要重写AI方法,我们继续使用上面定义的弹幕,注意我将aiStyle设置为了-1,我们要自定义AI了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class TempSumeProjectile : ModProjectile
{
    public override void SetDefaults()
    {
        Projectile.friendly = true;//友好
        Projectile.aiStyle = -1;   //不建议使用神秘数字
        Projectile.timeLeft = 60;  //时间
        Projectile.penetrate = -1; //无限穿透
        Projectile.ignoreWater = true; //不受水
        Projectile.tileCollide = false;//穿墙
        Projectile.scale = 1.1f;
        base.SetDefaults();
    }
    
    public override void AI()
	{
    }

}
  • 该方法每秒会执行60次,如果要进行额外更新,可以在SetDefaults方法添加extraUpdates的设置

​ 开始之前,先了解几个基本的Vector2方法,大多数来源于Terraria对其的扩展

方法 说明
ToRotation() 获取向量的方向角
建议这样使用Projectile.velocity.ToRotation()
先获取弹幕速度,然后获取角度,来源于扩展方法
SafeNormalize() 安全的归一化向量,传入一个失败的默认值
用来计算速度时非常有用,来源于扩展方法

​ 还有一些关于Main我们需要知道的

属性 / 字段 / 方法 说明
player 全部的玩家,通常用来获取弹幕的主人
MouseWorld 玩家鼠标在世界中的位置
screenPosition 玩家屏幕在世界中的位置
myPlayer 该玩家在player数组中的索引,255说明是服务器

​ 想让弹幕朝着既定的方向运行,我们需要使用 目标位置 - 弹幕位置

开始


​ 现在,我们设计一个弹幕,要求弹幕追随玩家鼠标

  1. 如果你不想让弹幕始终向你的贴图一样的方向,请使用Projectile.rotation = Projectile.velocity.ToRotation();让弹幕的旋转角度等于速度的方向角

  2. 要让弹幕追随鼠标,我们需要使用目标位置 - 弹幕位置

    Main.MouseWorld - Projectile.Center

    需要注意的是,这样做向量有方向,也有速度,而且速度你是没法确定的,因为这取决于他们之间的距离,这时候我们就需要归一化了,让向量的速度为1,方向仍然存在,需要设置他的速度就将归一化的向量乘以速度就行了

1
2
Vector2 velocity = 
    (Main.MouseWorld - Projectile.Center).SafeNormalize(Vector2.Zero) * 12f;
  1. 这样我们就得到了一个速度12的,追随鼠标方向的向量
  2. 需要注意的是,我们将他写了AI中,也就是说,该向量的方向每秒更新60次,但是速度是不变的,如果你只希望他在第一次发射时想着鼠标,那你大可不自定义AI了,因为基础武器的射弹默认就是这样的。
  3. 让我们设置弹幕的速度等于我们计算的向量 注意,写在AI方法中
1
2
3
4
Vector2 velocity = (Main.MouseWorld - Projectile.Center).SafeNormalize(Vector2.Zero) * 12f;
//弹幕的旋转等于弹幕速度的旋转角
Projectile.rotation = Projectile.velocity.ToRotation();
Projectile.velocity = velocity;
使用 Hugo 构建
主题 StackJimmy 设计