万年素人からHackerへの道

万年素人がHackerになれるまで殴り書きするぜ。

  • ・資産運用おすすめ
    10万円は1000円くらい利益
    資産運用ブログ アセマネ
    • ・寄付お願いします
      YENTEN:YYzNPzdsZWqr5THWAdMrKDj7GT8ietDc2W
      BitZenny:ZfpUbVya8MWQkjjGJMjA7P9pPkqaLnwPWH
      c0ban:8KG95GXdEquNpPW8xJAJf7nn5kbimQ5wj1
      Skycoin:KMqcn7x8REwwzMHPi9fV9fbNwdofYAWKRo

    OpenGLで作るiPhone SDKゲームプログラミングを参考に
    iPhoneではなくAndroid用のパーティクルを移植してみたが、
    うまく動かない・・・

    particle.pngを「drawable-hdpi」、「drawable-ldpi」
    「drawable-mdpi」へそれぞれ配置した。

    変なコメントや、趣味で片言英語に翻訳された部分があるので悪しからず

    ParticleSystem.java

    package sample.game.utils;
    
    import javax.microedition.khronos.opengles.GL10;
    //import java.nio.FloatBuffer;
    import sample.game.utils.GraphicUtils;
    public class ParticleSystem {
        
    //    private GL10  gl;
        private Particle particle[];
        private int capacity;
    
        /**
         * Constructor
         * @param capacity
         * @param particleLifeSpan
         */
        public ParticleSystem(int capacity, int particleLifeSpan) {
            this.capacity = capacity;
            
            // create dynamically particle array
            particle = new Particle[capacity];
            
            // create array for particle management
            for(int i=0;i<capacity;i++) {
                particle[i] = new Particle();
                particle[i].setLifeSpan(particleLifeSpan);
            }
        }
    
        public void add(float x, float y, float size, float moveX, float moveY) {
            
            for(int i=0;i<capacity;i++) {
                // search non-active(not using) status particle
                if(particle[i].isActiveFlag() == false) {
                    particle[i].setActiveFlag(true); // set active(using)
                    particle[i].setX(x);
                    particle[i].setY(y);
                    particle[i].setSize(size);
                    particle[i].setMoveX(moveX);
                    particle[i].setMoveY(moveY);
                    particle[i].setFrameNumber(0);
                    break;
                }
            }
        }
        
        // draw particles TODO
        public void draw(GL10 gl, int textureId) {
        
            // array for vertices
            // every a particle  6頂点 x 2要素(x,y) x max particle number
            float vertices[] = new float[6 * 2 * capacity]; 
             
            // array for colors
            // every a particle 6頂点 x 4要素(r,g,b,a) x max particle number
            float colors[] = new float[6 * 4 * capacity]; 
     
            // array for texture mapping
            // every a particle 6頂点 x 2要素(x,y) x max particle number
            float texCoords[] = new float[6 * 2 * capacity]; 
             
            // active particle count
            int vertexIndex = 0;
            int colorIndex = 0;
            int texCoordIndex = 0;
            
            int activeParticleCount = 0;
            // watch individually every particle
            for (int i=0;i<capacity;i++) {
                // render only active status particle
                if (particle[i].isActiveFlag() == true) {
                    
                    // add vertices 頂点座標を追加します
                    float centerX = particle[i].getX();
                    float centerY = particle[i].getY();
                    float size = particle[i].getSize();
                    float vLeft = -0.5f*size + centerX;
                    float vRight = 0.5f*size + centerX;
                    float vTop = 0.5f*size + centerY;
                    float vBottom = -0.5f*size + centerY;
                    
                    // polygon1
                    vertices[vertexIndex++] = vLeft; vertices[vertexIndex++] = vTop; // left-up
                    vertices[vertexIndex++] = vRight; vertices[vertexIndex++] = vTop; // right-up
                    vertices[vertexIndex++] = vLeft; vertices[vertexIndex++] = vBottom; // left-down
                    
                    // polygon2
                    vertices[vertexIndex++] = vRight; vertices[vertexIndex++] = vTop; // right-up
                    vertices[vertexIndex++] = vLeft; vertices[vertexIndex++] = vBottom; // left-down
                    vertices[vertexIndex++] = vRight; vertices[vertexIndex++] = vBottom; // right-down
                    
                    // color
                    float lifePercentage = (float)(particle[i].getFrameNumber()) / (float)(particle[i].getLifeSpan());
                    int alpha;
                    if (lifePercentage <= 0.5f) { // まだ寿命が半分以上のこっている場合
                        alpha = (int)Math.round(lifePercentage * 2.0f * 255.0f);
                    } else {
                        alpha = 255 - (int)Math.round(lifePercentage * 2.0f * 255.0f);
                    }
                    
                    colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = alpha;    
                    colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = alpha;    
                    colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = alpha;    
                    colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = alpha;    
                    colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = alpha;    
                    colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = 255; colors[colorIndex++] = alpha;    
                    
                    // mapping coords
                    // polygon1
                    texCoords[texCoordIndex++] = 0.0f; texCoords[texCoordIndex++] = 0.0f; // left-up
                    texCoords[texCoordIndex++] = 1.0f; texCoords[texCoordIndex++] = 0.0f; // right-up
                    texCoords[texCoordIndex++] = 0.0f; texCoords[texCoordIndex++] = 1.0f; // left-down
                    // polygon2
                    texCoords[texCoordIndex++] = 1.0f; texCoords[texCoordIndex++] = 0.0f; // right-up
                    texCoords[texCoordIndex++] = 0.0f; texCoords[texCoordIndex++] = 1.0f; // left-down
                    texCoords[texCoordIndex++] = 1.0f; texCoords[texCoordIndex++] = 1.0f; // right-down
                    
                    // count active particle
                    activeParticleCount++;
                }
            }
            
            gl.glEnable(GL10.GL_TEXTURE_2D);
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); // TODO 要チェック
            gl.glVertexPointer(2, GL10.GL_FLOAT, 0, GraphicUtils.getFloatBuffer(vertices)); // 描画する頂点配列を設定
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    //        gl.glColorPointer(4, GL10.GL_UNSIGNED_BYTE, 0, FloatBuffer.wrap(colors));
            gl.glColorPointer(4, GL10.GL_UNSIGNED_BYTE, 0, GraphicUtils.getFloatBuffer(colors));
            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    //        gl.glRotatef((float) (90/180.0f*Math.PI), 1.0f, 0.0f, 0.0f);// TODO
            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, GraphicUtils.getFloatBuffer(texCoords));
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            
            gl.glDrawArrays(GL10.GL_TRIANGLES, 0, activeParticleCount * 6);
            
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glDisable(GL10.GL_TEXTURE_2D);
        }
    
        public void update() {
            for (int i=0;i<capacity;i++) {
                // work only active(using) particle
                if (particle[i].isActiveFlag() == true) {
                    particle[i].update();
                }
            }
        }
    }
    
    package sample.game.utils;
    //import org.primitive.GraphicUtil;
    //import javax.microedition.khronos.opengles.GL10;
    
    /**
     * Particle System
     */
    
    public class Particle {
        // gradient value
        private float x;
        private float y;
        private float size;
        private boolean activeFlag;
        private float moveX;
        private float moveY;
        private int frameNumber;
        private int lifeSpan;
    
        /**
         * Constructor
         *
         */
        public Particle() {
            x = 0.0f;
            y = 0.0f;
            size = 1.0f;
            activeFlag = false;
            moveX = 0.0f;
            moveY = 0.0f;
            frameNumber = 0;
            lifeSpan = 0;
        }
    /* 使ってない??
        public void draw(GL10 gl, int tex_id) {
            float lifePercentage = (float)frameNumber / (float)getLifeSpan();
            int alpha;
            
            if (lifePercentage <= 0.5f){ // if life is more than half
                // fade in
                alpha = (int)Math.round(lifePercentage * 2.0f * 255.0f);
            } else {
                // fade out
                alpha = 255 - (int)Math.round(lifePercentage * 2.0f * 255.0f);
            }
            GraphicUtil.drawTexture(gl, tex_id, x, y, size, size, 255, 255, 255, alpha);
        }
        */
        public void update() {
            frameNumber++;
            if (frameNumber >= getLifeSpan()) setActiveFlag(false);
            
            x += moveX;
            y += moveY;
        }
    
        public void setX(float x) {
            this.x = x;
        }
    
        public float getX() {
            return x;
        }
    
        public void setY(float y) {
            this.y = y;
        }
    
        public float getY() {
            return y;
        }
    
        public void setLifeSpan(int lifeSpan) {
            this.lifeSpan = lifeSpan;
        }
    
        public void setActiveFlag(boolean activeFlag) {
            this.activeFlag = activeFlag;
        }
        
        public int getLifeSpan() {
            return lifeSpan;
        }
    
        public boolean isActiveFlag() {
            return activeFlag;
        }
        
        public boolean setActiveFlag() {
            return activeFlag;
        }
        
        public void setFrameNumber(int frameNumber) {
            this.frameNumber = frameNumber;
        }
    
        public float getFrameNumber() {
            return size;
        }
        
        public void setMoveX(float moveX) {
            this.moveX = moveX;
        }
    
        public float getMoveX() {
            return moveX;
        }
    
        public void setMoveY(float moveY) {
            this.moveY = moveY;
        }
    
        public float getMoveY() {
            return moveY;
        }
        
        public void setSize(float size) {
            this.size = size;
        }
    
        public float getSize() {
            return size;
        }
    }
    

    ■以下、ParticleSystemの読み込み元での処理

    ・パーティクルシステムの変数初期化

        private static ParticleSystem particleSystem;
        private static int particleTexture;
    

    ・パーティクルシステムのオブジェクトの初期化

    particleSystem = new ParticleSystem(100, 30);
    

    テクスチャの読み込み(このTextureLoader.javaのソースは初歩からわかるAndroid最新プログラミングを使ってるので、載せられません・・・)TextureLoader

            particleTexture = TextureLoader.loadTexture(gl, this, R.drawable.particle);
    

    毎回呼ばれる処理(update()みたいなメソッドから呼ぶ)で以下を挿入

        particleSystem.update();
    

    パーティクルの追加時

        particleSystem.add(0.0f, 0.0f, 0.5f, moveX, moveY);