我怎样才能扩大子弹的图案形状?

我想制作一系列形状像正方形,三角形等扩大的子弹模式。在下面的video中可以看到我后来的一个例子,当收集星星时,子弹爆炸成一个形状扩大明星:

最简单的方法是首先devise形状,然后计算粒子的运动。 在这个答案中,我将构造一个正方形,但这适用于任何形状。

开始devise你的形状作为一些原点周围的相对位置。

广场

现在你需要计算形状的展开方式。 要做到这一点,我们简单地计算从origin到每个point的vector,从我们point的位置减去origin位置,然后归一化vector。 vector = normalize(point.x - origin.x, point.y - origin.y)

向量

现在我们可以通过使用这个向量来计算任意时间点的位置。 你可以通过做point.position += point.vector * point.velocity来计算点的下一个位置。 使用我们以前的观点的伪代码示例:

 // When you start your program you set these values. point.position = (-3, 3); // Start position. Can be anything. point.vector = normalize(-3, 3); // Normalized vector. point.velocity = 3; // Can be anything. // You do this calculation every frame. point.position += point.vector * point.velocity; // point.vector * point.velocity = (-3, 3) // point.position is now (-6, 6) since (-3, 3) + (-3, 3) = (-6, 6) 

这样做会将每个点向外移动3个单位。


笔记

  • 你可以在这里阅读一些简单的vectormath。
  • 只要所有位置都相对于某个原点,位置就可以是任何东西。
  • 所有的点的速度应该是相同的,以确保均匀的运动,但有不同的速度可能会给你有趣的结果。
  • 如果运动似乎closures,你应该检查原点。 如果它不在形状的正中间,形状可能会以奇怪的方式展开。

正如Charanor指出的那样,您可以使用一系列点来定义您的形状,然后随着时间的推移更新它们的位置。 以下是如何使用点来实现星形或自定义形状的工作示例:

 package com.mygdx.gtest; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; public class Test extends ApplicationAdapter{ public SpriteBatch sb; private StarShape ss, ssBig; @Override public void create() { sb = new SpriteBatch(); Pixmap pmap = new Pixmap(2, 2,Format.RGBA8888); pmap.setColor(Color.WHITE); pmap.fill(); ss = new StarShape(50,50,new Texture(pmap), 10, true); ssBig = new StarShape(250,250,new Texture(pmap), 50, false); pmap.dispose(); } @Override public void render() { super.render(); Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); ss.update(Gdx.graphics.getDeltaTime()); ssBig.update(Gdx.graphics.getDeltaTime()); sb.begin(); ss.draw(sb); ssBig.draw(sb); sb.end(); } @Override public void dispose() { super.dispose(); } private class StarShape{ public float progress = 1f; public Texture bulletTex; public Array<Vector2> points = new Array<Vector2>(); public Vector2 center; public StarShape(float x, float y, Texture tex, float initialSize, boolean mathWay){ center = new Vector2(x,y); bulletTex = tex; if(mathWay){ // define star shape with maths float alpha = (float)(2 * Math.PI) / 10; float radius = initialSize; for(int i = 11; i != 0; i--){ float r = radius*(i % 2 + 1)/2; float omega = alpha * i; points.add( new Vector2( (float)(r * Math.sin(omega)), (float)(r * Math.cos(omega)) ) ); } }else{ // or define star shape manually (better for non geometric shapes etc //define circle points.add(new Vector2(-3f,0f)); points.add(new Vector2(-2.8f,1f)); points.add(new Vector2(-2.2f,2.2f)); points.add(new Vector2(-1f,2.8f)); points.add(new Vector2(0f,3f)); points.add(new Vector2(1f,2.8f)); points.add(new Vector2(2.2f,2.2f)); points.add(new Vector2(2.8f,1f)); points.add(new Vector2(3f,0f)); points.add(new Vector2(2.8f,-1f)); points.add(new Vector2(2.2f,-2.2f)); points.add(new Vector2(1f,-2.8f)); points.add(new Vector2(0f,-3f)); points.add(new Vector2(-1f,-2.8f)); points.add(new Vector2(-2.2f,-2.2f)); points.add(new Vector2(-2.8f,-1f)); // mouth points.add(new Vector2(-2,-1)); points.add(new Vector2(-1,-1)); points.add(new Vector2(0,-1)); points.add(new Vector2(1,-1)); points.add(new Vector2(2,-1)); points.add(new Vector2(-1.5f,-1.1f)); points.add(new Vector2(-1,-2)); points.add(new Vector2(0,-2.2f)); points.add(new Vector2(1,-2)); points.add(new Vector2(1.5f,-1.1f)); points.add(new Vector2(-1.5f,1.5f)); points.add(new Vector2(1.5f,1.5f)); } } public void update(float deltaTime){ this.progress+= deltaTime; } public void draw(SpriteBatch sb){ Vector2 temp = new Vector2(0,0); for(Vector2 point: points){ temp.x = (point.x); temp.y = (point.y); temp.scl(progress); sb.draw(bulletTex,temp.x + center.x,temp.y +center.y); } } } } 

所以这里有一个名为BulletML的项目,它是创建复杂粒子/子弹模式的标记语言。 你几乎肯定需要将代码移植到你自己的语言中,但是它可以做一些非常了不起的事情。

例如, 这个老板是在BulletML for Unity3D(经过大量修改)的扩展中完成的(该模式的作者上传了这个video,Misery是疯狂的,也是不错的)。 这是这个敌人最困难的变化,它展示了BulletML能够做的很好的事情(并且像Wallmaster一样查看一些Misery的其他老板)。

或者我可以看到这个例子,这是我在扩展“最后的联邦”时编写的一个模式:

子弹模式示例

在那里制造那些戒指的绿色子弹是由高速旋转的父母子弹产生的,但是自己却没有动作。 他们造成巨大的伤害,让玩家保持更远的距离,限制他们降低伤害的武器,并允许移动防御者骚扰玩家(如果中间的不动结构被破坏,玩家将获胜)。

扩张的其他模式之一实际上是由苦难写的,虽然我做了一些修改。 起初它是一种低伤害,穿透射击,飞出远程,然后爆炸成一个巨大的烟花汇演,造成大量的损失。 它的最大射程比玩家能够达到的高得多,基本上迫使他们在短距离内进行,这对于NPC部队是有利的。

BulletML通常很容易处理,而且可以做很棒的事情。 项目符号可以改变方向,改变速度,产生其他模式,提前死亡,在一个循环中重复收集命令,使用延迟,改变子弹精灵图像,跟随他们的父母(或不)…和任何它不支持你写入它。

我肯定会推荐它,如果你正在做一个严肃的拍摄他们的游戏。 你仍然需要计算坐标math来获得所需的形状,正如Charanor在他的回答中所谈到的那样,但是像BulletML这样的子弹引擎会给你更多的灵活性,所以你会花更多的时间来devise新的模式,而不是搞清楚如何编码他们。