2012年7月27日金曜日

日記ちゃんあんどろ


GL10PrimitiveEx1.apk
size: 1.59MB

 BGMの再生、オブジェクト管理クラスの追加あたり。
オブジェクト動作管理は自分で双方向リストを構築してなんとかしている。
javaの汎用コンテナだとメモリをどっかから持ってきそうでいやな予感がしたから回避した。
 あらかじめ用意した頂点数をオーバーするので表示されないオブジェクトがちらちらする、ロマン。
実機で10FPS程度、エミュだと3FPSぐらい。もうちょっと現実的な環境を用意したいが。
 未使用オブジェクトの検索が線形なので、
リストにするとかして効率をあげたほうがいいかも。



以下ソースコード。1200行ぐらい
package my.gl10primitiveex;
 
import android.app.Activity;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
 
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Map;
import java.util.Random;
 
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
 
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.opengl.GLU;
import android.view.MotionEvent;
 
import android.media.SoundPool;
import android.media.AudioManager;
import java.util.HashMap;
import android.content.Context;
 
import android.media.MediaPlayer;
 
 
 
 
public class GL10PrimitiveEx1 extends Activity
{
  private GLSurfaceView glView;
  private float prevTouchPosX;
  private float prevTouchPosY;
  
//  @Override
  protected void onCreate( Bundle bundle )
  {
    super.onCreate( bundle );
    
    glView = new GLSurfaceView( this );
    glView.setRenderer( new GLRenderer(this) );
//    glView.setRenderMode( GLSurfaceView.RENDERMODE_WHEN_DIRTY );
  //  glView.setDebugFlags( GLSurfaceView.DEBUG_CHECK_GL_ERROR | GLSurfaceView.DEBUG_LOG_GL_CALLS );
    setContentView( glView );
    glView.setFocusable( true );
    AppObject.getInstance().getSoundManager().create( AppObject.SOUND_HIT, this, R.raw.sound );
  }
  
//  @Override
  public void onResume()
  {
    super.onResume();
    glView.onResume();
    AppObject.getInstance().getMusic().create( this, R.raw.music );
    AppObject.getInstance().getMusic().play();
  }
  
//  @Override
  public void onPause()
  {
    super.onPause();
    glView.onPause();
    AppObject.getInstance().getMusic().release();
  }
  
  public boolean onTouchEvent( MotionEvent event )
  {
    if ( event.getAction() == MotionEvent.ACTION_MOVE )
    {
      float rate = 0.01f;
      float vx = (event.getX() - prevTouchPosX) * rate;
      float vy = (event.getY() - prevTouchPosY) * rate;
      
      // 移動距離が長すぎるようなら移動しないように
      if ( 0.5 > Math.sqrt( (double)(vx*vx + vy*vy) ) )
      {
        AppObject.getInstance().getPlayerObject().move( vx, -vy );
      }
    }
    
    prevTouchPosX = event.getX();
    prevTouchPosY = event.getY();
    
    return super.onTouchEvent( event );
  }
}
 
 
 
 
 
class AppObject
{
  // 効果音
  public static final int SOUND_HIT = 0;
  
  // priority
  public static final int PRIO_ENEMY = 1;
  public static final int PRIO_PLAYER = 2;
  public static final int PRIO_SHOT = 3;
  public static final int PRIO_EFFECT = 4;
  public static final int PRIO_BULLET = 5;
 
  
  
  private ImageArray imageArray = new ImageArray( 128 );
  
  private TestObject[] testObj = new TestObject[ 8 ];
  private ShotObject[] shotObj = new ShotObject[ 16 ];
  private Bullet[] bulletObj = new Bullet[ 128 ];
  private ShotHitEffect[] shotHitObj = new ShotHitEffect[ 64 ];
  private PlayerObject playerObject = new PlayerObject();
  private RenderObject tmpObj = new RenderObject();
  
  TaskManager taskMan = new TaskManager();
  
  private Texture texture = new Texture();
  FPSCount fps = new FPSCount();
  SoundManager sound = new SoundManager();
  Music music = new Music();
  Random random = new Random();
  
  
  
  static private AppObject instance = null;
  static public AppObject getInstance()
  {
    if ( instance == null ) instance = new AppObject();
    return instance;
  }
  
  FPSCount getFPSCount() { return fps; }
  SoundManager getSoundManager() { return sound; }
  Music getMusic() { return music; }
  PlayerObject getPlayerObject() { return playerObject; }
  Random getRandom() { return random; }
  
  
  
  
  private AppObject()
  {
    for (int i=0; i<testObj.length; ++i)
    {
      float x = (random.nextFloat() * 2 - 1) * 2;
      float y = (random.nextFloat() * 2 - 1) * 2;
      testObj[i] = new TestObject( x, y );
      testObj[i].vx = (random.nextFloat()*2-1) * 0.0625f;
      testObj[i].vy = (random.nextFloat()*2-1) * 0.0625f;
 
      taskMan.add( testObj[i], PRIO_ENEMY );
    }
    
    for (int i=0; i<shotObj.length; ++i)
    {
      shotObj[i] = new ShotObject();
    }
    
    for (int i=0; i<shotHitObj.length; ++i)
    {
      shotHitObj[i] = new ShotHitEffect();
    }
    
    for (int i=0; i<bulletObj.length; ++i)
    {
      bulletObj[i] = new Bullet(); 
    }
    
    taskMan.add( playerObject, PRIO_PLAYER );
  }
  
  
  
  public void makeTexture( GL10 gl, Bitmap bmp )
  {
    texture.makeTexture( gl, bmp );
  }
  
  public void update()
  {
    taskMan.update();
    
    sound.update();
  }
  
  public void render( GL11 gl )
  {
    imageArray.clear();
 
    taskMan.render( imageArray );
    renderNum( fps.getFps(), 0, 0 );
    renderNum( taskMan.getCount(), 0, 0.5f );
 
    imageArray.render( gl, texture.getTextureID() );
  }
  
  public void renderNum( int num, float x, float y )
  {
    tmpObj.x = x;
    tmpObj.y = y;
    tmpObj.width = 0.5f;
    tmpObj.height = 0.5f;
    for (;;)
    {
      tmpObj.setUVs( 256, 256, 0 + (num%10)*16, 48, 16, 16 );
      imageArray.push( tmpObj );
      
      
      num /= 10;
      if ( num == 0 ) break;
      tmpObj.x -= 0.5f;
    }
  }
  
  public void createShotObject( float x, float y, float angle, float speed )
  {
    for (int i=0; i<shotObj.length; ++i)
    {
      if ( shotObj[i].getState() == Task.STATE_NONE )
      {
        shotObj[i].set( x, y, angle, speed );
        taskMan.add( shotObj[i], PRIO_SHOT );
        break;
      }
    }
  }
  
  public void createShotHitEffect( float x, float y )
  {
    int num = 0;
    for (int i=0; i<shotHitObj.length; ++i)
    {
      if ( shotHitObj[i].getState() == Task.STATE_NONE )
      {
        shotHitObj[i].set( x, y, random.nextFloat()*360, random.nextFloat()*0.25f );
        taskMan.add( shotHitObj[i], PRIO_EFFECT );
        if ( ++num > 8 ) break;
      }
    }
  }
  
  public void createBullet( float x, float y, float angle, float speed )
  {
    for (int i=0; i<bulletObj.length; ++i)
    {
      if ( bulletObj[i].getState() == Task.STATE_NONE )
      {
        bulletObj[i].set( x, y, angle, speed );
        taskMan.add( bulletObj[i], PRIO_BULLET );
        break;
      }
    }
  }
}
 
 
 
 
 
class GLRenderer implements GLSurfaceView.Renderer
{
  private Activity activity;
  private float aspect;
  private long prevTime;
 
 
  GLRenderer( Activity activity )
  {
    this.activity = activity;
    prevTime = 0;
  }
 
//  @Override
  public void onSurfaceCreated( GL10 gl, EGLConfig eglConfig )
  {
    gl.glEnableClientState( GL10.GL_VERTEX_ARRAY );
    gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY );
    gl.glEnable( GL10.GL_TEXTURE_2D );
    ///*
    gl.glFrontFace( GL10.GL_CCW );
    gl.glEnable( GL10.GL_CULL_FACE );
    gl.glCullFace( GL10.GL_BACK );
    //*/
 
    Bitmap bmp = BitmapFactory.decodeResource( activity.getResources(), R.drawable.image );
    AppObject.getInstance().makeTexture( gl, bmp );
 
    gl.glEnable( GL10.GL_BLEND );
    gl.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA );
  }
 
//  @Override
  public void onSurfaceChanged( GL10 gl, int w, int h )
  {
    gl.glViewport( 0, 0, w, h );
    aspect = (float)w / (float)h;
    
  }
  
//  @Override
  public void onDrawFrame( GL10 gl )
  {
    
    AppObject.getInstance().update();
 
    
    
    gl.glClearColor( 1, 1, 1, 1 );
    gl.glClear( GL10.GL_COLOR_BUFFER_BIT );
 
    gl.glMatrixMode( GL10.GL_PROJECTION );
    gl.glLoadIdentity();
    GLU.gluPerspective( gl, 45.f, aspect, 0.01f, 100 );
    
    gl.glMatrixMode( GL10.GL_MODELVIEW );
    gl.glLoadIdentity();
    GLU.gluLookAt( gl, 0,0,5, 0,0,0, 0,1,0 );
 
//    gl.glTexParameterx( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR );
//    gl.glTexParameterx( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR );
    AppObject.getInstance().render( (GL11)gl );
    
    
    
    long now = System.currentTimeMillis();
    if ( now-prevTime < 33 )
    {
      try
      {
        Thread.sleep( 33 - (now-prevTime) );
      }
      catch ( Exception e ) {}
    }
    prevTime = now;
    
    AppObject.getInstance().getFPSCount().update( now );
  }
}
 
 
 
 
class Texture
{
  private int textureID;
  
  public Texture()
  {
    textureID = 0;
  }
  
 
  public void dispose( GL10 gl )
  {
    if ( textureID != 0 )
    {
      gl.glDeleteTextures( 0, new int[]{textureID}, 0 );
      textureID = 0;
    }
  }
  
  public int makeTexture( GL10 gl, Bitmap bmp )
  {
    dispose( gl );
    
    int[] textureIDs = new int[1];
    gl.glGenTextures( 1, textureIDs, 0 );
    
    gl.glActiveTexture( GL10.GL_TEXTURE0 );
    gl.glBindTexture( GL10.GL_TEXTURE_2D, textureIDs[0] );
    GLUtils.texImage2D( GL10.GL_TEXTURE_2D, 0, bmp, 0 );
    
    gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST );
    gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST );
    
    textureID = textureIDs[0];
    return textureIDs[0]; 
  }
  
  
  int getTextureID() { return textureID; }
}
 
 
 
 
 
class ImageArray
{
  private FloatBuffer vertexBuffer;
  private FloatBuffer uvBuffer;
  private ShortBuffer indexBuffer;
  private int maxNumOfSprite;
  private int numOfRenderSprite;
  
  /**
   * constructor
   * @param num numOfSprite
   */
  public ImageArray( int numOfSprite )
  {
    this.maxNumOfSprite = numOfSprite;
 
    // 四角の数*(x,y,z)*4(=四角で必要な頂点数)*sizeof(float)
    vertexBuffer = ByteBuffer.allocateDirect( numOfSprite * 3 * 4 * 4 ).order( ByteOrder.nativeOrder() ).asFloatBuffer();
    // 四角の数*(u,v)*4(=四角で必要な頂点数)*sizeof(float)
    uvBuffer = ByteBuffer.allocateDirect( numOfSprite * 2 * 4 * 4 ).order( ByteOrder.nativeOrder() ).asFloatBuffer();
    // 四角の数*6(=四角で必要な頂点index数) * sizeof(short)
    indexBuffer = ByteBuffer.allocateDirect( numOfSprite * 6 * 2 ).order( ByteOrder.nativeOrder() ).asShortBuffer();
 
    setIndexs();
    
    vertexBuffer.position( 0 );
    uvBuffer.position( 0 );
    indexBuffer.position( 0 );
    numOfRenderSprite = 0;
  }
  
  public void push( RenderObject obj )
  {
    if ( numOfRenderSprite < maxNumOfSprite )
    {
      int n = numOfRenderSprite;
      
      ///*
      double rad = ((double)obj.angle / 180) * Math.PI;
      float c = (float)Math.cos( rad );
      float s = (float)Math.sin( rad );
      
      vertexBuffer.put( n*3*4+0, 0.5f*obj.width*(-s) - 0.5f*obj.height*c + obj.x );  // 左上
      vertexBuffer.put( n*3*4+1, 0.5f*obj.height*c + 0.5f*obj.width*(-s) + obj.y );
      vertexBuffer.put( n*3*4+2, 0 );
      vertexBuffer.put( n*3*4+3, 0.5f*obj.width*c - 0.5f*obj.height*s + obj.x );  // 右上  
      vertexBuffer.put( n*3*4+4, 0.5f*obj.height*s + 0.5f*obj.width*c + obj.y );
      vertexBuffer.put( n*3*4+5, 0 );
      vertexBuffer.put( n*3*4+6, 0.5f*obj.width*(-c) - 0.5f*obj.height*(-s) + obj.x );  // 左下
      vertexBuffer.put( n*3*4+7, 0.5f*obj.height*(-s) + 0.5f*obj.width*(-c) + obj.y );
      vertexBuffer.put( n*3*4+8, 0 );
      vertexBuffer.put( n*3*4+9, 0.5f*obj.width*s - 0.5f*obj.height*(-c)+ obj.x );  // 右下
      vertexBuffer.put( n*3*4+10, 0.5f*obj.height*(-c) + 0.5f*obj.width*s + obj.y );
      vertexBuffer.put( n*3*4+11, 0 );
      //*/
      
      /*
      vertexBuffer.put( n*3*4+0, -0.5f*obj.width + obj.x );  // 左上
      vertexBuffer.put( n*3*4+1, 0.5f*obj.height + obj.y );
      vertexBuffer.put( n*3*4+2, 0 );
      vertexBuffer.put( n*3*4+3, 0.5f*obj.width + obj.x );  // 右上  
      vertexBuffer.put( n*3*4+4, 0.5f*obj.height + obj.y );
      vertexBuffer.put( n*3*4+5, 0 );
      vertexBuffer.put( n*3*4+6, -0.5f*obj.width + obj.x );  // 左下
      vertexBuffer.put( n*3*4+7, -0.5f*obj.height + obj.y );
      vertexBuffer.put( n*3*4+8, 0 );
      vertexBuffer.put( n*3*4+9, 0.5f*obj.width + obj.x );  // 右下
      vertexBuffer.put( n*3*4+10, -0.5f*obj.height + obj.y );
      vertexBuffer.put( n*3*4+11, 0 );
      //*/
      
      uvBuffer.put( n*2*4+0, obj.uvs[0] ); //u1[0]
      uvBuffer.put( n*2*4+1, obj.uvs[1] ); //v1
      uvBuffer.put( n*2*4+2, obj.uvs[2] ); //u2[1]
      uvBuffer.put( n*2*4+3, obj.uvs[1] ); //v1
      uvBuffer.put( n*2*4+4, obj.uvs[0] ); //u1[2]
      uvBuffer.put( n*2*4+5, obj.uvs[3] ); //v2
      uvBuffer.put( n*2*4+6, obj.uvs[2] ); //u2[3]
      uvBuffer.put( n*2*4+7, obj.uvs[3] ); //v2
      
      numOfRenderSprite++;
    }
  }
  
  public void render( GL11 gl, int textureID )
  {
    if ( numOfRenderSprite > 0 )
    {
      vertexBuffer.position( 0 );
      uvBuffer.position( 0 );
      indexBuffer.position( 0 );
  
      gl.glVertexPointer( 3, GL10.GL_FLOAT, 0, vertexBuffer );
      gl.glActiveTexture( GL10.GL_TEXTURE0 );
      gl.glBindTexture( GL10.GL_TEXTURE_2D, textureID );
      gl.glTexCoordPointer( 2, GL10.GL_FLOAT, 0, uvBuffer );
      gl.glDrawElements( GL10.GL_TRIANGLES, 3*2*numOfRenderSprite, GL10.GL_UNSIGNED_SHORT, indexBuffer );
    }
  }
  
  public void render( GL11 gl, int textureID, int startIndex, int endIndex )
  {
    if ( numOfRenderSprite > 0 &&
        startIndex < numOfRenderSprite && endIndex < numOfRenderSprite )
    {
      vertexBuffer.position( startIndex*3*4 );
      uvBuffer.position( startIndex*2*4 );
      indexBuffer.position( startIndex*3*2 );
      
      gl.glVertexPointer( 3, GL10.GL_FLOAT, 0, vertexBuffer );
      gl.glActiveTexture( GL10.GL_TEXTURE0 );
      gl.glBindTexture( GL10.GL_TEXTURE_2D, textureID );
      gl.glTexCoordPointer( 2, GL10.GL_FLOAT, 0, uvBuffer );
      gl.glDrawElements( GL10.GL_TRIANGLES, 3*2*(endIndex-startIndex), GL10.GL_UNSIGNED_SHORT, indexBuffer );
    }
  }
  
  public void clear() { numOfRenderSprite = 0; }
  
  public FloatBuffer getVertexBuffer() { return vertexBuffer; }
  public FloatBuffer getUVBuffer() { return uvBuffer; }
  public ShortBuffer getIndexBuffer() { return indexBuffer; }
  public int getMaxNumOfSprite() { return maxNumOfSprite; }
  public int getNumOfRenderSprite() { return numOfRenderSprite; }
  
  
  
  private void setIndexs()
  {
    int n = maxNumOfSprite;
    for (int i=0; i<n; ++i)
    {
      indexBuffer.put( i*6 + 0, (short)(0 + i*4) );
      indexBuffer.put( i*6 + 1, (short)(2 + i*4) );
      indexBuffer.put( i*6 + 2, (short)(1 + i*4) );
      indexBuffer.put( i*6 + 3, (short)(2 + i*4) );
      indexBuffer.put( i*6 + 4, (short)(3 + i*4) );
      indexBuffer.put( i*6 + 5, (short)(1 + i*4) );
    }
  }
}
 
 
 
 
 
class RenderObject
{
  public float x, y, width, height;
  public float angle;  // no use
  public float[] uvs = new float[ 4 ];  //< u1, v1, u2, v2
  
  protected void setUVs( int texWidth, int texHeight, int srcX, int srcY, int width, int height )
  {
    uvs[0] = (float)srcX / (float)texWidth;
    uvs[1] = (float)srcY / (float)texHeight;
    uvs[2] = (float)(srcX+width) / (float)texWidth;
    uvs[3] = (float)(srcY+height) / (float)texHeight;
  }
}
 
 
class TestObject extends Task
{
  private RenderObject renderObj = new RenderObject();
  public float vx;
  public float vy;
  int time;
 
  public TestObject( float x, float y )
  {
    renderObj.x = x;
    renderObj.y = y;
    renderObj.width = 0.5f; 
    renderObj.height = 0.5f;
    renderObj.setUVs( 256, 256, 0, 0, 32 , 32 );
    renderObj.angle = x*27 + y*31;
  }
  
  public void update()
  {
    renderObj.angle += 8;
    if ( renderObj.angle > 360 ) renderObj.angle -= 360;
    
    renderObj.x += vx;
    renderObj.y += vy;
    if ( renderObj.x < -3 || renderObj.x > 3 ) { vx = -vx; }
    if ( renderObj.y < -2 || renderObj.y > 2 ) { vy = -vy; }
    
    if ( (time & 3) == 0 )
    {
      float targetX = AppObject.getInstance().getPlayerObject().getPosX();
      float targetY = AppObject.getInstance().getPlayerObject().getPosY();
      float angle = (float)Math.atan2( (double)(targetY-getPosY()), (double)(targetX-getPosX()) ) * 180 / 3.141592f;
      
      for (int i=0; i<8; ++i)
      {
        float speed = AppObject.getInstance().getRandom().nextFloat()*0.125f + 0.0625f;
        AppObject.getInstance().createBullet( getPosX(), getPosY(), angle, speed );
      }
    }
    
    collision();
    
    time++;
/*    
    if ( playSound )
    {
      AppObject.getInstance().getSoundManager().play( AppObject.SOUND_HIT );
    }
*/
  }
  
  public void render( ImageArray image )
  {
    image.push( renderObj );
  }
  
  public float getPosX() { return renderObj.x; }
  public float getPosY() { return renderObj.y; }
  
  private void collision()
  {
    Task runner = parent.find( AppObject.PRIO_SHOT );
    while ( runner != null )
    {
      if ( runner.getPriority() == AppObject.PRIO_SHOT )
      {
        if ( runner.getState() == Task.STATE_NORMAL )
        {
          try
          {
            ShotObject obj = (ShotObject)runner;
            double tmpX = obj.getPosX() - getPosX();
            double tmpY = obj.getPosY() - getPosY();
            double dist = Math.sqrt( tmpX*tmpX + tmpY*tmpY );
            if ( dist < 0.25 )
            {
              AppObject.getInstance().createShotHitEffect( obj.getPosX(), obj.getPosY() );
              obj.kill();
            }
          }
          catch ( Exception e ) {}
        }
      }
      else break;
      
      runner = runner.next;
    }
  }
}
 
 
 
 
class PlayerObject extends Task
{
  private RenderObject renderObj = new RenderObject();
  private float vx, vy;
  private int time;
 
  public PlayerObject()
  {
    vx = vy = 0;
    time = 0;
 
    renderObj.x = 0;
    renderObj.y = 0;
    renderObj.width = 0.5f;
    renderObj.height = 0.5f;
    renderObj.angle = 0;
    renderObj.setUVs( 256, 256, 32, 0, 32, 32 );
  }
 
  public void update()
  {
    if ( (time & 3) == 0 )
    {
      float angle = (float)Math.atan2( (double)vy, (double)vx ) * 180 / 3.141592f;
      AppObject.getInstance().createShotObject( renderObj.x, renderObj.y, angle, 0.25f );
    }
    
    renderObj.x += vx;
    renderObj.y += vy;
    vy = vx = 0;
 
    collision();
    
    
    time++;
  }
  
  public void render( ImageArray image )
  {
    image.push( renderObj );
  }
  
  synchronized void move( float vx, float vy )
  {
    this.vx += vx;
    this.vy += vy;
  }
  
  private void collision()
  {
    Task runner = parent.find( AppObject.PRIO_BULLET );
    while ( runner != null )
    {
      if ( runner.getPriority() == AppObject.PRIO_BULLET )
      {
        if ( runner.getState() == Task.STATE_NORMAL )
        {
          try
          {
            Bullet b = (Bullet)runner;
            double tmpX = b.getPosX() - getPosX();
            double tmpY = b.getPosY() - getPosY();
            double dist = Math.sqrt( tmpX*tmpX + tmpY*tmpY );
            if ( dist < 0.125 )
            {
              b.kill();
            }
          }
          catch ( Exception e )
          {
          }
          
        }
      }
      else break;
      
      runner = runner.next;
    }
  }
  
  
  public float getPosX() { return renderObj.x; }
  public float getPosY() { return renderObj.y; }
}
 
 
 
 
class ShotObject extends Task
{
  private RenderObject renderObj = new RenderObject(); 
  private float vx;
  private float vy;
  private int time;
  
  ShotObject()
  {
    renderObj.width = 0.5f;
    renderObj.height = 0.5f;
    renderObj.setUVs( 256, 256, 64, 0, 32, 32 );
  }
  
  public void set( float x, float y, float angle, float speed )
  {
    //System.out.println("shotObject.set() " + x + ", " + y );
    super.state = Task.STATE_NORMAL;
 
    time = 0;
    renderObj.x = x;
    renderObj.y = y;
    renderObj.angle = angle;
    double rad = angle / 180 * 3.141592;
    vx = (float)Math.cos( rad ) * speed;
    vy = (float)Math.sin( rad ) * speed;
  }
  
  public void update()
  {
    renderObj.x += vx;
    renderObj.y += vy;
    
    if ( renderObj.x < -3 || renderObj.x > 3 || renderObj.y < -2 || renderObj.y > 2 || time > 60 )
    {
      //System.out.println("shotObject.update() - no used" );
      kill();
    }
 
    time++;
  }
  
  public void render( ImageArray image )
  {
    image.push( renderObj );
  }
  
 
  public float getPosX() { return renderObj.x; }
  public float getPosY() { return renderObj.y; }
}
 
 
 
 
 
 
class ShotHitEffect extends Task
{
  private RenderObject renderObj = new RenderObject();
  private float vx;
  private float vy;
  private int time;
  
  ShotHitEffect()
  {
    renderObj.width = 0.125f;
    renderObj.height = 0.125f;
    renderObj.setUVs( 256, 256, 64, 0, 32, 32 );
  }
  
  public void set( float x, float y, float angle, float speed )
  {
    //System.out.println("shotObject.set() " + x + ", " + y );
    super.state = Task.STATE_NORMAL;
 
    time = AppObject.getInstance().getRandom().nextInt() & 7;
    renderObj.x = x;
    renderObj.y = y;
    renderObj.angle = angle;
    double rad = angle / 180 * 3.141592;
    vx = (float)Math.cos( rad ) * speed;
    vy = (float)Math.sin( rad ) * speed;
  }
  
  public void update()
  {
    renderObj.x += vx;
    renderObj.y += vy;
    vx *= 0.92f;
    vy *= 0.92f;
    
    if ( time > 18 )
    {
      //System.out.println("shotObject.update() - no used" );
      kill();
    }
 
    time++;
  }
  
  public void render( ImageArray image )
  {
    image.push( renderObj );
  }
}
 
 
 
 
class Bullet extends Task
{
  private RenderObject renderObj = new RenderObject();
  private float vx;
  private float vy;
  private int time;
  
  Bullet()
  {
    renderObj.width = 0.25f;
    renderObj.height = 0.25f;
    renderObj.setUVs( 256, 256, 96, 0, 32, 32 );
  }
  
  public void set( float x, float y, float angle, float speed )
  {
    super.state = Task.STATE_NORMAL;
 
    time = 0;
    renderObj.x = x;
    renderObj.y = y;
    renderObj.angle = angle;
    double rad = angle / 180 * 3.141592;
    vx = (float)Math.cos( rad ) * speed;
    vy = (float)Math.sin( rad ) * speed;
  }
  
  public void update()
  {
    renderObj.x += vx;
    renderObj.y += vy;
    
    if ( renderObj.x < -3 || renderObj.x > 3 || renderObj.y < -2 || renderObj.y > 2 || time > 60 )
    {
      //System.out.println("shotObject.update() - no used" );
      kill();
    }
 
    time++;
  }
  
  public void render( ImageArray image )
  {
    image.push( renderObj );
  }
  
  public float getPosX() { return renderObj.x; }
  public float getPosY() { return renderObj.y; } 
}
 
 
 
 
class FPSCount
{
  private int fps;
  private int[] data = new int[ 32 ];
  private int lastSecond;
  
  public FPSCount()
  {
    int n = data.length;
    for (int i=0; i<n; ++i)
    {
      data[i] = 0;
    }
    
    fps = 0;
    lastSecond = 0;
  }
  
  void update( long now )
  {
    //long now = System.currentTimeMillis();
    int a = (int)(now / 200);
    data[ a & 31 ]++;
    
    if ( a != lastSecond )
    {
      lastSecond = a;
      fps = 0;
      for (int i=1; i<=5; ++i)
      {
        fps += data[ (a-i)&31 ];
      }
      for (int i=5; i<=20; ++i) data[ (a+i)&31 ] = 0;
    }
  }
  
  public int getFps() { return fps; }
}
 
 
 
//[参考]http://www.kumikomi.net/archives/2011/12/di09and3.php?page=4
class SoundManager
{
  class SoundData
  {
    public static final int STATE_NONE = 0;
    public static final int STATE_PLAY = 1;
    public static final int STATE_STOP = 2;
    
    public int soundID;
    public int state;
    public int streamID;
 
    SoundData()
    {
      soundID = -1;
      streamID = -1;
      state = STATE_NONE;
    }
  }
  
  private static final int NUM_OF_STREAM = 8; 
  private SoundPool sound = new SoundPool( NUM_OF_STREAM, AudioManager.STREAM_MUSIC, 0 );
  private HashMap<Integer, SoundData> list = new HashMap<Integer, SoundData>();
 
 
  
  void update()
  {
    for ( Map.Entry<Integer, SoundData> e: list.entrySet() )
    {
      SoundData data = e.getValue(); 
      if ( data.state == SoundData.STATE_PLAY )
      {
        sound.stop( data.streamID );
 
        // 再生
        data.streamID = sound.play( data.soundID, 1.0f, 1.0f, 0, 0, 1.0f );
        
        data.state = SoundData.STATE_NONE;
      }
    }
  }
 
  void create( int soundID, Context context, int resID )
  {
    release( soundID );
    
    SoundData data = new SoundData();
    data.soundID = sound.load( context, resID, 1 );
    
    list.put( soundID, data );
  }
  
  void release( int soundID )
  {
    SoundData data = list.get( soundID );
    if ( data != null )
    {
      sound.unload( data.soundID );
      list.remove( soundID );
    }
  }
  
  
  void release()
  {
    for ( Map.Entry<Integer, SoundData> e: list.entrySet() )
    {
      sound.unload( e.getValue().soundID );
    }
 
    list.clear();
  }
  
  public void play( int soundID )
  {
    SoundData data = list.get( soundID );
    if ( data != null )
    {
      data.state = SoundData.STATE_PLAY;
    }
  }
 
}
 
 
 
 
class Music
{
  private MediaPlayer music = null;
  
  public void release()
  {
    if ( music != null )
    {
      music.stop();
      music.release();
      music = null;
    }
  }
  
  public void create( Context context, int resID )
  {
    release();
 
    music = MediaPlayer.create( context, resID );
    music.setLooping( true );
  }
  
  
  public void play()
  {
    if ( music != null )
    {
      music.start();
    }
  }
}
 
 
 
 
class Task
{
  public static final int STATE_NONE = -2;
  public static final int STATE_KILL = -1;
  public static final int STATE_NORMAL = 0;
  
  
  public int priority = 0;
  public int state = STATE_NONE;
  public Task prev = null;
  public Task next = null;
  public TaskManager parent = null;
  
  public void update() {}
  public void render( ImageArray image ) {}
  public void release() {}
  
  public int getPriority() { return priority; }
  public int getState() { return state; }
  public TaskManager getParent() { return parent; }
 
  public void kill() { state = STATE_KILL; }
}
 
 
 
class TaskManager
{  
  private Task begin = new Task();
  private Task end = new Task();
  
  
  public final static int MAX_PRIORITY = 16;
  private Task prioTop[] = new Task[ MAX_PRIORITY ];  //< ラストにendTaskをおくので+1する
  
  private int count = 0;
  
  
  private void link( Task newTask, Task next )
  {
    newTask.next = next;
    newTask.prev = next.prev;
    next.prev.next = newTask;
    next.prev = newTask;
  }
  
  private Task findTopPrioObj( int priority )
  {
    if ( priority >= 0 && priority < MAX_PRIORITY )
    {
      for (int i=priority; i<MAX_PRIORITY; ++i)
      {
        if ( prioTop[i] != null ) return prioTop[i]; 
      }
    }
    
    return null;
  }
  
  /**
   * constructor
   */
  TaskManager()
  {
    begin.priority = 0;
    begin.next = end;
    begin.parent = this;
    end.priority = MAX_PRIORITY;
    end.prev = begin;
    end.parent = this;
    
    prioTop[0] = begin;
    prioTop[ MAX_PRIORITY-1 ] = end;
  }
  
  public Task add( Task newTask, int priority )
  {
    if ( priority >= 0 && priority < MAX_PRIORITY )
    {
      Task next = findTopPrioObj( priority );
      if ( next == null ) next = end;
      
      link( newTask, next );
        
      newTask.priority = priority;
      newTask.parent = this;
      newTask.state = Task.STATE_NORMAL;
      prioTop[ priority ] = newTask;
      
      count++;
 
      return newTask;
    }
    
    return null;
  }
  
  public Task addBack( Task newTask, int priority )
  {
    if ( priority >= 0 && priority < MAX_PRIORITY )
    {
      Task next = findTopPrioObj( priority+1 );
      if ( next == null ) next = end;
      
      link( newTask, next );
      
      newTask.priority = priority;
      newTask.parent = this;
      if ( prioTop[ priority ] == null ) prioTop[ priority ] = newTask;
      
      count++;
 
      return newTask;
    }
    
    return null;
  }
  
  public void update()
  {
    Task runner = begin;
    while ( runner != null )
    {
      if ( runner.getState() == Task.STATE_NORMAL )
      {
        runner.update();
      }
      else if ( runner.getState() == Task.STATE_KILL )
      {
        Task del = runner;
        runner = runner.prev;
        del.prev.next = del.next;
        del.next.prev = del.prev;
        // priority先端チェック
        if ( prioTop[del.getPriority()] == del )
        {
          if ( del.next.getPriority() == del.getPriority() )
          {
            prioTop[ del.getPriority() ] = del.next;
          }
          else
          {
            prioTop[ del.getPriority() ] = null;
          }
        }
        
        count--;
        del.state = Task.STATE_NONE;
        del.release();
      }
      
      runner = runner.next;
    }
  }
  
  public void render( ImageArray image )
  {
    Task runner = begin;
    while ( runner != null )
    {
      if ( runner.getState() == Task.STATE_NORMAL ) runner.render( image );
      runner = runner.next;
    }
  }
  
  public Task find( int priority )
  {
    if ( priority >= 0 && priority < MAX_PRIORITY )
    {
      return prioTop[ priority ];
    }
 
    return null;
  }
  
  public int getCount() { return count; }
}

0 件のコメント: