《Genesis-3D开源游戏引擎完整实例教程-2D射击游戏篇08:弹幕系统》本系列完结
8.弹幕系统
弹幕系统概述:
弹幕系统的设计体现了射击游戏的基本要素,玩家要在敌人放出的大量子弹(弹幕)的细小空隙间闪避,能在玩家闪躲弹幕的时候给玩家带来快感,接近满屏的子弹,增加了对玩家的视觉冲击力。
弹幕系统原理:
每一个敌机都持有一个弹幕实例,每个弹幕实例中包含多个子弹实例,通过配置弹幕的属性,使每个子弹实例在轨迹管理器的作用下,形成一种有规律性的直线运动,在视觉上给玩家展现出弹幕的效果。如图8-1所示。

图8-1
实现方法:
步骤1:
子弹类,定义子弹的属性和借口。
01 |
public class Bullet |
02 |
{ |
03 |
//从模板创建子弹Actor |
04 |
public void CreateActor () |
05 |
{ |
06 |
_obj = ActorManager.CreateFromTemplate( @"asset:bullet01.template" , false ); |
07 |
08 |
} |
09 |
10 |
//激活,显示子弹 |
11 |
public void ActiveObj (Vector2 startPos) |
12 |
{ |
13 |
_obj.Active(); |
14 |
if (_obj.GetChildCount()>0) |
15 |
{ |
16 |
_obj.GetChild(0).Active(); |
17 |
} |
18 |
19 |
_obj.WorldPosition = new Vector3 (startPos.X,startPos.Y,2.0f); |
20 |
} |
21 |
22 |
//隐藏子弹 |
23 |
public void DeactiveObj () |
24 |
{ |
25 |
_obj.Deactive(); |
26 |
if (_obj.GetChildCount()>0) |
27 |
{ |
28 |
_obj.GetChild(0).Deactive(); |
29 |
} |
30 |
} |
31 |
private Actor _obj = new Actor(); |
32 |
private UInt32 _id; |
33 |
private UInt32 _target_id; |
34 |
private Vector2 _startPos; |
35 |
private bool _isShooted = false ; |
36 |
} |
步骤2:
配置弹幕发射子弹的属性。
01 |
public class Barrage |
02 |
{ |
03 |
//发射子弹 |
04 |
public void ShootBullet ( float elapsedTime, Vector3 pos) |
05 |
{ |
06 |
timer += elapsedTime; |
07 |
if (timer >= _shoot_interval && _needshoot_id <= (Bullets.Count - 1)) |
08 |
{ |
09 |
Vector2 posV2 = new Vector2(pos.X,pos.Y); |
10 |
Bullets[_needshoot_id].ActiveObj(posV2); |
11 |
Bullets[_needshoot_id].SetShooted( true ); |
12 |
_needshoot_id ++; |
13 |
timer = 0.0f; |
14 |
} |
15 |
private UInt32 _id; |
16 |
private UInt32 _obj_id; |
17 |
private float _start_speed; |
18 |
private float _accel_speed; |
19 |
private float _shoot_interval; |
20 |
private float _shoot_direction; |
21 |
private float _direction_offset; |
22 |
private List< Bullet> Bullets; |
23 |
private TrajectoryType _tt ; |
24 |
private float timer = 0.0f; |
25 |
private int _needshoot_id = 0; |
26 |
private Actor _owner; |
27 |
} |
28 |
} |
步骤3:
设计弹幕管理器,管理每一个弹幕实例的发射。
01 |
public class BarrageMgr |
02 |
{ |
03 |
//请求子弹 |
04 |
public bool AskForBullets ( int count, List< Bullet> bullets, Actor owner) |
05 |
{ |
06 |
if (ReloadBullet.Count == 0) |
07 |
{ |
08 |
return false ; |
09 |
} |
10 |
11 |
if (count >= ReloadBullet.Count) |
12 |
{ |
13 |
count = ReloadBullet.Count; |
14 |
} |
15 |
16 |
for ( int i = 0; i < count; i++) |
17 |
{ |
18 |
ReloadBullet[i].DeactiveObj(); |
19 |
Vector2 pos = new Vector2(owner.WorldPosition.X,owner.WorldPosition.Y); |
20 |
21 |
ReloadBullet[i].setPos(pos); |
22 |
bullets.Add(ReloadBullet[i]); |
23 |
24 |
} |
25 |
ReloadBullet.RemoveRange(0,count); |
26 |
return true ; |
27 |
} |
28 |
//处理轨迹 |
29 |
public void DealTrajectory (Barrage barrage, float elapsedTime) |
30 |
{ |
31 |
_trajectoryMgr.MoveBarrage(barrage,elapsedTime); |
32 |
} |
33 |
//更新弹幕位置 |
34 |
public void Tick( float elapsedTime) |
35 |
{ |
36 |
foreach (KeyValuePair< uint ,Barrage> pair in _barrageDict) |
37 |
{ |
38 |
39 |
Barrage barrage = pair.Value; |
40 |
|
41 |
DealTrajectory(barrage,elapsedTime); |
42 |
barrage.DestroyBullet(); |
43 |
if (!barrage.IsOwnerActive() && barrage.IsAllBulletsDeactive()) |
44 |
{ |
45 |
barrage.Reload(); |
46 |
} |
47 |
} |
48 |
Debug.Dbgout( _barrageDict.Count.ToString() ); |
49 |
} |
50 |
51 |
} |
步骤4:
设计轨迹管理器,使子弹形成一种有规律性的直线运动。
01 |
public class Trajectory |
02 |
{ |
03 |
//直线轨迹算法 |
04 |
public static Vector2 GoStraight(Vector2 start_pos, float direction, |
05 |
float start_speed, float accel_speed, float use_time, out Vector2 pos) |
06 |
{ |
07 |
float angle = direction * ( float )Math.PI / 180.0f; |
08 |
float seconds = ( float )use_time; |
09 |
float move_length = start_speed * seconds + accel_speed * seconds * seconds / 2.0f; |
10 |
pos.X = move_length * ( float )Math.Cos(angle) + start_pos.X; |
11 |
pos.Y = move_length * ( float )Math.Sin(angle) + start_pos.Y; |
12 |
return pos; |
13 |
} |
14 |
|
15 |
//这里的跟踪算法主要适用于匀速圆周运动类型的要跟踪,速率不变,一定的旋转角度 |
16 |
//追踪轨迹算法 |
17 |
public static Vector2 Tracking(Vector2 start_pos, ref float direction, Vector2 dest_pos, |
18 |
float start_speed, float accel_speed, float track_degree, float use_time) |
19 |
{ |
20 |
Vector2 newpos = new Vector2(0, 0); |
21 |
|
22 |
if (direction < 0) |
23 |
{ |
24 |
direction += 360; |
25 |
} |
26 |
else |
27 |
{ |
28 |
direction = direction % 360; |
29 |
} |
30 |
|
31 |
//判断目标与飞行的夹角 |
32 |
float degree =( float ) (Math.Atan2(dest_pos.Y - start_pos.Y, |
33 |
dest_pos.X - start_pos.X) * 180 / Math.PI); |
34 |
if (degree < 0) |
35 |
{ |
36 |
degree += 360; |
37 |
} |
38 |
|
39 |
//最小目标夹角 |
40 |
float dest_degree = ( float )Math.Abs(degree - direction) % 360; |
41 |
if (dest_degree > 180) |
42 |
{ |
43 |
dest_degree = 360 - dest_degree; |
44 |
} |
45 |
if (dest_degree < 0.000001) |
46 |
{ |
47 |
GoStraight(start_pos, direction, start_speed, accel_speed, use_time, out newpos); |
48 |
return newpos; |
49 |
} |
50 |
|
51 |
//计算最终旋转的夹角 |
52 |
float use_seconds = use_time / 1000.0f; |
53 |
float rotate_degree = track_degree * use_seconds; |
54 |
if (rotate_degree > dest_degree) |
55 |
{ |
56 |
rotate_degree = dest_degree; |
57 |
} |
58 |
double inner_degree = degree - direction; |
59 |
if (inner_degree > 180) |
60 |
{ |
61 |
direction -= rotate_degree; |
62 |
} |
63 |
else if (inner_degree <= 180 && inner_degree >= 0) |
64 |
{ |
65 |
direction += rotate_degree; |
66 |
} |
67 |
else if (inner_degree < -180) |
68 |
{ |
69 |
direction += rotate_degree; |
70 |
} |
71 |
else if (inner_degree >= -180 && inner_degree <= 0) |
72 |
{ |
73 |
direction -= rotate_degree; |
74 |
} |
75 |
|
76 |
GoStraight(start_pos, direction, start_speed, accel_speed, use_time, out newpos); |
77 |
return newpos; |
78 |
} |
79 |
80 |
} |
引擎官方网站:http://www.genesis-3d.com.cn/
官方论坛:http://bbs.9tech.cn/genesis-3d/
官方千人大群:59113309 135439306
YY频道-游戏开发大讲堂(完全免费,定期开课):51735288
Genesis-3D开源游戏引擎:游戏起源,皆因有我!!!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步