第3个例子其实是一个简易的飞行射击游戏的模型了=。= 看一下效果
场景中存在的预设物体
看看背后是如何做的:
有3个脚本:CExample3,CAsteroid3,CBullet3
难点:控制序列帧动画,控制动作,销毁物体
先在场景中预设了3个石头,一个子弹,然后通过实例化这些预设物体来进行多帧相同物体的操作
下面的东西可能没什么深度-,- 我会在后面补偿的
首先看看CExample3:MonoBehaviour
public OTSprite bullet; //用来附带子弹的脚本的
public OTAnimatingSprite a1; //因为这个例子里面有三种不同的动画,所以有三种不同的Animate
public OTAnimatingSprite a2;
public OTAnimatingSprite a3;
OTAnimatingSprite gun; //枪的动画是
bool initialized = false; //
void Awake()
{ //重点,为什么这么做呢,将他们的active设为false不就动不了了吗?-,- 原因是为了复制clone
a1.gameObject.active = false;
a2.gameObject.active = false;
a3.gameObject.active = false;
// By de-acivating a gameobject is becomes invisible but can still
// be used them to instantiate copies.
}
int dp = 100;
//这个方法创造一个随机点在屏幕上的石头,
// 可以有一个新的尺寸
OTAnimatingSprite RandomBlock(Rect r, float min, float max, OTObject o)
{
int t = 1 + (int)Mathf.Floor(Random.value * 3); //3种石头 随机一种
float s = min + Random.value * (max - min); //最小值到 最大值的随机尺寸
GameObject g = null;
switch (t)
{
case 1: g = OT.CreateObject("asteroid1");
break;
case 2: g = OT.CreateObject("asteroid2");
break;
case 3: g = OT.CreateObject("asteroid3");
break;
}
if (g != null)
{
g.gameObject.active = true;
OTAnimatingSprite sprite = g.GetComponent<OTAnimatingSprite>();
if (o != null)
sprite.size = o.size * s;
else
sprite.size = sprite.size * s;
sprite.position = new Vector2(r.xMin + Random.value * r.width, r.yMin + Random.value * r.height); //设置随机点
sprite.rotation = Random.value * 360;
sprite.depth = dp++;
if (dp > 750) dp = 100; //为了防止爆深度,-,-深度只在-1000 到1000
return sprite;
}
return null; //奇怪,这个方法没有返回值为什么还要设类型
}
void CreateObjectPools() //创建缓冲池
{
OT.PreFabricate("asteroid1",20);
OT.PreFabricate("asteroid2",20);
OT.PreFabricate("asteroid3",20);
}
void Initialize()
{
gun = OT.ObjectByName("gun") as OTAnimatingSprite;
gun.onAnimationFinish = OnAnimationFinish; //枪的完成动画回调函数
// 重点 Create our object pool if we want.
OT.objectPooling = true;
if (OT.objectPooling)
CreateObjectPools();
initialized = true;
}
public void Explode(OTObject o, CBullet3 bullet) //被摧毁的效果
{
// Determine how many debree has to be be created
int blocks = 2 + (int)Mathf.Floor(Random.value * 2);
OT.DestroyObject(o);
// Create debree
for (int b = 0; b < blocks; b++)
{
// Shrink asteroid's rect to act as the random position container
// for the debree
Rect r = new Rect(
o.rect.x + o.rect.width / 4,
o.rect.y + o.rect.height / 4,
o.rect.width / 2,
o.rect.height / 2);
// Create a debree that is relatively smaller than the asteroid that was detroyed
OTAnimatingSprite a = RandomBlock(r, 0.6f, 0.75f, o);
// Add this debree to the bullet telling the bullet to ignore this debree
// in this update cycle - otherwise the bullet explosions could enter some
// recursive 'dead' loop creating LOTS of debree
bullet.AddDebree(a);
// Recusively explode 2 asteroids if they are big enough, to get a nice
// exploding debree effect.
if (b < 2 && a.size.x > 30)
Explode(a, bullet);
}
}
void Update () {
if (!OT.isValid) return;
if (!initialized)
{
Initialize();
return;
}
gun.RotateTowards(OT.view.mouseWorldPosition); //设置我们的枪的指向
bullet.rotation = gun.rotation; //子弹方向
if (Input.GetMouseButtonDown(0)) //发射子弹
{
//重点,创建新子弹
OTSprite nBullet = (Instantiate(bullet.gameObject) as GameObject).GetComponent<OTSprite>();
nBullet.position = gun.position + ((Vector2)gun.transform.up * (gun.size.y / 2));
gun.PlayOnce("shoot"); //枪播放射击的动画
}
//不能多于15个子弹
if (OT.objectCount <= 15)
RandomBlock(OT.view.worldRect, 0.6f, 1.2f, null);
}
//枪的动画回调函数
public void OnAnimationFinish(OTObject owner)
{
if (owner == gun)
{
gun.PlayLoop("idle"); //播放完射击的动画之后,枪回调回正常的动画
}
}
看看太空石头的类
public class CAsteroid3 : MonoBehaviour {
OTAnimatingSprite sprite; // 石头动画的sprite
Vector2 forwardVector = Vector2.zero; // 石头的运动方向
OTSpriteSheet sheet1;
void Start () {
sprite = GetComponent<OTAnimatingSprite>();
sheet1 = OT.ContainerByName("asteroid sheet 1") as OTSpriteSheet;
}
void Update () {
// If we did not capture this sprite's formward vector we capture it once
if (Vector2.Equals(forwardVector, Vector2.zero))
forwardVector = transform.up;
sprite.position += (forwardVector * 50 * Time.deltaTime);
sprite.rotation += 30 * Time.deltaTime;
if (sprite.size.x < 50 || sprite.size.y < 50)
{
sprite.Stop();
sprite.depth = 100;
sprite.frameIndex = 0;
sprite.rotation += 90 * Time.deltaTime;
if (sprite.size.x < 10 || sprite.size.y < 10)
{
sprite.spriteContainer = sheet1;
sprite.size = sprite.size * (1f - (0.99f * Time.deltaTime));
}
else
sprite.size = sprite.size * (1f - (0.95f * Time.deltaTime));
//如果石头小于2个像素则删除它
if (sprite.size.x < 2 || sprite.size.y < 2)
OT.DestroyObject(sprite);
}
//超出视野就将石头放回缓冲池
if (sprite.outOfView)
OT.DestroyObject(sprite);
}
}
// 子弹的类 //
public class CBullet3 : MonoBehaviour {
OTSprite sprite; // 子弹的sprite
CExample3 app; //主应用的类
int speed = 1000; // 子弹速率 speed 将会乘以一个子弹方向
float ignoreCollisions = 0; // 作为一个子弹的
List<OTAnimatingSprite> debree = // created debree list
new List<OTAnimatingSprite>();
void Start () {
app = Camera.main.GetComponent<CExample3>();
sprite = GetComponent<OTSprite>();
sprite.onCollision = OnCollision;
}
void Update () {
//检查是否是刚成立的,忽略刚成立0.1秒的物体
if (ignoreCollisions > 0)
{
ignoreCollisions -= Time.deltaTime; //忽略时间每秒减1
if (ignoreCollisions < 0) ignoreCollisions = 0;
}
else
{
//不再忽略已经成立了1秒的
debree.Clear();
}
// 更新子弹位置
sprite.position += (Vector2)sprite.transform.up * speed * Time.deltaTime;
//消除子弹如果失去视野
if (sprite.outOfView)
OT.DestroyObject(sprite);
}
public void AddDebree(OTAnimatingSprite debreeObject)
{
debree.Add(debreeObject);
}
//碰撞
public void OnCollision(OTObject owner)
{
//检查我们碰撞的是否在我们的忽略列表里面
if (debree.IndexOf(owner.collisionObject as OTAnimatingSprite) < 0)
{
// 忽略0.1秒之前发生的
ignoreCollisions = 0.1f;
// Lets Explode this asteroid
app.Explode(owner.collisionObject, this);
}
}
}