├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── styles.xml
│ │ │ ├── drawable
│ │ │ │ ├── background.jpg
│ │ │ │ ├── rain_texture.png
│ │ │ │ └── particle_texture.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ └── raw
│ │ │ │ ├── rain.plist
│ │ │ │ ├── snow.plist
│ │ │ │ └── test.plist
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── yang
│ │ │ └── firework
│ │ │ └── sample
│ │ │ └── MainActivity.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── yang
│ │ │ └── firework
│ │ │ └── sample
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── yang
│ │ └── firework
│ │ └── sample
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── firework
├── .gitignore
├── src
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ └── attrs.xml
│ │ │ └── raw
│ │ │ │ ├── simpe_fragment_shader.glsl
│ │ │ │ ├── simple_vertex_shader.glsl
│ │ │ │ ├── particle_frag.glsl
│ │ │ │ └── particle_vert.glsl
│ │ └── java
│ │ │ └── com
│ │ │ └── yang
│ │ │ └── firework
│ │ │ ├── ModeB.java
│ │ │ ├── ModeA.java
│ │ │ ├── BlendFunc.java
│ │ │ ├── Color4F.java
│ │ │ ├── Particle.java
│ │ │ ├── Constants.java
│ │ │ ├── Vec2.java
│ │ │ ├── utils
│ │ │ ├── RawResourceReader.java
│ │ │ ├── TextureHelper.java
│ │ │ └── ESShader.java
│ │ │ ├── TextureLayer.java
│ │ │ ├── FireworkView.java
│ │ │ ├── ParticleLayer.java
│ │ │ └── ParticleSystem.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── yang
│ │ │ └── firework
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── yang
│ │ └── firework
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── art
└── demo.gif
├── .idea
├── copyright
│ └── profiles_settings.xml
├── modules.xml
├── runConfigurations.xml
├── gradle.xml
├── compiler.xml
└── misc.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── README.md
├── .gitignore
├── gradle.properties
├── gradlew.bat
├── gradlew
└── LICENSE
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/firework/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':firework'
2 |
--------------------------------------------------------------------------------
/art/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/art/demo.gif
--------------------------------------------------------------------------------
/firework/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | firework
3 |
4 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/firework/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | firework
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/app/src/main/res/drawable/background.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rain_texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/app/src/main/res/drawable/rain_texture.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/particle_texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/app/src/main/res/drawable/particle_texture.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqf19930712/firework/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # firework
2 |
3 | 
4 |
5 | opengl es实现粒子效果,可加载particle designer导出的plist文件
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.iml
3 | .gradle
4 | /local.properties
5 | /.idea/workspace.xml
6 | /.idea/libraries
7 | .DS_Store
8 | /build
9 | /captures
10 | .externalNativeBuild
11 |
--------------------------------------------------------------------------------
/firework/src/main/res/raw/simpe_fragment_shader.glsl:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | uniform sampler2D u_texture;
4 | varying vec2 v_texCoord;
5 |
6 | void main() {
7 |
8 | gl_FragColor = texture2D(u_texture,v_texCoord);
9 |
10 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/ModeB.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | /**
4 | * Created by qinfeng on 16/8/4.
5 | */
6 |
7 | public class ModeB {
8 | float angle;
9 | float degreesPerSecond;
10 | float radius;
11 | float deltaRadius;
12 | }
13 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/ModeA.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | /**
4 | * Created by qinfeng on 16/8/4.
5 | */
6 |
7 | public class ModeA {
8 | Vec2 dir = new Vec2(0f,0f);
9 | float radialAccel;
10 | float tangentialAccel;
11 | }
12 |
--------------------------------------------------------------------------------
/firework/src/main/res/raw/simple_vertex_shader.glsl:
--------------------------------------------------------------------------------
1 |
2 | precision mediump float;
3 |
4 | attribute vec2 a_position;
5 | attribute vec2 a_texCoord;
6 |
7 | varying vec2 v_texCoord;
8 | void main() {
9 | gl_Position = vec4(a_position,0.0,1.0);
10 | v_texCoord = a_texCoord;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/firework/src/main/res/raw/particle_frag.glsl:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | uniform sampler2D u_texture;
4 |
5 | varying vec4 v_fragmentColor;
6 | varying vec2 v_texCoord;
7 |
8 | void main()
9 | {
10 |
11 | gl_FragColor = v_fragmentColor * texture2D(u_texture, v_texCoord) ;
12 | }
13 |
14 |
15 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/BlendFunc.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | /**
4 | * Created by qinfeng on 16/8/4.
5 | */
6 |
7 | class BlendFunc {
8 | int src;
9 | int dst;
10 | public BlendFunc(int src, int dst) {
11 | this.src = src;
12 | this.dst = dst;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/firework/src/main/res/raw/particle_vert.glsl:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | uniform mat4 u_matrix;
4 |
5 | attribute vec2 a_position;
6 | attribute vec4 a_color;
7 | attribute vec2 a_texCoord;
8 |
9 |
10 | varying vec4 v_fragmentColor;
11 | varying vec2 v_texCoord;
12 |
13 | void main()
14 | {
15 | gl_Position = u_matrix * vec4(a_position,0.0,1.0);
16 | v_fragmentColor = a_color;
17 | v_texCoord = a_texCoord;
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/Color4F.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | /**
4 | * Created by qinfeng on 16/8/4.
5 | */
6 | public class Color4F {
7 | float r;
8 | float g;
9 | float b;
10 | float a;
11 |
12 | public Color4F() {
13 | }
14 |
15 | public Color4F(float r, float g, float b, float a) {
16 | this.r = r;
17 | this.g = g;
18 | this.b = b;
19 | this.a = a;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/firework/src/test/java/com/yang/firework/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/test/java/com/yang/firework/sample/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework.sample;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/Particle.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | /**
4 | * Created by qinfeng on 16/8/4.
5 | */
6 |
7 | public class Particle {
8 | Vec2 pos = new Vec2(0f,0f);;
9 | Vec2 startPos = new Vec2(0f,0f);
10 | Color4F color = new Color4F(0f,0f,0f,1f);
11 | Color4F deltaColor = new Color4F(0f,0f,0f,1f);
12 | float size;
13 | float deltaSize;
14 | float rotation;
15 | float deltaRotation;
16 | float timeToLive;
17 | int atlasIndex;
18 | // Mode A: gravity, direction, radial accel, tangential accel.
19 | ModeA modeA = new ModeA();
20 |
21 | // Mode B: radius mode.
22 | ModeB modeB = new ModeB();
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Applications/cocos2dx/V3.5/adt-bundle/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/firework/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Applications/cocos2dx/V3.5/adt-bundle/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/firework/src/androidTest/java/com/yang/firework/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.yang.firework.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/yang/firework/sample/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework.sample;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.yang.firework.sample", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/firework/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 15
9 | targetSdkVersion 24
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | compile fileTree(dir: 'libs', include: ['*.jar'])
26 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
27 | exclude group: 'com.android.support', module: 'support-annotations'
28 | })
29 | testCompile 'junit:junit:4.12'
30 | compile 'com.googlecode.plist:dd-plist:1.16'
31 | }
32 |
--------------------------------------------------------------------------------
/firework/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.1"
6 | defaultConfig {
7 | applicationId "com.yang.firework.sample"
8 | minSdkVersion 15
9 | targetSdkVersion 24
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | compile 'com.android.support:appcompat-v7:24.2.1'
28 | testCompile 'junit:junit:4.12'
29 | compile project(':firework')
30 | }
31 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/Constants.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | /**
4 | * Created by qinfeng on 16/8/4.
5 | */
6 |
7 | public class Constants {
8 | /* BlendingFactorDest */
9 | public static final int GL_ZERO = 0;
10 | public static final int GL_ONE = 1;
11 | public static final int GL_SRC_COLOR = 0x0300;
12 | public static final int GL_ONE_MINUS_SRC_COLOR = 0x0301;
13 | public static final int GL_SRC_ALPHA = 0x0302;
14 | public static final int GL_ONE_MINUS_SRC_ALPHA = 0x0303;
15 | public static final int GL_DST_ALPHA = 0x0304;
16 | public static final int GL_ONE_MINUS_DST_ALPHA = 0x0305;
17 |
18 | /* BlendingFactorSrc */
19 | /* GL_ZERO */
20 | /* GL_ONE */
21 | public static final int GL_DST_COLOR = 0x0306;
22 | public static final int GL_ONE_MINUS_DST_COLOR = 0x0307;
23 | public static final int GL_SRC_ALPHA_SATURATE = 0x0308;
24 | /* GL_SRC_ALPHA */
25 | /* GL_ONE_MINUS_SRC_ALPHA */
26 | /* GL_DST_ALPHA */
27 | /* GL_ONE_MINUS_DST_ALPHA */
28 |
29 |
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/Vec2.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | /**
4 | * Created by qinfeng on 16/8/4.
5 | */
6 |
7 | public class Vec2 {
8 | public float x;
9 | public float y;
10 |
11 | public Vec2(float x, float y) {
12 | this.x = x;
13 | this.y = y;
14 | }
15 |
16 | public Vec2(Vec2 vec2) {
17 | this.x = vec2.x;
18 | this.y = vec2.y;
19 | }
20 |
21 |
22 | public Vec2 add(Vec2 vec2) {
23 | return new Vec2(x + vec2.x, y + vec2.y);
24 | }
25 |
26 | public float getAngle(){
27 | return (float) Math.atan2(y,x);
28 | }
29 |
30 | public Vec2 subtract(Vec2 vec2) {
31 | return new Vec2(x - vec2.x, y - vec2.y);
32 | }
33 |
34 | public float length() {
35 | return (float) Math.sqrt(x * x + y * y);
36 | }
37 |
38 |
39 | public Vec2 scale(float f) {
40 | return new Vec2(
41 | x * f,
42 | y * f);
43 | }
44 |
45 | public Vec2 getNormalized() {
46 | return scale(1f / length());
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/utils/RawResourceReader.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework.utils;
2 |
3 | import android.content.Context;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.InputStreamReader;
9 |
10 | public class RawResourceReader
11 | {
12 | public static String readTextFileFromRawResource(final Context context,
13 | final int resourceId)
14 | {
15 | final InputStream inputStream = context.getResources().openRawResource(
16 | resourceId);
17 | final InputStreamReader inputStreamReader = new InputStreamReader(
18 | inputStream);
19 | final BufferedReader bufferedReader = new BufferedReader(
20 | inputStreamReader);
21 |
22 | String nextLine;
23 | final StringBuilder body = new StringBuilder();
24 |
25 | try
26 | {
27 | while ((nextLine = bufferedReader.readLine()) != null)
28 | {
29 | body.append(nextLine);
30 | body.append('\n');
31 | }
32 | }
33 | catch (IOException e)
34 | {
35 | return null;
36 | }
37 |
38 | return body.toString();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
15 |
16 |
17 |
18 |
23 |
24 |
30 |
36 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yang/firework/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework.sample;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.View;
6 | import android.widget.Button;
7 |
8 | import com.yang.firework.FireworkView;
9 | import com.yang.firework.ParticleLayer;
10 |
11 | public class MainActivity extends AppCompatActivity {
12 |
13 | @Override
14 | protected void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_main);
17 | final FireworkView fireworkView = (FireworkView) findViewById(R.id.firework);
18 | Button snowBtn = (Button) findViewById(R.id.snow);
19 | snowBtn.setOnClickListener(new View.OnClickListener() {
20 | @Override
21 | public void onClick(View v) {
22 | fireworkView.queueEvent(new Runnable() {
23 | @Override
24 | public void run() {
25 | fireworkView.setParticleSystem(new ParticleLayer(MainActivity.this,R.raw.snow,R.drawable.particle_texture));
26 | }
27 | });
28 |
29 | }
30 | });
31 | Button rainingBtn = (Button) findViewById(R.id.raining);
32 | rainingBtn.setOnClickListener(new View.OnClickListener() {
33 | @Override
34 | public void onClick(View v) {
35 | fireworkView.queueEvent(new Runnable() {
36 | @Override
37 | public void run() {
38 | fireworkView.setParticleSystem(new ParticleLayer(MainActivity.this,R.raw.rain,R.drawable.rain_texture));
39 | }
40 | });
41 |
42 | }
43 | });
44 | Button testBtn = (Button) findViewById(R.id.test);
45 | testBtn.setOnClickListener(new View.OnClickListener() {
46 | @Override
47 | public void onClick(View v) {
48 | fireworkView.queueEvent(new Runnable() {
49 | @Override
50 | public void run() {
51 | fireworkView.setParticleSystem(new ParticleLayer(MainActivity.this,R.raw.test,R.drawable.particle_texture));
52 | }
53 | });
54 |
55 | }
56 | });
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/utils/TextureHelper.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework.utils;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 | import android.opengl.GLES20;
7 | import android.opengl.GLUtils;
8 |
9 | public class TextureHelper
10 | {
11 |
12 | private static boolean isFirst =true;
13 |
14 | public static int loadTexture(final Context context, final int resourceId)
15 | {
16 | final int[] textureHandle = new int[1];
17 |
18 | GLES20.glGenTextures(1, textureHandle, 0);
19 |
20 | if (textureHandle[0] != 0)
21 | {
22 | final BitmapFactory.Options options = new BitmapFactory.Options();
23 |
24 | options.inScaled = false; // No pre-scaling
25 |
26 | // Read in the resource
27 | final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
28 |
29 | // Bind to the texture in OpenGL
30 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
31 |
32 | // Set filtering
33 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
34 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
35 |
36 | // Load the bitmap into the bound texture.
37 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
38 |
39 | // Recycle the bitmap, since its data has been loaded into OpenGL.
40 | bitmap.recycle();
41 | }
42 |
43 | if (textureHandle[0] == 0)
44 | {
45 | throw new RuntimeException("Error loading texture.");
46 | }
47 |
48 | return textureHandle[0];
49 | }
50 |
51 | public static int loadTexture(Bitmap bitmap)
52 | {
53 | final int[] textureHandle = new int[1];
54 |
55 | GLES20.glGenTextures(1, textureHandle, 0);
56 | if (textureHandle[0] != 0)
57 | {
58 | // Bind to the texture in OpenGL
59 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
60 | // Set filtering
61 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
62 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
63 | // Load the bitmap into the bound texture.
64 |
65 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
66 |
67 |
68 |
69 | }
70 |
71 | if (textureHandle[0] == 0)
72 | {
73 | throw new RuntimeException("Error loading texture.");
74 |
75 |
76 | }
77 |
78 | return textureHandle[0];
79 | }
80 |
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 1.8
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/TextureLayer.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.opengl.GLES20;
6 |
7 | import com.yang.firework.utils.ESShader;
8 | import com.yang.firework.utils.RawResourceReader;
9 | import com.yang.firework.utils.TextureHelper;
10 |
11 | import java.nio.ByteBuffer;
12 | import java.nio.ByteOrder;
13 | import java.nio.FloatBuffer;
14 | import java.nio.ShortBuffer;
15 |
16 | /**
17 | * Created by qinfeng on 16/8/2.
18 | */
19 |
20 | public class TextureLayer {
21 | private final float[] vertexsData =
22 | {
23 | -1f, 1f,// Position 0
24 | 0.0f, 0.0f, // TexCoord 0
25 | -1f, -1f, // Position 1
26 | 0.0f, 1.0f, // TexCoord 1
27 | 1f, 1f, // Position 3
28 | 1.0f, 0.0f , // TexCoord 3
29 | 1f, -1f, // Position 2
30 | 1.0f, 1.0f // TexCoord 2
31 |
32 | };
33 |
34 | private final short[] indicesData =
35 | {
36 | 0, 1, 2, 3, 2, 1
37 | };
38 | private final FloatBuffer vertexBuffer;
39 | private final ShortBuffer indiceBuffer;
40 | private final int mProgrammerHandle;
41 | private final int textureUniformHandle;
42 | private final int mPositionHandle;
43 | private final int mTexCoordHandle;
44 | private int mTextureHandle;
45 |
46 | public TextureLayer(Context context, Bitmap bitmap) {
47 | vertexBuffer = ByteBuffer.allocateDirect(vertexsData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
48 | vertexBuffer.put(vertexsData);
49 | vertexBuffer.position(0);
50 |
51 | indiceBuffer = ByteBuffer.allocateDirect ( indicesData.length * 2 )
52 | .order ( ByteOrder.nativeOrder() ).asShortBuffer();
53 | indiceBuffer.put (indicesData).position ( 0 );
54 |
55 |
56 | mProgrammerHandle = ESShader.loadProgram(RawResourceReader.readTextFileFromRawResource(context, R.raw.simple_vertex_shader), RawResourceReader.readTextFileFromRawResource(context,R.raw.simpe_fragment_shader));
57 | mPositionHandle = GLES20.glGetAttribLocation(mProgrammerHandle, "a_position");
58 | mTexCoordHandle = GLES20.glGetAttribLocation(mProgrammerHandle, "a_texCoord");
59 | ;
60 |
61 | mTextureHandle = TextureHelper.loadTexture(bitmap);
62 |
63 |
64 | textureUniformHandle = GLES20.glGetUniformLocation(mProgrammerHandle, "u_texture");
65 |
66 |
67 | }
68 |
69 | public void draw() {
70 |
71 | GLES20.glUseProgram ( mProgrammerHandle );
72 |
73 | // Load the vertex position
74 | vertexBuffer.position ( 0 );
75 | GLES20.glVertexAttribPointer ( mPositionHandle, 2, GLES20.GL_FLOAT,
76 | false,
77 | 4 * 4, vertexBuffer );
78 |
79 | vertexBuffer.position (2);
80 | GLES20.glVertexAttribPointer (mTexCoordHandle, 2, GLES20.GL_FLOAT,
81 | false,
82 | 4 * 4,
83 | vertexBuffer);
84 |
85 | GLES20.glEnableVertexAttribArray (mPositionHandle);
86 | GLES20.glEnableVertexAttribArray (mTexCoordHandle);
87 |
88 |
89 |
90 | // Bind the base map
91 | GLES20.glActiveTexture ( GLES20.GL_TEXTURE0);
92 | GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, mTextureHandle);
93 | // Set the base map sampler to texture unit to 0
94 | GLES20.glUniform1i (textureUniformHandle, 0);
95 |
96 | GLES20.glDrawElements ( GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, indiceBuffer);
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/FireworkView.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.opengl.GLES20;
8 | import android.opengl.GLES30;
9 | import android.opengl.GLSurfaceView;
10 | import android.util.AttributeSet;
11 |
12 | import javax.microedition.khronos.egl.EGLConfig;
13 | import javax.microedition.khronos.opengles.GL10;
14 |
15 | import static android.opengl.GLES10.glBlendFunc;
16 | import static android.opengl.GLES20.GL_BLEND;
17 | import static android.opengl.GLES20.GL_ONE;
18 | import static android.opengl.GLES20.GL_SRC_ALPHA;
19 | import static android.opengl.GLES20.glDepthMask;
20 | import static android.opengl.GLES20.glEnable;
21 |
22 | /**
23 | * Created by qinfeng on 2016/9/27.
24 | */
25 |
26 | public class FireworkView extends GLSurfaceView{
27 | private Context mContext;
28 | private Bitmap mBackground;
29 | private int mPlistFileResourceId;
30 | private int mTextureResourceId;
31 |
32 | public TextureLayer getTextureLayer() {
33 | return mTextureLayer;
34 | }
35 |
36 | public void setTextureLayer(TextureLayer textureLayer) {
37 | mTextureLayer = textureLayer;
38 | }
39 |
40 | public ParticleLayer getParticleSystem() {
41 | return mParticleSystem;
42 | }
43 |
44 | public void setParticleSystem(ParticleLayer particleSystem) {
45 | mParticleSystem = particleSystem;
46 | }
47 |
48 | private TextureLayer mTextureLayer;
49 | private ParticleLayer mParticleSystem;
50 |
51 | public FireworkView(Context context) {
52 | super(context);
53 | init(context,null);
54 | }
55 |
56 | public FireworkView(Context context, AttributeSet attrs) {
57 | super(context, attrs);
58 | init(context,attrs);
59 | }
60 |
61 | private void handleTypedArray(Context context, AttributeSet attrs) {
62 | if (attrs == null) {
63 | return;
64 | }
65 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FireworkView);
66 | mTextureResourceId = typedArray.getResourceId(R.styleable.FireworkView_texture,0);
67 | mPlistFileResourceId = typedArray.getResourceId(R.styleable.FireworkView_plistFile,0);
68 | int backgroundResourceId = typedArray.getResourceId(R.styleable.FireworkView_backgroundImage,0);
69 | mBackground = BitmapFactory.decodeResource(context.getResources(), backgroundResourceId);
70 | }
71 | private void init(Context context, AttributeSet attrs) {
72 | handleTypedArray(context,attrs);
73 |
74 | mContext = context;
75 | setEGLContextClientVersion(2);
76 | FireworkRenderer fireworkRenderer = new FireworkRenderer();
77 | setRenderer(fireworkRenderer);
78 | }
79 |
80 | public class FireworkRenderer implements Renderer {
81 |
82 |
83 |
84 |
85 | @Override
86 | public void onSurfaceCreated(GL10 unused, EGLConfig config) {
87 | GLES20.glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
88 | mParticleSystem = new ParticleLayer(mContext, mPlistFileResourceId,mTextureResourceId);
89 | if (mBackground != null)
90 | mTextureLayer = new TextureLayer(mContext, mBackground);
91 |
92 | }
93 |
94 | @Override
95 | public void onDrawFrame(GL10 unused) {
96 | // Set the view-port
97 | GLES20.glViewport ( 0, 0,getWidth(),getHeight() );
98 | // Clear the color buffer
99 | GLES20.glClear ( GLES30.GL_COLOR_BUFFER_BIT );
100 | if (mBackground != null)
101 | mTextureLayer.draw();
102 |
103 | glDepthMask(false);
104 | glEnable(GL_BLEND);
105 |
106 | //TODO particle system support BlendFuc
107 | glBlendFunc(GL_SRC_ALPHA, GL_ONE);
108 |
109 | mParticleSystem.update(1f / 60f);
110 | mParticleSystem.updateBuffer();
111 | mParticleSystem.draw();
112 |
113 |
114 | }
115 |
116 | @Override
117 | public void onSurfaceChanged(GL10 unused, int width, int height) {
118 | // Adjust the viewport based on geometry changes,
119 | // such as screen rotation
120 | GLES20.glViewport(0, 0, width, height);
121 |
122 | }
123 |
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/rain.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | angle
6 | 90
7 | angleVariance
8 | 30
9 | blendFuncDestination
10 | 771
11 | blendFuncSource
12 | 1
13 | duration
14 | -1
15 | emitterType
16 | 0.0
17 | finishColorAlpha
18 | 1
19 | finishColorBlue
20 | 1
21 | finishColorGreen
22 | 1
23 | finishColorRed
24 | 1
25 | finishColorVarianceAlpha
26 | 0.0
27 | finishColorVarianceBlue
28 | 0.0
29 | finishColorVarianceGreen
30 | 0.0
31 | finishColorVarianceRed
32 | 0.0
33 | finishParticleSize
34 | 6
35 | finishParticleSizeVariance
36 | 0
37 | gravityx
38 | 0
39 | gravityy
40 | 400
41 | maxParticles
42 | 1000
43 | maxRadius
44 | 100
45 | maxRadiusVariance
46 | 0.0
47 | minRadius
48 | 0.0
49 | particleLifespan
50 | 9
51 | particleLifespanVariance
52 | 8
53 | radialAccelVariance
54 | 0.0
55 | radialAcceleration
56 | 0.0
57 | rotatePerSecond
58 | 0.0
59 | rotatePerSecondVariance
60 | 0.0
61 | rotationEnd
62 | 0.0
63 | rotationEndVariance
64 | 0.0
65 | rotationStart
66 | 0.0
67 | rotationStartVariance
68 | 0.0
69 | sourcePositionVariancex
70 | 320
71 | sourcePositionVariancey
72 | 10
73 | sourcePositionx
74 | 160
75 | sourcePositiony
76 | -10
77 | speed
78 | 85
79 | speedVariance
80 | 30
81 | startColorAlpha
82 | 1
83 | startColorBlue
84 | 1
85 | startColorGreen
86 | 1
87 | startColorRed
88 | 1
89 | startColorVarianceAlpha
90 | 0.0
91 | startColorVarianceBlue
92 | 0.0
93 | startColorVarianceGreen
94 | 0.0
95 | startColorVarianceRed
96 | 0.0
97 | startParticleSize
98 | 10
99 | startParticleSizeVariance
100 | 9
101 | tangentialAccelVariance
102 | 0.0
103 | tangentialAcceleration
104 | 0.0
105 | textureFileName
106 | rain_texture.png
107 | textureImageData
108 | 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
109 |
110 |
111 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/snow.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | angle
6 | 90
7 | angleVariance
8 | 30
9 | blendFuncDestination
10 | 771
11 | blendFuncSource
12 | 1
13 | duration
14 | -1
15 | emitterType
16 | 0.0
17 | finishColorAlpha
18 | 0.23999999463558197
19 | finishColorBlue
20 | 0.0
21 | finishColorGreen
22 | 0.0
23 | finishColorRed
24 | 0.0
25 | finishColorVarianceAlpha
26 | 0.0
27 | finishColorVarianceBlue
28 | 0.0
29 | finishColorVarianceGreen
30 | 0.0
31 | finishColorVarianceRed
32 | 0.0
33 | finishParticleSize
34 | 32
35 | finishParticleSizeVariance
36 | 24
37 | gravityx
38 | 7
39 | gravityy
40 | 28
41 | maxParticles
42 | 200
43 | maxRadius
44 | 100
45 | maxRadiusVariance
46 | 0.0
47 | minRadius
48 | 0.0
49 | particleLifespan
50 | 9
51 | particleLifespanVariance
52 | 4
53 | radialAccelVariance
54 | 0.0
55 | radialAcceleration
56 | 0.0
57 | rotatePerSecond
58 | 0.0
59 | rotatePerSecondVariance
60 | 0.0
61 | rotationEnd
62 | 0.0
63 | rotationEndVariance
64 | 0.0
65 | rotationStart
66 | 0.0
67 | rotationStartVariance
68 | 0.0
69 | sourcePositionVariancex
70 | 320
71 | sourcePositionVariancey
72 | 10
73 | sourcePositionx
74 | 160
75 | sourcePositiony
76 | -10
77 | speed
78 | 85
79 | speedVariance
80 | 30
81 | startColorAlpha
82 | 0.6
83 | startColorBlue
84 | 1
85 | startColorGreen
86 | 1
87 | startColorRed
88 | 1
89 | startColorVarianceAlpha
90 | 0.0
91 | startColorVarianceBlue
92 | 0.0
93 | startColorVarianceGreen
94 | 0.0
95 | startColorVarianceRed
96 | 0.0
97 | startParticleSize
98 | 16
99 | startParticleSizeVariance
100 | 12
101 | tangentialAccelVariance
102 | 0.0
103 | tangentialAcceleration
104 | 0.0
105 | textureFileName
106 | particle_texture.png
107 | textureImageData
108 | H4sIAAAAAAAAA+1bB1RURxd+byu9g1RZpINUpVtoKoiKIqJYorisdESqLRINkihGjSHEFo0EC/ZoRCRWLMRoFHuPEIMlNizY4/5z3fvic7MrmJic84vr+Tjj7My997tt5i1L796UE0UFqlD/wUsqldJvgv/CJrTr35KrjBunGfyn/nib/FvIldsMmvXJWzOYejv8X8OZzYsnB74c5N9X5pO36od/wl8Jb3m+DD8BQtgMmHXyfpH3xVvxw9/h3wLe8nxVCFQRaiyoI9hzzDoVBf546354U/4t5M3mzPDUINAk0CLQVgItXKPB8ou8L17rh3+TvxLu8rwZzgxf4KVDoEugR6BPYEBgKAcDfE8P1+rgXsYfjC8U+eFv+6Al/BXkOzvminhrof16yMuIwJjAhMCUwIzAnMACYY5zprjGGPcYoAwdlKnID/K58Eb10Bz/FsRcRY63LsaR4WyGHC0JrAisCWwIbOVgg+9Z4VoL3Mv4Qh9ls/2g8k9zoYX8FXFnYq6OOarD4m2CMbVETsDPgcCJoD2BK4EbgTvCDefa4xoH3GONMsxRJuMHHdSpzsoFhT74J/ylf815ee4QB23MUUMWbxHG0wE5AT9PAi8CXwJ/ggA5+ON7XrjWDfc6oCwRyw+GqFMbbVDmg2ZzQBn/Zrgz+a7NirkZxgpsdSRwQR7eyK0LQRBBKEF3gjCCcEQYzoXimi64xxtluKBMG9RhxsoFxgdqf8cHivi3kDuT78YYF6hbe4wZ2OxD0JkgmKAHQQRBJEEUQTRBDMFARAzOReGaCNwTjDJ8UGZ71GGFOo2lL+vhb/ngNfzZNS+f82zu0KesMT5uGLNOBCEY20jkFkswjCCOQEwgIRiFkOBcHK6JxT2RKCMEZXqjDkfUaaHAB+xaaLYXyPNXEnuB9NV6Z7i3lcpyEnqWh1RWv4EYuz4EAwiGEowkSCBIJcggyCLIIchF5OBcBq5JwD1DUUYflBmIOjxQpw3awPiA3Q/YZ6PSHFDCX547nDPqctwtUL+zVJabUK+Qr5C7/QmGYEyTCcYgzwkE+QQfE0wlKERMxbl8XJOLe5JRxhCUGYE6/FGnM9rAzgNttJU5G1/xwev4K4g9u+bhvIGeC30Has8aYwB2QP+G3tVbKqvl4QSJGM+xyAs4FhHMIphDUExQgijGuVm4ZiruGYsyElFmDOoIRZ2eaIM12mSENmpKX+0FSnNAAX9leQ/1BecO9F7oP1CDHhgLsAdydJBUlrcpUllOT8L4zkSO8wkWEZQSlBEsRZTh3CJcU4x7ClFGDsociTr6oE5/tMERbTJDG9m94LU5wPBvJvZw54LcgrPXUirrwdCHoBaDMSZgF+RqOsZtCsYSuCxEfisIVhOsJ9hAsBGxAedW45pS3FOMMqagzHTUMQh1BqMNbmiTJdqojzY3mwNy/JXFHu6dTN5DvcE5BL0Y+hHUZAzGBuwbR1CA8ZtLsISgHPltIqgi2Eawg2AnYgfOVeGa9bhnCcqYiTLHoY6RqDMCbfBGm2ykL+tAtyU5oIS/stjDHQxyDeoOziPoydCXhktl+TkW7ZwtleUx5PUa5LSVYBfBPoL9BAcIDiIO4Nw+XLMV96xBGfNRZgHqSEGd/dGGTmiTI9rYbA6w+UtfzX12z2fqnh17uIvBfQTOZKhD6M3Qn6BGp2CswF6o63UElRjjGuRaS3CM4CTBKcRJnKvFNTW4pxJlLEWZM1FHDuocgjaEoE0ucjnA9AH2WfBKDbD4K8p9pufD2WIpld3Fwc9wJ4N7CZzNUI/Qo6FPQa3OxZiB3VsIqgl+Qm4nCM4QnCe4SFCHuIhzZ3BNLe6pRhnrUOZc1DEJdYrRhnC0yRNttESbmbNAaQ0o4M/OfThL4Rkc+iqcMUzdQ9+BuxncT+CMhpyEXg39Cmp2DcYO7IfcPkpwmuACQT3BbwSXCa4gLuNcPa45jXsOoIxKlLkEdRSizmS0IRJtYvqANdpsgByU1oAS/sx9h8l9uF/A8yj0WThzoObgfgp9CO4p+VJZbkLPhr4FtbsTYwg8zmKMgeNVgt8JbhDcRNzAuau45iLuOYoydqLMctQxE3WOQRui0SZ/tNEWbWZqgLkPNcdfUd+Xz314NoO+C3d0uKfCXW0qxgXOLejd0L+ghmsxlsCnATkC39sEdwjuIu7g3E1c04B7TqOMGpS5HnUUo85ctCEWbeoi/WsNKDoH2J8TKePP1D70UrhbwD0Lns3h+RTyDZ5T4K4O91WoSehPKzBO0MOhj0EtX8CYAq9byPUeQZMc7uF7t3Dtb7j3BMrahbJXoK4i1J2KtkSibV5oqxXarqgHyPNn9z75cw8+k2NqH+4acO+C51R4VoMelC+V3Vvh7gb3FzjD92HcoJ9BTV/F2AK/+wQPCB4SPEI8xLn7uOYm7qlHGbUoswp1LEKd+WhDHNoUijYyPcBU+tdzUP6ZSBl/du+DMwU+n4L6gs8poN6g98IzGzy3wN2dyX24x8BZDufZeenL2N/GGD9Azo8JniAe49wDXHNb+jIHzqOs/SibqYE5qDsLbYlG2/zRVhup4h74Ov7yvR/u0nCWMr0Pnjngsxq4e8EzO5zDTO3D+QT32B1SWd+GM/2iVNbbb2BcmzDWDPenCMYHD3HNHdxzGWWcRJk7UEeZ9GUPyEFbYtC2AOnLHmiOHJSeAUr4M8+6sJfp/e4oG85a+MwGPreA/gNnETzDwR0F7vLQq6Fe4V4DZzucb5DPd5HbIznubB88wjV3cc8VlHEKZe5EHUtRZyHaMAptCkcb3aUvzwCGv/p7/i3m31rzv7X3v9Z6/rX2+8/7++/755/3z7+t+/OPVvv5V2v//PP959/vf//R2n//9f73n6/NgVbx+28lOdCqvv8glwPydfDOf//lNTnQar7/9AY+eCe//9ZCH7zT33+U8wG7F8j74J39/quCHJD3wTv//Wc5H7BrgX02vrPff1fiB2W58E7+/UMLfKDID+/c378o8EFzfnjn/v7pDf3A+ELeH//Xf//WQj+wfcH2h7xf5HnK8+XKyXwrvFm2vw0xjCz6Nb5Q5BNFULSHftu8WTa/TXFsufK+eJ1PlHL9NzjL2flviZbXo8wf/ylfBXZRlBZRxyX/oalA8oNmjTkvxjyKCqyguThPFtMCHHPID114H2YpFVqPtcYQx+Rd2oglsw2zPpCizVnro1gy+/+pd/snWZSQojTCyHjfC5NV8B+N/8h7vZLSR3N0KCotPTszqkewaFDsYJHwEJGkSgkoD4qKE2dl9O7fPRq2h3cLEWWRRYwHZK5+cFI2OOYS1lckekMn6oozMrOJpL5k3CFekiUm4wIyTs3LzoD5RjI2GJkCYw5wN8gkBpKxMYwTZOP2L9bIxoEwjk9LjydjsDkjPi0exnvI+NPcHAkZc3uRcWFukiSPjI+TsU1qTloSGT+CvWmSuCziPg2Yz5aIE8nYnYw1MqOjQsi4E3GiRgJrPJI1zpaMzQZSIaMzxmUmJSRmixzEjiIPPz9fUZgkL1WSne3SN06cEpcZLwoZnZYRlz6OomScX7z0wLci4mRvDz9vbxdPVw+Wo177ZgtfEFvZ6F6/FzGjjQ6+nFO0bnQpRfk2Ed/Mfjk3ch5FbZ5KUcZnX87ZfENR2iRuFYdZfIwgXxKzszP83dzy8vJckyRiV3Don69mF7TgxdLnCuL+dI8oVDIqLic1WwR+E49OHZ2TKcrKiBNLRC6vJPE/2ajYjvZRklGSTEk62RFDsiwpPYGEOz0+KTtpdLooKV1ZEP/mNrmXLK/JS7/sOWUw3JXSOWxAcW8epHj66hR36CLyDv1n3HqpxlBQeQMtr8jy/sVLQQflzIIfWUkJL/aFREWLxDmZubL3oCwpPqVGaVMGlAnVlrKmHCgXypPyoQJIo+pG9aQiqWgqlvqAElOJVBqVSeVRE6nJVCFVRM2mvqTmU4upMqqcWkttoDZTW6ld1D7qAFVLnaDOUXVUA3WdaqQeUE9pmhbSmrQ+bUJb0ra0M+1J+9Jd6G50LzqKjqVH0Al0Op1DT6Q/povoOfR8egldTn9Hb6F30fvpI/QZup6+Rt+ln3C4HA2OAceCY8dx4/hygjgRnGjOME4CZwxnPKeAM5Mzl1PKWc2p4OziHOCc4NRxrnOaSANX5xpxrbguXF9uCDeSO5g7ipvJncSdzi3hlnLXcqu4Ndxj3DruDe5jnoCnzxPxXHgBvDDeAJ6YN4Y3iTeDN5+3glfB28M7xqvnNfKe8zX55nxnvj8/nD+In8DP4xfyS/jL+Jv4e/kn+A38BwKBwEhgL/ARhAliBcmCCYIZgq8F6wQ7BUcElwRNQqHQROgs7CyMFMYJs4WFwnnC1cIdwqPCBuEjFXUVSxVPle4qg1XSVaaolKisVNmuclTlispTVR1VW1V/1UjVeNVxqrNUy1SrVA+rNqg+VdNVs1frrBatlqw2WW2u2lq1vWrn1e6pq6u3U/dT76eepP6R+lz19eo/qterP9bQ03DSCNEYqpGjMVNjucZOjTMa9zQ1Ne00AzUHa2ZrztQs19yt+YvmIy19LVetcK14rXytBVoVWke1bmmrattqB2l/oD1eu0R7o/Zh7Rs6qjp2OiE6cTqTdBbobNE5pdOkq6/roRupm6Y7Q3el7n7dq3pCPTu9bnrxegV63+rt1rukz9W31g/RF+t/rF+mv1e/wUBgYG8QbpBsUGSwxuCQQaOhnmFHwxjDsYYLDLcZ1hlxjeyMwo1SjWYZbTA6afSkjUWboDaSNtParG1ztM1DYzPjQGOJ8XTjdcYnjJ+YiEy6maSYfG6y2eSCKc/UybSfaZ7pItO9pjfMDMwCzMRm0802mJ0155g7mUeZTzD/1vygeZNFW4seFhkW8yx2W9xoa9Q2sG1y2+K229tes9S37GKZZFlsucPyd5GhKEiUKpor2iNqtDK3CrPKsVpidcjqaTv7dgPaTWm3rt0FazVrX+tR1sXW1daNNpY2vW0m2qyyOWurautrm2j7lW2N7UM7e7uBdp/Ybba7am9sH24/3n6V/XkHTYeuDmMcSh2OOwocfR1THL92rHXiOHk5JTotcDrszHH2dk5y/tr5SHt+e7/26e1L259y0XAJcsl1WeVS72rk2st1iutm11tuNm6D3T53q3F77u7lnupe5n7OQ8+jp8cUjyqPu55OnmLPBZ7HO2h26N4hv0NlhzsdnTtKOi7qeNpL36u31yde1V5/ePt4Z3qv9b7mY+MzwmehzylfA9++vjN8f/Tj+wX75ftt9Xvs7+2f7b/B/3aAS0BKwMqAq53sO0k6lXW61Lld57jOSzrXdRF1GdHlmy51Xa26xnUt7fproHVgfOCywCtBjkHJQauDbgW7B2cGbwp+GOIf8mHIzlBuaI/Q6aGHuul1G9BtfrdfurfrntB9VffGHl49JvTYGcYPiwj7POxUuEW4OLw8vLGnT88Pe+6J0IjoHzE/4tdeTr0ye1X15vTu2fuL3uf72PZJ77M5kooMj/wi8kJf+75j+v7QT9Cvb78F/S5HeURNjKrpr99/eP+V/R9EB0fPij43wGFAzoDqGO2YoTHlMQ8Hhg6cM7BukNugDwcdiDWNTYqtHCwcHDN42eCmId2GfDmkYajX0MKhJ4fZDxs7bP8Hph+kfrBtuPbwuOEbR/BHDByxcsSzuMi40rimkeEjF45sFIeIvxJfjw+ML46/JuksmSO5MqrzqDmjriZ0Tvgi4Vpi18SSxBtJIUnzk+4khyUvTn6YEpmyPEWaOjB1XZpK2oi0Lel66Snpe0a3HT129JEM54zCjLox/mO+HNOYGZG5LIvOGpZVmW1ALlMHcxxypubU53bJXZD7KC8mb+NY3bHpYw+Ocxo3bdyV8d3HL53AmyCeUD3RauLkifUfBn24ZBI9aeSk6nzr/IL8ho96fLRistrklMk/T3GfMmfK/Y8HflxVYFHwUcGlqT2mrirUKswsPPVJwCeLP+V9mvTpoWkdps2b9nx6/PSfityLSoqezRDP+Okzj8/mfiadOWrmoVnesxbNFsxOn33y866fr5ijO2f8nEtf9P6iolhUPL34/pfDv9xf0rFk8VdqX+V8VTe319zKeTbzZs97Nj9x/okFwQvWLTRfOG3hw6/jvz66KHDR2sUWi4sWP/km6ZvTS3osqSi1Ky35VvBt7reXy2LKapb6Li1fZrqsaNkfy9OX162IWrGn3Ke8fKX5ylmrOKtyVl1bPXR17ZrQNZVrXdYuWWe0rmg9tT5n/e/fjfju5IaIDdUbfTeu/d72+4Wb9DdNr6ArxlU0bk7cXFcZW3lkS88t1VUBVZt+cP1h+VarrQu2GW6btV1te8F26Y7xO5p2Zuy8sSth16Xq4dXndg/afXxPvz2H9kbs/XFf9327a4JqdvzY+cet+/33b/nJ96fNB7wPVBz0OrjpZ6+fNx3yPlRx2OdwZa1fbdWRTke2H+16dNex0GP7jocfP3Ciz4kjJwecPH1q6Km60/Gnr55JPXPnbO7Zp+c+Os8/P/2CzoWSX8x/Kb3oeHFdnXfdtvrQ+oO/9v/13CXxpeu/Zf32rKHgsublkiuWV8qvel7deq37tdrfh/zecD3j+tMbhTd1by685XDr+9uBtw82DmpsuJN5R3p3xj2Te8vvd7xf3dS36ZcHaQ+ePpz+yOTRise+j2ueDHxy5WneM+GzuX84/lH1POL5eWmaVPo/LX7Mrg5NAAA=
109 |
110 |
111 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/test.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | angle
6 | 0.0
7 | angleVariance
8 | 180
9 | blendFuncDestination
10 | 1
11 | blendFuncSource
12 | 775
13 | duration
14 | -1
15 | emitterType
16 | 1
17 | finishColorAlpha
18 | 1
19 | finishColorBlue
20 | 1
21 | finishColorGreen
22 | 1
23 | finishColorRed
24 | 1
25 | finishColorVarianceAlpha
26 | 0.0
27 | finishColorVarianceBlue
28 | 0.0
29 | finishColorVarianceGreen
30 | 0.0
31 | finishColorVarianceRed
32 | 0.0
33 | finishParticleSize
34 | 10
35 | finishParticleSizeVariance
36 | 0.0
37 | gravityx
38 | 1.1499999761581421
39 | gravityy
40 | 1.5800000429153442
41 | maxParticles
42 | 928
43 | maxRadius
44 | 110
45 | maxRadiusVariance
46 | 0.0
47 | minRadius
48 | 100
49 | particleLifespan
50 | 3
51 | particleLifespanVariance
52 | 0.0
53 | radialAccelVariance
54 | 0.0
55 | radialAcceleration
56 | 0.0
57 | rotatePerSecond
58 | 100
59 | rotatePerSecondVariance
60 | 0.0
61 | rotationEnd
62 | 0.0
63 | rotationEndVariance
64 | 0.0
65 | rotationStart
66 | 0.0
67 | rotationStartVariance
68 | 0.0
69 | sourcePositionVariancex
70 | 50
71 | sourcePositionVariancey
72 | 50
73 | sourcePositionx
74 | 167.61000061035156
75 | sourcePositiony
76 | 240.02000427246094
77 | speed
78 | 20
79 | speedVariance
80 | 0.0
81 | startColorAlpha
82 | 1
83 | startColorBlue
84 | 0.5
85 | startColorGreen
86 | 0.5
87 | startColorRed
88 | 0.5
89 | startColorVarianceAlpha
90 | 1
91 | startColorVarianceBlue
92 | 1
93 | startColorVarianceGreen
94 | 1
95 | startColorVarianceRed
96 | 1
97 | startParticleSize
98 | 30
99 | startParticleSizeVariance
100 | 10
101 | tangentialAccelVariance
102 | 0.0
103 | tangentialAcceleration
104 | 0.0
105 | textureFileName
106 | particle_texture.png
107 | textureImageData
108 | H4sIAAAAAAAAA+1bB1RURxd+byu9g1RZpINUpVtoKoiKIqJYorisdESqLRINkihGjSHEFo0EC/ZoRCRWLMRoFHuPEIMlNizY4/5z3fvic7MrmJic84vr+Tjj7My997tt5i1L796UE0UFqlD/wUsqldJvgv/CJrTr35KrjBunGfyn/nib/FvIldsMmvXJWzOYejv8X8OZzYsnB74c5N9X5pO36od/wl8Jb3m+DD8BQtgMmHXyfpH3xVvxw9/h3wLe8nxVCFQRaiyoI9hzzDoVBf546354U/4t5M3mzPDUINAk0CLQVgItXKPB8ou8L17rh3+TvxLu8rwZzgxf4KVDoEugR6BPYEBgKAcDfE8P1+rgXsYfjC8U+eFv+6Al/BXkOzvminhrof16yMuIwJjAhMCUwIzAnMACYY5zprjGGPcYoAwdlKnID/K58Eb10Bz/FsRcRY63LsaR4WyGHC0JrAisCWwIbOVgg+9Z4VoL3Mv4Qh9ls/2g8k9zoYX8FXFnYq6OOarD4m2CMbVETsDPgcCJoD2BK4EbgTvCDefa4xoH3GONMsxRJuMHHdSpzsoFhT74J/ylf815ee4QB23MUUMWbxHG0wE5AT9PAi8CXwJ/ggA5+ON7XrjWDfc6oCwRyw+GqFMbbVDmg2ZzQBn/Zrgz+a7NirkZxgpsdSRwQR7eyK0LQRBBKEF3gjCCcEQYzoXimi64xxtluKBMG9RhxsoFxgdqf8cHivi3kDuT78YYF6hbe4wZ2OxD0JkgmKAHQQRBJEEUQTRBDMFARAzOReGaCNwTjDJ8UGZ71GGFOo2lL+vhb/ngNfzZNS+f82zu0KesMT5uGLNOBCEY20jkFkswjCCOQEwgIRiFkOBcHK6JxT2RKCMEZXqjDkfUaaHAB+xaaLYXyPNXEnuB9NV6Z7i3lcpyEnqWh1RWv4EYuz4EAwiGEowkSCBIJcggyCLIIchF5OBcBq5JwD1DUUYflBmIOjxQpw3awPiA3Q/YZ6PSHFDCX547nDPqctwtUL+zVJabUK+Qr5C7/QmGYEyTCcYgzwkE+QQfE0wlKERMxbl8XJOLe5JRxhCUGYE6/FGnM9rAzgNttJU5G1/xwev4K4g9u+bhvIGeC30Has8aYwB2QP+G3tVbKqvl4QSJGM+xyAs4FhHMIphDUExQgijGuVm4ZiruGYsyElFmDOoIRZ2eaIM12mSENmpKX+0FSnNAAX9leQ/1BecO9F7oP1CDHhgLsAdydJBUlrcpUllOT8L4zkSO8wkWEZQSlBEsRZTh3CJcU4x7ClFGDsociTr6oE5/tMERbTJDG9m94LU5wPBvJvZw54LcgrPXUirrwdCHoBaDMSZgF+RqOsZtCsYSuCxEfisIVhOsJ9hAsBGxAedW45pS3FOMMqagzHTUMQh1BqMNbmiTJdqojzY3mwNy/JXFHu6dTN5DvcE5BL0Y+hHUZAzGBuwbR1CA8ZtLsISgHPltIqgi2Eawg2AnYgfOVeGa9bhnCcqYiTLHoY6RqDMCbfBGm2ykL+tAtyU5oIS/stjDHQxyDeoOziPoydCXhktl+TkW7ZwtleUx5PUa5LSVYBfBPoL9BAcIDiIO4Nw+XLMV96xBGfNRZgHqSEGd/dGGTmiTI9rYbA6w+UtfzX12z2fqnh17uIvBfQTOZKhD6M3Qn6BGp2CswF6o63UElRjjGuRaS3CM4CTBKcRJnKvFNTW4pxJlLEWZM1FHDuocgjaEoE0ucjnA9AH2WfBKDbD4K8p9pufD2WIpld3Fwc9wJ4N7CZzNUI/Qo6FPQa3OxZiB3VsIqgl+Qm4nCM4QnCe4SFCHuIhzZ3BNLe6pRhnrUOZc1DEJdYrRhnC0yRNttESbmbNAaQ0o4M/OfThL4Rkc+iqcMUzdQ9+BuxncT+CMhpyEXg39Cmp2DcYO7IfcPkpwmuACQT3BbwSXCa4gLuNcPa45jXsOoIxKlLkEdRSizmS0IRJtYvqANdpsgByU1oAS/sx9h8l9uF/A8yj0WThzoObgfgp9CO4p+VJZbkLPhr4FtbsTYwg8zmKMgeNVgt8JbhDcRNzAuau45iLuOYoydqLMctQxE3WOQRui0SZ/tNEWbWZqgLkPNcdfUd+Xz314NoO+C3d0uKfCXW0qxgXOLejd0L+ghmsxlsCnATkC39sEdwjuIu7g3E1c04B7TqOMGpS5HnUUo85ctCEWbeoi/WsNKDoH2J8TKePP1D70UrhbwD0Lns3h+RTyDZ5T4K4O91WoSehPKzBO0MOhj0EtX8CYAq9byPUeQZMc7uF7t3Dtb7j3BMrahbJXoK4i1J2KtkSibV5oqxXarqgHyPNn9z75cw8+k2NqH+4acO+C51R4VoMelC+V3Vvh7gb3FzjD92HcoJ9BTV/F2AK/+wQPCB4SPEI8xLn7uOYm7qlHGbUoswp1LEKd+WhDHNoUijYyPcBU+tdzUP6ZSBl/du+DMwU+n4L6gs8poN6g98IzGzy3wN2dyX24x8BZDufZeenL2N/GGD9Azo8JniAe49wDXHNb+jIHzqOs/SibqYE5qDsLbYlG2/zRVhup4h74Ov7yvR/u0nCWMr0Pnjngsxq4e8EzO5zDTO3D+QT32B1SWd+GM/2iVNbbb2BcmzDWDPenCMYHD3HNHdxzGWWcRJk7UEeZ9GUPyEFbYtC2AOnLHmiOHJSeAUr4M8+6sJfp/e4oG85a+MwGPreA/gNnETzDwR0F7vLQq6Fe4V4DZzucb5DPd5HbIznubB88wjV3cc8VlHEKZe5EHUtRZyHaMAptCkcb3aUvzwCGv/p7/i3m31rzv7X3v9Z6/rX2+8/7++/755/3z7+t+/OPVvv5V2v//PP959/vf//R2n//9f73n6/NgVbx+28lOdCqvv8glwPydfDOf//lNTnQar7/9AY+eCe//9ZCH7zT33+U8wG7F8j74J39/quCHJD3wTv//Wc5H7BrgX02vrPff1fiB2W58E7+/UMLfKDID+/c378o8EFzfnjn/v7pDf3A+ELeH//Xf//WQj+wfcH2h7xf5HnK8+XKyXwrvFm2vw0xjCz6Nb5Q5BNFULSHftu8WTa/TXFsufK+eJ1PlHL9NzjL2flviZbXo8wf/ylfBXZRlBZRxyX/oalA8oNmjTkvxjyKCqyguThPFtMCHHPID114H2YpFVqPtcYQx+Rd2oglsw2zPpCizVnro1gy+/+pd/snWZSQojTCyHjfC5NV8B+N/8h7vZLSR3N0KCotPTszqkewaFDsYJHwEJGkSgkoD4qKE2dl9O7fPRq2h3cLEWWRRYwHZK5+cFI2OOYS1lckekMn6oozMrOJpL5k3CFekiUm4wIyTs3LzoD5RjI2GJkCYw5wN8gkBpKxMYwTZOP2L9bIxoEwjk9LjydjsDkjPi0exnvI+NPcHAkZc3uRcWFukiSPjI+TsU1qTloSGT+CvWmSuCziPg2Yz5aIE8nYnYw1MqOjQsi4E3GiRgJrPJI1zpaMzQZSIaMzxmUmJSRmixzEjiIPPz9fUZgkL1WSne3SN06cEpcZLwoZnZYRlz6OomScX7z0wLci4mRvDz9vbxdPVw+Wo177ZgtfEFvZ6F6/FzGjjQ6+nFO0bnQpRfk2Ed/Mfjk3ch5FbZ5KUcZnX87ZfENR2iRuFYdZfIwgXxKzszP83dzy8vJckyRiV3Don69mF7TgxdLnCuL+dI8oVDIqLic1WwR+E49OHZ2TKcrKiBNLRC6vJPE/2ajYjvZRklGSTEk62RFDsiwpPYGEOz0+KTtpdLooKV1ZEP/mNrmXLK/JS7/sOWUw3JXSOWxAcW8epHj66hR36CLyDv1n3HqpxlBQeQMtr8jy/sVLQQflzIIfWUkJL/aFREWLxDmZubL3oCwpPqVGaVMGlAnVlrKmHCgXypPyoQJIo+pG9aQiqWgqlvqAElOJVBqVSeVRE6nJVCFVRM2mvqTmU4upMqqcWkttoDZTW6ld1D7qAFVLnaDOUXVUA3WdaqQeUE9pmhbSmrQ+bUJb0ra0M+1J+9Jd6G50LzqKjqVH0Al0Op1DT6Q/povoOfR8egldTn9Hb6F30fvpI/QZup6+Rt+ln3C4HA2OAceCY8dx4/hygjgRnGjOME4CZwxnPKeAM5Mzl1PKWc2p4OziHOCc4NRxrnOaSANX5xpxrbguXF9uCDeSO5g7ipvJncSdzi3hlnLXcqu4Ndxj3DruDe5jnoCnzxPxXHgBvDDeAJ6YN4Y3iTeDN5+3glfB28M7xqvnNfKe8zX55nxnvj8/nD+In8DP4xfyS/jL+Jv4e/kn+A38BwKBwEhgL/ARhAliBcmCCYIZgq8F6wQ7BUcElwRNQqHQROgs7CyMFMYJs4WFwnnC1cIdwqPCBuEjFXUVSxVPle4qg1XSVaaolKisVNmuclTlispTVR1VW1V/1UjVeNVxqrNUy1SrVA+rNqg+VdNVs1frrBatlqw2WW2u2lq1vWrn1e6pq6u3U/dT76eepP6R+lz19eo/qterP9bQ03DSCNEYqpGjMVNjucZOjTMa9zQ1Ne00AzUHa2ZrztQs19yt+YvmIy19LVetcK14rXytBVoVWke1bmmrattqB2l/oD1eu0R7o/Zh7Rs6qjp2OiE6cTqTdBbobNE5pdOkq6/roRupm6Y7Q3el7n7dq3pCPTu9bnrxegV63+rt1rukz9W31g/RF+t/rF+mv1e/wUBgYG8QbpBsUGSwxuCQQaOhnmFHwxjDsYYLDLcZ1hlxjeyMwo1SjWYZbTA6afSkjUWboDaSNtParG1ztM1DYzPjQGOJ8XTjdcYnjJ+YiEy6maSYfG6y2eSCKc/UybSfaZ7pItO9pjfMDMwCzMRm0802mJ0155g7mUeZTzD/1vygeZNFW4seFhkW8yx2W9xoa9Q2sG1y2+K229tes9S37GKZZFlsucPyd5GhKEiUKpor2iNqtDK3CrPKsVpidcjqaTv7dgPaTWm3rt0FazVrX+tR1sXW1daNNpY2vW0m2qyyOWurautrm2j7lW2N7UM7e7uBdp/Ybba7am9sH24/3n6V/XkHTYeuDmMcSh2OOwocfR1THL92rHXiOHk5JTotcDrszHH2dk5y/tr5SHt+e7/26e1L259y0XAJcsl1WeVS72rk2st1iutm11tuNm6D3T53q3F77u7lnupe5n7OQ8+jp8cUjyqPu55OnmLPBZ7HO2h26N4hv0NlhzsdnTtKOi7qeNpL36u31yde1V5/ePt4Z3qv9b7mY+MzwmehzylfA9++vjN8f/Tj+wX75ftt9Xvs7+2f7b/B/3aAS0BKwMqAq53sO0k6lXW61Lld57jOSzrXdRF1GdHlmy51Xa26xnUt7fproHVgfOCywCtBjkHJQauDbgW7B2cGbwp+GOIf8mHIzlBuaI/Q6aGHuul1G9BtfrdfurfrntB9VffGHl49JvTYGcYPiwj7POxUuEW4OLw8vLGnT88Pe+6J0IjoHzE/4tdeTr0ye1X15vTu2fuL3uf72PZJ77M5kooMj/wi8kJf+75j+v7QT9Cvb78F/S5HeURNjKrpr99/eP+V/R9EB0fPij43wGFAzoDqGO2YoTHlMQ8Hhg6cM7BukNugDwcdiDWNTYqtHCwcHDN42eCmId2GfDmkYajX0MKhJ4fZDxs7bP8Hph+kfrBtuPbwuOEbR/BHDByxcsSzuMi40rimkeEjF45sFIeIvxJfjw+ML46/JuksmSO5MqrzqDmjriZ0Tvgi4Vpi18SSxBtJIUnzk+4khyUvTn6YEpmyPEWaOjB1XZpK2oi0Lel66Snpe0a3HT129JEM54zCjLox/mO+HNOYGZG5LIvOGpZVmW1ALlMHcxxypubU53bJXZD7KC8mb+NY3bHpYw+Ocxo3bdyV8d3HL53AmyCeUD3RauLkifUfBn24ZBI9aeSk6nzr/IL8ho96fLRistrklMk/T3GfMmfK/Y8HflxVYFHwUcGlqT2mrirUKswsPPVJwCeLP+V9mvTpoWkdps2b9nx6/PSfityLSoqezRDP+Okzj8/mfiadOWrmoVnesxbNFsxOn33y866fr5ijO2f8nEtf9P6iolhUPL34/pfDv9xf0rFk8VdqX+V8VTe319zKeTbzZs97Nj9x/okFwQvWLTRfOG3hw6/jvz66KHDR2sUWi4sWP/km6ZvTS3osqSi1Ky35VvBt7reXy2LKapb6Li1fZrqsaNkfy9OX162IWrGn3Ke8fKX5ylmrOKtyVl1bPXR17ZrQNZVrXdYuWWe0rmg9tT5n/e/fjfju5IaIDdUbfTeu/d72+4Wb9DdNr6ArxlU0bk7cXFcZW3lkS88t1VUBVZt+cP1h+VarrQu2GW6btV1te8F26Y7xO5p2Zuy8sSth16Xq4dXndg/afXxPvz2H9kbs/XFf9327a4JqdvzY+cet+/33b/nJ96fNB7wPVBz0OrjpZ6+fNx3yPlRx2OdwZa1fbdWRTke2H+16dNex0GP7jocfP3Ciz4kjJwecPH1q6Km60/Gnr55JPXPnbO7Zp+c+Os8/P/2CzoWSX8x/Kb3oeHFdnXfdtvrQ+oO/9v/13CXxpeu/Zf32rKHgsublkiuWV8qvel7deq37tdrfh/zecD3j+tMbhTd1by685XDr+9uBtw82DmpsuJN5R3p3xj2Te8vvd7xf3dS36ZcHaQ+ePpz+yOTRise+j2ueDHxy5WneM+GzuX84/lH1POL5eWmaVPo/LX7Mrg5NAAA=
109 |
110 |
111 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/utils/ESShader.java:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2013 Dan Ginsburg, Budirijanto Purnomo
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in
13 | // all copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | // THE SOFTWARE.
22 |
23 | //
24 | // Book: OpenGL(R) ES 3.0 Programming Guide, 2nd Edition
25 | // Authors: Dan Ginsburg, Budirijanto Purnomo, Dave Shreiner, Aaftab Munshi
26 | // ISBN-10: 0-321-93388-5
27 | // ISBN-13: 978-0-321-93388-1
28 | // Publisher: Addison-Wesley Professional
29 | // URLs: http://www.opengles-book.com
30 | // http://my.safaribooksonline.com/book/animation-and-3d/9780133440133
31 | //
32 |
33 | // ESShader
34 | //
35 | // Utility functions for loading GLSL ES 3.0 shaders and creating program objects.
36 | //
37 |
38 | package com.yang.firework.utils;
39 |
40 | import android.content.Context;
41 | import android.opengl.GLES20;
42 | import android.util.Log;
43 |
44 | import java.io.ByteArrayOutputStream;
45 | import java.io.IOException;
46 | import java.io.InputStream;
47 |
48 | public class ESShader
49 | {
50 | //
51 | ///
52 | /// \brief Read a shader source into a String
53 | /// \param context Application context
54 | /// \param fileName Name of shader file
55 | /// \return A String object containing shader source, otherwise null
56 | //
57 | private static String readShader (Context context, String fileName )
58 | {
59 | String shaderSource = null;
60 |
61 | if ( fileName == null )
62 | {
63 | return shaderSource;
64 | }
65 |
66 | // Read the shader file from assets
67 | InputStream is = null;
68 | byte [] buffer;
69 |
70 | try
71 | {
72 | is = context.getAssets().open ( fileName );
73 |
74 | // Create a buffer that has the same diameter as the InputStream
75 | buffer = new byte[is.available()];
76 |
77 | // Read the text file as a stream, into the buffer
78 | is.read ( buffer );
79 |
80 | ByteArrayOutputStream os = new ByteArrayOutputStream();
81 |
82 | // Write this buffer to the output stream
83 | os.write ( buffer );
84 |
85 | // Close input and output streams
86 | os.close();
87 | is.close();
88 |
89 | shaderSource = os.toString();
90 | }
91 | catch ( IOException ioe )
92 | {
93 | is = null;
94 | }
95 |
96 | if ( is == null )
97 | {
98 | return shaderSource;
99 | }
100 |
101 | return shaderSource;
102 | }
103 |
104 | //
105 | ///
106 | /// \brief Load a shader, check for compile errors, print error messages to
107 | /// output log
108 | /// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
109 | /// \param shaderSrc Shader source string
110 | /// \return A new shader object on success, 0 on failure
111 | //
112 | public static int loadShader ( int type, String shaderSrc )
113 | {
114 | int shader;
115 | int[] compiled = new int[1];
116 |
117 | // Create the shader object
118 | shader = GLES20.glCreateShader ( type );
119 |
120 | if ( shader == 0 )
121 | {
122 | return 0;
123 | }
124 |
125 | // Load the shader source
126 | GLES20.glShaderSource ( shader, shaderSrc );
127 |
128 | // Compile the shader
129 | GLES20.glCompileShader ( shader );
130 |
131 | // Check the compile status
132 | GLES20.glGetShaderiv ( shader, GLES20.GL_COMPILE_STATUS, compiled, 0 );
133 |
134 | if ( compiled[0] == 0 )
135 | {
136 | Log.e ( "ESShader", GLES20.glGetShaderInfoLog ( shader ) );
137 | GLES20.glDeleteShader ( shader );
138 | return 0;
139 | }
140 |
141 | return shader;
142 | }
143 |
144 | //
145 | ///
146 | /// \brief Load a vertex and fragment shader, create a program object, link
147 | /// program.
148 | /// Errors output to log.
149 | /// \param vertShaderSrc Vertex shader source code
150 | /// \param fragShaderSrc Fragment shader source code
151 | /// \return A new program object linked with the vertex/fragment shader
152 | /// pair, 0 on failure
153 | //
154 | public static int loadProgram (String vertShaderSrc, String fragShaderSrc )
155 | {
156 | int vertexShader;
157 | int fragmentShader;
158 | int programObject;
159 | int[] linked = new int[1];
160 |
161 | // Load the vertex/fragment shaders
162 | vertexShader = loadShader ( GLES20.GL_VERTEX_SHADER, vertShaderSrc );
163 |
164 | if ( vertexShader == 0 )
165 | {
166 | return 0;
167 | }
168 |
169 | fragmentShader = loadShader ( GLES20.GL_FRAGMENT_SHADER, fragShaderSrc );
170 |
171 | if ( fragmentShader == 0 )
172 | {
173 | GLES20.glDeleteShader ( vertexShader );
174 | return 0;
175 | }
176 |
177 | // Create the program object
178 | programObject = GLES20.glCreateProgram();
179 |
180 | if ( programObject == 0 )
181 | {
182 | return 0;
183 | }
184 |
185 | GLES20.glAttachShader ( programObject, vertexShader );
186 | GLES20.glAttachShader ( programObject, fragmentShader );
187 |
188 | // Link the program
189 | GLES20.glLinkProgram ( programObject );
190 |
191 | // Check the link status
192 | GLES20.glGetProgramiv ( programObject, GLES20.GL_LINK_STATUS, linked, 0 );
193 |
194 | if ( linked[0] == 0 )
195 | {
196 | Log.e ( "ESShader", "Error linking program:" );
197 | Log.e ( "ESShader", GLES20.glGetProgramInfoLog ( programObject ) );
198 | GLES20.glDeleteProgram ( programObject );
199 | return 0;
200 | }
201 |
202 | // Free up no longer needed shader resources
203 | GLES20.glDeleteShader ( vertexShader );
204 | GLES20.glDeleteShader ( fragmentShader );
205 |
206 | return programObject;
207 | }
208 |
209 | //
210 | ///
211 | /// \brief Load a vertex and fragment shader from "assets", create a program object, link
212 | /// program.
213 | /// Errors output to log.
214 | /// \param vertShaderFileName Vertex shader source file name
215 | /// \param fragShaderFileName Fragment shader source file name
216 | /// \return A new program object linked with the vertex/fragment shader
217 | /// pair, 0 on failure
218 | //
219 | public static int loadProgramFromAsset (Context context, String vertexShaderFileName, String fragShaderFileName )
220 | {
221 | int vertexShader;
222 | int fragmentShader;
223 | int programObject;
224 | int[] linked = new int[1];
225 |
226 | String vertShaderSrc = null;
227 | String fragShaderSrc = null;
228 |
229 | // Read vertex shader from assets
230 | vertShaderSrc = readShader ( context, vertexShaderFileName );
231 |
232 | if ( vertShaderSrc == null )
233 | {
234 | return 0;
235 | }
236 |
237 | // Read fragment shader from assets
238 | fragShaderSrc = readShader ( context, fragShaderFileName );
239 |
240 | if ( fragShaderSrc == null )
241 | {
242 | return 0;
243 | }
244 |
245 | // Load the vertex shader
246 | vertexShader = loadShader ( GLES20.GL_VERTEX_SHADER, vertShaderSrc );
247 |
248 | if ( vertexShader == 0 )
249 | {
250 | return 0;
251 | }
252 |
253 | // Load the fragment shader
254 | fragmentShader = loadShader ( GLES20.GL_FRAGMENT_SHADER, fragShaderSrc );
255 |
256 | if ( fragmentShader == 0 )
257 | {
258 | GLES20.glDeleteShader ( vertexShader );
259 | return 0;
260 | }
261 |
262 | // Create the program object
263 | programObject = GLES20.glCreateProgram();
264 |
265 | if ( programObject == 0 )
266 | {
267 | return 0;
268 | }
269 |
270 | GLES20.glAttachShader ( programObject, vertexShader );
271 | GLES20.glAttachShader ( programObject, fragmentShader );
272 |
273 | // Link the program
274 | GLES20.glLinkProgram ( programObject );
275 |
276 | // Check the link status
277 | GLES20.glGetProgramiv ( programObject, GLES20.GL_LINK_STATUS, linked, 0 );
278 |
279 | if ( linked[0] == 0 )
280 | {
281 | Log.e ( "ESShader", "Error linking program:" );
282 | Log.e ( "ESShader", GLES20.glGetProgramInfoLog ( programObject ) );
283 | GLES20.glDeleteProgram ( programObject );
284 | return 0;
285 | }
286 |
287 | // Free up no longer needed shader resources
288 | GLES20.glDeleteShader ( vertexShader );
289 | GLES20.glDeleteShader ( fragmentShader );
290 |
291 | return programObject;
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/ParticleLayer.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.opengl.GLES20;
6 |
7 | import com.yang.firework.utils.ESShader;
8 | import com.yang.firework.utils.RawResourceReader;
9 | import com.yang.firework.utils.TextureHelper;
10 |
11 | import java.nio.ByteBuffer;
12 | import java.nio.ByteOrder;
13 | import java.nio.FloatBuffer;
14 | import java.nio.ShortBuffer;
15 | import java.util.Arrays;
16 |
17 | import static android.opengl.GLES20.glUniformMatrix4fv;
18 |
19 | /**
20 | * Created by qinfeng on 16/8/4.
21 | */
22 |
23 | public class ParticleLayer extends ParticleSystem {
24 | private static final int POSITION_COMPONENT_COUNT = 2;
25 | private static final int COLOR_COMPONENT_COUNT = 4;
26 | private static final int COORD_COMPONENT_COUNT = 2;
27 | private static final int VERTEX_COMPONENT_COUNT =
28 | POSITION_COMPONENT_COUNT
29 | + COLOR_COMPONENT_COUNT
30 | + COORD_COMPONENT_COUNT;
31 | private static final int VERTEX_PER_QUAD = 4;
32 | private static final int QUAD_COMPONENT_COUNT = VERTEX_PER_QUAD * VERTEX_COMPONENT_COUNT;
33 |
34 |
35 | public static final int TL = 0;
36 | public static final int BL = 1;
37 | public static final int TR = 2;
38 | public static final int BR = 3;
39 |
40 | float[] _vertexs;
41 | short[] _indices;
42 | int [] _vboIds = {0,0};
43 |
44 | FloatBuffer _vertexsBuffer;
45 | ShortBuffer _indicesBuffer;
46 | private int mProgrammerHandle;
47 | private int mTextureHandle;
48 | private int textureUniformHandle;
49 | private int mPositionHandle;
50 | private int mColorHandle;
51 | private int mTexCoordHandle;
52 | private float[] projectionMatrix;
53 | private int mMatrixUniformHandle;
54 |
55 |
56 |
57 | // class Vec3 {
58 | // float x;
59 | // float y;
60 | // float z;
61 | // }
62 | // struct CC_DLL Color4B
63 | // {
64 | //
65 | // GLubyte r;
66 | // GLubyte g;
67 | // GLubyte b;
68 | // GLubyte a;
69 | //
70 | // };
71 |
72 | // struct CC_DLL Tex2F {
73 | // float u;
74 | // float v;
75 | // };
76 |
77 | // struct CC_DLL V3F_C4B_T2F
78 | // {
79 | // /// vertices (3F)
80 | // Vec3 vertices; // 12 bytes
81 | //
82 | // /// colors (4B)
83 | // Color4B colors; // 4 bytes
84 | //
85 | // // tex coords (2F)
86 | // Tex2F texCoords; // 8 bytes
87 | // };
88 | // struct CC_DLL V3F_C4B_T2F_Quad
89 | // {
90 | // /// top left
91 | // V3F_C4B_T2F tl;
92 | // /// bottom left
93 | // V3F_C4B_T2F bl;
94 | // /// top right
95 | // V3F_C4B_T2F tr;
96 | // /// bottom right
97 | // V3F_C4B_T2F br;
98 | // };
99 |
100 |
101 | public ParticleLayer(Context context, int plistFile, int resourceId ) {
102 | super(context, plistFile,resourceId);
103 |
104 |
105 | }
106 |
107 | ParticleLayer(Context context, int numberOfParticles) {
108 | super(context, numberOfParticles);
109 | }
110 |
111 |
112 | public void draw(){
113 | // Use the program object
114 | GLES20.glUseProgram ( mProgrammerHandle );
115 |
116 | // if ( _vboIds[0] == 0 && _vboIds[1] == 0 ) {
117 | // // Only allocate on the first draw
118 | // GLES20.glGenBuffers(2, _vboIds, 0);
119 | //
120 | // _vertexsBuffer.position(0);
121 | // GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, _vboIds[0]);
122 | // GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, VERTEX_COMPONENT_COUNT * 4 * _totalParticles,
123 | // _vertexsBuffer, GLES20.GL_DYNAMIC_DRAW);
124 | //
125 | // _indicesBuffer.position(0);
126 | // GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, _vboIds[1]);
127 | // GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, _indices.length * 2,
128 | // _indicesBuffer, GLES20.GL_STATIC_DRAW);
129 | // }
130 | // else {
131 | // _vertexsBuffer.position ( 0 );
132 | // GLES20.glBindBuffer ( GLES20.GL_ARRAY_BUFFER, _vboIds[0] );
133 | // GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0,VERTEX_COMPONENT_COUNT * 4 *_totalParticles,
134 | // _vertexsBuffer);
135 | // }
136 |
137 |
138 |
139 | // GLES20.glBindBuffer ( GLES20.GL_ARRAY_BUFFER, _vboIds[0] );
140 | // GLES20.glBindBuffer ( GLES20.GL_ELEMENT_ARRAY_BUFFER, _vboIds[1] );
141 |
142 | GLES20.glEnableVertexAttribArray ( mPositionHandle );
143 | GLES20.glEnableVertexAttribArray ( mColorHandle );
144 | GLES20.glEnableVertexAttribArray ( mTexCoordHandle );
145 |
146 | // Load the vertex position
147 | int dataOffset = 0;
148 | _vertexsBuffer.position (dataOffset);
149 | GLES20.glVertexAttribPointer ( mPositionHandle, POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT,
150 | false,
151 | VERTEX_COMPONENT_COUNT * 4, _vertexsBuffer);//dataOffset * 4
152 |
153 | // Load the color
154 | dataOffset += POSITION_COMPONENT_COUNT;
155 | _vertexsBuffer.position (dataOffset);
156 | GLES20.glVertexAttribPointer ( mColorHandle, COLOR_COMPONENT_COUNT, GLES20.GL_FLOAT,
157 | false,
158 | VERTEX_COMPONENT_COUNT * 4,
159 | _vertexsBuffer);
160 | // Load the texture coordinate
161 | dataOffset += COLOR_COMPONENT_COUNT;
162 | _vertexsBuffer.position (dataOffset);
163 | GLES20.glVertexAttribPointer ( mTexCoordHandle, COORD_COMPONENT_COUNT, GLES20.GL_FLOAT,
164 | false,
165 | VERTEX_COMPONENT_COUNT * 4,
166 | _vertexsBuffer );
167 |
168 |
169 | glUniformMatrix4fv(mMatrixUniformHandle, 1, false, projectionMatrix,0);
170 |
171 | // Bind the base map
172 | GLES20.glActiveTexture ( GLES20.GL_TEXTURE0 );
173 | GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, mTextureHandle);
174 |
175 | // Set the base map sampler to texture unit to 0
176 | GLES20.glUniform1i ( textureUniformHandle, 0 );
177 |
178 | GLES20.glDrawElements ( GLES20.GL_TRIANGLES, _indices.length, GLES20.GL_UNSIGNED_SHORT, _indicesBuffer);
179 | GLES20.glDisableVertexAttribArray ( mPositionHandle );
180 | GLES20.glDisableVertexAttribArray ( mColorHandle );
181 | GLES20.glDisableVertexAttribArray ( mTexCoordHandle );
182 |
183 | // GLES20.glBindBuffer ( GLES20.GL_ARRAY_BUFFER, 0 );
184 | // GLES20.glBindBuffer ( GLES20.GL_ELEMENT_ARRAY_BUFFER, 0 );
185 |
186 | }
187 |
188 |
189 |
190 | @Override
191 | boolean initWithTotalParticles(int maxParticles) {
192 | // base initialization
193 | if(super.initWithTotalParticles(maxParticles) ) {
194 | // _vertexs =new float[]
195 | // {
196 | // -1f, 1f,// Position 0
197 | // 1.0f,0.0f,0.0f,1.0f,
198 | // 0.0f, 0.0f, // TexCoord 0
199 | // -1f, -1f, // Position 1
200 | // 1.0f,0.0f,0.0f,1.0f,
201 | // 0.0f, 1.0f, // TexCoord 1
202 | // 1f, 1f, // Position 3
203 | // 1.0f,0.0f,0.0f,1.0f,
204 | // 1.0f, 0.0f , // TexCoord 3
205 | // 1f, -1f, // Position 2
206 | // 1.0f,0.0f,0.0f,1.0f,
207 | // 1.0f, 1.0f // TexCoord 2
208 | //
209 | // };
210 |
211 | // _indices = new short[]
212 | // {
213 | // 0, 1, 2, 3, 2, 1
214 | // };
215 | _vertexs = new float[_totalParticles * QUAD_COMPONENT_COUNT];
216 | _vertexsBuffer = ByteBuffer.allocateDirect(_vertexs.length * 4).order(ByteOrder.nativeOrder())
217 | .asFloatBuffer()
218 | .put(_vertexs);
219 | _vertexsBuffer.position(0);
220 |
221 |
222 | _indices = new short[_totalParticles * 6];
223 | initIndices();
224 | _indicesBuffer = ByteBuffer.allocateDirect(_indices.length * 2).order(ByteOrder.nativeOrder())
225 | .asShortBuffer()
226 | .put(_indices);
227 | _indicesBuffer.position(0);
228 |
229 |
230 |
231 |
232 |
233 | projectionMatrix = new float[16];
234 |
235 | createOrthographicOffCenter(0f,(float) _width,(float) _height,0f,-1024,1024,projectionMatrix);
236 |
237 | // MatrixHelper.perspectiveM(projectionMatrix, 45, (float) width
238 | // / (float) height, 1f, 10f);
239 |
240 | mProgrammerHandle = ESShader.loadProgram(RawResourceReader.readTextFileFromRawResource(context, R.raw.particle_vert), RawResourceReader.readTextFileFromRawResource(context,R.raw.particle_frag));
241 |
242 | mPositionHandle = GLES20.glGetAttribLocation(mProgrammerHandle, "a_position");
243 | mColorHandle = GLES20.glGetAttribLocation(mProgrammerHandle, "a_color");
244 | mTexCoordHandle = GLES20.glGetAttribLocation(mProgrammerHandle, "a_texCoord");
245 |
246 | mMatrixUniformHandle = GLES20.glGetUniformLocation(mProgrammerHandle, "u_matrix");
247 |
248 | textureUniformHandle = GLES20.glGetUniformLocation(mProgrammerHandle, "u_texture");
249 |
250 |
251 | return true;
252 | }
253 | return false;
254 | }
255 |
256 | @Override
257 | void setTexture(int resourceId) {
258 | mTextureHandle = TextureHelper.loadTexture(context,resourceId);
259 | initTexCoord();
260 |
261 | }
262 | @Override
263 | void setTexture(Bitmap texture) {
264 | mTextureHandle = TextureHelper.loadTexture(texture);
265 | initTexCoord();
266 |
267 | }
268 |
269 | @Override
270 | void updateQuadWithParticle(Particle particle, Vec2 newPosition) {
271 |
272 | updatePos(particle, newPosition);
273 | updateColor(particle);
274 | // initTexCoord();
275 |
276 | }
277 |
278 | @Override
279 | void clearData() {
280 | Arrays.fill(_vertexs,0);
281 | initTexCoord();
282 | }
283 |
284 | @Override
285 | public void updateBuffer() {
286 | //udpate _vertexsBuffer
287 | _vertexsBuffer.position(0);
288 | _vertexsBuffer.put(_vertexs);
289 | _vertexsBuffer.position(0);
290 |
291 | _indicesBuffer.position(0);
292 | _indicesBuffer.put(_indices);
293 | _indicesBuffer.position(0);
294 | }
295 | private void createOrthographicOffCenter(float left, float right, float bottom, float top,
296 | float zNearPlane, float zFarPlane, float[] dst) {
297 | dst[0] = 2 / (right - left);
298 | dst[5] = 2 / (top - bottom);
299 | dst[10] = 2 / (zNearPlane - zFarPlane);
300 |
301 | dst[12] = (left + right) / (left - right);
302 | dst[13] = (top + bottom) / (bottom - top);
303 | dst[14] = (zNearPlane + zFarPlane) / (zNearPlane - zFarPlane);
304 | dst[15] = 1;
305 | }
306 |
307 | private void updatePos(Particle particle, Vec2 newPosition) {
308 | // vertices
309 |
310 | float size_2 = particle.size/2;
311 | if (particle.rotation == 0f) {
312 | float x1 = -size_2;
313 | float y1 = -size_2;
314 |
315 | float x2 = size_2;
316 | float y2 = size_2;
317 | float x = newPosition.x;
318 | float y = newPosition.y;
319 |
320 | float r = -CC_DEGREES_TO_RADIANS(particle.rotation);
321 | float cr =(float) Math.cos(r);
322 | float sr =(float) Math.sin(r);
323 | float ax = x1 * cr - y1 * sr + x;
324 | float ay = x1 * sr + y1 * cr + y;
325 | float bx = x2 * cr - y1 * sr + x;
326 | float by = x2 * sr + y1 * cr + y;
327 | float cx = x2 * cr - y2 * sr + x;
328 | float cy = x2 * sr + y2 * cr + y;
329 | float dx = x1 * cr - y2 * sr + x;
330 | float dy = x1 * sr + y2 * cr + y;
331 |
332 |
333 | ax *=_density;
334 | ay *= _density;
335 | bx *= _density;
336 | by *= _density;
337 | cx *= _density;
338 | cy *= _density;
339 | dx *= _density;
340 | dy *= _density;
341 |
342 |
343 | // bottom-left
344 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
345 | + (BL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
346 | + 0 % POSITION_COMPONENT_COUNT] = ax;
347 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
348 | + (BL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
349 | + 1 % POSITION_COMPONENT_COUNT] = ay;
350 | // bottom-right vertex:
351 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
352 | +(BR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
353 | + 0 % POSITION_COMPONENT_COUNT] = bx;
354 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
355 | +(BR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
356 | + 1 % POSITION_COMPONENT_COUNT] = by;
357 | // top-left vertex:
358 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
359 | + (TL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
360 | + 0 % POSITION_COMPONENT_COUNT] = dx;
361 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
362 | + (TL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
363 | + 1 % POSITION_COMPONENT_COUNT] = dy;
364 |
365 | // top-right vertex:
366 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
367 | + (TR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
368 | + 0 % POSITION_COMPONENT_COUNT] = cx;
369 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
370 | + (TR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
371 | + 1 % POSITION_COMPONENT_COUNT] = cy;
372 | } else {
373 |
374 | // bottom-left
375 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
376 | + (BL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
377 | + 0 % POSITION_COMPONENT_COUNT] = (newPosition.x - size_2) * _density;
378 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
379 | + (BL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
380 | + 1 % POSITION_COMPONENT_COUNT] = (newPosition.y - size_2) * _density;
381 | // bottom-right vertex:
382 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
383 | + (BR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
384 | + 0 % POSITION_COMPONENT_COUNT] = (newPosition.x + size_2) * _density;
385 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
386 | + (BR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
387 | + 1 % POSITION_COMPONENT_COUNT] = (newPosition.y - size_2) * _density;
388 | // top-left vertex:
389 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
390 | + (TL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
391 | + 0 % POSITION_COMPONENT_COUNT] = (newPosition.x - size_2) * _density;
392 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
393 | + (TL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
394 | + 1 % POSITION_COMPONENT_COUNT] = (newPosition.y + size_2) * _density;
395 |
396 | // top-right vertex:
397 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
398 | + (TR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
399 | + 0 % POSITION_COMPONENT_COUNT] = (newPosition.x + size_2) * _density;
400 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
401 | + (TR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
402 | + 1 % POSITION_COMPONENT_COUNT] = (newPosition.y + size_2) * _density;
403 | }
404 | }
405 |
406 | private void updateColor(Particle particle) {
407 | // bottom-left vertex:
408 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
409 | + (BL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
410 | + POSITION_COMPONENT_COUNT
411 | + 0 % COLOR_COMPONENT_COUNT] = particle.color.r;
412 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
413 | + (BL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
414 | + POSITION_COMPONENT_COUNT
415 | + 1 % COLOR_COMPONENT_COUNT] = particle.color.g;
416 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
417 | + (BL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
418 | + POSITION_COMPONENT_COUNT
419 | + 2 % COLOR_COMPONENT_COUNT] = particle.color.b;
420 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
421 | + (BL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
422 | + POSITION_COMPONENT_COUNT
423 | + 3 % COLOR_COMPONENT_COUNT] = particle.color.a;
424 | // bottom-right vertex:
425 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
426 | + (BR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
427 | + POSITION_COMPONENT_COUNT
428 | + 0 % COLOR_COMPONENT_COUNT] = particle.color.r;
429 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
430 | + (BR % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT
431 | + POSITION_COMPONENT_COUNT
432 | + 1 % COLOR_COMPONENT_COUNT] = particle.color.g;
433 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
434 | + (BR % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT
435 | + POSITION_COMPONENT_COUNT
436 | + 2 % COLOR_COMPONENT_COUNT] = particle.color.b;
437 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
438 | + (BR % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT
439 | + POSITION_COMPONENT_COUNT
440 | + 3 % COLOR_COMPONENT_COUNT] = particle.color.a;
441 | // top-left vertex:
442 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
443 | + (TL % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT
444 | + POSITION_COMPONENT_COUNT
445 | + 0 % COLOR_COMPONENT_COUNT] = particle.color.r;
446 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
447 | + (TL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
448 | + POSITION_COMPONENT_COUNT
449 | + 1 % COLOR_COMPONENT_COUNT] = particle.color.g;
450 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
451 | + (TL % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
452 | + POSITION_COMPONENT_COUNT
453 | + 2 % COLOR_COMPONENT_COUNT] = particle.color.b;
454 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
455 | + (TL % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT
456 | + POSITION_COMPONENT_COUNT
457 | + 3 % COLOR_COMPONENT_COUNT] = particle.color.a;
458 | // top-right vertex:
459 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
460 | + (TR % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT
461 | + POSITION_COMPONENT_COUNT
462 | + 0 % COLOR_COMPONENT_COUNT] = particle.color.r;
463 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
464 | + (TR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
465 | + POSITION_COMPONENT_COUNT
466 | + 1 % COLOR_COMPONENT_COUNT] = particle.color.g;
467 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
468 | + (TR % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT
469 | + POSITION_COMPONENT_COUNT
470 | + 2 % COLOR_COMPONENT_COUNT] = particle.color.b;
471 | _vertexs[_particleIdx * QUAD_COMPONENT_COUNT
472 | + (TR % VERTEX_PER_QUAD) * VERTEX_COMPONENT_COUNT
473 | + POSITION_COMPONENT_COUNT
474 | + 3 % COLOR_COMPONENT_COUNT] = particle.color.a;
475 | }
476 |
477 | private void initTexCoord() {
478 | for(int i=0; i<_totalParticles; i++)
479 | {
480 | // bottom-left vertex:
481 | _vertexs[i * QUAD_COMPONENT_COUNT
482 | + (BL % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT+ POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT
483 | + 0 % COORD_COMPONENT_COUNT] = 0.0f;
484 | _vertexs[i * QUAD_COMPONENT_COUNT
485 | + (BL % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT+ POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT
486 | + 1 % COORD_COMPONENT_COUNT] = 1.0f;
487 | // bottom-right vertex:
488 | _vertexs[i * QUAD_COMPONENT_COUNT
489 | + (BR % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT+ POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT
490 | + 0 % COORD_COMPONENT_COUNT] = 1.0f;
491 | _vertexs[i * QUAD_COMPONENT_COUNT
492 | + (BR % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT+ POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT
493 | + 1 % COORD_COMPONENT_COUNT] = 1.0f;
494 | // top-left vertex:
495 | _vertexs[i * QUAD_COMPONENT_COUNT
496 | + (TL % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT+ POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT
497 | + 0 % COORD_COMPONENT_COUNT] = 0.0f;
498 | _vertexs[i * QUAD_COMPONENT_COUNT
499 | + (TL % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT+ POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT
500 | + 1 % COORD_COMPONENT_COUNT] = 0.0f;
501 | // top-right vertex:
502 | _vertexs[i * QUAD_COMPONENT_COUNT
503 | + (TR % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT+ POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT
504 | + 0 % COORD_COMPONENT_COUNT] = 1.0f;
505 | _vertexs[i * QUAD_COMPONENT_COUNT
506 | + (TR % VERTEX_PER_QUAD ) * VERTEX_COMPONENT_COUNT+ POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT
507 | + 1 % COORD_COMPONENT_COUNT] = 0.0f;
508 | }
509 | }
510 |
511 | // @Override
512 | // public void setTotalParticles(int tp) {
513 | // super.setTotalParticles(tp);
514 | // // If we are setting the total number of particles to a number higher
515 | // // than what is allocated, we need to allocate new arrays
516 | // if( tp > _allocatedParticles ) {
517 | // // Allocate new memory
518 | // size_t particlesSize = tp * sizeof(tParticle);
519 | // size_t quadsSize = sizeof(_quads[0]) * tp * 1;
520 | // size_t indicesSize = sizeof(_indices[0]) * tp * 6 * 1;
521 | //
522 | // tParticle* particlesNew = (tParticle*)realloc(_particles, particlesSize);
523 | // V3F_C4B_T2F_Quad* quadsNew = (V3F_C4B_T2F_Quad*)realloc(_quads, quadsSize);
524 | // GLushort* indicesNew = (GLushort*)realloc(_indices, indicesSize);
525 | //
526 | // if (particlesNew && quadsNew && indicesNew)
527 | // {
528 | // // Assign pointers
529 | // _particles = particlesNew;
530 | // _quads = quadsNew;
531 | // _indices = indicesNew;
532 | //
533 | // // Clear the memory
534 | // memset(_particles, 0, particlesSize);
535 | // memset(_quads, 0, quadsSize);
536 | // memset(_indices, 0, indicesSize);
537 | //
538 | // _allocatedParticles = tp;
539 | // }
540 | // else
541 | // {
542 | // // Out of memory, failed to resize some array
543 | // if (particlesNew) _particles = particlesNew;
544 | // if (quadsNew) _quads = quadsNew;
545 | // if (indicesNew) _indices = indicesNew;
546 | //
547 | // CCLOG("Particle system: out of memory");
548 | // return;
549 | // }
550 | //
551 | // _totalParticles = tp;
552 | //
553 | // // Init particles
554 | // if (_batchNode)
555 | // {
556 | // for (int i = 0; i < _totalParticles; i++)
557 | // {
558 | // _particles[i].atlasIndex=i;
559 | // }
560 | // }
561 | //
562 | // initIndices();
563 | // if (Configuration::getInstance().supportsShareableVAO())
564 | // {
565 | // setupVBOandVAO();
566 | // }
567 | // else
568 | // {
569 | // setupVBO();
570 | // }
571 | //
572 | // // fixed http://www.cocos2d-x.org/issues/3990
573 | // // Updates texture coords.
574 | // updateTexCoords();
575 | // } else {
576 | // _totalParticles = tp;
577 | // }
578 | //
579 | // // fixed issue #5762
580 | // // reset the emission rate
581 | // setEmissionRate(_totalParticles / _life);
582 | //
583 | // resetSystem();
584 | // }
585 |
586 |
587 | private void initIndices()
588 | {
589 | for(short i = 0; i < _totalParticles; ++i)
590 | {
591 | short i6 = (short) (i*6);
592 | short i4 = (short) (i*4);
593 | _indices[i6+0] = (short) (i4+0);
594 | _indices[i6+1] = (short) (i4+1);
595 | _indices[i6+2] = (short) (i4+2);
596 |
597 | _indices[i6+5] = (short) (i4+1);
598 | _indices[i6+4] = (short) (i4+2);
599 | _indices[i6+3] = (short) (i4+3);
600 | }
601 | }
602 | }
603 |
--------------------------------------------------------------------------------
/firework/src/main/java/com/yang/firework/ParticleSystem.java:
--------------------------------------------------------------------------------
1 | package com.yang.firework;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.util.DisplayMetrics;
6 |
7 | import com.dd.plist.NSDictionary;
8 | import com.dd.plist.NSNumber;
9 | import com.dd.plist.PropertyListParser;
10 |
11 | import java.io.InputStream;
12 | import java.util.ArrayList;
13 | import java.util.Collections;
14 | import java.util.List;
15 | import java.util.Random;
16 |
17 |
18 | /**
19 | * Created by qinfeng on 16/8/4.
20 | */
21 |
22 | public abstract class ParticleSystem {
23 |
24 | /** Creates an initializes a ParticleSystem from a plist file.
25 | This plist files can be created manually or with Particle Designer:
26 | http://particledesigner.71squared.com/
27 | */
28 | ParticleSystem(Context context, int plistFile, int resourceId) {
29 | this.context = context;
30 | initWithFile(plistFile,resourceId);
31 |
32 | }
33 |
34 | public void update(float dt) {
35 | if (_isActive && _emissionRate != 0f)
36 | {
37 | float rate = 1.0f / 30;
38 | //issue #1201, prevent bursts of particles, due to too high emitCounter
39 | if (_particleCount < _totalParticles)
40 | {
41 | _emitCounter += dt;
42 | }
43 |
44 | while (_particleCount < _totalParticles && _emitCounter > rate )
45 | {
46 | addParticle();
47 | _emitCounter -= rate;
48 | }
49 |
50 |
51 |
52 | _elapsed += dt;
53 | if (_duration != -1 && _duration < _elapsed)
54 | {
55 | // stopSystem();
56 | }
57 | }
58 |
59 | _particleIdx = 0;
60 |
61 | Vec2 currentPosition = new Vec2(0f,0f);
62 | if (_positionType == PositionType.FREE)
63 | {
64 | currentPosition = new Vec2(0f,0f);
65 | }
66 | else if (_positionType == PositionType.RELATIVE)
67 | {
68 | currentPosition = _position;
69 | }
70 |
71 |
72 | {
73 |
74 | clearData();
75 |
76 | Vec2 newPos = new Vec2(0f,0f);
77 | Vec2 radial= new Vec2(0f,0f);
78 | Vec2 tangential= new Vec2(0f,0f);
79 |
80 | while (_particleIdx < _particleCount)
81 | {
82 | Particle p = _particles.get(_particleIdx);
83 |
84 | // life
85 | p.timeToLive -= dt;
86 |
87 |
88 |
89 | if (p.timeToLive > 0) {
90 | // Mode A: gravity, direction, tangential accel & radial accel
91 | if (_emitterMode == Mode.GRAVITY) {
92 |
93 | radial.x = 0f;
94 | radial.y = 0f;
95 | tangential.x = 0f;
96 | tangential.y = 0f;
97 |
98 | // radial acceleration
99 | if (p.pos.x != 0|| p.pos.y != 0) {
100 | radial.x = p.pos.x / (float) Math.sqrt(p.pos.x * p.pos.x + p.pos.y * p.pos.y);
101 | radial.y = p.pos.y / (float) Math.sqrt(p.pos.x * p.pos.x + p.pos.y * p.pos.y);
102 | }
103 | tangential = radial;
104 | radial.x = radial.x * p.modeA.radialAccel;
105 | radial.y = radial.y * p.modeA.radialAccel;
106 |
107 | // tangential acceleration
108 | float newy = tangential.x;
109 | tangential.x = -tangential.y;
110 | tangential.y = newy;
111 |
112 | tangential.x = tangential.x * p.modeA.tangentialAccel;
113 | tangential.y = tangential.y * p.modeA.tangentialAccel;
114 | // (gravity + radial + tangential) * dt
115 | p.modeA.dir.x = p.modeA.dir.x + ((radial.x + tangential.x + gravityX) * dt);
116 | p.modeA.dir.y = p.modeA.dir.y + ((radial.y + tangential.y + gravityY) * dt);
117 |
118 |
119 | p.pos.x = p.pos.x + (p.modeA.dir.x * dt * _yCoordFlipped);
120 | p.pos.y = p.pos.y + (p.modeA.dir.y * dt * _yCoordFlipped);
121 |
122 | } else {
123 | // Mode B: radius movement
124 | // Update the angle and radius of the particle.
125 | p.modeB.angle += p.modeB.degreesPerSecond * dt;
126 | p.modeB.radius += p.modeB.deltaRadius * dt;
127 |
128 | p.pos.x = -(float) Math.cos(p.modeB.angle) * p.modeB.radius;
129 | p.pos.y = - (float) Math.sin(p.modeB.angle) * p.modeB.radius;
130 | p.pos.y *= _yCoordFlipped;
131 | }
132 |
133 | // color
134 | p.color.r += (p.deltaColor.r * dt);
135 | p.color.g += (p.deltaColor.g * dt);
136 | p.color.b += (p.deltaColor.b * dt);
137 | p.color.a += (p.deltaColor.a * dt);
138 |
139 | // diameter
140 | p.size += (p.deltaSize * dt);
141 | p.size = Math.max( 0, p.size );
142 |
143 | // angle
144 | p.rotation += (p.deltaRotation * dt);
145 |
146 | //
147 | // update values in quad
148 | //
149 |
150 |
151 |
152 | if (_positionType == PositionType.FREE) { // p.startPos == VEC2_ZERO
153 | newPos.x = p.pos.x - (currentPosition.x - p.startPos.x) + _position.x;
154 | newPos.y = p.pos.y - (currentPosition.y - p.startPos.y) + _position.y;
155 | } else if(_positionType == PositionType.RELATIVE) {
156 |
157 | newPos.x = p.pos.x - (currentPosition.x - p.startPos.x);
158 | newPos.y = p.pos.y - (currentPosition.y - p.startPos.y);
159 | } else {
160 | newPos = p.pos;
161 | }
162 |
163 | // translate newPos to correct _position, since matrix transform isn't performed in batchnode
164 | // don't update the particle with the new _position information, it will interfere with the radius and tangential calculations
165 | if (_batchNode) {
166 | // newPos.x+=_position.x;
167 | // newPos.y+=_position.y;
168 | }
169 |
170 | updateQuadWithParticle(p, newPos);
171 | //updateParticleImp(self, updateParticleSel, p, newPos);
172 |
173 | // update particle counter
174 | ++_particleIdx;
175 | } else {
176 | // life < 0
177 | int currentIndex = p.atlasIndex;
178 | if( _particleIdx != _particleCount-1 ) {
179 |
180 | Collections.rotate(_particles.subList(_particleIdx, _particleCount), -1);
181 | // particle = _particles.get(_particleCount-1);
182 | }
183 | if (_batchNode) {
184 | // //disable the switched particle
185 | // _batchNode.disableParticle(_atlasIndex+currentIndex);
186 | //
187 | // //switch indexes
188 | // _particles[_particleCount-1].atlasIndex = currentIndex;
189 | }
190 |
191 |
192 | --_particleCount;
193 |
194 | if( _particleCount == 0 && _isAutoRemoveOnFinish ) {
195 | _unschedule = true;
196 | return;
197 | }
198 | }
199 | } //while
200 | _transformSystemDirty = false;
201 | }
202 |
203 | // only update gl buffer when visible
204 | if (_visible) {
205 |
206 | postStep();
207 | }
208 |
209 | }
210 | abstract void setTexture(int resourceId);
211 | abstract void setTexture(Bitmap texture);
212 | public abstract void updateBuffer();
213 |
214 | public abstract void draw();
215 |
216 | abstract void updateQuadWithParticle(Particle particle, Vec2 newPosition);
217 | abstract void clearData();
218 |
219 |
220 | private void initWithFile(int plistFile,int resourceId) {
221 | final InputStream inputStream = context.getResources().openRawResource(
222 | plistFile);
223 |
224 | try {
225 | NSDictionary rootDict = (NSDictionary) PropertyListParser.parse(inputStream);
226 | do
227 | {
228 | int maxParticles = ((NSNumber)rootDict.get("maxParticles")).intValue();
229 |
230 | //// texture
231 | //// Try to get the texture from the cache
232 | // String textureName = ((NSString)rootDict.get("textureFileName")).toString();
233 | //
234 | // int index = textureName.indexOf(".");
235 | // if (index > 0)
236 | // textureName = textureName.substring(0, index);
237 | //
238 | // Resources resources = context.getResources();
239 | // final int resourceId = resources.getIdentifier(textureName, "drawable",
240 | // context.getPackageName());
241 |
242 | setTexture(resourceId);
243 |
244 | // self, not super
245 | if(initWithTotalParticles(maxParticles))
246 | {
247 | // Emitter name in particle designer 2.0
248 | // _configName =((NSString)rootDict.get("configName")).toString();
249 |
250 | // angle
251 | _angle = ((NSNumber)rootDict.get("angle")).floatValue();
252 | _angleVar = ((NSNumber)rootDict.get("angleVariance")).floatValue();
253 |
254 | // duration
255 | _duration =((NSNumber)rootDict.get("duration")).floatValue();
256 |
257 | // blend function
258 | // if (_configName.length()>0)
259 | // {
260 | // _blendFunc.src = ((NSNumber)rootDict.get("blendFuncSource")).intValue();
261 | // }
262 | // else
263 | // {
264 | // _blendFunc.src = ((NSNumber)rootDict.get("blendFuncSource")).intValue();
265 | // }
266 |
267 |
268 | _blendFunc.src = ((NSNumber)rootDict.get("blendFuncSource")).intValue();
269 | _blendFunc.dst = ((NSNumber)rootDict.get("blendFuncDestination")).intValue();
270 |
271 | // color
272 | _startColor.r = ((NSNumber)rootDict.get("startColorRed")).floatValue();
273 | _startColor.g = ((NSNumber)rootDict.get("startColorGreen")).floatValue();
274 | _startColor.b = ((NSNumber)rootDict.get("startColorBlue")).floatValue();
275 | _startColor.a = ((NSNumber)rootDict.get("startColorAlpha")).floatValue();
276 |
277 | _startColorVar.r = ((NSNumber)rootDict.get("startColorVarianceRed")).floatValue();
278 | _startColorVar.g = ((NSNumber)rootDict.get("startColorVarianceGreen")).floatValue();
279 | _startColorVar.b = ((NSNumber)rootDict.get("startColorVarianceBlue")).floatValue();
280 | _startColorVar.a = ((NSNumber)rootDict.get("startColorVarianceAlpha")).floatValue();
281 |
282 | _endColor.r = ((NSNumber)rootDict.get("finishColorRed")).floatValue();
283 | _endColor.g = ((NSNumber)rootDict.get("finishColorGreen")).floatValue();
284 | _endColor.b = ((NSNumber)rootDict.get("finishColorBlue")).floatValue();
285 | _endColor.a = ((NSNumber)rootDict.get("finishColorAlpha")).floatValue();
286 |
287 | _endColorVar.r = ((NSNumber)rootDict.get("finishColorVarianceRed")).floatValue();
288 | _endColorVar.g = ((NSNumber)rootDict.get("finishColorVarianceGreen")).floatValue();
289 | _endColorVar.b = ((NSNumber)rootDict.get("finishColorVarianceBlue")).floatValue();
290 | _endColorVar.a = ((NSNumber)rootDict.get("finishColorVarianceAlpha")).floatValue();
291 |
292 | // particle diameter
293 | _startSize = ((NSNumber)rootDict.get("startParticleSize")).floatValue();
294 | _startSizeVar = ((NSNumber)rootDict.get("startParticleSizeVariance")).floatValue();
295 | _endSize = ((NSNumber)rootDict.get("finishParticleSize")).floatValue();
296 | _endSizeVar = ((NSNumber)rootDict.get("finishParticleSizeVariance")).floatValue();
297 |
298 | // _position
299 | float x = ((NSNumber)rootDict.get("sourcePositionx")).floatValue();
300 | float y = ((NSNumber)rootDict.get("sourcePositiony")).floatValue();
301 | _position = new Vec2(x,y);
302 | _posVar.x = ((NSNumber)rootDict.get("sourcePositionVariancex")).floatValue();
303 | _posVar.y = ((NSNumber)rootDict.get("sourcePositionVariancey")).floatValue();
304 |
305 | // Spinning
306 | _startSpin = ((NSNumber)rootDict.get("rotationStart")).floatValue();
307 | _startSpinVar = ((NSNumber)rootDict.get("rotationStartVariance")).floatValue();
308 | _endSpin= ((NSNumber)rootDict.get("rotationEnd")).floatValue();
309 | _endSpinVar= ((NSNumber)rootDict.get("rotationEndVariance")).floatValue();
310 | if (((NSNumber)rootDict.get("emitterType")).intValue() == 0){
311 | _emitterMode = Mode.GRAVITY;
312 | }else if (((NSNumber)rootDict.get("emitterType")).intValue() == 1) {
313 | _emitterMode = Mode.RADIUS;
314 | }
315 |
316 |
317 |
318 | // Mode A: Gravity + tangential accel + radial accel
319 | if (_emitterMode == Mode.GRAVITY)
320 | {
321 | //TODO modeA.gravity.x always changed
322 | // gravity
323 | modeA.gravity.x = ((NSNumber)rootDict.get("gravityx")).floatValue();
324 | modeA.gravity.y = ((NSNumber)rootDict.get("gravityy")).floatValue();
325 |
326 | gravityX = ((NSNumber)rootDict.get("gravityx")).floatValue();
327 | gravityY = ((NSNumber)rootDict.get("gravityy")).floatValue();
328 | // speed
329 | modeA.speed = ((NSNumber)rootDict.get("speed")).floatValue();
330 | modeA.speedVar = ((NSNumber)rootDict.get("speedVariance")).floatValue();
331 |
332 | // radial acceleration
333 | modeA.radialAccel = ((NSNumber)rootDict.get("radialAcceleration")).floatValue();
334 | modeA.radialAccelVar = ((NSNumber)rootDict.get("radialAccelVariance")).floatValue();
335 |
336 | // tangential acceleration
337 | modeA.tangentialAccel = ((NSNumber)rootDict.get("tangentialAcceleration")).floatValue();
338 | modeA.tangentialAccelVar = ((NSNumber)rootDict.get("tangentialAccelVariance")).floatValue();
339 |
340 | // rotation is dir
341 | // modeA.rotationIsDir = ((NSNumber)rootDict.get("rotationIsDir")).boolValue();
342 | }
343 |
344 | // or Mode B: radius movement
345 | else if (_emitterMode == Mode.RADIUS)
346 | {
347 | // if (_configName.length()>0)
348 | // {
349 | // modeB.startRadius = ((NSNumber)rootDict.get("maxRadius")).intValue();
350 | // }
351 | // else
352 | // {
353 | // modeB.startRadius = ((NSNumber)rootDict.get("maxRadius")).floatValue();
354 | // }
355 | modeB.startRadius = ((NSNumber)rootDict.get("maxRadius")).floatValue();
356 | modeB.startRadiusVar = ((NSNumber)rootDict.get("maxRadiusVariance")).floatValue();
357 | // if (_configName.length()>0)
358 | // {
359 | // modeB.endRadius = ((NSNumber)rootDict.get("minRadius")).intValue();
360 | // }
361 | // else
362 | // {
363 | // modeB.endRadius = ((NSNumber)rootDict.get("minRadius")).floatValue();
364 | // }
365 | modeB.endRadius = ((NSNumber)rootDict.get("minRadius")).floatValue();
366 |
367 | if (rootDict.get("minRadiusVariance") != null)
368 | {
369 | modeB.endRadiusVar = ((NSNumber)rootDict.get("minRadiusVariance")).floatValue();
370 | }
371 | else
372 | {
373 | modeB.endRadiusVar = 0.0f;
374 | }
375 |
376 | // if (_configName.length()>0)
377 | // {
378 | // modeB.rotatePerSecond = ((NSNumber)rootDict.get("rotatePerSecond")).intValue();
379 | // }
380 | // else
381 | // {
382 | // modeB.rotatePerSecond = ((NSNumber)rootDict.get("rotatePerSecond")).floatValue();
383 | // }
384 | modeB.rotatePerSecond = ((NSNumber)rootDict.get("rotatePerSecond")).floatValue();
385 | modeB.rotatePerSecondVar = ((NSNumber)rootDict.get("rotatePerSecondVariance")).floatValue();
386 |
387 | }
388 |
389 | // life span
390 | _life = ((NSNumber)rootDict.get("particleLifespan")).floatValue();
391 | _lifeVar = ((NSNumber)rootDict.get("particleLifespanVariance")).floatValue();
392 |
393 | // emission Rate
394 | _emissionRate = _totalParticles / _life ;
395 |
396 |
397 | }
398 | } while (false);
399 |
400 | } catch (Exception e) {
401 | e.printStackTrace();
402 | }
403 |
404 | }
405 |
406 |
407 |
408 |
409 | boolean initWithTotalParticles(int totalParticles) {
410 | _totalParticles = totalParticles;
411 | _particles = new ArrayList<>(totalParticles);
412 | for (int i = 0; i < totalParticles; i++) {
413 | _particles.add(new Particle());
414 | }
415 | DisplayMetrics metrics = context.getResources().getDisplayMetrics();
416 | _density = metrics.density;
417 | _width = metrics.widthPixels;
418 | _height = metrics.heightPixels;
419 |
420 | // default, active
421 | _isActive = true;
422 |
423 | // default blend function
424 | _blendFunc = new BlendFunc(Constants.GL_ONE, Constants.GL_ONE_MINUS_SRC_ALPHA);
425 |
426 | // default movement type;
427 | _positionType = PositionType.FREE;
428 |
429 | // by default be in mode A:
430 | _emitterMode = Mode.GRAVITY;
431 |
432 | // default: modulate
433 | // FIXME. not used
434 | // colorModulate = YES;
435 |
436 | _isAutoRemoveOnFinish = false;
437 |
438 | // Optimization: compile updateParticle method
439 | //updateParticleSel = @selector(updateQuadWithParticle:newPosition:);
440 | //updateParticleImp = (CC_UPDATE_PARTICLE_IMP) [self methodForSelector:updateParticleSel];
441 | //for batchNode
442 | _transformSystemDirty = false;
443 |
444 | return true;
445 | }
446 |
447 | /** Create a system with a fixed number of particles.
448 | *
449 | * @param numberOfParticles A given number of particles.
450 | * @return An autoreleased ParticleSystemQuad object.
451 | * @js NA
452 | */
453 | ParticleSystem(Context context, int numberOfParticles) {
454 | this.context = context;
455 | initWithTotalParticles(numberOfParticles);
456 |
457 | }
458 |
459 | /** Add a particle to the emitter.
460 | *
461 | * @return True if add success.
462 | * @js ctor
463 | */
464 | boolean addParticle() {
465 | if (isFull())
466 | {
467 | return false;
468 | }
469 |
470 | Particle particle = _particles.get(_particleCount);
471 | initParticle(particle);
472 | ++_particleCount;
473 | return true;
474 | }
475 |
476 | /** Initializes a particle.
477 | *
478 | * @param particle A given particle pointer.
479 | */
480 | void initParticle(Particle particle) {
481 | // timeToLive
482 | // no negative life. prevent division by 0
483 | particle.timeToLive = _life + _lifeVar * CCRANDOM_MINUS1_1();
484 | particle.timeToLive = Math.abs(particle.timeToLive );
485 | particle.timeToLive = Math.max(0.1f, particle.timeToLive);
486 |
487 | //TODO fix timeToLive is 0 bug
488 |
489 | // position
490 | particle.pos.x = _sourcePosition.x + _posVar.x * CCRANDOM_MINUS1_1();
491 |
492 | particle.pos.y = _sourcePosition.y + _posVar.y * CCRANDOM_MINUS1_1();
493 |
494 |
495 | // Color
496 | Color4F start = new Color4F();
497 | start.r = clampf(_startColor.r + _startColorVar.r * CCRANDOM_MINUS1_1(), 0, 1);
498 | start.g = clampf(_startColor.g + _startColorVar.g * CCRANDOM_MINUS1_1(), 0, 1);
499 | start.b = clampf(_startColor.b + _startColorVar.b * CCRANDOM_MINUS1_1(), 0, 1);
500 | start.a = clampf(_startColor.a + _startColorVar.a * CCRANDOM_MINUS1_1(), 0, 1);
501 |
502 | Color4F end = new Color4F();
503 | end.r = clampf(_endColor.r + _endColorVar.r * CCRANDOM_MINUS1_1(), 0, 1);
504 | end.g = clampf(_endColor.g + _endColorVar.g * CCRANDOM_MINUS1_1(), 0, 1);
505 | end.b = clampf(_endColor.b + _endColorVar.b * CCRANDOM_MINUS1_1(), 0, 1);
506 | end.a = clampf(_endColor.a + _endColorVar.a * CCRANDOM_MINUS1_1(), 0, 1);
507 |
508 | particle.color = start;
509 | particle.deltaColor.r = (end.r - start.r) / particle.timeToLive;
510 | particle.deltaColor.g = (end.g - start.g) / particle.timeToLive;
511 | particle.deltaColor.b = (end.b - start.b) / particle.timeToLive;
512 | particle.deltaColor.a = (end.a - start.a) / particle.timeToLive;
513 |
514 | // diameter
515 | float startS = _startSize + _startSizeVar * CCRANDOM_MINUS1_1();
516 | startS = Math.max(0, startS); // No negative value
517 |
518 | particle.size = startS;
519 |
520 | if (_endSize == START_SIZE_EQUAL_TO_END_SIZE)
521 | {
522 | particle.deltaSize = 0;
523 | }
524 | else
525 | {
526 | float endS = _endSize + _endSizeVar * CCRANDOM_MINUS1_1();
527 | endS = Math.max(0, endS); // No negative values
528 | particle.deltaSize = (endS - startS) / particle.timeToLive;
529 | }
530 |
531 | // rotation
532 | float startA = _startSpin + _startSpinVar * CCRANDOM_MINUS1_1();
533 | float endA = _endSpin + _endSpinVar * CCRANDOM_MINUS1_1();
534 | particle.rotation = startA;
535 | particle.deltaRotation = (endA - startA) / particle.timeToLive;
536 |
537 | // position
538 | if (_positionType == PositionType.FREE)
539 | {
540 | particle.startPos = new Vec2(0f,0f);
541 | }
542 | else if (_positionType == PositionType.RELATIVE)
543 | {
544 | particle.startPos = _position;
545 | }
546 |
547 | // direction
548 | float a = CC_DEGREES_TO_RADIANS( _angle + _angleVar * CCRANDOM_MINUS1_1() );
549 |
550 | // Mode Gravity: A
551 | if (_emitterMode == Mode.GRAVITY)
552 | {
553 | Vec2 v = new Vec2((float) Math.cos(a), (float) Math.sin(a));
554 | float s = modeA.speed + modeA.speedVar * CCRANDOM_MINUS1_1();
555 |
556 | // direction
557 | particle.modeA.dir = v.scale(s) ;
558 |
559 | // radial accel
560 | particle.modeA.radialAccel = modeA.radialAccel + modeA.radialAccelVar * CCRANDOM_MINUS1_1();
561 |
562 |
563 | // tangential accel
564 | particle.modeA.tangentialAccel = modeA.tangentialAccel + modeA.tangentialAccelVar * CCRANDOM_MINUS1_1();
565 |
566 | // rotation is dir
567 | if(modeA.rotationIsDir)
568 | particle.rotation = -CC_RADIANS_TO_DEGREES(particle.modeA.dir.getAngle());
569 | }
570 |
571 | // Mode Radius: B
572 | else
573 | {
574 | // Set the default diameter of the particle from the source position
575 | float startRadius = modeB.startRadius + modeB.startRadiusVar * CCRANDOM_MINUS1_1();
576 | float endRadius = modeB.endRadius + modeB.endRadiusVar * CCRANDOM_MINUS1_1();
577 |
578 | particle.modeB.radius = startRadius;
579 |
580 | if (modeB.endRadius == START_RADIUS_EQUAL_TO_END_RADIUS)
581 | {
582 | particle.modeB.deltaRadius = 0;
583 | }
584 | else
585 | {
586 | particle.modeB.deltaRadius = (endRadius - startRadius) / particle.timeToLive;
587 | }
588 |
589 | particle.modeB.angle = a;
590 | particle.modeB.degreesPerSecond = CC_DEGREES_TO_RADIANS(modeB.rotatePerSecond + modeB.rotatePerSecondVar * CCRANDOM_MINUS1_1());
591 | }
592 | }
593 |
594 | public void setTotalParticles(int var) {
595 | _totalParticles = var;
596 | }
597 |
598 |
599 | /** Stop emitting particles. Running particles will continue to run until they die.
600 | */
601 | void stopSystem() {
602 | _isActive = false;
603 | _elapsed = _duration;
604 | _emitCounter = 0;
605 |
606 | }
607 | /** Kill all living particles.
608 | */
609 | void resetSystem() {
610 | _isActive = true;
611 | _elapsed = 0;
612 | for (_particleIdx = 0; _particleIdx < _particleCount; ++_particleIdx)
613 | {
614 | Particle particle = _particles.get(_particleIdx);
615 | particle.timeToLive = 0;
616 | }
617 | }
618 | /** Whether or not the system is full.
619 | *
620 | * @return True if the system is full.
621 | */
622 | boolean isFull() {
623 | return _particleCount == _totalParticles;
624 | }
625 |
626 | /** Update the verts _position data of particle,
627 | should be overridden by subclasses.
628 | *
629 | * @param particle A certain particle.
630 | * @param newPosition A new _position.
631 | */
632 | void updateQuadWithParticle(List particle, Vec2 newPosition) {
633 |
634 | }
635 | /** Update the VBO verts buffer which does not use batch node,
636 | should be overridden by subclasses. */
637 | void postStep() {
638 |
639 | }
640 |
641 | /** Call the update mathod with no time..
642 | */
643 | void updateWithNoTime() {
644 |
645 | }
646 |
647 |
648 |
649 |
650 | boolean _visible = true;
651 | Vec2 _position = new Vec2(0f,0f);
652 | private boolean _batchNode = true;
653 | private boolean _unschedule = false;
654 |
655 |
656 | Context context;
657 |
658 | float _density;
659 |
660 | int _width;
661 | int _height;
662 | boolean _isBlendAdditive = false;
663 |
664 | /** whether or not the node will be auto-removed when it has no particles left.
665 | By default it is false.
666 | @since v0.8
667 | */
668 | boolean _isAutoRemoveOnFinish = false;
669 | String _plistFile = "";
670 | //! time elapsed since the start of the system (in seconds)
671 | float _elapsed ;
672 |
673 |
674 |
675 | //! Array of particles
676 | List _particles = new ArrayList<>() ;
677 |
678 | //Emitter name
679 | String _configName = "";
680 |
681 | // color modulate
682 | // BOOL colorModulate;
683 |
684 | //! How many particles can be emitted per second
685 | float _emitCounter;
686 |
687 | //! particle idx
688 | int _particleIdx ;
689 |
690 |
691 | // index of system in batch node array
692 | int _atlasIndex;
693 |
694 | //true if scaled or rotated
695 | boolean _transformSystemDirty = false;
696 | // Number of allocated particles
697 | int _allocatedParticles;
698 |
699 | /** Is the emitter active */
700 | boolean _isActive = true;
701 |
702 | /** Quantity of particles that are being simulated at the moment */
703 | int _particleCount = 0 ;
704 | /** How many seconds the emitter will run. -1 means 'forever' */
705 | float _duration;
706 | /** sourcePosition of the emitter */
707 | Vec2 _sourcePosition = new Vec2(0f,0f);
708 | /** Position variance of the emitter */
709 | Vec2 _posVar = new Vec2(0f,0f);
710 | /** life, and life variation of each particle */
711 | float _life;
712 | /** life variance of each particle */
713 | float _lifeVar;
714 | /** angle and angle variation of each particle */
715 | float _angle;
716 | /** angle variance of each particle */
717 | float _angleVar;
718 |
719 | /** Switch between different kind of emitter modes:
720 | - kParticleModeGravity: uses gravity, speed, radial and tangential acceleration
721 | - kParticleModeRadius: uses radius movement + rotation
722 | */
723 | Mode _emitterMode = Mode.GRAVITY;
724 |
725 | /** start diameter in pixels of each particle */
726 | float _startSize;
727 | /** diameter variance in pixels of each particle */
728 | float _startSizeVar;
729 | /** end diameter in pixels of each particle */
730 | float _endSize;
731 | /** end diameter variance in pixels of each particle */
732 | float _endSizeVar;
733 | /** start color of each particle */
734 | Color4F _startColor = new Color4F();
735 | /** start color variance of each particle */
736 | Color4F _startColorVar = new Color4F();
737 | /** end color and end color variation of each particle */
738 | Color4F _endColor = new Color4F();
739 | /** end color variance of each particle */
740 | Color4F _endColorVar = new Color4F();
741 | //* initial angle of each particle
742 | float _startSpin;
743 | //* initial angle of each particle
744 | float _startSpinVar;
745 | //* initial angle of each particle
746 | float _endSpin;
747 | //* initial angle of each particle
748 | float _endSpinVar;
749 | /** emission rate of the particles */
750 | float _emissionRate;
751 |
752 |
753 |
754 | /** Math.maximum particles of the system */
755 | int _totalParticles;
756 | /** conforms to CocosNodeTexture protocol */
757 | int _textureResourceId;
758 | /** conforms to CocosNodeTexture protocol */
759 | BlendFunc _blendFunc;
760 | /** does the alpha value modify color */
761 | boolean _opacityModifyRGB = false;
762 | /** does FlippedY variance of each particle */
763 | int _yCoordFlipped = 1;
764 |
765 | /** particles movement type: Free or Grouped
766 | @since v0.8
767 | */
768 | PositionType _positionType;
769 | ModeA modeA = new ModeA();
770 | ModeB modeB = new ModeB();
771 |
772 |
773 | float gravityX;
774 | float gravityY;
775 | /** Mode
776 | * @js cc.ParticleSystem.MODE_GRAVITY;
777 | */
778 |
779 |
780 | enum Mode
781 | {
782 | GRAVITY,
783 | RADIUS,
784 | }
785 |
786 | /** PositionType
787 | Possible types of particle positions.
788 | * @js cc.ParticleSystem.TYPE_FREE
789 | */
790 | enum PositionType
791 | {
792 | FREE, /** Living particles are attached to the world and are unaffected by emitter repositioning. */
793 |
794 | RELATIVE, /** Living particles are attached to the world but will follow the emitter repositioning.
795 | Use case: Attach an emitter to an sprite, and you want that the emitter follows the sprite.*/
796 |
797 | GROUPED, /** Living particles are attached to the emitter and are translated along with it. */
798 |
799 | }
800 | /** The Particle emitter lives forever. */
801 | final static int DURATION_INFINITY = -1;
802 | /** The starting diameter of the particle is equal to the ending diameter. */
803 | final static int START_SIZE_EQUAL_TO_END_SIZE = -1;
804 | /** The starting radius of the particle is equal to the ending radius. */
805 | final static int START_RADIUS_EQUAL_TO_END_RADIUS = -1;
806 |
807 | // Different modes
808 | //! Mode A:Gravity + Tangential Accel + Radial Accel
809 | class ModeA {
810 | /** Gravity value. Only available in 'Gravity' mode. */
811 | Vec2 gravity = new Vec2(0f,0f);
812 | /** speed of each particle. Only available in 'Gravity' mode. */
813 | float speed;
814 | /** speed variance of each particle. Only available in 'Gravity' mode. */
815 | float speedVar;
816 | /** tangential acceleration of each particle. Only available in 'Gravity' mode. */
817 | float tangentialAccel;
818 | /** tangential acceleration variance of each particle. Only available in 'Gravity' mode. */
819 | float tangentialAccelVar;
820 | /** radial acceleration of each particle. Only available in 'Gravity' mode. */
821 | float radialAccel;
822 | /** radial acceleration variance of each particle. Only available in 'Gravity' mode. */
823 | float radialAccelVar;
824 | /** set the rotation of each particle to its direction Only available in 'Gravity' mode. */
825 | boolean rotationIsDir;
826 | }
827 | //! Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode)
828 | class ModeB {
829 | /** The starting radius of the particles. Only available in 'Radius' mode. */
830 | float startRadius;
831 | /** The starting radius variance of the particles. Only available in 'Radius' mode. */
832 | float startRadiusVar;
833 | /** The ending radius of the particles. Only available in 'Radius' mode. */
834 | float endRadius;
835 | /** The ending radius variance of the particles. Only available in 'Radius' mode. */
836 | float endRadiusVar;
837 | /** Number of degrees to rotate a particle around the source pos per second. Only available in 'Radius' mode. */
838 | float rotatePerSecond;
839 | /** Variance in degrees for rotatePerSecond. Only available in 'Radius' mode. */
840 | float rotatePerSecondVar;
841 | }
842 |
843 |
844 | /** @def CC_RADIANS_TO_DEGREES
845 | converts radians to degrees
846 | */
847 | public static float CC_RADIANS_TO_DEGREES(float angle) {
848 | return angle * 57.29577951f;
849 |
850 | }
851 | /** @def CC_DEGREES_TO_RADIANS
852 | converts degrees to radians
853 | */
854 | public static float CC_DEGREES_TO_RADIANS(float angle) {
855 | return angle * 0.01745329252f;
856 | }
857 |
858 | static Random _random = new Random();
859 |
860 | public static float CCRANDOM_MINUS1_1() {
861 | return _random.nextFloat() * 2 - 1; // rng.nextDouble() is between 0 and 1
862 | }
863 |
864 | public static float clampf(float val, float min, float max) {
865 | return Math.max(min, Math.min(max, val));
866 | }
867 |
868 | }
869 |
--------------------------------------------------------------------------------