初次提交

This commit is contained in:
2022-09-19 18:05:01 +08:00
commit 57051fc44b
5401 changed files with 325410 additions and 0 deletions
@@ -0,0 +1,291 @@
package com.bn.archieModel;
import android.opengl.GLES20;
import com.bn.commonObject.BallTextureByVertex;
import com.bn.commonObject.CubeForDraw;
import com.bn.commonObject.NumberForDraw;
import com.bn.commonObject.TextureRect;
import com.bn.core.MatrixState;
import com.bn.gameView.BombForControl;
import com.bn.gameView.GLGameView;
import static com.bn.gameView.Constant.*;
import static com.bn.gameView.GLGameView.cx;
import static com.bn.gameView.GLGameView.cz;
/*
* 高射炮的控制类
*/
/*
* 绘制高射炮
* 其中原点位于炮台的几何中心处
* 那么 挡板上升的距离为 挡板的高度的一半和炮台高度的一半,左右的偏移量为炮管的半径
* 炮管最低端的位置为向上移动的距离为 : 炮台高度一半+炮管长度一半
*/
public class ArchieForControl
{
GLGameView gv;//主绘制类
public float[] position=new float[3];//高射炮的摆放位置
public float[] targetPosition=new float[3];//高射炮的旋转轴处的位置
public float[] barrel_center_position=new float[3];//炮管中心处的坐标
public float[] bomb_position_init=new float[3];//高射炮发射炮弹的初始位置
int row;
int col;
private float oldTime=0;//记录上次发射的时间
//--------------------
BarrelForDraw barrel;//炮管
BarbetteForDraw barbette;//炮台
CubeForDraw cube;//创建挡板
private BallTextureByVertex bomb_ball;//炮弹
public float barrel_elevation=30;//炮管的仰角
public float barrel_direction=0;//炮管的方向角
float barrel_down_X=0;//炮管底端的坐标
public float barrel_down_Y=barbette_length/2+cube_height/2;
float barrel_down_Z=0;
public float barrel_curr_X;//炮管几何中心的X坐标
public float barrel_curr_Y;//炮管几何中心的Y坐标
public float barrel_curr_Z;//炮管几何中心的Z坐标
public NumberForDraw nm;//数字引用
public TextureRect backgroundRect;//背景
public float yAnglexue;//血转动
public float xue_scale=0.4f;//血缩放比例
public int blood=100;//血
public int drawblood;
public TextureRect mark_plane;//标记矩形
//标记军火库位置的颜色矩形位置
float arsenal_x,arsenal_y,arsenal_z;
public boolean this_isno_Lock;//是否被锁定
public TextureRect mark_lock;//标记被锁定的矩形
//-----------------------------
public ArchieForControl(GLGameView gv,BarrelForDraw barrel,BarbetteForDraw barbette,CubeForDraw cube,
BallTextureByVertex bomb_ball,float []position,int row,int col,
TextureRect backgroundRect,NumberForDraw nm,TextureRect mark_plane,TextureRect mark_lock
)
{
this.col=col;
this.row=row;
this.nm=nm;
this.backgroundRect=backgroundRect;
this.gv=gv;
this.barrel=barrel;//初始化炮管
this.barbette=barbette;//初始化炮台
this.cube=cube;//初始化挡板
this.bomb_ball=bomb_ball;//炮弹
this.position[0]=position[0];
this.position[1]=position[1];
this.position[2]=position[2];
this.targetPosition[0]=position[0];
this.targetPosition[1]=position[1]+barrel_down_Y;
this.targetPosition[2]=position[2];
this.mark_plane=mark_plane;
this.mark_lock=mark_lock;
arsenal_x=-scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-targetPosition[0])/(MapArray[mapId].length*WIDTH_LALNDFORM);
arsenal_y=scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-targetPosition[2])/(MapArray[mapId].length*WIDTH_LALNDFORM);
}
//绘制方法
public void drawSelf(int[] texBarbetteId,int texCubeId,int[] texBarrelId,int i,int j,int rowR,int colR,
int backgroundRectId,int numberID,int locktexId
)
{
if(row<i||row>rowR||col<j||col>colR)
{
return;
}
drawblood=blood;
MatrixState.pushMatrix();
MatrixState.translate(position[0], position[1], position[2]);
//这里计算炮管的姿态
barrel_curr_Y=(float) (barrel_down_Y+Math.sin(Math.toRadians(barrel_elevation))*barrel_length/2);//炮管的Y坐标
barrel_curr_Z=(float) (barrel_down_Z-Math.cos(Math.toRadians(barrel_elevation))*barrel_length/2);//炮管的Z坐标
MatrixState.pushMatrix();
MatrixState.rotate(barrel_direction,0, 1, 0);
//绘制炮台
MatrixState.pushMatrix();
barbette.drawSelf(texBarbetteId);
MatrixState.popMatrix();
//创建左挡板
MatrixState.pushMatrix();
MatrixState.translate(-barrel_radius-cube_length/2, cube_height/2+barbette_length/2, 0);
cube.drawSelf(texCubeId);
MatrixState.popMatrix();
//创建右挡板
MatrixState.pushMatrix();
MatrixState.translate(barrel_radius+cube_length/2, cube_height/2+barbette_length/2, 0);
cube.drawSelf(texCubeId);
MatrixState.popMatrix();
//绘制炮管
MatrixState.pushMatrix();
//先移动
MatrixState.translate(0, barrel_curr_Y, barrel_curr_Z);
//后旋转
MatrixState.rotate(barrel_elevation-90, 1, 0, 0);
barrel.drawSelf(texBarrelId);
MatrixState.popMatrix();
MatrixState.popMatrix();
MatrixState.popMatrix();
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
if(drawblood>=0){
MatrixState.pushMatrix();
MatrixState.translate(position[0], position[1]+65, position[2]);
MatrixState.scale(xue_scale, xue_scale, xue_scale);
MatrixState.rotate(yAnglexue, 0,1, 0);
backgroundRect.bloodValue=drawblood*2-100+6;
backgroundRect.drawSelf(backgroundRectId);
MatrixState.popMatrix();
}
if(this_isno_Lock)
{
MatrixState.pushMatrix();//绘制锁定的
MatrixState.translate(position[0], position[1]+20, position[2]);
MatrixState.rotate(yAnglexue, 0,1, 0);
MatrixState.rotate(rotationAngle_Plane_Z, 0,0, 1);
MatrixState.scale(1.1f, 1.1f, 0);
mark_lock.drawSelf(locktexId);
MatrixState.popMatrix();
}
GLES20.glDisable(GLES20.GL_BLEND);
}
public void drawSelfMark(int texId){//标记矩形,仪表板
MatrixState.pushMatrix();
MatrixState.translate(arsenal_x,arsenal_y,0);
mark_plane.drawSelf(texId);
MatrixState.popMatrix();
}
//这里计算标志板的朝向
public void calculateBillboardDirection()
{//根据摄像机位置计算焰火粒子面朝向
float currX_span=position[0]-cx;
float currZ_span=position[2]-cz;
if(currZ_span<0)
{
yAnglexue=(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}else if(currZ_span==0){
yAnglexue=currX_span>0?90:-90;
}
else
{
yAnglexue=180+(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}
if(isno_Lock){
this_isno_Lock=false;
return;
}
//计算其是否被锁定
float x1,y1,z1,x2,y2,z2;
x1=position[0]-PLANE_X;
y1=position[1]-PLANE_Y;
z1=position[2]-PLANE_Z;
float distance1=(float) Math.sqrt(x1*x1+y1*y1+z1*z1);
if(distance1>minimumdistance){//如果距离超出范围,或者已经有一个被锁定了,则自己不能被锁定
this_isno_Lock=false;
return;
}//计算飞机飞行的方向向量
x2=directionX;//-(float) (Math.cos(Math.toRadians(rotationAngle_Plane_X))*Math.sin(Math.toRadians(rotationAngle_Plane_Y)));
y2=directionY;//(float) (Math.sin(Math.toRadians(rotationAngle_Plane_X)));
z2=directionZ;//-(float) (Math.cos(Math.toRadians(rotationAngle_Plane_X))*Math.cos(Math.toRadians(rotationAngle_Plane_Y)));
float cosa=(float) Math.acos((x1*x2+y1*y2+z1*z2)/(distance1*1));
if(cosa<Lock_angle){
if(Lock_Arch!=null){
Lock_Arch.this_isno_Lock=false;
}
this.this_isno_Lock=true;
minimumdistance=distance1;//最小距离设置为该距离
nx=x1;ny=y1+10;nz=z1;//发射子弹方向向量
isno_Lock=true;//已经被锁定
Lock_Arch=this;//自己被锁定
}else{
this_isno_Lock=false;
}
}
//时时改变高射炮的角度
public void go()
{
calculateBillboardDirection();
//这里获取飞机的位置
float curr_planeX=PLANE_X;
float curr_planeY=PLANE_Y;
float curr_planeZ=PLANE_Z;
//计算当前高射炮的目标点和飞机之间的距离 这里是 平方
float curr_distance=(curr_planeX-targetPosition[0])*(curr_planeX-targetPosition[0])+
(curr_planeY-targetPosition[1])*(curr_planeY-targetPosition[1])+
(curr_planeZ-targetPosition[2])*(curr_planeZ-targetPosition[2]);
curr_distance=(float) Math.sqrt(curr_distance);
if(curr_distance>ARCHIE_MAX_DISTANCE)
{
return;//如果超出高射炮的扫面范围,那么直接返回
}
//这里计算高度差
float curr_y_span=curr_planeY-targetPosition[1];
if(curr_y_span<=0)
{
return;//如果小于0,那么直接返回
}
//这里计算高射炮的仰角和方位角
float curr_elevation=(float) Math.toDegrees( Math.asin(curr_y_span/curr_distance));
barrel_elevation=curr_elevation;//仰角
//根据反正切计算方位角
float curr_x_span=curr_planeX-targetPosition[0];
float curr_z_span=curr_planeZ-targetPosition[2];
float curr_direction=(float)Math.toDegrees(Math.atan(curr_x_span/curr_z_span));
if(curr_x_span==0&&curr_z_span==0)
{
barrel_direction=curr_direction=0;
}
else if(curr_z_span>=0)
{
barrel_direction=curr_direction=curr_direction+180;
}
else
{
barrel_direction=curr_direction;
}
//---------------如何可以发炮
//这里计算高射炮炮弹的初始位置
if(System.nanoTime()-oldTime>1000000000)//每隔一秒发射一次炮弹
{
bomb_position_init[0]=(float) (targetPosition[0]-Math.cos(Math.toRadians(barrel_elevation))*
Math.sin(Math.toRadians(barrel_direction))*barrel_length);//X
bomb_position_init[1]=(float) (targetPosition[1]+Math.sin(Math.toRadians(barrel_elevation))*
barrel_length);//Y
bomb_position_init[2]=(float) (targetPosition[2]-Math.cos(Math.toRadians(barrel_elevation))*
Math.cos(Math.toRadians(barrel_direction))*barrel_length);//Z
// 发射炮弹
archie_bomb_List.add(new BombForControl(gv,bomb_ball,bomb_position_init,barrel_elevation,
barrel_direction));
gv.activity.playSound(7,0);
oldTime=System.nanoTime();
}
}
}
@@ -0,0 +1,66 @@
package com.bn.archieModel;
import static com.bn.gameView.Constant.*;
import com.bn.commonObject.*;
import com.bn.core.MatrixState;
/*
* 绘制高射炮
* 其中原点位于炮台的几何中心处
* 那么 挡板上升的距离为 挡板的高度的一半和炮台高度的一半,左右的偏移量为炮管的半径
* 炮管最低端的位置为向上移动的距离为 : 炮台高度一半+炮管长度一半
*/
public class ArchieForDraw
{
BarrelForDraw barrel;//炮管
BarbetteForDraw barbette;//炮台
CubeForDraw cube;//创建挡板
public float barrel_elevation=30;//炮管的仰角
public float barrel_direction=0;//炮管的方向角
float barrel_down_X=0;//炮管底端的坐标
public float barrel_down_Y=barbette_length/2+cube_height/2;
float barrel_down_Z=0;
public float barrel_curr_X;//炮管几何中心的X坐标
public float barrel_curr_Y;//炮管几何中心的Y坐标
public float barrel_curr_Z;//炮管几何中心的Z坐标
public ArchieForDraw(BarrelForDraw barrel,BarbetteForDraw barbette,CubeForDraw cube)
{
//创建炮管
this.barrel=barrel;
this.barbette=barbette;
this.cube=cube;
}
public void drawSelf(int texBarbetteId[],int texCubeId,int texBarrelId[])
{
//这里计算炮管的姿态
barrel_curr_Y=(float) (barrel_down_Y+Math.sin(Math.toRadians(barrel_elevation))*barrel_length/2);//炮管的Y坐标
barrel_curr_Z=(float) (barrel_down_Z-Math.cos(Math.toRadians(barrel_elevation))*barrel_length/2);//炮管的Z坐标
MatrixState.pushMatrix();
MatrixState.rotate(barrel_direction,0, 1, 0);
//绘制炮台
MatrixState.pushMatrix();
barbette.drawSelf(texBarbetteId);
MatrixState.popMatrix();
//创建左挡板
MatrixState.pushMatrix();
MatrixState.translate(-barrel_radius-cube_length/2, cube_height/2+barbette_length/2, 0);
cube.drawSelf(texCubeId);
MatrixState.popMatrix();
//创建右挡板
MatrixState.pushMatrix();
MatrixState.translate(barrel_radius+cube_length/2, cube_height/2+barbette_length/2, 0);
cube.drawSelf(texCubeId);
MatrixState.popMatrix();
//绘制炮管
MatrixState.pushMatrix();
//先移动
MatrixState.translate(0, barrel_curr_Y, barrel_curr_Z);
//后旋转
MatrixState.rotate(barrel_elevation-90, 1, 0, 0);
barrel.drawSelf(texBarrelId);
MatrixState.popMatrix();
MatrixState.popMatrix();
}
}
@@ -0,0 +1,34 @@
package com.bn.archieModel;
import com.bn.commonObject.CircleForDraw;
import com.bn.commonObject.CylinderForDraw;
import com.bn.core.MatrixState;
/*
* 创建炮台,为圆柱体炮台,其几何中心位于原点
*/
public class BarbetteForDraw
{
CylinderForDraw cylinder;//圆柱
CircleForDraw circle;//圆面
private float length;
public BarbetteForDraw(float length,float radius,int mProgram)
{
this.length=length;
cylinder=new CylinderForDraw(radius, length, mProgram);
circle=new CircleForDraw(mProgram, radius);
}
public void drawSelf(int texBarbetteId[])//0表示圆柱,1表示圆面
{
MatrixState.pushMatrix();
cylinder.drawSelf(texBarbetteId[0]);//圆柱
MatrixState.popMatrix();
MatrixState.pushMatrix();
MatrixState.rotate(-90, 1, 0, 0);
MatrixState.translate(0, 0, length/2 );
circle.drawSelf(texBarbetteId[1]);//上半圆
MatrixState.popMatrix();
}
}
@@ -0,0 +1,71 @@
package com.bn.archieModel;
import com.bn.commonObject.*;
import com.bn.core.MatrixState;
/*
* 绘制炮管,用于绘制高射炮的炮管部分
*/
public class BarrelForDraw
{
CylinderForDraw longCylinder;//长炮筒
CylinderForDraw shortCylinder;//短炮筒
CircleForDraw bigCircle;//大圆,用于短炮筒
CircleForDraw shortCircle;//小圆,用于长炮筒
private float radius_ratio=1.2f;//短炮筒半径与长炮筒半径的比例
private float cylinder_ratio=0.2f;//短炮筒占长炮筒的比例
private float length_long;//长炮筒的长度
private float length_short;//短炮筒的长度
private float radius_short;//短炮筒的半径
public BarrelForDraw(float length,float radius,int mProgram)
{
this.length_long=length;
this.length_short=length*cylinder_ratio;
this.radius_short=radius*radius_ratio;
longCylinder=new CylinderForDraw(radius, length, mProgram);//绘制长炮筒
shortCircle=new CircleForDraw(mProgram, radius);//长炮筒端口圆
shortCylinder=new CylinderForDraw(radius_short, length_short, mProgram);//绘制短炮筒
bigCircle=new CircleForDraw(mProgram, radius_short);//短炮筒端口圆
}
public void drawSelf(int texBarrelId[])//其中0表示长炮筒圆柱,1表示长炮筒圆面,2表示短炮筒圆柱,3表示短炮筒圆面
{
//--------------------绘制长炮筒------------------------
//绘制长炮筒
MatrixState.pushMatrix();
longCylinder.drawSelf(texBarrelId[0]);
MatrixState.popMatrix();
//绘制长炮筒上部端口圆
MatrixState.pushMatrix();
MatrixState.rotate(-90, 1, 0, 0);
MatrixState.translate(0, 0, length_long/2);
shortCircle.drawSelf(texBarrelId[1]);
MatrixState.popMatrix();
//绘制长炮筒下部的圆
MatrixState.pushMatrix();
MatrixState.rotate(90, 1, 0, 0);
MatrixState.translate(0, 0, length_long/2);
shortCircle.drawSelf(texBarrelId[1]);
MatrixState.popMatrix();
//---------------------绘制短炮筒-------------------------
MatrixState.pushMatrix();
MatrixState.translate(0, length_long/2-length_short, 0);
MatrixState.pushMatrix();
shortCylinder.drawSelf(texBarrelId[2]);
MatrixState.popMatrix();
//绘制长炮筒上部端口圆
MatrixState.pushMatrix();
MatrixState.rotate(-90, 1, 0, 0);
MatrixState.translate(0, 0, length_short/2);
bigCircle.drawSelf(texBarrelId[3]);
MatrixState.popMatrix();
//绘制长炮筒下部的圆
MatrixState.pushMatrix();
MatrixState.rotate(90, 1, 0, 0);
MatrixState.translate(0, 0, length_short/2);
bigCircle.drawSelf(texBarrelId[3]);
MatrixState.popMatrix();
MatrixState.popMatrix();
}
}
@@ -0,0 +1,136 @@
package com.bn.arsenal;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
public class Annulus {//颜色圆环
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
int vCount=0;//顶点数量
public Annulus(int mProgram,float R,float r,int angle){
this.mProgram=mProgram;
//初始化着色器的initShader方法
initShader();
vCount=360/angle*6;
float vertices[]=new float[vCount*3];
int j=0;
for(int i=0;i<360/angle;i++){
vertices[j++]=(float) (R*Math.cos(Math.toRadians(i*angle)));
vertices[j++]=0;
vertices[j++]=(float) (R*Math.sin(Math.toRadians(i*angle)));
vertices[j++]=(float) (r*Math.cos(Math.toRadians(i*angle)));
vertices[j++]=0;
vertices[j++]=(float) (r*Math.sin(Math.toRadians(i*angle)));
vertices[j++]=(float) (r*Math.cos(Math.toRadians((1+i)*angle)));
vertices[j++]=0;
vertices[j++]=(float) (r*Math.sin(Math.toRadians((1+i)*angle)));
vertices[j++]=(float) (R*Math.cos(Math.toRadians(i*angle)));
vertices[j++]=0;
vertices[j++]=(float) (R*Math.sin(Math.toRadians(i*angle)));
vertices[j++]=(float) (r*Math.cos(Math.toRadians((1+i)*angle)));
vertices[j++]=0;
vertices[j++]=(float) (r*Math.sin(Math.toRadians((1+i)*angle)));
vertices[j++]=(float) (R*Math.cos(Math.toRadians((1+i)*angle)));
vertices[j++]=0;
vertices[j++]=(float) (R*Math.sin(Math.toRadians((1+i)*angle)));
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
float texCoor[]=new float[vCount*2];//顶点颜色值数组,每个顶点4个色彩值RGBA
j=0;
float texAngle=1.0f/(360.0f/angle);
for(int i=0;i<360/angle;i++){
texCoor[j++]=i*texAngle;
texCoor[j++]=0;
texCoor[j++]=i*texAngle;
texCoor[j++]=1;
texCoor[j++]=(i+1)*texAngle;
texCoor[j++]=1;
texCoor[j++]=i*texAngle;
texCoor[j++]=0;
texCoor[j++]=(i+1)*texAngle;
texCoor[j++]=1;
texCoor[j++]=(i+1)*texAngle;
texCoor[j++]=0;
}
//创建顶点纹理坐标数据缓冲
ByteBuffer cbb = ByteBuffer.allocateDirect(texCoor.length*4);
cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTexCoorBuffer = cbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(texCoor);//向缓冲区中放入顶点着色数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
}
public void drawSelf(int texId)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//传入顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
}
@@ -0,0 +1,142 @@
package com.bn.arsenal;
import static com.bn.gameView.Constant.ARSENAL_Y;
import static com.bn.gameView.Constant.BUTTON_RADAR_BG_WIDTH;
import static com.bn.gameView.Constant.Lock_angle;
import static com.bn.gameView.Constant.Lock_arsenal;
import static com.bn.gameView.Constant.MapArray;
import static com.bn.gameView.Constant.PLANE_X;
import static com.bn.gameView.Constant.PLANE_Y;
import static com.bn.gameView.Constant.PLANE_Z;
import static com.bn.gameView.Constant.WIDTH_LALNDFORM;
import static com.bn.gameView.Constant.directionX;
import static com.bn.gameView.Constant.directionY;
import static com.bn.gameView.Constant.directionZ;
import static com.bn.gameView.Constant.isOvercome;
import static com.bn.gameView.Constant.isno_Lock;
import static com.bn.gameView.Constant.mapId;
import static com.bn.gameView.Constant.minimumdistance;
import static com.bn.gameView.Constant.nx;
import static com.bn.gameView.Constant.ny;
import static com.bn.gameView.Constant.nz;
import static com.bn.gameView.Constant.rotationAngle_Plane_Z;
import static com.bn.gameView.Constant.scalMark;
import static com.bn.gameView.GLGameView.cx;
import static com.bn.gameView.GLGameView.cz;
import android.opengl.GLES20;
import com.bn.commonObject.NumberForDraw;
import com.bn.commonObject.TextureRect;
import com.bn.core.MatrixState;
public class Arsenal_House
{
public House house;//模型
public float tx,ty,tz;//模型位置
public NumberForDraw nm;//数字引用
public TextureRect bfh;//百分号
public TextureRect backgroundRect;//背景
public int blood=com.bn.gameView.Constant.arsenal_blood;//血
public int drawblood;
float yAngle=0;//血显示转动角度
public TextureRect mark_plane;//标记矩形
//标记军火库位置的颜色矩形位置
float arsenal_x,arsenal_y,arsenal_z;
public boolean this_isno_Lock;//是否被锁定
public TextureRect mark_lock;//标记被锁定的矩形
int row;//所在行列
int col;
public Arsenal_House(House house,float tx,float ty,float tz,TextureRect mark_plane,TextureRect mark_lock,int col,int row){
this.mark_lock=mark_lock;
this.house=house;
this.tx=tx;
this.ty=ty;
this.tz=tz;
this.col=col;
this.row=row;
this.mark_plane=mark_plane;
arsenal_x=-scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-tx)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
arsenal_y=scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-tz)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
}
public void drawSelf(int texFrot,int texSide,int texRoof,int texAnnulus,float yuanAngle,
int backgroundRectId,int numberID,int locktexId,int ii,int jj,int rowR,int colR){
if(row<ii||row>rowR||col<jj||col>colR)
{
return;
}
calculateBillboardDirection();
drawblood=blood;
MatrixState.pushMatrix();
MatrixState.translate(tx,ty,tz);
house.drawSelf(texFrot, texSide, texRoof,texAnnulus,yuanAngle,
backgroundRectId, numberID,drawblood,yAngle);
MatrixState.popMatrix();
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
if(this_isno_Lock&&!isOvercome)
{
MatrixState.pushMatrix();//绘制锁定的
MatrixState.translate(tx, ty+ARSENAL_Y/2, tz);
MatrixState.rotate(yAngle, 0,1, 0);
MatrixState.rotate(rotationAngle_Plane_Z, 0,0, 1);
MatrixState.scale(3.5f, 3.5f, 0);
mark_lock.drawSelf(locktexId);
MatrixState.popMatrix();
}
GLES20.glDisable(GLES20.GL_BLEND);
}
public void drawSelfMark(int texId){
MatrixState.pushMatrix();
MatrixState.translate(arsenal_x,arsenal_y,0);
mark_plane.drawSelf(texId);
MatrixState.popMatrix();
}
//这里计算标志板的朝向
public void calculateBillboardDirection()
{//根据摄像机位置计算焰火粒子面朝向
float currX_span=tx-cx;
float currZ_span=tz-cz;
if(currZ_span<0)
{
yAngle=(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}else if(currZ_span==0){
yAngle=currX_span>0?90:-90;
}
else
{
yAngle=180+(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}
//计算其是否被锁定
float x1,y1,z1,x2,y2,z2;
x1=tx-PLANE_X;
y1=ty+ARSENAL_Y/2-PLANE_Y;
z1=tz-PLANE_Z;
float distance1=(float) Math.sqrt(x1*x1+y1*y1+z1*z1);
if(distance1>minimumdistance){//如果距离超出范围,或者已经有一个被锁定了,则自己不能被锁定
this_isno_Lock=false;
return;
}//计算飞机飞行的方向向量
x2=directionX;//-(float) (Math.cos(Math.toRadians(rotationAngle_Plane_X))*Math.sin(Math.toRadians(rotationAngle_Plane_Y)));
y2=directionY;//(float) (Math.sin(Math.toRadians(rotationAngle_Plane_X)));
z2=directionZ;//-(float) (Math.cos(Math.toRadians(rotationAngle_Plane_X))*Math.cos(Math.toRadians(rotationAngle_Plane_Y)));
float cosa=(float) Math.acos((x1*x2+y1*y2+z1*z2)/(distance1*1));
if(cosa<Lock_angle){
if(Lock_arsenal!=null){
Lock_arsenal.this_isno_Lock=false;
}
this.this_isno_Lock=true;
minimumdistance=distance1;//最小距离设置为该距离
nx=x1;ny=y1+ARSENAL_Y/3;nz=z1;//发射子弹方向向量
isno_Lock=true;//已经被锁定
Lock_arsenal=this;
}else{
this_isno_Lock=false;
}
}
}
@@ -0,0 +1,106 @@
package com.bn.arsenal;
import static com.bn.gameView.Constant.ARSENAL_X;
import static com.bn.gameView.Constant.ARSENAL_Y;
import static com.bn.gameView.Constant.ARSENAL_Z;
import static com.bn.gameView.Constant.isOvercome;
import android.opengl.GLES20;
import com.bn.commonObject.NumberForDraw;
import com.bn.commonObject.TextureRect;
import com.bn.core.MatrixState;
public class House
{
public float house_width=ARSENAL_X;
public float house_height=ARSENAL_Y;//房屋的大小
public float house_length=ARSENAL_Z;
public float house_roof_width=ARSENAL_X+15;
public float house_roof_height=45;//屋顶矩形的大小
public float roof_front_Angle=10;//屋顶与平面的夹角
public TextureRect house_front;//前后
public TextureRect house_side;//侧面
public TextureRect house_roof;//屋顶
public Triangle triangle;//侧面三角形
public Annulus annulus;//颜色圆环
public NumberForDraw nm;//数字引用
public TextureRect backgroundRect;//背景
public float annulusR=250;
public float annulusr=200;
float roofx=0;
float roofy=house_height+house_length/2*(float)Math.tan(Math.toRadians(roof_front_Angle))-
house_roof_height*(float)Math.sin(Math.toRadians(roof_front_Angle))/2;
float roofz=house_roof_height*(float)Math.cos(Math.toRadians(roof_front_Angle))/2;
public House(int mProgram,TextureRect backgroundRect,NumberForDraw nm)
{
this.nm=nm;
this.backgroundRect=backgroundRect;
house_front=new TextureRect( house_width, house_height-1.5f,mProgram);
house_side=new TextureRect( house_length, house_height,mProgram);
house_roof=new TextureRect( house_roof_width, house_roof_height,mProgram);
annulus=new Annulus(mProgram,annulusR,annulusr,15);
triangle=new Triangle(mProgram,house_length,house_length/2*(float)Math.tan(Math.toRadians(roof_front_Angle))-0.5f);
}
public void drawSelf(int texFrot,int texSide,int texRoof,int texAnnulus,float yuanAngle,
int backgroundRectId,int numberID,int blood,float yAngle
){
MatrixState.pushMatrix();
MatrixState.translate(0, house_height/2, house_length/2);
house_front.drawSelf(texFrot);
MatrixState.translate(0, 0, -house_length);
MatrixState.rotate(180, 0, 1, 0);
house_front.drawSelf(texFrot);
MatrixState.popMatrix();
MatrixState.pushMatrix();
MatrixState.translate(-house_width/2, house_height/2,0);
MatrixState.rotate(-90, 0, 1, 0);
house_side.drawSelf(texSide);
MatrixState.translate(0, 0, -house_width);
MatrixState.rotate(180, 0, 1, 0);
house_side.drawSelf(texSide);
MatrixState.translate(0, house_height/2, 0);
triangle.drawSelf(texSide);
MatrixState.translate(0, 0, -house_width);
MatrixState.rotate(180, 0, 1, 0);
triangle.drawSelf(texSide);
MatrixState.popMatrix();
MatrixState.pushMatrix();
MatrixState.translate(roofx,roofy,roofz);
MatrixState.rotate(roof_front_Angle-90, 1, 0, 0);
house_roof.drawSelf(texRoof);
MatrixState.rotate(180, 0, 1, 0);
house_roof.drawSelf(texRoof);
MatrixState.popMatrix();
MatrixState.pushMatrix();
MatrixState.translate(roofx,roofy,-roofz);
MatrixState.rotate(90-roof_front_Angle, 1, 0, 0);
house_roof.drawSelf(texRoof);
MatrixState.rotate(180, 0, 1, 0);
house_roof.drawSelf(texRoof);
MatrixState.popMatrix();
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
MatrixState.pushMatrix();
MatrixState.translate(0,4,0);
MatrixState.rotate(yuanAngle, 0, 1, 0);
annulus.drawSelf(texAnnulus);//地下圆环
MatrixState.popMatrix();
if(blood>=0&&!isOvercome){
MatrixState.pushMatrix();
MatrixState.translate(0,house_height+60,0f);
MatrixState.rotate(yAngle, 0,1, 0);
MatrixState.scale(0.75f, 0.8f, 0.1f);
backgroundRect.bloodValue=blood*2-100+6;
backgroundRect.drawSelf(backgroundRectId);
MatrixState.popMatrix();
}
GLES20.glDisable(GLES20.GL_BLEND);
}
}
@@ -0,0 +1,36 @@
package com.bn.arsenal;
import static com.bn.gameView.Constant.house_height;
import com.bn.commonObject.*;
import com.bn.core.MatrixState;
public class PlaneHouse {
public int col, row;//ËùÔÚµÄÐÐÁÐ
public CubeForDraw cub;//·¿×Ó
Light_Tower lt;//ÑÌ´Ñ
float tx,ty,tz;
public PlaneHouse(float tx,float ty,float tz,CubeForDraw cub,Light_Tower lt,int col,int row){
this.cub=cub;
this.lt=lt;
this.col=col;
this.row=row;
this.cub=cub;
this.tx=tx;this.ty=ty;this.tz=tz;
}
public void drawSelf(int cubtexId,int cubtexId1,int smallcubtexId,int smallcubtexId2,int lttexId,int ii,int jj,int rowR,int colR){
if(row<ii||row>rowR||col<jj||col>colR)
{
return;
}
MatrixState.pushMatrix();
MatrixState.translate(tx,ty,tz);
cub.drawSelf(cubtexId, cubtexId1);
MatrixState.translate(30, -house_height/2, 70);
lt.drawSelf(lttexId);
MatrixState.translate(50, house_height/2*0.3f, 80);
MatrixState.scale(0.5f, 0.3f, 0.6f);
cub.drawSelf(smallcubtexId, smallcubtexId2);
MatrixState.popMatrix();
}
}
@@ -0,0 +1,95 @@
package com.bn.arsenal;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.bn.core.MatrixState;
import android.opengl.GLES20;
public class Triangle
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
int vCount=0;//顶点数量
public Triangle(int mProgram,float width,float height)
{
this.mProgram=mProgram;
//初始化着色器的initShader方法
initShader();
vCount=3;
float vertices[]=new float[]
{
0,height,0,
-width/2,0,0,
width/2,0,0,
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
float texCoor[]=new float[]//顶点颜色值数组,每个顶点4个色彩值RGBA
{
0.5f,0, 0,1, 1,1,
};
//创建顶点纹理坐标数据缓冲
ByteBuffer cbb = ByteBuffer.allocateDirect(texCoor.length*4);
cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTexCoorBuffer = cbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(texCoor);//向缓冲区中放入顶点着色数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
}
public void drawSelf(int texId)
{
//制定使用某套着色器程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入着色器程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
}
@@ -0,0 +1,171 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import com.bn.core.MatrixState;
import android.opengl.GLES20;
//绘制纹理球,根据传入的阈值,可以判断是半球还是整球
public class BallTextureByVertex
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
int vCount=0; //顶点数
private float aspan=18;//纹理球横纵切分的角度间隔
public BallTextureByVertex(float radius,int mProgram,float vAngle_Domain)//vAngle_Domain是半球还是整球
{
this.mProgram=mProgram;
//调用初始化顶点数据的initVertexData方法
initVertexData(radius,vAngle_Domain);
//初始化着色器的initShader方法
initShader();
}
//初始化顶点数据的initVertexData方法
public void initVertexData(float radius,float vAngle_Domain)
{
ArrayList<Float> alVertix=new ArrayList<Float>();//存放顶点坐标的ArrayList
for(float vAngle=90;vAngle>vAngle_Domain;vAngle=vAngle-aspan)//垂直方向angleSpan度一份
{
for(float hAngle=360;hAngle>0;hAngle=hAngle-aspan)//水平方向angleSpan度一份
{
double xozLength=radius*Math.cos(Math.toRadians(vAngle));
float x1=(float)(xozLength*Math.cos(Math.toRadians(hAngle)));
float z1=(float)(xozLength*Math.sin(Math.toRadians(hAngle)));
float y1=(float)(radius*Math.sin(Math.toRadians(vAngle)));
xozLength=radius*Math.cos(Math.toRadians(vAngle-aspan));
float x2=(float)(xozLength*Math.cos(Math.toRadians(hAngle)));
float z2=(float)(xozLength*Math.sin(Math.toRadians(hAngle)));
float y2=(float)(radius*Math.sin(Math.toRadians(vAngle-aspan)));
xozLength=radius*Math.cos(Math.toRadians(vAngle-aspan));
float x3=(float)(xozLength*Math.cos(Math.toRadians(hAngle-aspan)));
float z3=(float)(xozLength*Math.sin(Math.toRadians(hAngle-aspan)));
float y3=(float)(radius*Math.sin(Math.toRadians(vAngle-aspan)));
xozLength=radius*Math.cos(Math.toRadians(vAngle));
float x4=(float)(xozLength*Math.cos(Math.toRadians(hAngle-aspan)));
float z4=(float)(xozLength*Math.sin(Math.toRadians(hAngle-aspan)));
float y4=(float)(radius*Math.sin(Math.toRadians(vAngle)));
//构建第一三角形
alVertix.add(x1);alVertix.add(y1);alVertix.add(z1);
alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
//构建第二三角形
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);
}
}
vCount=alVertix.size()/3;//顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标
float vertices[]=new float[vCount*3];
for(int i=0;i<alVertix.size();i++)
{
vertices[i]=alVertix.get(i);
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
float texCoor[]=generateTexCoor
(
(int)(360/aspan), //纹理图切分的列数
(int)(180/aspan) //纹理图切分的行数
);
ByteBuffer cbb = ByteBuffer.allocateDirect(texCoor.length*4);
cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTexCoorBuffer = cbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(texCoor);//向缓冲区中放入顶点着色数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
//初始化着色器的initShader方法
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置、纹理坐标数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制整个球
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
//自动切分纹理产生纹理数组的方法
public float[] generateTexCoor(int bw,int bh)
{
float[] result=new float[bw*bh*6*2];
float sizew=1.0f/bw;//列数
float sizeh=1.0f/bh;//行数
int c=0;
for(int i=0;i<bh;i++)
{
for(int j=0;j<bw;j++)
{
//每行列一个矩形,由两个三角形构成,共六个点,12个纹理坐标
float s=j*sizew;
float t=i*sizeh;
result[c++]=s;
result[c++]=t;
result[c++]=s;
result[c++]=t+sizeh;
result[c++]=s+sizew;
result[c++]=t;
result[c++]=s+sizew;
result[c++]=t;
result[c++]=s;
result[c++]=t+sizeh;
result[c++]=s+sizew;
result[c++]=t+sizeh;
}
}
return result;
}
}
@@ -0,0 +1,130 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
/**
* 用triangle_fan方式绘制纹理圆面 此圆面是平行于XY平面的
* 用于绘制圆,圆面的中心位于原点
* 在高射炮中用到
*/
public class CircleForDraw
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
private int vCount;
float angleSpan=12;//切分角度
public CircleForDraw
(
int mProgram,
float radius//圆半径
)
{
this.mProgram=mProgram;
initVertexData(radius);
initShader();
}
public void initVertexData
(
float radius//圆半径
)
{
//顶点纹理坐标数据的初始化================begin============================
vCount=1+(int)(360/angleSpan)+1;//顶点的个数
float[] vertices=new float[vCount*3];//初始化顶点数组
float[] textures=new float[vCount*2];
//存放中心点坐标
vertices[0]=0;
vertices[1]=0;
vertices[2]=0;
//存放中心点纹理
textures[0]=0.5f;
textures[1]=0.5f;
int vcount=3;//当前顶点坐标索引
int tcount=2;//当前纹理坐标索引
for(float angle=0;angle<=360;angle=angle+angleSpan)
{
double angleRadian=Math.toRadians(angle);
//顶点坐标
vertices[vcount++]=radius*(float)Math.cos(angleRadian);
vertices[vcount++]=radius*(float)Math.sin(angleRadian);
vertices[vcount++]=0;
textures[tcount++]=textures[0]+0.5f*(float)Math.cos(angleRadian);
textures[tcount++]=textures[1]+0.5f*(float)Math.sin(angleRadian);
}
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTexCoorBuffer = tbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(textures);//向缓冲区中放入顶点着色数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
}
public void drawSelf(int texId)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置、纹理坐标数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制图形
GLES20.glDrawArrays
(
GL10.GL_TRIANGLE_FAN, //以TRIANGLE_FAN方式填充
0,
vCount
);
}
}
@@ -0,0 +1,101 @@
package com.bn.commonObject;
import com.bn.core.MatrixState;
/* 绘制长方体,其中心点位于原点 其中长平行于X轴,宽平行于Z轴,高平行于Y轴
* 分别由长宽高来指定
*/
public class CubeForDraw
{
//长方体的三个面
TextureRect sideXY;//前面
TextureRect sideYZ;//侧面
TextureRect sideXZ;//上面
float length;
float width;
float height;
public CubeForDraw
(
float length,
float width,
float height,
int mProgram
)
{
this.length=length;
this.width=width;
this.height=height;
sideXY=new TextureRect( length, height,mProgram);//创建前面
sideYZ=new TextureRect( width, height,mProgram);//创建侧面
sideXZ=new TextureRect(length, width, mProgram);//创建上面
}
public void drawSelf(int texId)
{
//绘制前面
MatrixState.pushMatrix();
MatrixState.translate(0, 0,width/2);
sideXY.drawSelf(texId);
MatrixState.popMatrix();
//绘制后面
MatrixState.pushMatrix();
MatrixState.rotate(180, 0, 1, 0);
MatrixState.translate(0, 0, width/2);
sideXY.drawSelf(texId);
MatrixState.popMatrix();
//绘制左面
MatrixState.pushMatrix();
MatrixState.rotate(-90, 0, 1, 0);
MatrixState.translate(0,0, length/2);
sideYZ.drawSelf(texId);
MatrixState.popMatrix();
//绘制右面
MatrixState.pushMatrix();
MatrixState.rotate(90, 0, 1, 0);
MatrixState.translate(0,0, length/2);
sideYZ.drawSelf(texId);
MatrixState.popMatrix();
//绘制上面
MatrixState.pushMatrix();
MatrixState.rotate(-90, 1, 0, 0);
MatrixState.translate(0,0, height/2);
sideXZ.drawSelf(texId);
MatrixState.popMatrix();
//绘制下面
MatrixState.pushMatrix();
MatrixState.rotate(90, 1, 0, 0);
MatrixState.translate(0,0, height/2);
sideXZ.drawSelf(texId);
MatrixState.popMatrix();
}
public void drawSelf(int texId,int texId1)
{
//绘制前面
MatrixState.pushMatrix();
MatrixState.translate(0, 0,width/2);
sideXY.drawSelf(texId);
MatrixState.popMatrix();
//绘制后面
MatrixState.pushMatrix();
MatrixState.rotate(180, 0, 1, 0);
MatrixState.translate(0, 0, width/2);
sideXY.drawSelf(texId);
MatrixState.popMatrix();
//绘制左面
MatrixState.pushMatrix();
MatrixState.rotate(-90, 0, 1, 0);
MatrixState.translate(0,0, length/2);
sideYZ.drawSelf(texId);
MatrixState.popMatrix();
//绘制右面
MatrixState.pushMatrix();
MatrixState.rotate(90, 0, 1, 0);
MatrixState.translate(0,0, length/2);
sideYZ.drawSelf(texId);
MatrixState.popMatrix();
//绘制上面
MatrixState.pushMatrix();
MatrixState.rotate(-90, 1, 0, 0);
MatrixState.translate(0,0, height/2);
sideXZ.drawSelf(texId1);
MatrixState.popMatrix();
}
}
@@ -0,0 +1,189 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
/*
* 用于绘制圆柱,只有纹理
* 圆柱的中心位于原点,圆柱中心轴平行于Y轴
* 在高射炮中用到
*/
public class CylinderForDraw
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
int vCount=0;//顶点数量
float aspan=15;//切分角度
float lspan;//切分长度
public CylinderForDraw
(
float radius,//圆柱半径
float length,//圆柱长度
int mProgram
)
{
this.mProgram=mProgram;
lspan=length;//初始化切分的单位长度
//初始化顶点
initVertexData(radius,length);
//初始化着色器的initShader方法
initShader();
}
//初始化顶点坐标与着色数据的方法
public void initVertexData
(
float r,//圆柱半径
float length//圆柱长度
)
{
//顶点坐标数据的初始化================begin============================
//获取切分整图的纹理数组
ArrayList<Float> alVertix=new ArrayList<Float>();//存放顶点坐标的ArrayList
for(float tempY=length/2;tempY>-length/2;tempY=tempY-lspan)//垂直方向lspan长度一份
{
for(float hAngle=360;hAngle>0;hAngle=hAngle-aspan)//水平方向angleSpan度一份
{
//纵向横向各到一个角度后计算对应的此点在球面上的四边形顶点坐标
//并构建两个组成四边形的三角形
float x1=(float)(r*Math.cos(Math.toRadians(hAngle)));
float z1=(float)(r*Math.sin(Math.toRadians(hAngle)));
float y1=tempY;
float x2=(float)(r*Math.cos(Math.toRadians(hAngle)));
float z2=(float)(r*Math.sin(Math.toRadians(hAngle)));
float y2=tempY-lspan;
float x3=(float)(r*Math.cos(Math.toRadians(hAngle-aspan)));
float z3=(float)(r*Math.sin(Math.toRadians(hAngle-aspan)));
float y3=tempY-lspan;
float x4=(float)(r*Math.cos(Math.toRadians(hAngle-aspan)));
float z4=(float)(r*Math.sin(Math.toRadians(hAngle-aspan)));
float y4=tempY;
//构建第一三角形
alVertix.add(x1);alVertix.add(y1);alVertix.add(z1);
alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
//构建第二三角形
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);
}
}
vCount=alVertix.size()/3;//顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标
//将alVertix中的坐标值转存到一个int数组中
float vertices[]=new float[vCount*3];
for(int i=0;i<alVertix.size();i++)
{
vertices[i]=alVertix.get(i);
}
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
float[] texCoorArray=generateTexCoor
(
(int)(360/aspan), //纹理图切分的列数
(int)(length/lspan) //纹理图切分的行数
);
//创建顶点纹理坐标数据缓冲
ByteBuffer cbb = ByteBuffer.allocateDirect(texCoorArray.length*4);
cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTexCoorBuffer = cbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(texCoorArray);//向缓冲区中放入顶点着色数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
}
public void drawSelf(int texId)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置、纹理坐标数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制整个圆柱
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
//自动切分纹理产生纹理数组的方法
public float[] generateTexCoor(int bw,int bh)
{
float[] result=new float[bw*bh*6*2];
float sizew=1.0f/bw;//列数
float sizeh=1.0f/bh;//行数
int c=0;
for(int i=0;i<bh;i++)
{
for(int j=0;j<bw;j++)
{
//每行列一个矩形,由两个三角形构成,共六个点,12个纹理坐标
float s=j*sizew;
float t=i*sizeh;
result[c++]=s;
result[c++]=t;
result[c++]=s;
result[c++]=t+sizeh;
result[c++]=s+sizew;
result[c++]=t;
result[c++]=s+sizew;
result[c++]=t;
result[c++]=s;
result[c++]=t+sizeh;
result[c++]=s+sizew;
result[c++]=t+sizeh;
}
}
return result;
}
}
@@ -0,0 +1,368 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.bn.core.MatrixState;
import android.opengl.GLES20;
import static com.bn.gameView.Constant.*;
/*
* 绘制大坝
*/
public class DamForDraw
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
int vCount;
public boolean isShaderOk;
public DamForDraw(float height,float length1,float length2,float length3,int mProgram)
{
this.mProgram=mProgram;
initData(height,length1,length2,length3);
}
//初始化顶点的信息
public void initData(float height,float length1,float length2,float length3)
{
float vertex[]=new float[(ArchieArray[mapId][5].length/2-1)*6*9*2];
float texture[]=new float[(ArchieArray[mapId][5].length/2-1)*6*6*2];
vCount=vertex.length/3;
int t=0;
int d=0;
for(int i=0;i<ArchieArray[mapId][5].length/2-1;i++)
{
float x1,z1;
float x2,z2;
float texX,texY1,texY2,texY3,texY4;
float spanx=1.0f/(ArchieArray[mapId][5].length/2-1);
texX=spanx*i;
texY1=0;
texY2=0.4f;
texY3=0.6f;
texY4=1;
x1=ArchieArray[mapId][5][2*i]*WIDTH_LALNDFORM;
x2=ArchieArray[mapId][5][2*(1+i)]*WIDTH_LALNDFORM;
z1=ArchieArray[mapId][5][2*i+1]*WIDTH_LALNDFORM;
z2=ArchieArray[mapId][5][2*(1+i)+1]*WIDTH_LALNDFORM;
vertex[d++]=x1;//第一个三角形
vertex[d++]=0;
vertex[d++]=z1-length1;
vertex[d++]=x1;
vertex[d++]=height;
vertex[d++]=z1;
vertex[d++]=x2;
vertex[d++]=height;
vertex[d++]=z2;
texture[t++]=texX;
texture[t++]=texY1;
texture[t++]=texX;
texture[t++]=texY2;
texture[t++]=texX+spanx;
texture[t++]=texY2;
vertex[d++]=x1;//第一个三角形反面
vertex[d++]=0;
vertex[d++]=z1-length1;
vertex[d++]=x2;
vertex[d++]=-height;
vertex[d++]=z2;
vertex[d++]=x1;
vertex[d++]=-height;
vertex[d++]=z1;
texture[t++]=texX;
texture[t++]=texY1;
texture[t++]=texX+spanx;
texture[t++]=texY2;
texture[t++]=texX;
texture[t++]=texY2;
vertex[d++]=x1;//第二个三角形
vertex[d++]=0;
vertex[d++]=z1-length1;
vertex[d++]=x2;
vertex[d++]=height;
vertex[d++]=z2;
vertex[d++]=x2;
vertex[d++]=0;
vertex[d++]=z2-length1;
texture[t++]=texX;
texture[t++]=texY1;
texture[t++]=texX+spanx;
texture[t++]=texY2;
texture[t++]=texX+spanx;
texture[t++]=texY1;
vertex[d++]=x1;//第二个三角形反面
vertex[d++]=0;
vertex[d++]=z1-length1;
vertex[d++]=x2;
vertex[d++]=0;
vertex[d++]=z2-length1;
vertex[d++]=x2;
vertex[d++]=-height;
vertex[d++]=z2;
texture[t++]=texX;
texture[t++]=texY1;
texture[t++]=texX+spanx;
texture[t++]=texY1;
texture[t++]=texX+spanx;
texture[t++]=texY2;
vertex[d++]=x1;//第三个三角形
vertex[d++]=height;
vertex[d++]=z1;
vertex[d++]=x1;
vertex[d++]=height;
vertex[d++]=z1+length2;
vertex[d++]=x2;
vertex[d++]=height;
vertex[d++]=z2+length2;
texture[t++]=texX;
texture[t++]=texY2;
texture[t++]=texX;
texture[t++]=texY3;
texture[t++]=texX+spanx;
texture[t++]=texY3;
vertex[d++]=x1;//第三个三角形fanm反面
vertex[d++]=-height;
vertex[d++]=z1;
vertex[d++]=x2;
vertex[d++]=-height;
vertex[d++]=z2+length2;
vertex[d++]=x1;
vertex[d++]=-height;
vertex[d++]=z1+length2;
texture[t++]=texX;
texture[t++]=texY2;
texture[t++]=texX+spanx;
texture[t++]=texY3;
texture[t++]=texX;
texture[t++]=texY3;
vertex[d++]=x1;//第四个三角形
vertex[d++]=height;
vertex[d++]=z1;
vertex[d++]=x2;
vertex[d++]=height;
vertex[d++]=z2+length2;
vertex[d++]=x2;
vertex[d++]=height;
vertex[d++]=z2;
texture[t++]=texX;
texture[t++]=texY2;
texture[t++]=texX+spanx;
texture[t++]=texY3;
texture[t++]=texX+spanx;
texture[t++]=texY2;
vertex[d++]=x1;//第四个三角形反面
vertex[d++]=-height;
vertex[d++]=z1;
vertex[d++]=x2;
vertex[d++]=-height;
vertex[d++]=z2;
vertex[d++]=x2;
vertex[d++]=-height;
vertex[d++]=z2+length2;
texture[t++]=texX;
texture[t++]=texY2;
texture[t++]=texX+spanx;
texture[t++]=texY2;
texture[t++]=texX+spanx;
texture[t++]=texY3;
vertex[d++]=x1;//第五个三角形
vertex[d++]=height;
vertex[d++]=z1+length2;
vertex[d++]=x1;
vertex[d++]=0;
vertex[d++]=z1+length2+length3;
vertex[d++]=x2;
vertex[d++]=0;
vertex[d++]=z2+length2+length3;
texture[t++]=texX;
texture[t++]=texY3;
texture[t++]=texX;
texture[t++]=texY4;
texture[t++]=texX+spanx;
texture[t++]=texY4;
vertex[d++]=x1;//第五个三角形反面
vertex[d++]=-height;
vertex[d++]=z1+length2;
vertex[d++]=x2;
vertex[d++]=0;
vertex[d++]=z2+length2+length3;
vertex[d++]=x1;
vertex[d++]=0;
vertex[d++]=z1+length2+length3;
texture[t++]=texX;
texture[t++]=texY3;
texture[t++]=texX+spanx;
texture[t++]=texY4;
texture[t++]=texX;
texture[t++]=texY4;
vertex[d++]=x1;//第六个三角形
vertex[d++]=height;
vertex[d++]=z1+length2;
vertex[d++]=x2;
vertex[d++]=0;
vertex[d++]=z2+length2+length3;
vertex[d++]=x2;
vertex[d++]=height;
vertex[d++]=z2+length2;
texture[t++]=texX;
texture[t++]=texY3;
texture[t++]=texX+spanx;
texture[t++]=texY4;
texture[t++]=texX+spanx;
texture[t++]=texY3;
vertex[d++]=x1;//第六个三角形反面
vertex[d++]=-height;
vertex[d++]=z1+length2;
vertex[d++]=x2;
vertex[d++]=-height;
vertex[d++]=z2+length2;
vertex[d++]=x2;
vertex[d++]=0;
vertex[d++]=z2+length2+length3;
texture[t++]=texX;
texture[t++]=texY3;
texture[t++]=texX+spanx;
texture[t++]=texY3;
texture[t++]=texX+spanx;
texture[t++]=texY4;
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertex.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer.put(vertex);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);
ByteBuffer vbt=ByteBuffer.allocateDirect(texture.length*4);
vbt.order(ByteOrder.nativeOrder());
mTexCoorBuffer=vbt.asFloatBuffer();
mTexCoorBuffer.put(texture);
mTexCoorBuffer.position(0);
}
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
}
//绘制方法
public void drawSelf(int texId)
{
//使用某套指定的Shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入到Shader程序中
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入坐标数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制加载的物体
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
}
@@ -0,0 +1,71 @@
package com.bn.commonObject;
import java.util.Iterator;
import com.bn.core.MatrixState;
import static com.bn.gameView.GLGameView.*;
public class DrawBomb
{
float x,y,z;
float xAngle,yAngle,zAngle;
int index;//当前播放了第几幅图
TextureRect recw;//矩形引用
public DrawBomb(TextureRect recw,float x,float y,float z)
{
this.x=x;
this.y=y;
this.z=z;
this.recw=recw;
}
public void drawSelf()
{
index++;
if(index>15)
{
try
{
Iterator<DrawBomb> ite=baoZhaList.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
return;
}
calculateBillboardDirection();
MatrixState.pushMatrix();
MatrixState.translate(x, y, z);
MatrixState.rotate(xAngle, 1, 0, 0);
MatrixState.rotate(yAngle, 0, 1, 0);
MatrixState.rotate(zAngle, 0, 0, 1);
MatrixState.scale(index/3%5*0.8f, index/3%5*0.8f, index/3%5*0.8f);
recw.drawSelf(baoZhaXiaoguo2);// baoZhaTexId[index/3%5]);
MatrixState.popMatrix();
}
public void calculateBillboardDirection()
{//根据摄像机位置计算爆炸纹理面朝向
float xspan=x-cx;
float zspan=z-cz;
float yspan=y-cy;
if(zspan<=0)
{
yAngle=(float)Math.toDegrees(Math.atan(xspan/zspan));
}
else
{
yAngle=180+(float)Math.toDegrees(Math.atan(xspan/zspan));
}
xAngle=(float)Math.toDegrees(Math.atan(yspan/Math.sqrt(xspan*xspan+zspan*zspan)));
}
}
@@ -0,0 +1,357 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import com.bn.core.MatrixState;
import android.opengl.GLES20;
import static com.bn.gameView.Constant.*;
//构建地形的类 地形平行于XZ平面 并且位于XZ平面的第四象限
//这里的山地要贴四副纹理,在着色器中根据高度来判定
public class LandForm
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
int uTuCengTexHandle;//土层纹理属性引用id
int uCaoDiTexHandle;//草地纹理属性引用id
int uShiTouTexHandle;//石头纹理属性引用id
int uShanDingTexHandle;//山顶纹理属性引用id
int muHightHandle;//渐变高度
int muHightspanHandle;
int uLandFlagHandle;//不同类型的山的标志如果为1表示地面上的山
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTextureBuffer;//顶点着色数据缓冲
int vCount;//顶点数量
private boolean ishuidutu=false;//是否是灰度图还是程序生成
public LandForm(int terrainId,int mProgram)
{
this.mProgram=mProgram;
if(terrainId==3||terrainId==5||terrainId==6)//如果是陆地上的山,则不绘制倒影
{
ishuidutu=true;
}
initVertexData(terrainId);
initShader();
}
public void initVertexData(int terrainId)
{
int cols=LANDS_HEIGHT_ARRAY[terrainId][0].length-1;//列数
int rows=LANDS_HEIGHT_ARRAY[terrainId].length-1;//行数
//绘制程序生成的山
if(!ishuidutu)
{
//纹理的块数
float textureSize=1f;
float sizew=textureSize/cols;//列宽
float sizeh=textureSize/rows;//行宽
//顶点的集合
ArrayList<Float> alVertex=new ArrayList<Float>();
//纹理的 集合
ArrayList<Float> alTexture=new ArrayList<Float>();
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
//计算当前格子左上侧点坐标
float zsx=j*LAND_UNIT_SIZE;//当前点x坐标
float zsz=i*LAND_UNIT_SIZE;//当前点z坐标
float s=j*sizew; //s坐标
float t=i*sizeh; //t坐标
if(LANDS_HEIGHT_ARRAY[terrainId][i][j]!=0||LANDS_HEIGHT_ARRAY[terrainId][i+1][j]!=0||LANDS_HEIGHT_ARRAY[terrainId][i][j+1]!=0)
{
//左上点
alVertex.add(zsx);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i][j]);
alVertex.add(zsz);
//左下点
alVertex.add(zsx);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i+1][j]);
alVertex.add(zsz+LAND_UNIT_SIZE);
//右上点
alVertex.add(zsx+LAND_UNIT_SIZE);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i][j+1]);
alVertex.add(zsz);
alTexture.add(s);
alTexture.add(t);
alTexture.add(s);
alTexture.add(t+sizeh);
alTexture.add(s+sizew);
alTexture.add(t);
//--------------------绘制倒影-------------
//左上点
alVertex.add(zsx);
alVertex.add(-LANDS_HEIGHT_ARRAY[terrainId][i][j]);
alVertex.add(zsz);
//右上点
alVertex.add(zsx+LAND_UNIT_SIZE);
alVertex.add(-LANDS_HEIGHT_ARRAY[terrainId][i][j+1]);
alVertex.add(zsz);
//左下点
alVertex.add(zsx);
alVertex.add(-LANDS_HEIGHT_ARRAY[terrainId][i+1][j]);
alVertex.add(zsz+LAND_UNIT_SIZE);
alTexture.add(s);
alTexture.add(t);
alTexture.add(s+sizew);
alTexture.add(t);
alTexture.add(s);
alTexture.add(t+sizeh);
}
if(LANDS_HEIGHT_ARRAY[terrainId][i][j+1]!=0||LANDS_HEIGHT_ARRAY[terrainId][i+1][j]!=0||LANDS_HEIGHT_ARRAY[terrainId][i+1][j+1]!=0){
//右上点
alVertex.add(zsx+LAND_UNIT_SIZE);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i][j+1]);
alVertex.add(zsz);
//左下点
alVertex.add(zsx);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i+1][j]);
alVertex.add(zsz+LAND_UNIT_SIZE);
//右下点
alVertex.add(zsx+LAND_UNIT_SIZE);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i+1][j+1]);
alVertex.add(zsz+LAND_UNIT_SIZE);
alTexture.add(s+sizew);
alTexture.add(t);
alTexture.add(s);
alTexture.add(t+sizeh);
alTexture.add(s+sizew);
alTexture.add(t+sizeh);
//右上点
alVertex.add(zsx+LAND_UNIT_SIZE);
alVertex.add(-LANDS_HEIGHT_ARRAY[terrainId][i][j+1]);
alVertex.add(zsz);
//右下点
alVertex.add(zsx+LAND_UNIT_SIZE);
alVertex.add(-LANDS_HEIGHT_ARRAY[terrainId][i+1][j+1]);
alVertex.add(zsz+LAND_UNIT_SIZE);
//左下点
alVertex.add(zsx);
alVertex.add(-LANDS_HEIGHT_ARRAY[terrainId][i+1][j]);
alVertex.add(zsz+LAND_UNIT_SIZE);
alTexture.add(s+sizew);
alTexture.add(t);
alTexture.add(s+sizew);
alTexture.add(t+sizeh);
alTexture.add(s);
alTexture.add(t+sizeh);
}
}
}
vCount=alVertex.size()/3;
float vertices[]=new float[vCount*3];
for(int i=0;i<vCount*3;i++)
{
vertices[i]=alVertex.get(i);
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//创建顶点纹理缓冲
float textures[]=new float[alTexture.size()];
for(int i=0;i<alTexture.size();i++)
{
textures[i]=alTexture.get(i);
}
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTextureBuffer= tbb.asFloatBuffer();//转换为Float型缓冲
mTextureBuffer.put(textures);//向缓冲区中放入顶点着色数据
mTextureBuffer.position(0);//设置缓冲区起始位置
}
else//加载的灰度图,绘制的时候用trangle_strip方式的
{
//纹理的块数
float textureSize=1f;
float sizew=textureSize/cols;//列宽
float sizeh=textureSize/rows;//行宽
//顶点的集合
ArrayList<Float> alVertex=new ArrayList<Float>();
//纹理的 集合
ArrayList<Float> alTexture=new ArrayList<Float>();
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
//计算当前格子左上侧点坐标
float zsx=j*LAND_UNIT_SIZE;//当前点x坐标
float zsz=i*LAND_UNIT_SIZE;//当前点z坐标
float s=j*sizew; //s坐标
float t=i*sizeh; //t坐标
if(i!=0&&j==0)
{
//左上点
alVertex.add(zsx);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i][j]);
alVertex.add(zsz);
alTexture.add(s);
alTexture.add(t);
}
//左上点
alVertex.add(zsx);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i][j]);
alVertex.add(zsz);
alTexture.add(s);
alTexture.add(t);
//左下点
alVertex.add(zsx);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i+1][j]);
alVertex.add(zsz+LAND_UNIT_SIZE);
alTexture.add(s);
alTexture.add(t+sizeh);
if(j==cols-1)
{
//右上点
alVertex.add(zsx+LAND_UNIT_SIZE);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i][j+1]);
alVertex.add(zsz);
alTexture.add(s+sizew);
alTexture.add(t);
//右下点
alVertex.add(zsx+LAND_UNIT_SIZE);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i+1][j+1]);
alVertex.add(zsz+LAND_UNIT_SIZE);
alTexture.add(s+sizew);
alTexture.add(t+sizeh);
if(i!=rows-1)
{
//右下点
alVertex.add(zsx+LAND_UNIT_SIZE);
alVertex.add(LANDS_HEIGHT_ARRAY[terrainId][i+1][j+1]);
alVertex.add(zsz+LAND_UNIT_SIZE);
alTexture.add(s+sizew);
alTexture.add(t+sizeh);
}
}
}
}
vCount=alVertex.size()/3;
float vertices[]=new float[vCount*3];
for(int i=0;i<vCount*3;i++)
{
vertices[i]=alVertex.get(i);
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//创建顶点纹理缓冲
float textures[]=new float[alTexture.size()];
for(int i=0;i<alTexture.size();i++)
{
textures[i]=alTexture.get(i);
}
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
mTextureBuffer= tbb.asFloatBuffer();//转换为Float型缓冲
mTextureBuffer.put(textures);//向缓冲区中放入顶点着色数据
mTextureBuffer.position(0);//设置缓冲区起始位置
}
}
//初始化着色器的initShader方法
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//山地的三幅纹理图
uShanDingTexHandle=GLES20.glGetUniformLocation(mProgram, "usTextureShanDing");
uTuCengTexHandle=GLES20.glGetUniformLocation(mProgram, "usTextureTuCeng");
uCaoDiTexHandle=GLES20.glGetUniformLocation(mProgram, "usTextureCaoDi");
muHightHandle=GLES20.glGetUniformLocation(mProgram, "uheight");
muHightspanHandle=GLES20.glGetUniformLocation(mProgram, "uheight_span");
uShiTouTexHandle=GLES20.glGetUniformLocation(mProgram, "usTextureShiTou");
uLandFlagHandle=GLES20.glGetUniformLocation(mProgram, "uland_flag");
}
public void drawSelf(int landFlag,int tex_terrain_shandingId,int texTuCengId,int texCaoDiId,int texShiTouId,float height,float height_span)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
GLES20.glUniform1f(muHightHandle, height);//传入渐变的高度
GLES20.glUniform1f(muHightspanHandle, height_span);//传入渐变的高度
GLES20.glUniform1i(uLandFlagHandle, landFlag);//传入山的标志
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTextureBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texTuCengId);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texCaoDiId);
GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texShiTouId);
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex_terrain_shandingId);
GLES20.glUniform1i(uTuCengTexHandle, 0);
GLES20.glUniform1i(uCaoDiTexHandle, 1);
GLES20.glUniform1i(uShiTouTexHandle, 2);
GLES20.glUniform1i(uShanDingTexHandle, 3);
if(!ishuidutu)
{
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
else
{
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vCount);
}
}
}
@@ -0,0 +1,177 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import com.bn.core.MatrixState;
import android.opengl.GLES20;
public class Light_Tower {
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
int maNormalHandle; //顶点法向量属性引用id
int muraodonHandle;//扰动值引用
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
int vCount=0;
public Light_Tower(float R,float r,float height,int hSection){
ArrayList<Float> alVertix=new ArrayList<Float>();
float h=height/hSection;//每一小段的高度
int dians=18;//每次切分度数
int arey=360/dians;
for(int i=0;i<hSection;i++){
for(int j=0;j<arey;j++){
float hr=i*h;//上一个分段的高度
float Rhr1=r+(hr/height)*(R-r);//上一个分段的半径
float hr2=(i+1)*h;//下一个分段的高度
float Rhr2=r+(hr2/height)*(R-r);//下一段的半径
float x1=Rhr1*(float)(Math.cos(Math.toRadians(dians*j)));
float y1=hr;
float z1=Rhr1*(float)(Math.sin(Math.toRadians(dians*j)));
float x2=Rhr1*(float)(Math.cos(Math.toRadians(dians*(1+j))));
float y2=hr;
float z2=Rhr1*(float)(Math.sin(Math.toRadians(dians*(1+j))));
float x3=Rhr2*(float)(Math.cos(Math.toRadians(dians*j)));
float y3=hr2;
float z3=Rhr2*(float)(Math.sin(Math.toRadians(dians*j)));
float x4=Rhr2*(float)(Math.cos(Math.toRadians(dians*(1+j))));
float y4=hr2;
float z4=Rhr2*(float)(Math.sin(Math.toRadians(dians*(1+j))));
//构建第一三角形
alVertix.add(x1);alVertix.add(y1);alVertix.add(z1);
alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
//构建第二三角形
alVertix.add(x1);alVertix.add(y1);alVertix.add(z1);
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
}
}
vCount=alVertix.size()/3;//顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标
//将alVertix中的坐标值转存到一个float数组中
float vertices[]=new float[vCount*3];
for(int i=0;i<alVertix.size();i++)
{
vertices[i]=alVertix.get(i);
}
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//顶点纹理坐标数据的初始化================begin============================
float texCoor[]=generateTexCoor
(
(int)(360/dians), //纹理图切分的列数
hSection //纹理图切分的行数
);
//创建顶点纹理坐标数据缓冲
ByteBuffer cbb = ByteBuffer.allocateDirect(texCoor.length*4);
cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTexCoorBuffer = cbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(texCoor);//向缓冲区中放入顶点着色数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
//初始化着色器的initShader方法
public void initShader(int mProgram)
{
this.mProgram=mProgram;
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
//自动切分纹理产生纹理数组的方法
public float[] generateTexCoor(int bw,int bh)
{
float[] result=new float[bw*bh*6*2*2];
float sizew=1.0f/bw;//列数
float sizeh=1.0f/bh;//行数
int c=0;
for(int i=0;i<bh;i++)
{
for(int j=0;j<bw;j++)
{
//每行列一个矩形,由两个三角形构成,共六个点,12个纹理坐标
float s=(bw-j)*sizew;
float t=(bh-i)*sizeh;
result[c++]=s;
result[c++]=t;
result[c++]=s;
result[c++]=t-sizeh;
result[c++]=s-sizew;
result[c++]=t-sizeh;
result[c++]=s;
result[c++]=t;
result[c++]=s-sizew;
result[c++]=t-sizeh;
result[c++]=s-sizew;
result[c++]=t;
}
}
return result;
}
}
@@ -0,0 +1,146 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.bn.core.MatrixState;
import com.bn.core.ShaderUtil;
import com.bn.gameView.GLGameView;
import android.opengl.GLES20;
//加载后的物体——仅携带顶点信息,颜色随机
public class LoadedObjectVertexNormalTexture
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int muMMatrixHandle;//位置、旋转变换矩阵
int maPositionHandle; //顶点位置属性引用id
int maNormalHandle; //顶点法向量属性引用id
int maLightLocationHandle;//光源位置属性引用id
int maCameraHandle; //摄像机位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
FloatBuffer mNormalBuffer;//顶点法向量数据缓冲
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
int vCount=0;
public LoadedObjectVertexNormalTexture(GLGameView mv,float[] vertices,float[] normals,float texCoors[])
{
//初始化顶点数据的方法
initVertexData(vertices,normals,texCoors);
//初始化着色器的initShader方法
initShader(mv);
}
//初始化顶点数据的方法
public void initVertexData(float[] vertices,float[] normals,float texCoors[])
{
//顶点坐标数据的初始化================begin============================
vCount=vertices.length/3;
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//顶点法向量数据的初始化================begin============================
ByteBuffer cbb = ByteBuffer.allocateDirect(normals.length*4);
cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mNormalBuffer = cbb.asFloatBuffer();//转换为Float型缓冲
mNormalBuffer.put(normals);//向缓冲区中放入顶点法向量数据
mNormalBuffer.position(0);//设置缓冲区起始位置
//顶点纹理坐标数据的初始化================begin============================
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoors.length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
mTexCoorBuffer = tbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(texCoors);//向缓冲区中放入顶点纹理坐标数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
//初始化着色器的initShader方法
public void initShader(GLGameView mv)
{
//加载顶点着色器的脚本内容
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex.sh", mv.getResources());
//加载片元着色器的脚本内容
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag.sh", mv.getResources());
//基于顶点着色器与片元着色器创建程序
mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点颜色属性引用id
maNormalHandle= GLES20.glGetAttribLocation(mProgram, "aNormal");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//获取位置、旋转变换矩阵引用id
muMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix");
//获取程序中光源位置引用id
maLightLocationHandle=GLES20.glGetUniformLocation(mProgram, "uLightLocation");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中摄像机位置引用id
maCameraHandle=GLES20.glGetUniformLocation(mProgram, "uCamera");
}
public void drawSelf(int texId)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//将位置、旋转变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMMatrixHandle, 1, false, MatrixState.getMMatrix(), 0);
//将光源位置传入shader程序
GLES20.glUniform3fv(maLightLocationHandle, 1, MatrixState.lightPositionFB);
//将摄像机位置传入shader程序
GLES20.glUniform3fv(maCameraHandle, 1, MatrixState.cameraFB);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点法向量数据
GLES20.glVertexAttribPointer
(
maNormalHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mNormalBuffer
);
//为画笔指定顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置、法向量、纹理坐标数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maNormalHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制加载的物体
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
}
@@ -0,0 +1,57 @@
package com.bn.commonObject;
import com.bn.core.MatrixState;
//绘制0-9十个数字
public class NumberForDraw
{
//创建10个数字的纹理矩形
public TextureRect[] number;
String scoreStr;//数字字符串
float width;
float height;
public NumberForDraw(int numberSize,float width,float height,int mProgram)
{
number=new TextureRect[numberSize];
this.width=width;
this.height=height;
//生成十个数字的纹理矩形
for(int i=0;i<numberSize;i++)
{
number[i]=new TextureRect
(
width,
height,
new float[]
{
1f/numberSize*i,0,1f/numberSize*i,1, 1f/numberSize*(i+1),0,
1f/numberSize*(i+1),1,
},
mProgram
);
}
}
public void drawSelf(String score,int texId)//传入数字和纹理坐标
{
scoreStr=score;
MatrixState.pushMatrix();
MatrixState.translate(-scoreStr.length()*width, 0, 0);
for(int i=0;i<scoreStr.length();i++)//将得分中的每个数字字符绘制
{
char c=scoreStr.charAt(i);
MatrixState.translate(width, 0, 0);
number[c-'0'].drawSelf(texId);
}
MatrixState.popMatrix();
}
public void drawSelfLeft(String score,int texId)//传入数字和纹理坐标 左对齐
{
scoreStr=score;
MatrixState.pushMatrix();
for(int i=0;i<scoreStr.length();i++)//将得分中的每个数字字符绘制
{
char c=scoreStr.charAt(i);
MatrixState.translate(width, 0, 0);
number[c-'0'].drawSelf(texId);
}
MatrixState.popMatrix();
}
}
@@ -0,0 +1,249 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import com.bn.core.MatrixState;
import com.bn.gameView.GLGameView;
import android.opengl.GLES20;
/*
* 绘制纹理天空球
*/
public class SkyBall
{
//自定义渲染程序的引用
int mProgram;
//总变换矩阵的引用
int muMVPMatrixHandle;
//顶点属性的引用
int maPositionHandle;
//顶点纹理坐标属性的引用
int maTexCoorHandle;
//顶点数据缓冲以及顶点纹理坐标数据缓冲
FloatBuffer mVertexBuffer;
FloatBuffer mTexCoorBuffer;
//顶点数量
int vCount=0;
public SkyBall(GLGameView mv,float radius,int mProgram,float startX,float startY,float startZ)
{
this.mProgram=mProgram;
initVertexData(radius, startX, startY, startZ);
initShader(mProgram);
}
//初始化顶点数据的方法
public void initVertexData(float radius,float startX,float startY,float startZ)
{
float ANGLE_SPAN=15;//切分间隔
float angleV=90;//纵向上的起始度数
//获取切分整图的纹理数组
float[] texCoorArray=
generateTexCoor
(
(int)(360/ANGLE_SPAN), //纹理图切分的列数
(int)(angleV/ANGLE_SPAN) //纹理图切分的行数
);
int tc=0;//纹理数组计数器
int ts=texCoorArray.length;//纹理数组长度
ArrayList<Float> alVertix=new ArrayList<Float>();//存放顶点坐标的ArrayList
ArrayList<Float> alTexture=new ArrayList<Float>();//存放纹理坐标的ArrayList
for(float vAngle=angleV;vAngle>0;vAngle=vAngle-ANGLE_SPAN)//垂直方向angleSpan度一份
{
for(float hAngle=360;hAngle>0;hAngle=hAngle-ANGLE_SPAN)//水平方向angleSpan度一份
{
//纵向横向各到一个角度后计算对应的此点在球面上的四边形顶点坐标
//并构建两个组成四边形的三角形
double xozLength=radius*Math.cos(Math.toRadians(vAngle));
float x1=(float)(xozLength*Math.cos(Math.toRadians(hAngle)))+startX;
float z1=(float)(xozLength*Math.sin(Math.toRadians(hAngle)))+startZ;
float y1=(float)(radius*Math.sin(Math.toRadians(vAngle)))+startY;
xozLength=radius*Math.cos(Math.toRadians(vAngle-ANGLE_SPAN));
float x2=(float)(xozLength*Math.cos(Math.toRadians(hAngle)))+startX;
float z2=(float)(xozLength*Math.sin(Math.toRadians(hAngle)))+startZ;
float y2=(float)(radius*Math.sin(Math.toRadians(vAngle-ANGLE_SPAN)))+startY;
xozLength=radius*Math.cos(Math.toRadians(vAngle-ANGLE_SPAN));
float x3=(float)(xozLength*Math.cos(Math.toRadians(hAngle-ANGLE_SPAN)))+startX;
float z3=(float)(xozLength*Math.sin(Math.toRadians(hAngle-ANGLE_SPAN)))+startZ;
float y3=(float)(radius*Math.sin(Math.toRadians(vAngle-ANGLE_SPAN)))+startY;
xozLength=radius*Math.cos(Math.toRadians(vAngle));
float x4=(float)(xozLength*Math.cos(Math.toRadians(hAngle-ANGLE_SPAN)))+startX;
float z4=(float)(xozLength*Math.sin(Math.toRadians(hAngle-ANGLE_SPAN)))+startZ;
float y4=(float)(radius*Math.sin(Math.toRadians(vAngle)))+startY;
//构建第一三角形
alVertix.add(x1);alVertix.add(y1);alVertix.add(z1);
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
//构建第二三角形
alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);
//构建第一三角形
alVertix.add(x1);alVertix.add(-y1);alVertix.add(z1);
alVertix.add(x2);alVertix.add(-y2);alVertix.add(z2);
alVertix.add(x4);alVertix.add(-y4);alVertix.add(z4);
//构建第二三角形
alVertix.add(x2);alVertix.add(-y2);alVertix.add(z2);
alVertix.add(x3);alVertix.add(-y3);alVertix.add(z3);
alVertix.add(x4);alVertix.add(-y4);alVertix.add(z4);
int tcc=tc;
//第一三角形3个顶点的6个纹理坐标
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
//第二三角形3个顶点的6个纹理坐标
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
alTexture.add(texCoorArray[tc++%ts]);
//第一三角形3个顶点的6个纹理坐标
alTexture.add(texCoorArray[tcc++%ts]);
alTexture.add(texCoorArray[tcc++%ts]);
alTexture.add(texCoorArray[tcc++%ts+2]);
alTexture.add(texCoorArray[tcc++%ts+2]);
alTexture.add(texCoorArray[tcc++%ts-2]);
alTexture.add(texCoorArray[tcc++%ts-2]);
//第二三角形3个顶点的6个纹理坐标
alTexture.add(texCoorArray[tcc++%ts]);
alTexture.add(texCoorArray[tcc++%ts]);
alTexture.add(texCoorArray[tcc++%ts+2]);
alTexture.add(texCoorArray[tcc++%ts+2]);
alTexture.add(texCoorArray[tcc++%ts-2]);
alTexture.add(texCoorArray[tcc++%ts-2]);
}
}
vCount=alVertix.size()/3;//顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标
//将alVertix中的坐标值转存到一个float数组中
float vertices[]=new float[vCount*3];
for(int i=0;i<alVertix.size();i++)
{
vertices[i]=alVertix.get(i);
}
//创建绘制顶点数据缓冲
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//创建纹理坐标缓冲
float textureCoors[]=new float[alTexture.size()];//顶点纹理值数组
for(int i=0;i<alTexture.size();i++)
{
textureCoors[i]=alTexture.get(i);
}
ByteBuffer tbb = ByteBuffer.allocateDirect(textureCoors.length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTexCoorBuffer = tbb.asFloatBuffer();//转换为int型缓冲
mTexCoorBuffer.put(textureCoors);//向缓冲区中放入顶点着色数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
//初始化Shader程序的方法
public void initShader(int mProgram)
{
//获得顶点坐标数据的引用
maPositionHandle=GLES20.glGetAttribLocation(mProgram, "aPosition");
//顶点纹理坐标的引用id
maTexCoorHandle=GLES20.glGetAttribLocation(mProgram, "aTexCoor");
muMVPMatrixHandle=GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId,float curr_X,float curr_Y,float curr_Z,float rotationAngle_Y)
{
MatrixState.pushMatrix();
MatrixState.translate(curr_X, curr_Y, curr_Z);
MatrixState.rotate(rotationAngle_Y, 0, 1, 0);
//使用某套指定的Shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入到Shader程序中
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入坐标数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
MatrixState.popMatrix();
}
//自动切分纹理产生纹理数组的方法
public float[] generateTexCoor(int bw,int bh)
{
float[] result=new float[bw*bh*6*2];
float sizew=1.0f/bw;//列数
float sizeh=1.0f/bh;//行数
int c=0;
for(int i=0;i<bh;i++)
{
for(int j=0;j<bw;j++)
{
//每行列一个矩形,由两个三角形构成,共六个点,12个纹理坐标
float s=j*sizew;
float t=i*sizeh;
result[c++]=s;
result[c++]=t;
result[c++]=s+sizew;
result[c++]=t;
result[c++]=s;
result[c++]=t+sizeh;
result[c++]=s;
result[c++]=t+sizeh;
result[c++]=s+sizew;
result[c++]=t;
result[c++]=s+sizew;
result[c++]=t+sizeh;
}
}
return result;
}
}
@@ -0,0 +1,101 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.bn.core.MatrixState;
import android.opengl.GLES20;
//表示星空天球的类
public class SkyNight
{
float skyR=30.0f;//天球半径
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
int vCount=0;//星星数量
float scale;//星星尺寸
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int uPointSizeHandle;//顶点尺寸参数引用
public SkyNight(float scale,int vCount,float skyR)
{
this.skyR=skyR;
this.scale=scale;
this.vCount=vCount;
initVertexData();
}
//初始化顶点坐标的方法
public void initVertexData()
{
//顶点坐标数据的初始化================begin=======================================
float vertices[]=new float[vCount*6];
for(int i=0;i<vCount;i++)
{
//随机产生每个星星的xyz坐标
double angleTempJD=Math.PI*2*Math.random();
double angleTempWD=Math.PI/3*(Math.random());
vertices[i*6]=(float)(skyR*Math.cos(angleTempWD)*Math.sin(angleTempJD));
vertices[i*6+1]=(float)(skyR*Math.sin(angleTempWD));
vertices[i*6+2]=(float)(skyR*Math.cos(angleTempWD)*Math.cos(angleTempJD));
vertices[i*6+3]=(float)(skyR*Math.cos(angleTempWD)*Math.sin(angleTempJD));
vertices[i*6+4]=-(float)(skyR*Math.sin(angleTempWD));
vertices[i*6+5]=(float)(skyR*Math.cos(angleTempWD)*Math.cos(angleTempJD));
System.out.println();
}
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个Float四个字节
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
}
//初始化着色器的initShader方法
public void initShader(int mProgram)
{
this.mProgram = mProgram;
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//获取顶点尺寸参数引用
uPointSizeHandle = GLES20.glGetUniformLocation(mProgram, "uPointSize");
}
public void drawSelf()
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//将顶点尺寸传入Shader程序
GLES20.glUniform1f(uPointSizeHandle, scale);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
//绘制星星点
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vCount*2);
}
}
@@ -0,0 +1,223 @@
package com.bn.commonObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
//纹理矩形 其中该矩形是平行于XY平面的,关于原点中心对称
//这个也是用于绘制水面
//这个用于绘制按钮
//矩形的宽度和高度分别为 width,height
public class TextureRect
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
int uIsButtonDownHandle;//按钮是否按下引用Id
int uTypeHandle;//按钮的属性
int uCurrAlphaHandle;//当前按钮的不透明度
int uWidthHandle;//当前按钮的宽度
int uCurrXHandle;//传入的X坐标
int maSTOffset; //水面纹理图的偏移量引用id
int uBloodValueHandle;//生命值的引用
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
int vCount=0;
private boolean isFlow;//当前是否是水面
private boolean flag_flow_go=true;//水面是否运动
private float currStartST=0; //水面纹理坐标的当前起始坐标0~1
//按钮标志位,用来改变按钮的不透明度
private int index=0;//对象id,如果是1,表示当前为按钮,如果为2,表示绘制物体的生命值
public int button_type=0;//按钮的类型 0表示正常显示,1表示按下才透明的按钮,2表示循环变换的按钮,3表示卷动的面板
public float bloodValue;//物体的生命值
public int isButtonDown;//按钮是否按下0表示没有按下,1表示按下
public float currAlpha;//当前的不透明度
public float buttonWidth;//按钮的宽度
public float currX;//传入的X值
public float flowSpeed;//流动的速度
public float[] textures;//定义纹理坐标
//普通构造器
public TextureRect(float width,float height,int mProgram)
{
//初始化顶数据的initVertexDate方法
initVertexData(width,height,false,1);
//初始化着色器的initShader方法
initShader(mProgram);
}
//按钮/生命值构造器
public TextureRect(float width,float height,int mProgram,int index,int button_type)//1为按钮,2为生命值
{
this.index=index;
this.button_type=button_type;
//初始化顶点坐标与着色数据
initVertexData(width,height,false,1);
//初始化shader
initShader(mProgram);
}
//水面构造器
public TextureRect(float width,float height,int mProgram,boolean isWater,int n)
{
//初始化顶点坐标与着色数据
initVertexData(width,height,false,n);
//初始化shader
initShader(mProgram);
}
//纹理流动的构造器
public TextureRect(float width,float height,int mProgram,boolean isFlow,float speed)
{
this.isFlow=isFlow;
this.flowSpeed=speed;
//初始化顶点坐标与着色数据
initVertexData(width,height,false,1);
//初始化shader
initShader(mProgram);
//启动一个线程定时换帧
new Thread()
{
public void run()
{
while(flag_flow_go)
{
//所谓水面定时换帧只是修改每帧起始角度即可,
//水面顶点Y坐标的变化由顶点着色单元完成
currStartST=(currStartST+0.00008f*flowSpeed)%1;
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}.start();
}
//绘制数字的构造器,主要是将纹理坐标传入进来
public TextureRect(float width,float height,float[] textures,int mProgram)//传入宽高和纹理坐标数组
{
this.textures=textures;
initVertexData(width,height,true,1);
initShader(mProgram);
}
//初始化顶点坐标与着色数据的方法
public void initVertexData(float width,float height,boolean hasTexture,int n)
{
vCount=4;
float vertices[]=new float[]
{
-width/2,height/2,0,
-width/2,-height/2,0,
width/2,height/2,0,
width/2,-height/2,0
};
//创建顶点坐标数据缓冲
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
if(!hasTexture)//如果没有传入纹理
{
textures=new float[]//顶点颜色值数组,每个顶点4个色彩值RGBA
{
0,0, 0,n,
n,0, n,n
};
}
//创建顶点纹理坐标数据缓冲
ByteBuffer cbb = ByteBuffer.allocateDirect(textures.length*4);
cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTexCoorBuffer = cbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(textures);//向缓冲区中放入顶点着色数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
//初始化着色器的initShader方法
public void initShader(int mProgram)
{
this.mProgram=mProgram;
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
if(isFlow)
{
//获取水面纹理图偏移量的引用id
maSTOffset=GLES20.glGetUniformLocation(mProgram, "stK");
}
if(index==1)//当前为按钮
{
uIsButtonDownHandle=GLES20.glGetUniformLocation(mProgram, "isButtonDown");//按钮是否按下
uTypeHandle=GLES20.glGetUniformLocation(mProgram, "type");//按钮的类型
uCurrAlphaHandle=GLES20.glGetUniformLocation(mProgram, "currAlpha");//当前按钮的不透明度
uWidthHandle=GLES20.glGetUniformLocation(mProgram, "width");//当前按钮的宽度
uCurrXHandle=GLES20.glGetUniformLocation(mProgram, "currX");//传入的X坐标
}
else if(index==2)//当前为物体的生命值
{
uBloodValueHandle=GLES20.glGetUniformLocation(mProgram, "ublood");
}
}
public void drawSelf(int texId)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
if(isFlow)
{
//将水面纹理图的st偏移量传入shader程序
GLES20.glUniform1f(maSTOffset, currStartST);
}
if(index==1)//如果当前为按钮
{
GLES20.glUniform1i(uIsButtonDownHandle, isButtonDown);//按钮是否按下
GLES20.glUniform1i(uTypeHandle, button_type);//按钮的类型
GLES20.glUniform1f(uCurrAlphaHandle, currAlpha);//按钮的不透明度
GLES20.glUniform1f(uWidthHandle, buttonWidth);//按钮的宽度
GLES20.glUniform1f(uCurrXHandle, currX);//传入的X值
}
else if(index==2)//如果当前为物体生命值矩形框
{
GLES20.glUniform1f(uBloodValueHandle, bloodValue);
}
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vCount);
}
}
@@ -0,0 +1,69 @@
package com.bn.commonObject;
import static com.bn.gameView.GLGameView.cx;
import static com.bn.gameView.GLGameView.cy;
import static com.bn.gameView.GLGameView.cz;
import com.bn.core.MatrixState;
public class Tree implements Comparable<Tree>
{
public TextureRect rect;
public float tx,ty,tz;
public float yAngle;//树的朝向
int texId;
int col,row;
public Tree(TextureRect rect,float tx,float ty,float tz,int texId,int col,int row)
{
this.rect=rect;
this.tx=tx;
this.tz=tz;
this.ty=ty;
this.texId=texId;
this.col=col;
this.row=row;
}
public void drawSelf(int ii,int jj,int rowR,int colR){//绘制树
if(row<ii||row>rowR||col<jj||col>colR)
{
return;
}
MatrixState.pushMatrix();
MatrixState.translate(tx, ty, tz);
MatrixState.rotate(yAngle, 0, 1, 0);
rect.drawSelf(texId);
MatrixState.popMatrix();
}
//这里计算标志板的朝向
public void calculateBillboardDirection()
{//根据摄像机位置计算焰火粒子面朝向
float currX_span=tx-cx;
float currZ_span=tz-cz;
if(currZ_span<0)
{
yAngle=(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}
else if(currZ_span==0)
{
yAngle=currX_span>0?90:-90;
}
else
{
yAngle=180+(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}
}
@Override
public int compareTo(Tree another)
{//重写的比较两个粒子离摄像机距离的方法 从大到小进行排序
float x=tx-cx;
float z=ty-cz;
float y=tz-cy;
float xo=another.tx-cx;
float zo=another.ty-cz;
float yo=another.tz-cy;
float disA=x*x+y*y+z*z;
float disB=xo*xo+yo*yo+zo*zo;
return ((disA-disB)==0)?0:((disA-disB)>0)?-1:1;
}
}
@@ -0,0 +1,208 @@
package com.bn.core;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import android.content.res.Resources;
import android.util.Log;
import com.bn.commonObject.LoadedObjectVertexNormalTexture;
import com.bn.gameView.GLGameView;
public class LoadUtil
{
//求两个向量的叉积
public static float[] getCrossProduct(float x1,float y1,float z1,float x2,float y2,float z2)
{
//求出两个矢量叉积矢量在XYZ轴的分量ABC
float A=y1*z2-y2*z1;
float B=z1*x2-z2*x1;
float C=x1*y2-x2*y1;
return new float[]{A,B,C};
}
//向量规格化
public static float[] vectorNormal(float[] vector)
{
//求向量的模
float module=(float)Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]+vector[2]*vector[2]);
return new float[]{vector[0]/module,vector[1]/module,vector[2]/module};
}
//从obj文件中加载携带顶点信息的物体,并自动计算每个顶点的平均法向量
public static LoadedObjectVertexNormalTexture loadFromFileVertexOnly
(String fname, Resources r,GLGameView mv)
{
//加载后物体的引用
LoadedObjectVertexNormalTexture lo=null;
//原始顶点坐标列表--直接从obj文件中加载
ArrayList<Float> alv=new ArrayList<Float>();
//顶点组装面索引列表--根据面的信息从文件中加载
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();
//结果顶点坐标列表--按面组织好
ArrayList<Float> alvResult=new ArrayList<Float>();
//平均前各个索引对应的点的法向量集合Map
//此HashMap的key为点的索引, value为点所在的各个面的法向量的集合
HashMap<Integer,HashSet<Normal>> hmn=new HashMap<Integer,HashSet<Normal>>();
//原始纹理坐标列表
ArrayList<Float> alt=new ArrayList<Float>();
//纹理坐标结果列表
ArrayList<Float> altResult=new ArrayList<Float>();
try
{
InputStream in=r.getAssets().open(fname);
InputStreamReader isr=new InputStreamReader(in);
BufferedReader br=new BufferedReader(isr);
String temps=null;
//扫面文件,根据行类型的不同执行不同的处理逻辑
while((temps=br.readLine())!=null)
{
//用空格分割行中的各个组成部分
String[] tempsa=temps.split("[ ]+");
if(tempsa[0].trim().equals("v"))
{//此行为顶点坐标
//若为顶点坐标行则提取出此顶点的XYZ坐标添加到原始顶点坐标列表中
alv.add(Float.parseFloat(tempsa[1]));
alv.add(Float.parseFloat(tempsa[2]));
alv.add(Float.parseFloat(tempsa[3]));
}
else if(tempsa[0].trim().equals("vt"))
{//此行为纹理坐标行
alt.add(Float.parseFloat(tempsa[1])*1/2.0f);
alt.add(Float.parseFloat(tempsa[2])*1/2.0f);
}
else if(tempsa[0].trim().equals("f"))
{//此行为三角形面
/*
*若为三角形面行则根据 组成面的顶点的索引从原始顶点坐标列表中
*提取相应的顶点坐标值添加到结果顶点坐标列表中,同时根据三个
*顶点的坐标计算出此面的法向量并添加到平均前各个索引对应的点
*的法向量集合组成的Map中
*/
int[] index=new int[3];//三个顶点索引值的数组
//计算第0个顶点的索引,并获取此顶点的XYZ三个坐标
index[0]=Integer.parseInt(tempsa[1].split("/")[0])-1;
float x0=alv.get(3*index[0]);
float y0=alv.get(3*index[0]+1);
float z0=alv.get(3*index[0]+2);
alvResult.add(x0);
alvResult.add(y0);
alvResult.add(z0);
//计算第1个顶点的索引,并获取此顶点的XYZ三个坐标
index[1]=Integer.parseInt(tempsa[2].split("/")[0])-1;
float x1=alv.get(3*index[1]);
float y1=alv.get(3*index[1]+1);
float z1=alv.get(3*index[1]+2);
alvResult.add(x1);
alvResult.add(y1);
alvResult.add(z1);
//计算第2个顶点的索引,并获取此顶点的XYZ三个坐标
index[2]=Integer.parseInt(tempsa[3].split("/")[0])-1;
float x2=alv.get(3*index[2]);
float y2=alv.get(3*index[2]+1);
float z2=alv.get(3*index[2]+2);
alvResult.add(x2);
alvResult.add(y2);
alvResult.add(z2);
//记录此面的顶点索引
alFaceIndex.add(index[0]);
alFaceIndex.add(index[1]);
alFaceIndex.add(index[2]);
//通过三角形面两个边向量0-1,0-2求叉积得到此面的法向量
//求0号点到1号点的向量
float vxa=x1-x0;
float vya=y1-y0;
float vza=z1-z0;
//求0号点到2号点的向量
float vxb=x2-x0;
float vyb=y2-y0;
float vzb=z2-z0;
//通过求两个向量的叉积计算法向量
float[] vNormal=getCrossProduct
(
vxa,vya,vza,vxb,vyb,vzb
);
for(int tempInxex:index)
{//记录每个索引点的法向量到平均前各个索引对应的点的法向量集合组成的Map中
//获取当前索引对应点的法向量集合
HashSet<Normal> hsn=hmn.get(tempInxex);
if(hsn==null)
{//若集合不存在则创建
hsn=new HashSet<Normal>();
}
//将此点的法向量添加到集合中
//由于Normal类重写了equals方法,因此同样的法向量不会重复出现在此点
//对应的法向量集合中
hsn.add(new Normal(vNormal[0],vNormal[1],vNormal[2]));
//将集合放进HsahMap中
hmn.put(tempInxex, hsn);
}
//将纹理坐标组织到结果纹理坐标列表中
//第0个顶点的纹理坐标
int indexTex=Integer.parseInt(tempsa[1].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
//第1个顶点的纹理坐标
indexTex=Integer.parseInt(tempsa[2].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
//第2个顶点的纹理坐标
indexTex=Integer.parseInt(tempsa[3].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
}
}
//生成顶点数组
int size=alvResult.size();
float[] vXYZ=new float[size];
for(int i=0;i<size;i++)
{
vXYZ[i]=alvResult.get(i);
}
//生成法向量数组
float[] nXYZ=new float[alFaceIndex.size()*3];
int c=0;
for(Integer i:alFaceIndex)
{
//根据当前点的索引从Map中取出一个法向量的集合
HashSet<Normal> hsn=hmn.get(i);
//求出平均法向量
float[] tn=Normal.getAverage(hsn);
//将计算出的平均法向量存放到法向量数组中
nXYZ[c++]=tn[0];
nXYZ[c++]=tn[1];
nXYZ[c++]=tn[2];
}
//生成纹理数组
size=altResult.size();
float[] tST=new float[size];
for(int i=0;i<size;i++)
{
tST[i]=altResult.get(i);
}
//创建3D物体对象
lo=new LoadedObjectVertexNormalTexture(mv,vXYZ,nXYZ,tST);
}
catch(Exception e)
{
Log.d("load error", "load error");
e.printStackTrace();
}
return lo;
}
}
@@ -0,0 +1,180 @@
package com.bn.core;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.Matrix;
//存储系统矩阵状态的类
public class MatrixState
{
private static float[] mProjMatrix = new float[16];//4x4矩阵 投影用
private static float[] mVMatrix = new float[16];//摄像机位置朝向9参数矩阵
private static float[] currMatrix;//当前变换矩阵
public static float[] lightLocation=new float[]{0,0,0};//定位光光源位置
public static FloatBuffer cameraFB;
public static FloatBuffer lightPositionFB;
//保护变换矩阵的栈
static float[][] mStack=new float[10][16];
public static int stackTop=-1;
public static void setInitStack()//获取不变换初始矩阵
{
currMatrix=new float[16];
Matrix.setRotateM(currMatrix, 0, 0, 1, 0, 0);
}
public static void pushMatrix()//保护变换矩阵
{
stackTop++;
for(int i=0;i<16;i++)
{
mStack[stackTop][i]=currMatrix[i];
}
}
public static void popMatrix()//恢复变换矩阵
{
for(int i=0;i<16;i++)
{
currMatrix[i]=mStack[stackTop][i];
}
stackTop--;
}
public static void translate(float x,float y,float z)//设置沿xyz轴移动
{
Matrix.translateM(currMatrix, 0, x, y, z);
}
public static void rotate(float angle,float x,float y,float z)//设置绕xyz轴移动
{
Matrix.rotateM(currMatrix,0,angle,x,y,z);
}
public static void scale(float x,float y,float z)
{
Matrix.scaleM(currMatrix,0, x, y, z);
}
//插入自带矩阵
public static void matrix(float[] self)
{
float[] result=new float[16];
Matrix.multiplyMM(result,0,currMatrix,0,self,0);
currMatrix=result;
}
//设置摄像机
static ByteBuffer llbb= ByteBuffer.allocateDirect(3*4);
static float[] cameraLocation=new float[3];//摄像机位置
public static void setCamera
(
float cx, //摄像机位置x
float cy, //摄像机位置y
float cz, //摄像机位置z
float tx, //摄像机目标点x
float ty, //摄像机目标点y
float tz, //摄像机目标点z
float upx, //摄像机UP向量X分量
float upy, //摄像机UP向量Y分量
float upz //摄像机UP向量Z分量
)
{
Matrix.setLookAtM
(
mVMatrix,
0,
cx,
cy,
cz,
tx,
ty,
tz,
upx,
upy,
upz
);
cameraLocation[0]=cx;
cameraLocation[1]=cy;
cameraLocation[2]=cz;
llbb.clear();
llbb.order(ByteOrder.nativeOrder());//设置字节顺序
cameraFB=llbb.asFloatBuffer();
cameraFB.put(cameraLocation);
cameraFB.position(0);
}
//设置透视投影参数
public static void setProjectFrustum
(
float left, //near面的left
float right, //near面的right
float bottom, //near面的bottom
float top, //near面的top
float near, //near面距离
float far //far面距离
)
{
Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far);
}
//设置正交投影参数
public static void setProjectOrtho
(
float left, //near面的left
float right, //near面的right
float bottom, //near面的bottom
float top, //near面的top
float near, //near面距离
float far //far面距离
)
{
Matrix.orthoM(mProjMatrix, 0, left, right, bottom, top, near, far);
}
//用于一帧内的摄像机矩阵
private static float[] mVMatrixForSpecFrame = new float[16];//摄像机位置朝向9参数矩阵
public static void copyMVMatrix()
{
for(int i=0;i<16;i++)
{
mVMatrixForSpecFrame[i]=mVMatrix[i];
}
}
//获取具体物体的总变换矩阵
static float[] mMVPMatrix=new float[16];
public static float[] getFinalMatrix()
{
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrixForSpecFrame, 0, currMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
return mMVPMatrix;
}
//获取具体物体的变换矩阵
public static float[] getMMatrix()
{
return currMatrix;
}
//设置灯光位置的方法
static ByteBuffer llbbL = ByteBuffer.allocateDirect(3*4);
public static void setLightLocation(float x,float y,float z)
{
llbbL.clear();
lightLocation[0]=x;
lightLocation[1]=y;
lightLocation[2]=z;
llbbL.order(ByteOrder.nativeOrder());//设置字节顺序
lightPositionFB=llbbL.asFloatBuffer();
lightPositionFB.put(lightLocation);
lightPositionFB.position(0);
}
}
@@ -0,0 +1,11 @@
package com.bn.core;
//计算内存消耗情况,这里只考虑的是对象所消耗堆内存空间
public class Memory
{
public static long used()
{
long total=Runtime.getRuntime().totalMemory();
long free=Runtime.getRuntime().freeMemory();
return total-free;
}
}
@@ -0,0 +1,67 @@
package com.bn.core;
import java.util.Set;
//表示法向量的类,此类的一个对象表示一个法向量
public class Normal
{
public static final float DIFF=0.0000001f;//判断两个法向量是否相同的阈值
//法向量在XYZ轴上的分量
float nx;
float ny;
float nz;
public Normal(float nx,float ny,float nz)
{
this.nx=nx;
this.ny=ny;
this.nz=nz;
}
@Override
public boolean equals(Object o)
{
if(o instanceof Normal)
{//若两个法向量XYZ三个分量的差都小于指定的阈值则认为这两个法向量相等
Normal tn=(Normal)o;
if(Math.abs(nx-tn.nx)<DIFF&&
Math.abs(ny-tn.ny)<DIFF&&
Math.abs(ny-tn.ny)<DIFF
)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
//由于要用到HashSet,因此一定要重写hashCode方法
@Override
public int hashCode()
{
return 1;
}
//求法向量平均值的工具方法
public static float[] getAverage(Set<Normal> sn)
{
//存放法向量和的数组
float[] result=new float[3];
//把集合中所有的法向量求和
for(Normal n:sn)
{
result[0]+=n.nx;
result[1]+=n.ny;
result[2]+=n.nz;
}
//将求和后的法向量规格化
return LoadUtil.vectorNormal(result);
}
}
@@ -0,0 +1,99 @@
package com.bn.core;
/*
* 该类为姿态传感器的静态工具类,提供静态方法来计算
*/
public class RotateUtil
{
//angle为弧度 gVector 为重力向量[x,y,z,1]
//返回值为旋转后的向量
public static double[] pitchRotate(double angle,double[] gVector)
{
double[][] matrix=//绕x轴旋转变换矩阵
{
{1,0,0,0},
{0,Math.cos(angle),Math.sin(angle),0},
{0,-Math.sin(angle),Math.cos(angle),0}, //原来为:{0,-Math.sin(angle),Math.cos(angle),0},
{0,0,0,1}
};
double[] tempDot={gVector[0],gVector[1],gVector[2],gVector[3]};
for(int j=0;j<4;j++)
{
gVector[j]=(tempDot[0]*matrix[0][j]+tempDot[1]*matrix[1][j]+
tempDot[2]*matrix[2][j]+tempDot[3]*matrix[3][j]);
}
return gVector;
}
//angle为弧度 gVector 为重力向量[x,y,z,1]
//返回值为旋转后的向量
public static double[] rollRotate(double angle,double[] gVector)
{
double[][] matrix=//绕y轴旋转变换矩阵
{
{Math.cos(angle),0,-Math.sin(angle),0},
{0,1,0,0},
{Math.sin(angle),0,Math.cos(angle),0},
{0,0,0,1}
};
double[] tempDot={gVector[0],gVector[1],gVector[2],gVector[3]};
for(int j=0;j<4;j++)
{
gVector[j]=(tempDot[0]*matrix[0][j]+tempDot[1]*matrix[1][j]+
tempDot[2]*matrix[2][j]+tempDot[3]*matrix[3][j]);
}
return gVector;
}
//angle为弧度 gVector 为重力向量[x,y,z,1]
//返回值为旋转后的向量
public static double[] yawRotate(double angle,double[] gVector)
{
double[][] matrix=//绕z轴旋转变换矩阵
{
{Math.cos(angle),Math.sin(angle),0,0},
{-Math.sin(angle),Math.cos(angle),0,0},
{0,0,1,0},
{0,0,0,1}
};
double[] tempDot={gVector[0],gVector[1],gVector[2],gVector[3]};
for(int j=0;j<4;j++)
{
gVector[j]=(tempDot[0]*matrix[0][j]+tempDot[1]*matrix[1][j]+
tempDot[2]*matrix[2][j]+tempDot[3]*matrix[3][j]);
}
return gVector;
}
public static float[] getDirectionDot(double[] values)
{
double yawAngle=-Math.toRadians(values[0]);//获取Yaw轴旋转角度弧度
double pitchAngle=-Math.toRadians(values[1]);//获取Pitch轴旋转角度弧度
double rollAngle=-Math.toRadians(values[2]);//获取Roll轴旋转角度弧度
/*
* 算法思想为手机在一个姿态后首先虚拟出一个重力向量,
* 然后三次选装把手机恢复到原始姿态,期间重力向量伴随
* 变化,最后重力向量往手机平面上一投影。
*/
//虚拟一个重力向量
double[] gVector={0,0,-100,1};
/*
* 在这里需要注意沿三个空间方向x,y,z轴所旋转的角度的恢复顺序,由于Yaw轴始终指向竖直向上(重力加速度反向),和
* 标准的空间坐标系的z轴一样,所以 可以通过负向旋转直接进行角度恢复;沿yaw轴将转过的角度恢复后,此时的pitch轴
* 就变成了空间坐标系中的x轴,沿pitch(x)轴将 转过 的角度恢复,此时的roll轴就修正为了空间坐标系中的y轴,最后
* 按照y轴将转过的角度恢复,则此时手机平面所在的平面变成了空间坐标 系中x-y平面,而附着于手机平面上的重力加速度
* 的则是一个与手机平面相交的向量,将该向量投影到手机平面,通过投影点就可以计算出小球要滚动的方向
* 如果不按照上述顺序进行角度恢复,则空间坐标的计算转换将会非常复杂,而上述方法中每一步的角度恢复都是基于标准
* 的坐标系轴,而对标准坐标轴的转换在计算机图形
* 学中很容易实现
*/
//yaw轴恢复
gVector=RotateUtil.yawRotate(yawAngle,gVector);
//pitch轴恢复
gVector=RotateUtil.pitchRotate(pitchAngle,gVector);
//roll轴恢复
gVector=RotateUtil.rollRotate(rollAngle,gVector);
double mapX=gVector[0];
double mapY=gVector[1];
float[] result={(float)mapX,(float)mapY};
return result;
}
}
@@ -0,0 +1,123 @@
package com.bn.core;
import java.util.ArrayList;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class SQLiteUtil
{
static SQLiteDatabase sld;//声明数据库
//创建或打开数据库的方法
public static void createOrOpenDatabase()
{
try
{
sld=SQLiteDatabase.openDatabase
(
"/data/data/com.bn.menu/mydb", //当前应用程序只能在自己的包下创建数据库
null, //CursorFactory
SQLiteDatabase.OPEN_READWRITE|SQLiteDatabase.CREATE_IF_NECESSARY //读写、若不存在则创建
);
}
catch(Exception e)
{
e.printStackTrace();
}
}
//关闭数据库的方法
public static void closeDatabase()
{
try
{
sld.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
//建表
public static void createTable(String sql)
{
createOrOpenDatabase();//打开数据库
try
{
sld.execSQL(sql);//建表
}
catch(Exception e)
{
e.printStackTrace();
}
closeDatabase();//关闭数据库
}
//插入记录的方法
public static void insert(String sql)
{
createOrOpenDatabase();//打开数据库
try
{
sld.execSQL(sql);
}
catch(Exception e)
{
e.printStackTrace();
}
closeDatabase();//关闭数据库
}
//删除记录的方法
public static void delete(String sql)
{
createOrOpenDatabase();//打开数据库
try
{
sld.execSQL(sql);
}
catch(Exception e)
{
e.printStackTrace();
}
closeDatabase();//关闭数据库
}
//修改记录的方法
public static void update(String sql)
{
createOrOpenDatabase();//打开数据库
try
{
sld.execSQL(sql);
}
catch(Exception e)
{
e.printStackTrace();
}
closeDatabase();//关闭数据库
}
//查询的方法
public static ArrayList<String[]> query(String sql)
{
createOrOpenDatabase();//打开数据库
ArrayList<String[]> al=new ArrayList<String[]>();//新建存放查询结果的向量
try
{
Cursor cur=sld.rawQuery(sql, new String[]{});
while(cur.moveToNext())
{
int col=cur.getColumnCount(); //返回每一行都多少字段
String[]temp=new String[col];
for( int i=0;i<col;i++)
{
temp[i]=cur.getString(i);
}
al.add(temp);
}
cur.close();
}
catch(Exception e)
{
e.printStackTrace();
}
closeDatabase();//关闭数据库
return al;
}
}
@@ -0,0 +1,92 @@
package com.bn.core;
import android.content.res.Resources;
/*
* 该shader管理器主要是用于加载shader和编译shader
*/
public class ShaderManager
{
final static String[][] shaderName=
{
{"vertex_tex_only.sh","frag_tex_only.sh"},//loading 界面的shader
{"vertex_tex_water.sh","frag_tex_water.sh"},//水面流动的shader
{"vertex_landform.sh","frag_tex_landform.sh"},//地形的shader
{"vertex_button.sh","frag_button.sh"},//按钮的shader
{"vertex_xk.sh","frag_xk.sh"},//星空着色器
{"vertex_xue.sh","frag_xue.sh"},//血着色器
{"vertex_color.sh","frag_color.sh"},//仅有颜色着色器
};
static String[]mVertexShader=new String[shaderName.length];//顶点着色器字符串数组
static String[]mFragmentShader=new String[shaderName.length];//片元着色器字符串数组
static int[] program=new int[shaderName.length];//程序数组
//加载loading 界面的shader
public static void loadFirstViewCodeFromFile(Resources r)
{
mVertexShader[0]=ShaderUtil.loadFromAssetsFile(shaderName[0][0],r);
mFragmentShader[0]=ShaderUtil.loadFromAssetsFile(shaderName[0][1], r);
}
//加载shader字符串
public static void loadCodeFromFile(Resources r)
{
for(int i=1;i<shaderName.length;i++)
{
//加载顶点着色器的脚本内容
mVertexShader[i]=ShaderUtil.loadFromAssetsFile(shaderName[i][0],r);
//加载片元着色器的脚本内容
mFragmentShader[i]=ShaderUtil.loadFromAssetsFile(shaderName[i][1], r);
}
}
//这里主要是编译loading界面中的shader
public static void compileFirstViewShader()
{
program[0]=ShaderUtil.createProgram(mVertexShader[0], mFragmentShader[0]);
}
//编译其他的shader
public static void compileShader()
{
for(int i=1;i<shaderName.length;i++)
{
program[i]=ShaderUtil.createProgram(mVertexShader[i], mFragmentShader[i]);
}
}
//这里返回的是首次加载的shader
public static int getFirstViewShaderProgram()
{
return program[0];
}
//返回的是只有纹理的shader程序
public static int getOnlyTextureShaderProgram()
{
return program[0];
}
//这里返回的是水面流动的shader程序
public static int getWaterTextureShaderProgram()
{
return program[1];
}
//这里返回的是地形的shader
public static int getLandformTextureShaderProgram()
{
return program[2];
}
//这里返回的是按钮的shader
public static int getButtonTextureShaderProgram()
{
return program[3];
}
//这里返回星空的颜色的shader
public static int getStarrySkyShaderProgram()
{
return program[4];
}
//这里返回血颜色的shader
public static int getStarryXueShaderProgram()
{
return program[5];
}
//这里返回血颜色的shader
public static int getOnlyColorShaderProgram()
{
return program[6];
}
}
@@ -0,0 +1,126 @@
package com.bn.core;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import android.content.res.Resources;
import android.opengl.GLES20;
import android.util.Log;
//加载顶点Shader与片元Shader的工具类
public class ShaderUtil
{
//加载制定shader的方法
public static int loadShader
(
int shaderType, //shader的类型 GLES20.GL_VERTEX_SHADER GLES20.GL_FRAGMENT_SHADER
String source //shader的脚本字符串
)
{
//创建一个新shader
int shader = GLES20.glCreateShader(shaderType);
//若创建成功则加载shader
if (shader != 0)
{
//加载shader的源代码
GLES20.glShaderSource(shader, source);
//编译shader
GLES20.glCompileShader(shader);
//存放编译成功shader数量的数组
int[] compiled = new int[1];
//获取Shader的编译情况
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0)
{//若编译失败则显示错误日志并删除此shader
Log.e("ES20_ERROR", "Could not compile shader " + shaderType + ":");
Log.e("ES20_ERROR", GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
//创建shader程序的方法
public static int createProgram(String vertexSource, String fragmentSource)
{
//加载顶点着色器
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0)
{
return 0;
}
//加载片元着色器
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0)
{
return 0;
}
//创建程序
int program = GLES20.glCreateProgram();
//若程序创建成功则向程序中加入顶点着色器与片元着色器
if (program != 0)
{
//向程序中加入顶点着色器
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
//向程序中加入片元着色器
GLES20.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
//链接程序
GLES20.glLinkProgram(program);
//存放链接成功program数量的数组
int[] linkStatus = new int[1];
//获取program的链接情况
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
//若链接失败则报错并删除程序
if (linkStatus[0] != GLES20.GL_TRUE)
{
Log.e("ES20_ERROR", "Could not link program: ");
Log.e("ES20_ERROR", GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}
//检查每一步操作是否有错误的方法
public static void checkGlError(String op)
{
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR)
{
Log.e("ES20_ERROR", op + ": glError " + error);
throw new RuntimeException(op + ": glError " + error);
}
}
//从sh脚本中加载shader内容的方法
public static String loadFromAssetsFile(String fname,Resources r)
{
String result=null;
try
{
InputStream in=r.getAssets().open(fname);
int ch=0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((ch=in.read())!=-1)
{
baos.write(ch);
}
byte[] buff=baos.toByteArray();
baos.close();
in.close();
result=new String(buff,"UTF-8");
result=result.replaceAll("\\r\\n","\n");
}
catch(Exception e)
{
e.printStackTrace();
}
return result;
}
}
@@ -0,0 +1,470 @@
package com.bn.gameView;
import static com.bn.gameView.Constant.ANGLE_X_Z;
import static com.bn.gameView.Constant.ARCHIBALD_X;
import static com.bn.gameView.Constant.ARCHIBALD_Y;
import static com.bn.gameView.Constant.ARCHIBALD_Z;
import static com.bn.gameView.Constant.ARCHIE_BOMB_VELOCITY;
import static com.bn.gameView.Constant.ARSENAL_X;
import static com.bn.gameView.Constant.ARSENAL_Y;
import static com.bn.gameView.Constant.ARSENAL_Z;
import static com.bn.gameView.Constant.ArchieArray;
import static com.bn.gameView.Constant.BOMB_MAX_DISTANCE;
import static com.bn.gameView.Constant.BOMB_VELOCITY;
import static com.bn.gameView.Constant.PLANE_X;
import static com.bn.gameView.Constant.PLANE_X_R;
import static com.bn.gameView.Constant.PLANE_Y;
import static com.bn.gameView.Constant.PLANE_Y_R;
import static com.bn.gameView.Constant.PLANE_Z;
import static com.bn.gameView.Constant.TANK_BOMB_VELOCITY;
import static com.bn.gameView.Constant.archie_List;
import static com.bn.gameView.Constant.archie_bomb_List;
import static com.bn.gameView.Constant.bomb_List;
import static com.bn.gameView.Constant.fire_index;
import static com.bn.gameView.Constant.gradeArray;
import static com.bn.gameView.Constant.isno_Hit;
import static com.bn.gameView.Constant.isno_Lock;
import static com.bn.gameView.Constant.mapId;
import static com.bn.gameView.Constant.nx;
import static com.bn.gameView.Constant.ny;
import static com.bn.gameView.Constant.nz;
import static com.bn.gameView.Constant.tank_bomb_List;
import static com.bn.gameView.GLGameView.arsenal;
import static com.bn.gameView.GLGameView.baoZhaList;
import static com.bn.gameView.GLGameView.bombRect;
import static com.bn.gameView.GLGameView.bombRectr;
import static com.bn.gameView.GLGameView.bomb_height;
import static com.bn.gameView.GLGameView.enemy;
import static com.bn.gameView.GLGameView.tankeList;
import java.util.Iterator;
import com.bn.archieModel.ArchieForControl;
import com.bn.arsenal.Arsenal_House;
import com.bn.commonObject.BallTextureByVertex;
import com.bn.commonObject.DrawBomb;
import com.bn.core.MatrixState;
import com.bn.planeModel.EnemyPlane;
import com.bn.tankemodel.TanKe;
//炮弹的控制类
public class BombForControl
{
GLGameView gv;
private BallTextureByVertex bomb_ball;//子弹类
//定义发射炮弹时飞机的仰角和方位角
private float curr_elevation;
private float curr_direction;
//炮弹的位置
private float curr_x;
private float curr_y;
private float curr_z;
private float distance;//飞行距离
//飞机发射炮弹锁定
private boolean islocked;
private float curr_nx;
private float curr_ny;
private float curr_nz;
private float average;//平均向量
//飞机发射炮弹的构造器
public BombForControl(GLGameView gv,BallTextureByVertex bomb_ball,float plane_x,float plane_y,float plane_z,
float plane_elevation,float plane_direction,float rotationAngle_Plane_X,float rotationAngle_Plane_Y,
float rotationAngle_Plane_Z)
{
this.gv=gv;
//创建纹理球
this.bomb_ball=bomb_ball;
this.curr_elevation=plane_elevation;
this.curr_direction=plane_direction;
this.islocked=isno_Lock;
if(islocked)
{
curr_nx=nx;
curr_ny=ny;
curr_nz=nz;
average=(float) Math.sqrt(curr_nx*curr_nx+curr_ny*curr_ny+curr_nz*curr_nz);
}
//初始化炮弹的发射位置
initData(plane_x,plane_y,plane_z,rotationAngle_Plane_X,rotationAngle_Plane_Y,rotationAngle_Plane_Z);
}
//高射炮和坦克发射炮弹的构造器
public BombForControl(GLGameView gv,BallTextureByVertex bomb_ball,float[]init_position,float init_elevation,float init_direction)
{
this.gv=gv;
this.bomb_ball=bomb_ball;
curr_x=init_position[0];//
curr_y=init_position[1];//
curr_z=init_position[2];//
curr_elevation=init_elevation;
curr_direction=init_direction;
}
//确定飞机机翼炮弹的发射位置
public void initData(float plane_x,float plane_y,float plane_z,float rotationAngle_Plane_X,
float rotationAngle_Plane_Y,float rotationAngle_Plane_Z)
{
//设定左机翼发射炮弹的位置
curr_x=plane_x;
curr_y=plane_y;
curr_z=plane_z;
//炮弹位置的相关参数
float length;
float ori_y;
float ori_z;
length=12;
if(fire_index!=1)//左机翼发射炮弹
{
ori_y=90;
ori_z=-2;
}
else//右机翼发射炮弹
{
ori_y=-90;
ori_z=-2;
}
//确定炮弹的最终位置
curr_y=curr_y-(float)Math.sin(Math.toRadians(rotationAngle_Plane_Z+ori_z))*length;
curr_x=curr_x-(float)Math.cos(Math.toRadians(rotationAngle_Plane_Z+ori_z))*(float)Math.sin(Math.toRadians(rotationAngle_Plane_Y+ori_y))*length;
curr_z=curr_z-(float)Math.cos(Math.toRadians(rotationAngle_Plane_Z+ori_z))*(float)Math.cos(Math.toRadians(rotationAngle_Plane_Y+ori_y))*length;
}
public void drawSelf(int texId)
{
MatrixState.pushMatrix();
MatrixState.translate(curr_x, curr_y, curr_z);
bomb_ball.drawSelf(texId);
MatrixState.popMatrix();
}
//飞机发射炮弹
public void go()
{
distance+=BOMB_VELOCITY;//子弹的行驶路程增加
if(distance>=BOMB_MAX_DISTANCE)//如果子弹步长超出了
{
Iterator<BombForControl> ite=bomb_List.iterator();
gv.activity.playSound(1,0);
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
float tyy;
if((tyy=KeyThread.isYachtHeadCollectionsWithLandPaodan(curr_x,curr_y,curr_z))>0){
baoZhaList.add(new DrawBomb(bombRectr,curr_x,tyy,curr_z));//如果炮弹撞击地面
Iterator<BombForControl> ite=bomb_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
//判断是否和军火库发生碰撞
for(Arsenal_House as:arsenal){
if(//军火库还存在
curr_y>as.ty&&curr_y<as.ty+ARSENAL_Y
&&curr_x>as.tx-ARSENAL_X&&curr_x<as.tx+ARSENAL_X
&&curr_z>as.tz-ARSENAL_Z&&curr_z<as.tz+ARSENAL_Z){
as.blood-=ArchieArray[mapId][8][0];//军火库的血减1
if(as.blood<1){//如果军火库被炸毁
gv.activity.playSound(0,0);
try
{
Iterator<Arsenal_House> ite=arsenal.iterator();
while(ite.hasNext())
{
if(ite.next()==as)
{
ite.remove();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
baoZhaList.add(new DrawBomb(bombRect,as.tx,as.ty+bomb_height/2,as.tz));
gradeArray[1]+=ArchieArray[mapId][12][3];//得分增加,
}
Iterator<BombForControl> ite=bomb_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
}
for(ArchieForControl afc:archie_List){//查看有没有击中高射炮
if(curr_y>afc.position[1]&&curr_y<afc.position[1]+ARCHIBALD_Y*2
&&curr_x>afc.position[0]-ARCHIBALD_X*2&&curr_x<afc.position[0]+ARCHIBALD_X*2
&&curr_z>afc.position[2]-ARCHIBALD_Z*2&&curr_z<afc.position[2]+ARCHIBALD_Z*2){
afc.blood-=ArchieArray[mapId][8][2];//高射炮的血减10
if(afc.blood<0){
gv.activity.playSound(0,1);
try
{
Iterator<ArchieForControl> ite=archie_List.iterator();
while(ite.hasNext())
{
if(ite.next()==afc)
{
ite.remove();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
baoZhaList.add(new DrawBomb(bombRect,curr_x,afc.position[1]+ARCHIBALD_Y,curr_z));
gradeArray[1]+=ArchieArray[mapId][12][1];//得分增加,
}
Iterator<BombForControl> ite=bomb_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
}
for(TanKe afc:tankeList)//查看有没有击中坦克
{
if(curr_y>afc.ty&&curr_y<afc.ty+ARCHIBALD_Y
&&curr_x>afc.tx-ARCHIBALD_X&&curr_x<afc.tx+ARCHIBALD_X
&&curr_z>afc.tz-ARCHIBALD_Z&&curr_z<afc.tz+ARCHIBALD_Z)
{
afc.blood-=ArchieArray[mapId][8][1];//坦克的血减1
if(afc.blood<=0)
{
gv.activity.playSound(0,1);
try
{
Iterator<TanKe> ite=tankeList.iterator();
while(ite.hasNext())
{
if(ite.next()==afc)
{
ite.remove();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
gradeArray[1]+=ArchieArray[mapId][12][0];//得分增加,
}
baoZhaList.add(new DrawBomb(bombRect,curr_x,curr_y+bomb_height/5,curr_z));
Iterator<BombForControl> ite=bomb_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
}
//有没有击中敌机
for(EnemyPlane afc:enemy){//查看有没有击中
if(curr_y>afc.ty-PLANE_Y_R&&curr_y<afc.ty+PLANE_Y_R
&&curr_x>afc.tx-PLANE_X_R&&curr_x<afc.tx+PLANE_X_R
&&curr_z>afc.tz-ANGLE_X_Z&&curr_z<afc.tz+ANGLE_X_Z){
afc.blood-=ArchieArray[mapId][8][3];//敌机的血减1
gv.activity.playSound(8,0);
if(afc.blood<=0){
gv.activity.playSound(0,1);
try
{
Iterator<EnemyPlane> ite=enemy.iterator();
while(ite.hasNext())
{
if(ite.next()==afc)
{
ite.remove();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
gradeArray[1]+=ArchieArray[mapId][12][2];//得分增加,
}
baoZhaList.add(new DrawBomb(bombRect,curr_x,curr_y+bomb_height/5,curr_z));
Iterator<BombForControl> ite=bomb_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
}
//这里判断是否锁定目标
if(islocked)//如果锁定目标
{
curr_x+=curr_nx/average*BOMB_VELOCITY;
curr_z+=curr_nz/average*BOMB_VELOCITY;
curr_y+=curr_ny/average*BOMB_VELOCITY;
}
else
{
//计算炮弹下一步的位置
//计算当前仰角和方向角
curr_x=curr_x-(float)(Math.cos(Math.toRadians(curr_elevation))*Math.sin(Math.toRadians(curr_direction))*BOMB_VELOCITY);
curr_z=curr_z-(float)(Math.cos(Math.toRadians(curr_elevation))*Math.cos(Math.toRadians(curr_direction))*BOMB_VELOCITY);
curr_y=curr_y+(float)(Math.sin(Math.toRadians(curr_elevation))*BOMB_VELOCITY);//飞机的位置
}
}
//高射炮发射炮弹
public void go_archie()
{
float curr_planeX=PLANE_X;
float curr_planeY=PLANE_Y;
float curr_planeZ=PLANE_Z;
distance+=ARCHIE_BOMB_VELOCITY;//子弹的行驶路程增加
if(distance>=BOMB_MAX_DISTANCE)//如果子弹步长超出了
{
try
{
Iterator<BombForControl> ite=archie_bomb_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
//这里对炮弹是否击中飞机进行判断
float curr_distance=(curr_planeX-curr_x)*(curr_planeX-curr_x)+
(curr_planeY-curr_y)*(curr_planeY-curr_y)+
(curr_planeZ-curr_z)*(curr_planeZ-curr_z);
if(curr_distance<500)//炮弹与飞机相撞
{
gv.activity.playSound(1,0);
isno_Hit=true;//飞机被击中了一下
gv.plane.blood-=ArchieArray[mapId][9][1];//飞机血减少一滴
gv.activity.shake();//手机震动一次
try
{
Iterator<BombForControl> ite=archie_bomb_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
return ;
}
//计算炮弹下一步的位置
//计算当前仰角和方向角
curr_x=curr_x-(float)(Math.cos(Math.toRadians(curr_elevation))*Math.sin(Math.toRadians(curr_direction))*ARCHIE_BOMB_VELOCITY);
curr_z=curr_z-(float)(Math.cos(Math.toRadians(curr_elevation))*Math.cos(Math.toRadians(curr_direction))*ARCHIE_BOMB_VELOCITY);
curr_y=curr_y+(float)(Math.sin(Math.toRadians(curr_elevation))*ARCHIE_BOMB_VELOCITY);//飞机的位置
}
//坦克发射炮弹
public void go_tank()
{
float curr_planeX=PLANE_X;
float curr_planeY=PLANE_Y;
float curr_planeZ=PLANE_Z;
distance+=TANK_BOMB_VELOCITY;//子弹的行驶路程增加
if(distance>=BOMB_MAX_DISTANCE)//如果子弹步长超出了
{
try
{
Iterator<BombForControl> ite=tank_bomb_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
//这里对炮弹是否击中飞机进行判断
float curr_distance=(curr_planeX-curr_x)*(curr_planeX-curr_x)+
(curr_planeY-curr_y)*(curr_planeY-curr_y)+
(curr_planeZ-curr_z)*(curr_planeZ-curr_z);
if(curr_distance<500)//炮弹与飞机相撞
{
gv.activity.playSound(1,0);
isno_Hit=true;//飞机杯击中一下了
gv.plane.blood-=ArchieArray[mapId][9][0];//飞机血减少一滴
gv.activity.shake();//手机震动一次
try
{
Iterator<BombForControl> ite=tank_bomb_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
return ;
}
//计算炮弹下一步的位置
//计算当前仰角和方向角
curr_x=curr_x-(float)(Math.cos(Math.toRadians(curr_elevation))*Math.sin(Math.toRadians(curr_direction))*TANK_BOMB_VELOCITY);
curr_z=curr_z-(float)(Math.cos(Math.toRadians(curr_elevation))*Math.cos(Math.toRadians(curr_direction))*TANK_BOMB_VELOCITY);
curr_y=curr_y+(float)(Math.sin(Math.toRadians(curr_elevation))*TANK_BOMB_VELOCITY);
}
}
@@ -0,0 +1,396 @@
package com.bn.gameView;
import static com.bn.gameView.Constant.ANGLE_X_Z;
import static com.bn.gameView.Constant.ARCHIBALD_X;
import static com.bn.gameView.Constant.ARCHIBALD_Y;
import static com.bn.gameView.Constant.ARCHIBALD_Z;
import static com.bn.gameView.Constant.ARSENAL_X;
import static com.bn.gameView.Constant.ARSENAL_Y;
import static com.bn.gameView.Constant.ARSENAL_Z;
import static com.bn.gameView.Constant.ArchieArray;
import static com.bn.gameView.Constant.BULLET_MAX_DISTANCE;
import static com.bn.gameView.Constant.BULLET_VELOCITY;
import static com.bn.gameView.Constant.PLANE_X;
import static com.bn.gameView.Constant.PLANE_X_R;
import static com.bn.gameView.Constant.PLANE_Y;
import static com.bn.gameView.Constant.PLANE_Y_R;
import static com.bn.gameView.Constant.PLANE_Z;
import static com.bn.gameView.Constant.archie_List;
import static com.bn.gameView.Constant.bullet_List;
import static com.bn.gameView.Constant.gradeArray;
import static com.bn.gameView.Constant.isno_Lock;
import static com.bn.gameView.Constant.mapId;
import static com.bn.gameView.Constant.nx;
import static com.bn.gameView.Constant.ny;
import static com.bn.gameView.Constant.nz;
import static com.bn.gameView.GLGameView.arsenal;
import static com.bn.gameView.GLGameView.baoZhaList;
import static com.bn.gameView.GLGameView.bombRect;
import static com.bn.gameView.GLGameView.bomb_height;
import static com.bn.gameView.GLGameView.cx;
import static com.bn.gameView.GLGameView.cy;
import static com.bn.gameView.GLGameView.cz;
import static com.bn.gameView.GLGameView.enemy;
import static com.bn.gameView.GLGameView.tankeList;
import java.util.Iterator;
import com.bn.archieModel.ArchieForControl;
import com.bn.arsenal.Arsenal_House;
import com.bn.commonObject.DrawBomb;
import com.bn.commonObject.TextureRect;
import com.bn.core.MatrixState;
import com.bn.planeModel.EnemyPlane;
import com.bn.tankemodel.TanKe;
public class BulletForControl implements Comparable<BulletForControl>
{
private TextureRect bullet_rect;//子弹类
//定义发射子弹时的位置
private float curr_x;
private float curr_y;
private float curr_z;
//定义发射子弹时的仰角和方位角
private float curr_elevation;
private float curr_direction;
private float distance;//飞行距离
//锁定状态下的方向
private boolean islocked;
private float curr_nx;
private float curr_ny;
private float curr_nz;
private float average;//平均向量
//子弹的旋转角度
private float curr_rotation;
GLGameView gv;
public int bulletId;//子弹的id,看是敌机发出的还是自己发出的子弹,1为敌机发出的子弹
public BulletForControl(GLGameView gv,TextureRect bullet_rect,float plane_x,float plane_y,float plane_z,float plane_elevation,float plane_direction
,float rotationAngle_Plane_X,float rotationAngle_Plane_Y,
float rotationAngle_Plane_Z,int bulletIndex,int bulletId)//bulletIndex表示是左机翼发射子弹还是右机翼
{
this.bulletId=bulletId;
this.gv=gv;
//创建纹理球
this.bullet_rect=bullet_rect;
this.curr_x=plane_x;
this.curr_y=plane_y;
this.curr_z=plane_z;
this.curr_elevation=plane_elevation;
this.curr_direction=plane_direction;
this.islocked=isno_Lock;
if(islocked)
{
curr_nx=nx;
curr_ny=ny;
curr_nz=nz;
average=(float) Math.sqrt(curr_nx*curr_nx+curr_ny*curr_ny+curr_nz*curr_nz);
}
initData(plane_x,plane_y,plane_z,rotationAngle_Plane_X,rotationAngle_Plane_Y,rotationAngle_Plane_Z,bulletIndex);
}
//确定飞机机翼子弹的发射位置
public void initData(float plane_x,float plane_y,float plane_z,float rotationAngle_Plane_X,
float rotationAngle_Plane_Y,float rotationAngle_Plane_Z,int bulletIndex)
{
//设定左机翼发射炮弹的位置
curr_x=plane_x;
curr_y=plane_y;
curr_z=plane_z;
//炮弹位置的相关参数
float length;
float ori_y;
float ori_z;
length=6;
if(bulletIndex!=1)//左机翼发射子弹
{
ori_y=90;
ori_z=-2;
}
else//右机翼发射子弹
{
ori_y=-90;
ori_z=-2;
}
//确定子弹的最终位置
curr_y=curr_y-(float)Math.sin(Math.toRadians(rotationAngle_Plane_Z+ori_z))*length;
curr_x=curr_x-(float)Math.cos(Math.toRadians(rotationAngle_Plane_Z+ori_z))*(float)Math.sin(Math.toRadians(rotationAngle_Plane_Y+ori_y))*length;
curr_z=curr_z-(float)Math.cos(Math.toRadians(rotationAngle_Plane_Z+ori_z))*(float)Math.cos(Math.toRadians(rotationAngle_Plane_Y+ori_y))*length;
}
public void drawSelf(int texId)
{
MatrixState.pushMatrix();
MatrixState.translate(curr_x, curr_y, curr_z);//子弹移动到指定的位置
MatrixState.rotate(curr_rotation, 0, 1, 0);//根据摄像机的相对位置进行旋转
bullet_rect.drawSelf(texId);//进行绘制
MatrixState.popMatrix();
}
public void go()
{
distance+=BULLET_VELOCITY;//子弹的行驶路程增加
if(distance>=BULLET_MAX_DISTANCE)//如果子弹步长超出了
{
Iterator<BulletForControl> ite=bullet_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
if(bulletId==0)
{
//判断是否和军火库发生碰撞
for(Arsenal_House as:arsenal)
{
if(//军火库还存在
curr_y>as.ty&&curr_y<as.ty+ARSENAL_Y
&&curr_x>as.tx-ARSENAL_X&&curr_x<as.tx+ARSENAL_X
&&curr_z>as.tz-ARSENAL_Z&&curr_z<as.tz+ARSENAL_Z)
{
as.blood-=ArchieArray[mapId][7][0];//军火库
if(as.blood<1){//如果军火库被炸毁
gv.activity.playSound(0,0);
try
{
Iterator<Arsenal_House> ite=arsenal.iterator();
while(ite.hasNext())
{
if(ite.next()==as)
{
ite.remove();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
gradeArray[1]+=ArchieArray[mapId][12][3];//得分增加,
baoZhaList.add(new DrawBomb(bombRect,as.tx,as.ty+bomb_height/2,as.tz));
}
Iterator<BulletForControl> ite=bullet_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
}
for(ArchieForControl afc:archie_List)//查看有没有击中高射炮
{
if(curr_y>afc.position[1]&&curr_y<afc.position[1]+ARCHIBALD_Y
&&curr_x>afc.position[0]-ARCHIBALD_X&&curr_x<afc.position[0]+ARCHIBALD_X
&&curr_z>afc.position[2]-ARCHIBALD_Z&&curr_z<afc.position[2]+ARCHIBALD_Z)
{
afc.blood-=ArchieArray[mapId][7][2];//高射炮的血减1
try
{
if(afc.blood<1)
{
gv.activity.playSound(0,1);
try
{
Iterator<ArchieForControl> ite=archie_List.iterator();
while(ite.hasNext())
{
if(ite.next()==afc)
{
ite.remove();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
gradeArray[1]+=ArchieArray[mapId][12][1];//得分增加,
baoZhaList.add(new DrawBomb(bombRect,curr_x,curr_y+bomb_height/2,curr_z));
}
}
catch(Exception e)
{
e.printStackTrace();
}
Iterator<BulletForControl> ite=bullet_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
}
for(TanKe afc:tankeList){//查看有没有击中坦克
if(curr_y>afc.ty&&curr_y<afc.ty+ARCHIBALD_Y
&&curr_x>afc.tx-ARCHIBALD_X&&curr_x<afc.tx+ARCHIBALD_X
&&curr_z>afc.tz-ARCHIBALD_Z&&curr_z<afc.tz+ARCHIBALD_Z){
afc.blood-=ArchieArray[mapId][7][1];//坦克的血减1
if(afc.blood<=0)
{
gv.activity.playSound(0,1);
try
{
Iterator<TanKe> ite=tankeList.iterator();
while(ite.hasNext())
{
if(ite.next()==afc)
{
ite.remove();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
baoZhaList.add(new DrawBomb(bombRect,curr_x,curr_y+bomb_height/2,curr_z));
gradeArray[1]+=ArchieArray[mapId][12][0];//得分增加,
}
Iterator<BulletForControl> ite=bullet_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
}
//有没有击中敌机
for(EnemyPlane afc:enemy){//
if(curr_y>afc.ty-PLANE_Y_R&&curr_y<afc.ty+PLANE_Y_R
&&curr_x>afc.tx-PLANE_X_R&&curr_x<afc.tx+PLANE_X_R
&&curr_z>afc.tz-ANGLE_X_Z&&curr_z<afc.tz+ANGLE_X_Z){
afc.blood-=ArchieArray[mapId][7][3];//敌机的血减1
if(afc.blood<=0){
gv.activity.playSound(0,1);
try
{
Iterator<EnemyPlane> ite=enemy.iterator();
while(ite.hasNext())
{
if(ite.next()==afc)
{
ite.remove();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
baoZhaList.add(new DrawBomb(bombRect,curr_x,curr_y+bomb_height/5,curr_z));
gradeArray[1]+=ArchieArray[mapId][12][2];//得分增加,
}
Iterator<BulletForControl> ite=bullet_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
}
}
else//敌方的飞机发射的子弹击中我方的飞机
{
float curr_planeX=PLANE_X;
float curr_planeY=PLANE_Y;
float curr_planeZ=PLANE_Z;
//这里对炮弹是否击中飞机进行判断
float curr_distance=(curr_planeX-curr_x)*(curr_planeX-curr_x)+
(curr_planeY-curr_y)*(curr_planeY-curr_y)+
(curr_planeZ-curr_z)*(curr_planeZ-curr_z);
if(curr_distance<500)//炮弹与飞机相撞
{
gv.plane.blood-=ArchieArray[mapId][9][2];//飞机血减少一滴
try
{
Iterator<BulletForControl> ite=bullet_List.iterator();
while(ite.hasNext())
{
if(ite.next()==this)
{
ite.remove();
return;
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
return ;
}
}
//计算子弹下一步的位置
//计算当前仰角和方向角
//这里判断是否锁定目标
if(islocked)//如果锁定目标,则按照锁定方向发射子弹
{
curr_x+=curr_nx/average*BULLET_VELOCITY;
curr_z+=curr_nz/average*BULLET_VELOCITY;
curr_y+=curr_ny/average*BULLET_VELOCITY;
}
else
{
curr_x=curr_x-(float)(Math.cos(Math.toRadians(curr_elevation))*Math.sin(Math.toRadians(curr_direction))*BULLET_VELOCITY);
curr_z=curr_z-(float)(Math.cos(Math.toRadians(curr_elevation))*Math.cos(Math.toRadians(curr_direction))*BULLET_VELOCITY);
curr_y=curr_y+(float)(Math.sin(Math.toRadians(curr_elevation))*BULLET_VELOCITY);//飞机的位置
}
//计算朝向
calculateBillboardDirection();
}
//这里计算标志板的朝向
public void calculateBillboardDirection()
{//根据摄像机位置计算焰火粒子面朝向
float currX_span=curr_x-cx;
float currZ_span=curr_z-cz;
if(currZ_span<=0)
{
curr_rotation=(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}
else
{
curr_rotation=180+(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}
}
@Override
public int compareTo(BulletForControl another)
{//重写的比较两个粒子离摄像机距离的方法
float x=curr_x-cx;
float z=curr_y-cz;
float y=curr_z-cy;
float xo=another.curr_x-cx;
float zo=another.curr_y-cz;
float yo=another.curr_z-cy;
float disA=x*x+y*y+z*z;
float disB=xo*xo+yo*yo+zo*zo;
return ((disA-disB)==0)?0:((disA-disB)>0)?-1:1;
}
}
@@ -0,0 +1,125 @@
/**
*
* 用于绘制圆
*/
package com.bn.gameView;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import com.bn.commonObject.Light_Tower;
import com.bn.core.MatrixState;
import android.opengl.GLES20;
//用triangle_fan方式绘制圆面 此圆面是平行于XY平面的
public class CircleForDraw
{
float taizihight=30;
int mProgram;//自定义渲染管线程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maColorR; //颜色值的R分量引用id
int maColorG; //颜色值的G分量引用id
int maColorB; //颜色值的B分量引用id
int maColorA;
private static FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private static int vCount;
float r; //颜色值的R分量
float g; //颜色值的G分量
float b; //颜色值的B分量
Light_Tower taizi;
public CircleForDraw
(
int mProgram,
float angleSpan,//切分角度
float radius,//圆半径
float[]color,
int mProgramlitht
)
{
this.r=color[0];
this.g=color[1];
this.b=color[2];
initVertexData(angleSpan,radius);
initShader(mProgram);
taizi=new Light_Tower(radius,radius,taizihight,1);
taizi.initShader(mProgramlitht);
}
public static void initVertexData
(
float angleSpan,//切分角度
float radius//圆半径
)
{
//顶点纹理坐标数据的初始化================begin============================
vCount=1+(int)(360/angleSpan)+1;//顶点的个数
float[] vertices=new float[vCount*3];//初始化顶点数组
//存放中心点坐标
vertices[0]=0;
vertices[1]=0;
vertices[2]=0;
int vcount=3;//当前顶点坐标索引
for(float angle=0;angle<=360;angle=angle+angleSpan)
{
double angleRadian=Math.toRadians(angle);
//顶点坐标
vertices[vcount++]=radius*(float)Math.cos(angleRadian);
vertices[vcount++]=radius*(float)Math.sin(angleRadian);
vertices[vcount++]=0;
}
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
}
public void initShader(int mProgramIn)
{
mProgram = mProgramIn;
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
maColorR=GLES20.glGetUniformLocation(mProgram, "colorR");
maColorG=GLES20.glGetUniformLocation(mProgram, "colorG");
maColorB=GLES20.glGetUniformLocation(mProgram, "colorB");
maColorA=GLES20.glGetUniformLocation(mProgram, "colorA");
}
public void drawSelf(float alpha,int texId)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//将位置、旋转变换矩阵传入shader程序
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//允许顶点位置、法向量数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glUniform1f(maColorR , r);
GLES20.glUniform1f(maColorG , g);
GLES20.glUniform1f(maColorB , b);
GLES20.glUniform1f(maColorA , alpha);
//绘制图形
GLES20.glDrawArrays
(
GL10.GL_TRIANGLE_FAN, //以TRIANGLE_FAN方式填充
0,
vCount
);
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,359 @@
package com.bn.menu;
import static com.bn.gameView.Constant.SCREEN_HEIGHT;
import static com.bn.gameView.Constant.SCREEN_WIDTH;
import static com.bn.gameView.Constant.isMusicOn;
import static com.bn.gameView.Constant.isSoundOn;
import static com.bn.gameView.Constant.isVibrateOn;
import static com.bn.gameView.Constant.isCrash;
import static com.bn.gameView.Constant.isOvercome;
import static com.bn.gameView.Constant.isVideo;
import static com.bn.gameView.Constant.is_button_return;
import static com.bn.gameView.Constant.keyState;
import static com.bn.gameView.Constant.ratio_height;
import static com.bn.gameView.Constant.ratio_width;
import java.util.HashMap;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Service;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.content.pm.ConfigurationInfo;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.Window;
import android.view.WindowManager;
import com.bn.core.RotateUtil;
import com.bn.core.SQLiteUtil;
import com.bn.gameView.GLGameView;
@SuppressWarnings("deprecation")
public class Aircraft_Activity extends Activity
{
GLGameView gameView;//主游戏场景
static Handler handler;//消息接收器
SoundPool soundPool;//声音池
Vibrator mVibrator;//震动器
public MediaPlayer bgMusic[]=new MediaPlayer[2];//游戏背景音乐播放器
HashMap<Integer,Integer> soundMap;//存放声音池中的声音ID的Map
SensorManager mySensorManager;//传感器的引用
private boolean isNoBack;//返回键屏蔽主要是在欢迎界面播放过程中,屏蔽返回键
private int flag;//判断当前屏幕是否能够旋转的标志位
public float[] directionDotXY;//用于记录传感器的数据.directionDotXY[0]表示左右旋转,
public float lr_domain=4;//传感器左右旋转地阈值
private SensorListener mySensorListener = new SensorListener()
{
@Override
public void onAccuracyChanged(int sensor, int accuracy){}
@Override
public void onSensorChanged(int sensor, float[] values)
{
if(sensor == SensorManager.SENSOR_ORIENTATION)
{
directionDotXY=RotateUtil.getDirectionDot
(
new double[]{values[0],values[1],values[2]}
);
if(directionDotXY[0]>lr_domain)
{
//左转
keyState=keyState|0x4;
keyState=keyState&0x7;
}
else if(directionDotXY[0]<-lr_domain)
{
//右转
keyState=keyState|0x8;
keyState=keyState&0xB;
}
else
{
//相关数据复位
keyState=keyState&0xB;
keyState=keyState&0x7;
}}}};
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
flag =Settings.System.getInt(this.getContentResolver(), //判断当前是否能够旋转屏
Settings.System.ACCELEROMETER_ROTATION, 0);
if(flag==0)//打开旋转屏
{
Settings.System.putInt(this.getContentResolver(),Settings.System.ACCELEROMETER_ROTATION,1);
}
mySensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);//传感器管理者
initScreen();//初始化屏幕
initHandler();//消息接收器
initSound();//初始化
initDatebase();
collisionShake();//初始化振动器
goTo_StartVideo();
}
//消息接收器方法
public void initHandler()
{
handler=new Handler()
{
@Override
public void handleMessage(Message msg)//重写方法
{
switch(msg.what)
{
case 1:
isNoBack=false;//返回键可用
gameView=new GLGameView(Aircraft_Activity.this);
setContentView(gameView);
bgMusic[0].start();//开启背景音乐
break;
}}};}
//初始化屏幕分辨率
public void initScreen()
{
requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉通知栏
getWindow().setFlags//全屏显示
(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
DisplayMetrics dm=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int tempHeight=(int) (SCREEN_HEIGHT=dm.heightPixels);
int tempWidth=(int) (SCREEN_WIDTH=dm.widthPixels);
if(tempHeight<tempWidth)
{
SCREEN_HEIGHT=tempHeight;
SCREEN_WIDTH=tempWidth;
}
else
{
SCREEN_HEIGHT=tempWidth;
SCREEN_WIDTH=tempHeight;
}
ratio_width=SCREEN_WIDTH/800;
ratio_height=SCREEN_HEIGHT/480;
}
public void initDatebase()
{
String sql="create table if not exists plane(map char(2),grade char(4),time char(4),date char(10));";
SQLiteUtil.createTable(sql);//建表SQL语句
}
public void goTo_StartVideo(){ //游戏开始首先播放视频
isNoBack=true;//返回键不可用
setContentView(R.layout.start_video);
final MyVideoView myVideoView=(MyVideoView)findViewById(R.id.start_video_videoview);
myVideoView.setVideoURI(Uri.parse("android.resource://com.bn.menu/" + R.raw.logo));
myVideoView.start();
myVideoView.setOnCompletionListener(new OnCompletionListener(){
@Override
public void onCompletion(MediaPlayer mp){
if(getGLVersion()<2){//这里进行opengles测试
//弹出对话框,说明不支持该游戏
showDialog(0);
}else if(Build.VERSION.SDK_INT<Build.VERSION_CODES.FROYO){
showDialog(1);
}else
handler.sendEmptyMessage(1);//进入主菜单界面
}});
}
public int getGLVersion()//获取OPENGLES所支持的最高版本
{
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
int majorVersion=info.reqGlEsVersion;
majorVersion=majorVersion>>>16;
return majorVersion;
}
public void collisionShake()//手机震动
{
mVibrator=(Vibrator)getApplication().getSystemService
(Service.VIBRATOR_SERVICE);
}
public void shake()//震动
{
if(0==isVibrateOn)//开启震动
{
mVibrator.vibrate( new long[]{0,30},-1);
}
}
public void initSound()//加载声音资源
{
bgMusic[0]=MediaPlayer.create(this,R.raw.menubg_music);
bgMusic[0].setLooping(true);//是否循环
bgMusic[0].setVolume(0.3f, 0.3f);//声音大小
bgMusic[1]=MediaPlayer.create(this,R.raw.gamebg_music);
bgMusic[1].setLooping(true);//是否循环
bgMusic[1].setVolume(0.5f, 0.5f);//声音大小
soundPool=new SoundPool(4,AudioManager.STREAM_MUSIC,100);//创建声音池
soundMap=new HashMap<Integer,Integer>();//创建map
soundMap.put(0, soundPool.load(this, R.raw.explode,1));//飞机撞山或者死亡的声音
soundMap.put(1, soundPool.load(this, R.raw.awp_fire,1));//坦克和高射炮被击毙爆炸
soundMap.put(2, soundPool.load(this, R.raw.r700_fire,1));//爆炸
soundMap.put(3, soundPool.load(this, R.raw.bullet,1));//飞机发射子弹声音
soundMap.put(4, soundPool.load(this, R.raw.missile,1));//发射子弹声音
soundMap.put(5, soundPool.load(this, R.raw.m16_fire,1));//发射子弹声音
soundMap.put(6, soundPool.load(this, R.raw.rpg7_fire,1));//发射子弹声音
soundMap.put(7, soundPool.load(this, R.raw.w1200_fire,1));//坦克发射子弹声音
soundMap.put(8, soundPool.load(this, R.raw.ground,1));//坦克发射子弹声音
soundMap.put(9, soundPool.load(this, R.raw.rotation,1));//
}
//播放声音的方法
public void playSound(int sound,int loop)
{
if(0!=isSoundOn)
{
return;
}
AudioManager mgr = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float volume = streamVolumeCurrent / streamVolumeMax;
soundPool.play
(
soundMap.get(sound), //声音资源id
volume, //左声道音量
volume, //右声道音量
1, //优先级
loop, //循环次数 -1带表永远循环
0.5f //回放速度0.5f~2.0f之间
);
}
@Override
public Dialog onCreateDialog(int id)
{
Dialog dialog=null;
switch(id)
{
case 0://生成普通对话框的代码
String msg="该设备所支持的opengles版本过低,不支持此游戏!!!";
Builder b=new AlertDialog.Builder(this);
b.setIcon(R.drawable.icon);//设置图标
b.setTitle("不好意思...");//设置标题
b.setMessage(msg);//设置信息
b.setPositiveButton(//为对话框设置按钮
"退出" ,
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
System.exit(0);
}});
dialog=b.create();
break;
case 1://生成普通对话框的代码
String msgt="该设备当前Android版本是低于2.2,不支持此游戏!!!";
Builder bb=new AlertDialog.Builder(this);
bb.setIcon(R.drawable.icon);//设置图标
bb.setTitle("不好意思...");//设置标题
bb.setMessage(msgt);//设置信息
bb.setPositiveButton(//为对话框设置按钮
"退出" ,
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
System.exit(0);
}});
dialog=bb.create();
break;
}
return dialog;
}
@Override
protected void onResume()
{
super.onResume();
mySensorManager.registerListener(//注册监听 方法
mySensorListener,
SensorManager.SENSOR_ORIENTATION,
SensorManager.SENSOR_DELAY_UI
);
}
@Override
protected void onPause()
{
super.onPause();
mySensorManager.unregisterListener(mySensorListener); //取消注册监听器
}
public void exitRelease()//退出时需要执行的方法
{
if(flag==0)//关掉旋转屏
{
Settings.System.putInt(this.getContentResolver(),Settings.System.ACCELEROMETER_ROTATION,0);
}
System.exit(0);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent e)//设置屏幕监听
{
if(keyCode==KeyEvent.KEYCODE_VOLUME_DOWN||keyCode==KeyEvent.KEYCODE_VOLUME_UP)//控制音量键只能控制媒体音量的大小
{
setVolumeControlStream(AudioManager.STREAM_MUSIC);
return super.onKeyDown(keyCode, e);
}
if(keyCode==4)
{
if(isNoBack)//返回键屏蔽
{
return true;
}
if(!gameView.isGameOn)
{
return gameView.onKeyBackEvent();
}
else //游戏开始了
{
if(!isCrash&&!isOvercome)
{
if(!isVideo)
{
is_button_return=!is_button_return;//按下返回按钮
if(bgMusic[1].isPlaying())
{
bgMusic[1].pause();
}
else if(!bgMusic[1].isPlaying()&&isMusicOn==0)
{
bgMusic[1].start();
}
}
else
{
gameView.isTrueButtonAction=true;
GLGameView.isVideoPlaying=!GLGameView.isVideoPlaying;
if(bgMusic[1].isPlaying())
{
bgMusic[1].pause();
}
else if(!bgMusic[1].isPlaying()&&isMusicOn==0)
{
bgMusic[1].start();
}
}
}
return true;
}
}
return true;
}}
@@ -0,0 +1,111 @@
package com.bn.menu;
import android.opengl.GLES20;
import com.bn.commonObject.BallTextureByVertex;
import com.bn.commonObject.CylinderForDraw;
import com.bn.commonObject.TextureRect;
import com.bn.core.MatrixState;
/*
* 主要用于绘制导弹菜单
*/
public class MissileMenuForDraw
{
private TextureRect rect;//纹理矩形
private BallTextureByVertex halfBall;//弹头用的半球
private CylinderForDraw cylinder;//圆柱
private TextureRect rect_tail;//纹理矩形
private float rect_width=0.8f;//纹理矩形的宽度
private float rect_height=2.5f;//纹理矩形的高度
private float tail_width=2.3f;//尾翼的宽度
private float tail_height=1.2f;//尾翼的高度
private float rect_offset=(float) (rect_width/2/Math.tan(Math.toRadians(22.5f)));//纹理矩形沿Z轴负方向的偏移量
private float radius=(float) (rect_width/2/Math.sin(Math.toRadians(22.5f)));//半球和圆柱的半径
private float halfBall_span=rect_height/2;//半球的偏移量
private float cylinder_length=0.2f;//圆柱的长度
public MissileMenuForDraw(int mProgram)
{
rect=new TextureRect(rect_width, rect_height, mProgram);//创建纹理矩形对象
halfBall=new BallTextureByVertex(radius, mProgram, 0);//创建半球
cylinder=new CylinderForDraw(radius, cylinder_length, mProgram); //创建圆柱
rect_tail=new TextureRect( tail_width, tail_height,mProgram);//创建纹理矩形炮弹尾翼
}
public void drawSelft(int[]tex_RectId)
{
//------------------------绘制导弹中间部分
MatrixState.pushMatrix();
//绘制第一个面
MatrixState.pushMatrix();
MatrixState.translate(0, 0, rect_offset);
rect.drawSelf(tex_RectId[0]);
MatrixState.popMatrix();
//绘制第二个面
MatrixState.pushMatrix();
MatrixState.rotate(45, 0, 1, 0);
MatrixState.translate(0, 0, rect_offset);
rect.drawSelf(tex_RectId[1]);
MatrixState.popMatrix();
//绘制第三个面
MatrixState.pushMatrix();
MatrixState.rotate(90, 0, 1, 0);
MatrixState.translate(0, 0, rect_offset);
rect.drawSelf(tex_RectId[2]);
MatrixState.popMatrix();
//绘制第四个面
MatrixState.pushMatrix();
MatrixState.rotate(135, 0, 1, 0);
MatrixState.translate(0, 0, rect_offset);
rect.drawSelf(tex_RectId[3]);
MatrixState.popMatrix();
//绘制第五个面
MatrixState.pushMatrix();
MatrixState.rotate(180, 0, 1, 0);
MatrixState.translate(0, 0, rect_offset);
rect.drawSelf(tex_RectId[4]);
MatrixState.popMatrix();
//绘制第六个面
MatrixState.pushMatrix();
MatrixState.rotate(225, 0, 1, 0);
MatrixState.translate(0, 0, rect_offset);
rect.drawSelf(tex_RectId[5]);
MatrixState.popMatrix();
//绘制第七个面
MatrixState.pushMatrix();
MatrixState.rotate(270, 0, 1, 0);
MatrixState.translate(0, 0, rect_offset);
rect.drawSelf(tex_RectId[6]);
MatrixState.popMatrix();
//绘制第八个面
MatrixState.pushMatrix();
MatrixState.rotate(315, 0, 1, 0);
MatrixState.translate(0, 0, rect_offset);
rect.drawSelf(tex_RectId[7]);
MatrixState.popMatrix();
MatrixState.popMatrix();
//------------------------绘制导弹头部分
MatrixState.pushMatrix();
MatrixState.translate(0, halfBall_span, 0);
halfBall.drawSelf(tex_RectId[8]);
MatrixState.translate(0, -cylinder_length/2, 0);
cylinder.drawSelf(tex_RectId[9]);
MatrixState.popMatrix();
//------------------------绘制导弹尾部分
MatrixState.pushMatrix();
MatrixState.translate(0, -halfBall_span, 0);
MatrixState.rotate(180, 0, 0, 1);
halfBall.drawSelf(tex_RectId[8]);
MatrixState.translate(0, -cylinder_length/2, 0);
cylinder.drawSelf(tex_RectId[9]);
MatrixState.popMatrix();
//绘制扇叶
GLES20.glDisable(GLES20.GL_CULL_FACE);
MatrixState.pushMatrix();
MatrixState.translate(0, -halfBall_span-tail_height/2, 0);
rect_tail.drawSelf(tex_RectId[10]);
MatrixState.rotate(120, 0, 1, 0);
rect_tail.drawSelf(tex_RectId[10]);
MatrixState.rotate(120, 0, 1, 0);
rect_tail.drawSelf(tex_RectId[10]);
MatrixState.popMatrix();
GLES20.glEnable(GLES20.GL_CULL_FACE);
}
}
@@ -0,0 +1,25 @@
package com.bn.menu;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.VideoView;
import static com.bn.gameView.Constant.*;
/**
*
* @author lishengjie
* 重写VideoView,主要是将视频铺满全屏
*/
public class MyVideoView extends VideoView
{
public MyVideoView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = getDefaultSize((int) SCREEN_WIDTH, widthMeasureSpec);
int height = getDefaultSize((int) SCREEN_HEIGHT, heightMeasureSpec);
setMeasuredDimension(width,height);
}
}
@@ -0,0 +1,150 @@
package com.bn.planeModel;
import static com.bn.gameView.Constant.planezAngle;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
/*
* 绘制螺旋桨 顶点和纹理
*/
public class Airscrew
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
private FloatBuffer mVertexBuffer; //顶点坐标数据缓冲
private FloatBuffer mTextureBuffer; //顶点纹理数据缓冲
int vCount=6; //顶点数量
final int angleSpan=8; //每片螺旋桨叶片角度
float scale; //尺寸
float zSpan=0; //螺旋桨在z轴上的偏离
float speed_Airscrew=50f;//螺旋桨旋转地角速度
public Airscrew(float scale,int mProgram)
{
this.mProgram=mProgram;
this.scale=scale;
zSpan=scale/12; //螺旋桨在z轴上的偏离
initVertex(); //初始化顶点坐标数据
initTexture(); //初始化顶点纹理数据
initShader();
}
//初始化顶点的信息
public void initVertex()
{ //构建立方体
float x=(float) (this.scale*Math.cos(Math.toRadians(angleSpan)));//构建三角形顶点的x坐标的变量
float y=(float) (this.scale*Math.sin(Math.toRadians(angleSpan)));//构建三角形顶点的y坐标的变量
float z=zSpan; //构建三角形顶点的z坐标的变量
//顶点坐标缓冲数组初始化
float[] vertices=
{
//构成外侧表面三角形的坐标
0,0,0,
x,y,0,
x,-y,-z,
//构成内侧侧表面三角形的坐标
0,0,0,
x,-y,-z,
x,y,0,
};
ByteBuffer vbb=ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer=vbb.asFloatBuffer();//转换为float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
}
//初始化纹理的信息
public void initTexture()
{
float[] textures=generateTextures(); //生成纹理坐标数组
ByteBuffer tbb=ByteBuffer.allocateDirect(textures.length*4);
tbb.order(ByteOrder.nativeOrder()); //设置字节顺序为本地操作系统顺序
mTextureBuffer=tbb.asFloatBuffer(); //转换为float型缓冲
mTextureBuffer.put(textures); //向缓冲区中放入顶点坐标数据
mTextureBuffer.position(0); //设置缓冲区起始位置
}
//生成纹理
public float[] generateTextures()
{
float[] textures=new float[]
{//生成纹理坐标数组
0,0,1,0,0,1,
0,0,0,1,1,0,
};
return textures;
}
//初始化shader
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId)
{
MatrixState.pushMatrix();
drawOneAirscrew(texId);//绘制其中一个螺旋桨
MatrixState.rotate(60, 0, 0, 1);
drawOneAirscrew(texId);//绘制其中一个螺旋桨
MatrixState.rotate(60, 0, 0, 1);
drawOneAirscrew(texId);//绘制其中一个螺旋桨
MatrixState.rotate(60, 0, 0, 1);
drawOneAirscrew(texId);//绘制其中一个螺旋桨
MatrixState.rotate(60, 0, 0, 1);
drawOneAirscrew(texId);//绘制其中一个螺旋桨
MatrixState.rotate(60, 0, 0, 1);
drawOneAirscrew(texId);//绘制其中一个螺旋桨
MatrixState.popMatrix();
}
public void drawOneAirscrew(int texId)//绘制其中一个螺旋桨
{
MatrixState.pushMatrix();
MatrixState.rotate(planezAngle, 0, 0, 1);
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTextureBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
MatrixState.popMatrix();
}
}
@@ -0,0 +1,202 @@
package com.bn.planeModel;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
/*
* 用于绘制圆柱 顶点和纹理
*/
public class Column
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTextureBuffer;//顶点纹理数据缓冲
private int vCount; //顶点数量
public float mAngleX;//绕x轴旋转角度
public float mAngleY;//绕y轴旋转角度
public float mAngleZ;//绕z轴旋转角度
float mOffsetX;//沿x轴平移距离
float mOffsetY;//沿y轴平移距离
float mOffsetZ;//沿z轴平移距离
float height;//设置高
float radius;//设置半径
private float heightSpan=0.05f; //高度切分单元
private float angleSpan=30; //角度切分大小
//圆柱的切分行数和列数
int col=(int) (360/angleSpan);//圆柱的切分列数
int row=10; //圆柱的切分行数和列数
public Column(float height,float radius,int mProgram)
{
this.mProgram=mProgram;
this.height=height;
this.radius=radius;
heightSpan=height/row; //高度切分单元
initVertex(); //初始化顶点坐标数据
initTexture(); //初始化顶点纹理数据
initShader();
}
//初始化顶点信息
public void initVertex()
{
ArrayList<Float> alVertex=new ArrayList<Float>();//存放顶点
for(int i=0;i<=row;i++)
{
float y=(i-row/2.0f)*heightSpan;//构建三角形顶点的y坐标的变量
float hAngle=0; //水平面角度
for(int j=0;j<=col;j++)
{
hAngle=j*angleSpan; //水平面上的角度
float x=(float) (radius*Math.cos(Math.toRadians(hAngle)));//构建三角形顶点的x坐标的变量
float z=(float) (radius*Math.sin(Math.toRadians(hAngle)));//构建三角形顶点的z坐标的变量
alVertex.add(x); //添加x坐标
alVertex.add(y); //添加y坐标
alVertex.add(z); //添加z坐标
}
}
ArrayList<Integer> alIndex=new ArrayList<Integer>(); //创建索引
int ncol=col+1; //每行实际顶点数量
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
int k=i*ncol+j; //三角形索引
alIndex.add(k); //上三角形
alIndex.add(k+ncol);
alIndex.add(k+1);
alIndex.add(k+ncol); //下三角形
alIndex.add(k+ncol+1);
alIndex.add(k+1);
}
}
vCount=alIndex.size(); //顶点数量
float vertices[]=new float[alIndex.size()*3];//顶点坐标数组
for(int i=0;i<vCount;i++) //向数组中添加顶点
{
int k=alIndex.get(i); //取出三角形索引
vertices[i*3]=alVertex.get(k*3); //添加三角形x坐标
vertices[i*3+1]=alVertex.get(k*3+1);//添加三角形y坐标
vertices[i*3+2]=alVertex.get(k*3+2);//添加三角形z坐标
}
ByteBuffer vbb=ByteBuffer.allocateDirect(vertices.length*4);//一个float型4个byte
vbb.order(ByteOrder.nativeOrder()); //设置字节顺序为本地操作系统顺序
mVertexBuffer=vbb.asFloatBuffer(); //装换为float缓冲
mVertexBuffer.put(vertices); //放入顶点数组
mVertexBuffer.position(0); //设置起始位置
}
//初始化纹理信息
public void initTexture()
{
int tCount=row*col*2*3*2; //顶点数量
float[] textures=new float[tCount]; //纹理坐标数组
float sizew=1.0f/col; //横向纹理坐标单元
float sizeh=1.0f/row;
for(int i=0,temp=0;i<row;i++)
{
float t=i*sizeh;
for(int j=0;j<col;j++)
{
float s=j*sizew;
//左上三角形
textures[temp++]=s;
textures[temp++]=t;
textures[temp++]=s;
textures[temp++]=t+sizeh;
textures[temp++]=s+sizew;
textures[temp++]=t;
//右下三角形
textures[temp++]=s;
textures[temp++]=t+sizeh;
textures[temp++]=s+sizew;
textures[temp++]=t+sizeh;
textures[temp++]=s+sizew;
textures[temp++]=t;
}
}
ByteBuffer tbb=ByteBuffer.allocateDirect(textures.length*4);//一个float型4个byte
tbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTextureBuffer=tbb.asFloatBuffer();//转换为FLOAT型缓冲
mTextureBuffer.put(textures);//向缓冲区中放入顶点坐标数据
mTextureBuffer.position(0);//缓冲区的起始位置
}
//初始化着色器的initShader方法
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId)
{
MatrixState.pushMatrix();
MatrixState.translate(mOffsetX, mOffsetY, mOffsetZ);
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTextureBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
MatrixState.popMatrix();
}
public float[] getLengthWidthHeight()
{
float[] lwh=
{
this.radius*2,//长
this.radius*2,//宽
this.height //高
};
return lwh;
}
}
@@ -0,0 +1,194 @@
package com.bn.planeModel;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
/*
* 创建椭球体类 顶点和纹理
* 用于绘制机身,机头和机舱
*/
public class DrawSpheroid
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTextureBuffer;//纹理缓冲
public float mAngleX;//沿x轴旋转角度
public float mAngleY;//沿y轴旋转角度
public float mAngleZ;//沿z轴旋转角度
int vCount=0;
float a;
float b; //三轴半径长
float c;
float angleSpan;//将球进行单位切分的角度
float hAngleBegin;//经度绘制起始角度
float hAngleOver;//经度绘制结束角度
float vAngleBegin;//纬度绘制起始角度
float vAngleOver;//纬度绘制结束角度
//hAngle表示经度,vAngle表示纬度。
public DrawSpheroid(float a,float b,float c,float angleSpan,
float hAngleBegin,float hAngleOver,float vAngleBegin,float vAngleOver,int mProgram)
{
this.a=a;
this.b=b;
this.c=c;
this.hAngleBegin=hAngleBegin;
this.hAngleOver=hAngleOver;
this.vAngleBegin=vAngleBegin;
this.vAngleOver=vAngleOver;
this.mProgram=mProgram;
this.angleSpan=angleSpan;
initVertexData();
initShader();
}
//初始化顶点的信息
public void initVertexData()
{
ArrayList<Float> alVertix=new ArrayList<Float>();//存放顶点坐标
for(float vAngle=vAngleBegin;vAngle<vAngleOver;vAngle=vAngle+angleSpan)//垂直方向angleSpan度一份
{
for(float hAngle=hAngleBegin;hAngle<hAngleOver;hAngle=hAngle+angleSpan)//水平方向angleSpan度一份
{//纵向横向各到一个角度后计算对应的此点在球面上的坐标
float x1=(float)(a*Math.cos(Math.toRadians(vAngle))*Math.cos(Math.toRadians(hAngle)));
float y1=(float)(b*Math.cos(Math.toRadians(vAngle))*Math.sin(Math.toRadians(hAngle)));
float z1=(float)(c*Math.sin(Math.toRadians(vAngle)));
float x2=(float)(a*Math.cos(Math.toRadians(vAngle+angleSpan))*Math.cos(Math.toRadians(hAngle)));
float y2=(float)(b*Math.cos(Math.toRadians(vAngle+angleSpan))*Math.sin(Math.toRadians(hAngle)));
float z2=(float)(c*Math.sin(Math.toRadians(vAngle+angleSpan)));
float x3=(float)(a*Math.cos(Math.toRadians(vAngle+angleSpan))*Math.cos(Math.toRadians(hAngle+angleSpan)));
float y3=(float)(b*Math.cos(Math.toRadians(vAngle+angleSpan))*Math.sin(Math.toRadians(hAngle+angleSpan)));
float z3=(float)(c*Math.sin(Math.toRadians(vAngle+angleSpan)));
float x4=(float)(a*Math.cos(Math.toRadians(vAngle))*Math.cos(Math.toRadians(hAngle+angleSpan)));
float y4=(float)(b*Math.cos(Math.toRadians(vAngle))*Math.sin(Math.toRadians(hAngle+angleSpan)));
float z4=(float)(c*Math.sin(Math.toRadians(vAngle)));
//将计算出来的XYZ坐标加入存放顶点坐标的ArrayList
alVertix.add(x1);alVertix.add(y1);alVertix.add(z1);
alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);
}
}
vCount=alVertix.size()/3;//顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标
//将alVertix中的坐标值转存到一个int数组中
float[] vertices=new float[vCount*3];
for(int i=0;i<alVertix.size();i++)
{
vertices[i]=alVertix.get(i);
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//纹理
//获取切分整图的纹理数组
float[] texCoorArray=
generateTexCoor
(
(int)(180/angleSpan), //纹理图切分的列数
(int)(180/angleSpan) //纹理图切分的行数
);
ByteBuffer tbb=ByteBuffer.allocateDirect(texCoorArray.length*4);
tbb.order(ByteOrder.nativeOrder());
mTextureBuffer=tbb.asFloatBuffer();
mTextureBuffer.put(texCoorArray);
mTextureBuffer.position(0);
}
//初始化着色器的initShader方法
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId)
{
MatrixState.pushMatrix();
MatrixState.rotate(mAngleX, 1, 0, 0);
MatrixState.rotate(mAngleY, 0, 1, 0);
MatrixState.rotate(mAngleZ, 0, 0, 1);
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTextureBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
MatrixState.popMatrix();
}
//自动切分纹理产生纹理数组的方法
public float[] generateTexCoor(int bw,int bh)
{
float[] result=new float[bw*bh*6*2];
float sizew=1.0f/bw;//列数
float sizeh=1.0f/bh;//行数
int c=0;
for(int i=0;i<bh;i++)
{
for(int j=0;j<bw;j++)
{
//每行列一个矩形,由两个三角形构成,共六个点,12个纹理坐标
float s=j*sizew;
float t=i*sizeh;
result[c++]=s;
result[c++]=t;
result[c++]=s;
result[c++]=t+sizeh;
result[c++]=s+sizew;
result[c++]=t;
result[c++]=s+sizew;
result[c++]=t;
result[c++]=s;
result[c++]=t+sizeh;
result[c++]=s+sizew;
result[c++]=t+sizeh;
}
}
return result;
}
}
@@ -0,0 +1,271 @@
package com.bn.planeModel;
import static com.bn.gameView.Constant.BUTTON_RADAR_BG_WIDTH;
import static com.bn.gameView.Constant.ENEMYPLANE_SPAN;
import static com.bn.gameView.Constant.Lock_Distance;
import static com.bn.gameView.Constant.Lock_angle;
import static com.bn.gameView.Constant.MapArray;
import static com.bn.gameView.Constant.PLANE_RATIO;
import static com.bn.gameView.Constant.PLANE_X;
import static com.bn.gameView.Constant.PLANE_Y;
import static com.bn.gameView.Constant.PLANE_Z;
import static com.bn.gameView.Constant.WIDTH_LALNDFORM;
import static com.bn.gameView.Constant.bullet_List;
import static com.bn.gameView.Constant.directionX;
import static com.bn.gameView.Constant.directionY;
import static com.bn.gameView.Constant.directionZ;
import static com.bn.gameView.Constant.enemy_plane_place;
import static com.bn.gameView.Constant.isno_Hit;
import static com.bn.gameView.Constant.isno_Lock;
import static com.bn.gameView.Constant.mapId;
import static com.bn.gameView.Constant.minimumdistance;
import static com.bn.gameView.Constant.nx;
import static com.bn.gameView.Constant.ny;
import static com.bn.gameView.Constant.nz;
import static com.bn.gameView.Constant.rotationAngle_Plane_Z;
import static com.bn.gameView.Constant.scalMark;
import static com.bn.gameView.GLGameView.cx;
import static com.bn.gameView.GLGameView.cz;
import java.util.Collections;
import android.opengl.GLES20;
import com.bn.commonObject.NumberForDraw;
import com.bn.commonObject.TextureRect;
import com.bn.core.MatrixState;
import com.bn.gameView.BulletForControl;
import com.bn.gameView.GLGameView;
public class EnemyPlane
{
public Plane plane;//模型引用
public float tx,ty,tz;//初始位置
public float xAngle,yAngle,zAngle;//方向向量
public float arsenal_x,arsenal_y;//在仪表板中的位置
public float thisnx,thisny,thisnz;
public NumberForDraw nm;//数字引用
public TextureRect backgroundRect;//背景
public float xue_scale=0.4f;//血缩放比例
public TextureRect mark_lock;//标记被锁定的矩形
public TextureRect mark_plane;//标记矩形
public boolean this_isno_Lock=false;//自己是否被锁定,被锁定就绘制锁定矩形
public int blood=100;//坦克的生命值
int drawblood;
float yAnglexue;
public int id;//代表是第几个飞机
float distance1;//敌机和飞机的距离
GLGameView gv;
long oldTime;
public EnemyPlane(GLGameView gv,Plane plane,float tx,float ty,float tz,float xAngle,float yAngle,float zAngle,
TextureRect backgroundRect,NumberForDraw nm,TextureRect mark_plane,TextureRect mark_lock,int id
){
this.gv=gv;
this.id=id;
this.nm=nm;
this.backgroundRect=backgroundRect;
this.mark_plane=mark_plane;
this.mark_lock=mark_lock;
this.plane=plane;
this.tx=tx;this.ty=ty;this.tz=tz;
this.xAngle=xAngle;
this.yAngle=yAngle;
this.zAngle=zAngle;
thisnx=-(float) (ENEMYPLANE_SPAN*Math.sin(Math.toRadians(yAngle)));
thisnz=-(float) (ENEMYPLANE_SPAN*Math.cos(Math.toRadians(yAngle)));
thisny=0;
arsenal_x=scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-PLANE_X)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
arsenal_y=-scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-PLANE_Z)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
}
public void drawSelf(int texBodyHeadId,int texScrewId,int texBodyBackId,int texCabinId,//绘制飞机
int texFrontWingId,int texFrontWing2Id,int texCylinder3Id,int texCylinderId,
int texCylinder2Id,int texBackWingId,int texTopWingId,
int backgroundRectId,int numberID,int locktexId
){
drawblood=blood;
MatrixState.pushMatrix();
MatrixState.translate(tx, ty, tz);
MatrixState.rotate(xAngle, 1, 0, 0);
MatrixState.rotate(yAngle, 0, 1, 0);
MatrixState.rotate(zAngle, 0, 0, 1);
MatrixState.scale(PLANE_RATIO, PLANE_RATIO, PLANE_RATIO);
plane.drawSelf(texBodyHeadId, texScrewId, texBodyBackId, texCabinId, texFrontWingId,
texFrontWing2Id, texCylinder3Id, texCylinderId, texCylinder2Id, texBackWingId, texTopWingId);
MatrixState.popMatrix();
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
if(drawblood>=0){
MatrixState.pushMatrix();
MatrixState.translate(tx, ty+30, tz);
MatrixState.scale(xue_scale, xue_scale, xue_scale);
MatrixState.rotate(yAnglexue, 0,1, 0);
MatrixState.rotate(rotationAngle_Plane_Z, 0,0, 1);
backgroundRect.bloodValue=drawblood*2-100+6;
backgroundRect.drawSelf(backgroundRectId);
MatrixState.popMatrix();
}
if(this_isno_Lock)
{
MatrixState.pushMatrix();//绘制锁定的
MatrixState.translate(tx, ty, tz);
MatrixState.rotate(yAnglexue, 0,1, 0);
MatrixState.scale(0.8f, 0.8f,0.8f);
mark_lock.drawSelf(locktexId);
MatrixState.popMatrix();
}
GLES20.glDisable(GLES20.GL_BLEND);
}
public void drawSelfMark(int texId)//仪表盘上的标记位置的颜色框
{
MatrixState.pushMatrix();
MatrixState.translate(arsenal_x,arsenal_y,0);
plane.mark_plane.drawSelf(texId);
MatrixState.popMatrix();
}
public void go()
{
if(this_isno_Lock)//如果被锁定,敌机朝着飞机飞
{
thisnx=-nx;
thisny=-ny;
thisnz=-nz;
xAngle=(float) Math.toDegrees(Math.atan(thisny/Math.sqrt(thisnx*thisnx+thisnz*thisnz)));
}
else
{
thisny=0;
if(ty<enemy_plane_place[mapId][id][1]){//飞机高度
thisny+=4;
}else if(ty>enemy_plane_place[mapId][id][1]){
thisny-=4;
}
if(distance1>Lock_Distance*2f){//如果飞机在其一定范围内,则敌机飞向飞机
thisnx=-tx+PLANE_X;
thisny=-ty+PLANE_Y;
thisnz=-tz+PLANE_Z;
}
}
if(thisnz<0)
{
yAngle=(float)Math.toDegrees(Math.atan(thisnx/thisnz));
}
else if(thisnz==0)
{
yAngle=thisnx>0?90:-90;
}
else
{
yAngle=180+(float)Math.toDegrees(Math.atan(thisnx/thisnz));
}
float n=(float) (Math.sqrt(thisnx*thisnx+thisny*thisny+thisnz*thisnz));
tx+=ENEMYPLANE_SPAN*thisnx/n;
tz+=ENEMYPLANE_SPAN*thisnz/n;
ty+=ENEMYPLANE_SPAN*thisny/n;
calculateBillboardDirection();
//计算标记飞机位置的坐标
arsenal_x=-scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-tx)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
arsenal_y=scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-tz)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
if(arsenal_x*arsenal_x+arsenal_y*arsenal_y>BUTTON_RADAR_BG_WIDTH*BUTTON_RADAR_BG_WIDTH*0.4f*0.4f){
arsenal_x=(float) (arsenal_x*0.4f*
(BUTTON_RADAR_BG_WIDTH/Math.sqrt(arsenal_x*arsenal_x+arsenal_y*arsenal_y)));
arsenal_y=(float) (arsenal_y*0.4f*
(BUTTON_RADAR_BG_WIDTH/Math.sqrt(arsenal_x*arsenal_x+arsenal_y*arsenal_y)));
}
if(distance1>Lock_Distance*2)
{
return;
}
boolean isLock=isno_Lock;
//这里进行发射子弹
if(this_isno_Lock&&System.nanoTime()-oldTime>300000000)//这里设置连续发射子弹
{
isno_Lock=false;
//向列表中添加子弹对象
try
{
bullet_List.add(new BulletForControl(gv,gv.bullet_rect, tx, ty, tz,
xAngle, yAngle,xAngle,
yAngle,zAngle,0,1));
bullet_List.add(new BulletForControl(gv,gv.bullet_rect, tx, ty, tz,
xAngle, yAngle,xAngle,
yAngle,zAngle,1,1));
Collections.sort(bullet_List);
}
catch(Exception ee)
{
ee.printStackTrace();
}
oldTime=System.nanoTime();
}
isno_Lock=isLock;
}
//这里计算标志板的朝向
public void calculateBillboardDirection()
{//根据摄像机位置计算焰火粒子面朝向
float currX_span=tx-cx;
float currZ_span=tz-cz;
if(currZ_span<0)
{
yAnglexue=(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}else if(currZ_span==0){
yAnglexue=currX_span>0?90:-90;
}
else
{
yAnglexue=180+(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}
if(isno_Lock){
this_isno_Lock=false;
return;
}
//计算其是否被锁定
float x1,y1,z1,x2,y2,z2;
x1=tx-PLANE_X;
y1=ty-PLANE_Y;
z1=tz-PLANE_Z;
distance1=(float) Math.sqrt(x1*x1+y1*y1+z1*z1);
if(distance1>Lock_Distance){//如果距离超出范围,或者已经有一个被锁定了,则自己不能被锁定
this_isno_Lock=false;
return;
}//计算飞机飞行的方向向量
if(distance1<20)
{
gv.activity.playSound(3,0);
isno_Hit=true;//飞机被击中了一下
gv.plane.blood-=10;//飞机血减少一滴
gv.activity.shake();//手机震动一次
}
x2=directionX;//-(float) (Math.cos(Math.toRadians(rotationAngle_Plane_X))*Math.sin(Math.toRadians(rotationAngle_Plane_Y)));
y2=directionY;//(float) (Math.sin(Math.toRadians(rotationAngle_Plane_X)));
z2=directionZ;//-(float) (Math.cos(Math.toRadians(rotationAngle_Plane_X))*Math.cos(Math.toRadians(rotationAngle_Plane_Y)));
float cosa=(float) Math.acos((x1*x2+y1*y2+z1*z2)/(distance1*1));
if(cosa<Lock_angle){
this.zAngle+=40;
this.this_isno_Lock=true;
minimumdistance=distance1;//最小距离设置为该距离
nx=x1;ny=y1;nz=z1;//发射子弹方向向量
isno_Lock=true;//已经被锁定
}else{
this_isno_Lock=false;
this.zAngle=0;
}
}
}
@@ -0,0 +1,157 @@
package com.bn.planeModel;
import static com.bn.gameView.Constant.BODYBACK_A;
import static com.bn.gameView.Constant.BODYBACK_B;
import static com.bn.gameView.Constant.BODYBACK_C;
import static com.bn.gameView.Constant.BODYHEAD_A;
import static com.bn.gameView.Constant.BODYHEAD_B;
import static com.bn.gameView.Constant.BODYHEAD_C;
import static com.bn.gameView.Constant.BUTTON_RADAR_BG_WIDTH;
import static com.bn.gameView.Constant.CABIN_A;
import static com.bn.gameView.Constant.CABIN_B;
import static com.bn.gameView.Constant.CABIN_C;
import static com.bn.gameView.Constant.ENEMYPLANE_SIZE;
import static com.bn.gameView.Constant.MapArray;
import static com.bn.gameView.Constant.PLANE_SIZE;
import static com.bn.gameView.Constant.PLANE_X;
import static com.bn.gameView.Constant.PLANE_Z;
import static com.bn.gameView.Constant.WIDTH_LALNDFORM;
import static com.bn.gameView.Constant.mapId;
import static com.bn.gameView.Constant.plane_blood;
import static com.bn.gameView.Constant.scalMark;
import com.bn.commonObject.TextureRect;
import com.bn.core.MatrixState;
import com.bn.gameView.GLGameView;
/*
* 整体飞机的架构
*/
public class Plane
{
GLGameView gv; //MySurfaceView 的引用
DrawSpheroid bodyback; //机身引用
DrawSpheroid bodyhead; //机头引用
DrawSpheroid cabin; //机舱引用
Plane_Wing frontwing; //前机翼
Plane_Wing frontwing2; //前机翼
Plane_BackWing backwing; //后机翼
Plane_TopWing topwing; //上尾翼
Column cylinder; //圆柱体
Column cylinder2; //圆柱体
Column cylinder3; //炮管
Airscrew screw; //螺旋桨
float initAngleY=-90; //初始时沿x轴的倾角
float[] planePartLWH= //获得飞机的长高宽
{
BODYBACK_B*2,BODYBACK_C*2,BODYBACK_A+BODYHEAD_A, //机身
};
public int blood=plane_blood;
public TextureRect mark_plane;//标记矩形
//标记军火库位置的颜色矩形位置
public float arsenal_x,arsenal_y,arsenal_z;
public Plane(GLGameView gv,int mProgram, TextureRect mark_plane)
{
this.gv=gv;
//获得各部件的引用
bodyback=new DrawSpheroid(BODYBACK_A*PLANE_SIZE,BODYBACK_B*PLANE_SIZE,BODYBACK_C*PLANE_SIZE,18,-90,90,-90,90,mProgram);
bodyhead=new DrawSpheroid(BODYHEAD_A*PLANE_SIZE,BODYHEAD_B*PLANE_SIZE,BODYHEAD_C*PLANE_SIZE,18,-90,90,-90,90,mProgram);
cabin=new DrawSpheroid(CABIN_A*PLANE_SIZE,CABIN_B*PLANE_SIZE,CABIN_C*PLANE_SIZE,18,0,360,-90,90,mProgram);
frontwing = new Plane_Wing(0.4f*PLANE_SIZE*1.5f,0.12f*PLANE_SIZE*1.5f,0.004f*PLANE_SIZE*1.5f,mProgram);
frontwing2 = new Plane_Wing(0.4f*PLANE_SIZE*1.5f,0.12f*PLANE_SIZE*1.5f,0.004f*PLANE_SIZE*1.5f,mProgram);
backwing = new Plane_BackWing(0.14f*PLANE_SIZE*1.5f,0.06f*PLANE_SIZE*1.5f,0.004f*PLANE_SIZE*1.5f,mProgram);
topwing = new Plane_TopWing(0.05f*PLANE_SIZE*1.5f,0.07f*PLANE_SIZE*1.5f,0.01f*PLANE_SIZE*1.5f,mProgram);
cylinder = new Column(0.18f*PLANE_SIZE,0.006f*PLANE_SIZE,mProgram);//机身圆柱
cylinder2 = new Column(0.1f*PLANE_SIZE,0.015f*PLANE_SIZE,mProgram);//机身圆柱
cylinder3 = new Column(0.15f*PLANE_SIZE,0.02f*PLANE_SIZE,mProgram);//机身圆
screw = new Airscrew(0.30f*PLANE_SIZE,mProgram);
this.mark_plane=mark_plane;
arsenal_x=scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-PLANE_X)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
arsenal_y=-scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-PLANE_Z)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
}
public void drawSelf(int texBodyHeadId,int texScrewId,int texBodyBackId,int texCabinId,
int texFrontWingId,int texFrontWing2Id,int texCylinder3Id,int texCylinderId,
int texCylinder2Id,int texBackWingId,int texTopWingId)
{
MatrixState.pushMatrix();
MatrixState.rotate(initAngleY, 0, 1, 0);
MatrixState.pushMatrix();
MatrixState.rotate(180, 0, 1, 0);
bodyhead.drawSelf(texBodyHeadId); //画机头
MatrixState.rotate(90, 0, 1, 0);
MatrixState.translate(0, 0, 0.2f*ENEMYPLANE_SIZE);
screw.drawSelf(texScrewId); //螺旋桨
MatrixState.popMatrix();
MatrixState.pushMatrix();
MatrixState.rotate(180, 1, 0, 0);
bodyback.drawSelf(texBodyBackId);//画机身
MatrixState.popMatrix();
MatrixState.pushMatrix();
MatrixState.translate(0, BODYBACK_B*ENEMYPLANE_SIZE/5f, 0);
cabin.drawSelf(texCabinId); //机舱
MatrixState.popMatrix();
//前机翼
MatrixState.pushMatrix();
MatrixState.rotate(90, 0, 1, 0);
MatrixState.rotate(-90, 1, 0, 0);
MatrixState.translate(0, 0, 0.12f*PLANE_SIZE);
frontwing.drawSelf(texFrontWingId); //上前机翼
MatrixState.translate(0, 0, -0.2f*PLANE_SIZE);
frontwing2.drawSelf(texFrontWing2Id); //下前机翼
MatrixState.translate(-0.12f*PLANE_SIZE, 0,0.03f*PLANE_SIZE );
cylinder3.drawSelf(texCylinder3Id); //机身圆柱1
MatrixState.translate(0.24f*PLANE_SIZE, 0,0 );
cylinder3.drawSelf(texCylinder3Id); //机身圆柱2
MatrixState.popMatrix();
//机翼圆柱
MatrixState.pushMatrix();
MatrixState.translate(0.07f*PLANE_SIZE, 0.016f*PLANE_SIZE, -0.4f*PLANE_SIZE);
cylinder.drawSelf(texCylinderId);
MatrixState.translate(-0.14f*PLANE_SIZE, 0, 0);
cylinder.drawSelf(texCylinderId);
MatrixState.translate(0, 0, 0.8f*PLANE_SIZE);
cylinder.drawSelf(texCylinderId);
MatrixState.translate(0.14f*PLANE_SIZE, 0, 0);
cylinder.drawSelf(texCylinderId);
MatrixState.popMatrix();
//机身圆柱
MatrixState.pushMatrix();
MatrixState.translate(0, 0.096f*PLANE_SIZE, 0.08f*PLANE_SIZE);
MatrixState.rotate(30, 1, 0, 0);
cylinder2.drawSelf(texCylinder2Id);
MatrixState.translate(0, -0.096f*PLANE_SIZE, -0.16f*PLANE_SIZE);
MatrixState.rotate(-60, 1, 0, 0);
cylinder2.drawSelf(texCylinder2Id);
MatrixState.popMatrix();
//尾翼
MatrixState.pushMatrix();
MatrixState.translate(0.6f*PLANE_SIZE, 0, 0);
MatrixState.rotate(90, 0, 1, 0);
MatrixState.rotate(-90, 1, 0, 0);
backwing.drawSelf(texBackWingId);
MatrixState.popMatrix();
//上尾翼
MatrixState.pushMatrix();
MatrixState.translate(0.6f*PLANE_SIZE, 0, 0);
topwing.drawSelf(texTopWingId);
MatrixState.popMatrix();
MatrixState.popMatrix();
}
public void drawSelfMark(int texId){//仪表盘上的标记位置的颜色框
MatrixState.pushMatrix();
MatrixState.translate(arsenal_x,arsenal_y,0);
mark_plane.drawSelf(texId);
MatrixState.popMatrix();
}
}
@@ -0,0 +1,175 @@
package com.bn.planeModel;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
//纹理矩形,用于绘制后机翼,只有顶点和纹理
public class Plane_BackWing
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTextureBuffer;//顶点着色数据缓冲
int vCount ;
float mAngleX ;
public Plane_BackWing(float width,float height,float length,int mProgram)
{
this.mProgram=mProgram;
initVertexData(width,height,length);
initShader();
}
public void initVertexData(float width,float height,float length)
{
float vertices[]=new float[]
{
//上表面
0,height,length,-width,height,length,-13.0f/10.0f*width,2.0f/5.0f*height,length,//OAB
0,height,length,-13.0f/10.0f*width,2.0f/5.0f*height,length,-width,-height,length,//OBC
0,height,length,-width,-height,length,width,-height,length,//OCD
0,height,length,width,-height,length,13.0f/10.0f*width,2.0f/5.0f*height,length,//ODE
0,height,length,13.0f/10.0f*width,2.0f/5.0f*height,length,width,height,length,//OEF
//下表面
0,height,-length,-width,height,-length,-13.0f/10.0f*width,2.0f/5.0f*height,-length,//OAB
0,height,-length,-13.0f/10.0f*width,2.0f/5.0f*height,-length,-width,-height,-length,//OBC
0,height,-length,-width,-height,-length,width,-height,-length,//OCD
0,height,-length,width,-height,-length,13.0f/10.0f*width,2.0f/5.0f*height,-length,//ODE
0,height,-length,13.0f/10.0f*width,2.0f/5.0f*height,-length,width,height,-length,//OEF
-width,height,length,-width,height,-length,-13.0f/10.0f*width,2.0f/5.0f*height,-length,
0-width,height,length,-13.0f/10.0f*width,2.0f/5.0f*height,-length,-13.0f/10.0f*width,2.0f/5.0f*height,length,
-13.0f/10.0f*width,2.0f/5.0f*height,length,-13.0f/10.0f*width,2.0f/5.0f*height,-length,-width,-height,-length,
-13.0f/10.0f*width,2.0f/5.0f*height,length,-width,-height,-length,-width,-height,length,
-width,-height,length,-width,-height,-length,width,-height,-length,
-width,-height,length,width,-height,-length,width,-height,length,
width,-height,length,width,-height,-length,13.0f/10.0f*width,2.0f/5.0f*height,-length,
width,-height,length,13.0f/10.0f*width,2.0f/5.0f*height,-length,13.0f/10.0f*width,2.0f/5.0f*height,length,
13.0f/10.0f*width,2.0f/5.0f*height,length,13.0f/10.0f*width,2.0f/5.0f*height,-length,width,height,-length,
13.0f/10.0f*width,2.0f/5.0f*height,length,width,height,-length,width,height,length,
width,height,length,width,height,-length,-width,height,-length,
width,height,length,width,height,-length,0,height,-length,
width,height,length,0,height,-length,0,height,length,
0,height,length,0,height,-length,-width,height,-length,
0,height,length, -width,height,-length, -width,height,length,
};
vCount=vertices.length/3;
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
//转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题
//顶点坐标数据的初始化================end============================
//顶点纹理数据的初始化================begin============================
float textures[]=new float[]
{
//上表面
0.18f,0.0f,0.027f,0.0080f,0.0f,0.027f,
0.18f,0.0f,0.0f,0.027f,0.0f,0.09f,
0.18f,0.0f,0.0f,0.09f,0.035f,0.109f,
0.18f,0.0f,0.035f,0.109f,0.145f,0.109f,
0.18f,0.0f,0.145f,0.109f,0.168f,0.074f,
0.18f,0.0f,0.168f,0.074f,0.211f,0.07f,
//下表面
0.18f,0.0f,0.027f,0.0080f,0.0f,0.027f,
0.18f,0.0f,0.0f,0.027f,0.0f,0.09f,
0.18f,0.0f,0.0f,0.09f,0.035f,0.109f,
0.18f,0.0f,0.035f,0.109f,0.145f,0.109f,
0.18f,0.0f,0.145f,0.109f,0.168f,0.074f,
0.18f,0.0f,0.168f,0.074f,0.211f,0.07f,
//侧面
0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,
0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,
0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,
0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,
0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,
0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,
0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,0.168f,0.043f,0.152f,0.09f,0.223f,0.074f,
};
//创建顶点纹理数据缓冲
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTextureBuffer= tbb.asFloatBuffer();//转换为Float型缓冲
mTextureBuffer.put(textures);//向缓冲区中放入顶点着色数据
mTextureBuffer.position(0);//设置缓冲区起始位置
//特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
//转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题
//顶点纹理数据的初始化================end============================
}
//初始化着色器的initShader方法
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId)
{
MatrixState.pushMatrix();
MatrixState.rotate(mAngleX, 1, 0, 0);
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTextureBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
MatrixState.popMatrix();
}
}
@@ -0,0 +1,163 @@
package com.bn.planeModel;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
//纹理矩形,用于绘制上面的机翼 顶点和纹理
public class Plane_TopWing
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTextureBuffer;//顶点着色数据缓冲
float mAngleX;
float mAngleY;
int vCount = 42;
public Plane_TopWing(float width,float height,float length,int mProgram)
{
this.mProgram=mProgram;
initVertexData(width,height,length);
initShader();
}
public void initVertexData(float width,float height,float length)
{
float vertices[]=new float[]
{
-5.0f/6.0f*width,4.0f/3.0f*height,0,//A
-width,height,-length,//B
-width,height,length,//C
-5.0f/6.0f*width,4.0f/3.0f*height,0,//A
-width,height,length,//C
width,height,length,//D
-5.0f/6.0f*width,4.0f/3.0f*height,0,//A
width,height,length,//D
5.0f/6.0f*width,4.0f/3.0f*height,0,//O
5.0f/6.0f*width,4.0f/3.0f*height,0,//O
width,height,length,//D
width,height,-length,//E
5.0f/6.0f*width,4.0f/3.0f*height,0,//O
width,height,-length,//E
-width,height,-length,//B
5.0f/6.0f*width,4.0f/3.0f*height,0,//O
-width,height,-length,//B
-5.0f/6.0f*width,4.0f/3.0f*height,0,//A
-width,height,length,//C
-width,0,6.0f/5.0f*length,//F
width,0,6.0f/5.0f*length,//G
-width,height,length,//C
width,0,6.0f/5.0f*length,//G
width,height,length,//D
width,height,length,//D
width,0,6.0f/5.0f*length,//G
width,0,-6.0f/5.0f*length,//H
width,height,length,//D
width,0,-6.0f/5.0f*length,//H
width,height,-length,//E
width,height,-length,//E
width,0,-6.0f/5.0f*length,//H
-width,0,-6.0f/5.0f*length,//I
width,height,-length,//E
-width,0,-6.0f/5.0f*length,//I
-width,height,-length,//B
-width,height,-length,//B
-width,0,-6.0f/5.0f*length,//I
-width,0,6.0f/5.0f*length,//F
-width,height,-length,//B
-width,0,6.0f/5.0f*length,//F
-width,height,length,//C
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
float textures[]=new float[]
{
0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,
0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,
0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,
0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,
0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,
0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,
0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,
0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,0.133f, 0.211f,0.242f,0.492f,0.555f,0.289f,
};
//创建顶点纹理数据缓冲
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTextureBuffer= tbb.asFloatBuffer();//转换为Float型缓冲
mTextureBuffer.put(textures);//向缓冲区中放入顶点着色数据
mTextureBuffer.position(0);//设置缓冲区起始位置
}
//初始化着色器的initShader方法
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId)
{
MatrixState.pushMatrix();
MatrixState.rotate(mAngleX, 1, 0, 0);
MatrixState.rotate(mAngleY, 0, 1, 0);
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTextureBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
MatrixState.popMatrix();
}
}
@@ -0,0 +1,253 @@
package com.bn.planeModel;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
/*
* 纹理矩形,用于绘制机翼,只有顶点和纹理
*/
public class Plane_Wing
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
private FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
private FloatBuffer mTextureBuffer;//顶点着色数据缓冲
int vCount;
int texId;
float mAngleX ;
public Plane_Wing(float width,float height,float length,int mProgram)
{
this.mProgram=mProgram;
initVertexData(width,height,length);
initShader();
}
public void initVertexData(float width,float height,float length)
{
vCount=144;
float vertices[]=new float[]
{
//上表面
0,height,length,-width,height,length,-17.0f/15.0f*width,3.0f/5.0f*height,length,//OAB
0,height,length,-17.0f/15.0f*width,3.0f/5.0f*height,length,-17.0f/15.0f*width,-3.0f/5.0f*height,length,//OBC
0,height,length,-17.0f/15.0f*width,-3.0f/5.0f*height,length,-width,-height,length,//OCD
0,height,length,-width,-height,length,-1.0f/3.0f*width,-height,length,//ODE
0,height,length,-1.0f/3.0f*width,-height,length,-2.0f/15.0f*width,-2.0f/5.0f*height,length,//OEF
0,height,length,-2.0f/15.0f*width,-2.0f/5.0f*height,length,2.0f/15.0f*width,-2.0f/5.0f*height,length,//OFG
0,height,length,2.0f/15.0f*width,-2.0f/5.0f*height,length,1.0f/3.0f*width,-height,length,//OGH
0,height,length,1.0f/3.0f*width,-height,length,width,-height,length,//OHI
0,height,length,width,-height,length,17.0f/15.0f*width,-3.0f/5.0f*height,length,//OIJ
0,height,length,17.0f/15.0f*width,-3.0f/5.0f*height,length,17.0f/15.0f*width,3.0f/5.0f*height,length,//OJK
0,height,length,17.0f/15.0f*width,3.0f/5.0f*height,length,width,height,length,//OKL
//下表面
0,height,-length,-width,height,-length,-17.0f/15.0f*width,3.0f/5.0f*height,-length,//OAB
0,height,-length,-17.0f/15.0f*width,3.0f/5.0f*height,-length,-17.0f/15.0f*width,-3.0f/5.0f*height,-length,//OBC
0,height,-length,-17.0f/15.0f*width,-3.0f/5.0f*height,-length,-width,-height,-length,//OCD
0,height,-length,-width,-height,-length,-1.0f/3.0f*width,-height,-length,//ODE
0,height,-length,-1.0f/3.0f*width,-height,-length,-2.0f/15.0f*width,-2.0f/5.0f*height,-length,//OEF
0,height,-length,-2.0f/15.0f*width,-2.0f/5.0f*height,-length,2.0f/15.0f*width,-2.0f/5.0f*height,-length,//OFG
0,height,-length,2.0f/15.0f*width,-2.0f/5.0f*height,-length,1.0f/3.0f*width,-height,-length,//OGH
0,height,-length,1.0f/3.0f*width,-height,-length,width,-height,-length,//OHI
0,height,-length,width,-height,-length,17.0f/15.0f*width,-3.0f/5.0f*height,-length,//OIJ
0,height,-length,17.0f/15.0f*width,-3.0f/5.0f*height,-length,17.0f/15.0f*width,3.0f/5.0f*height,-length,//OJK
0,height,-length,17.0f/15.0f*width,3.0f/5.0f*height,-length,width,height,-length,//OKL
//侧面
-width,height,length,-width,height,-length,-17.0f/15.0f*width,3.0f/5.0f*height,-length,//A//A1//B1
-width,height,length,-17.0f/15.0f*width,3.0f/5.0f*height,-length,-17.0f/15.0f*width,3.0f/5.0f*height,length,//A//B1//B
-17.0f/15.0f*width,3.0f/5.0f*height,length,-17.0f/15.0f*width,3.0f/5.0f*height,-length,-17.0f/15.0f*width,-3.0f/5.0f*height,-length,//B//B1//C1
-17.0f/15.0f*width,3.0f/5.0f*height,length,-17.0f/15.0f*width,-3.0f/5.0f*height,-length,-17.0f/15.0f*width,-3.0f/5.0f*height,length,//B//C1//C
-17.0f/15.0f*width,-3.0f/5.0f*height,length,-17.0f/15.0f*width,-3.0f/5.0f*height,-length,-width,-height,-length,//CC1D1
-17.0f/15.0f*width,-3.0f/5.0f*height,length,-width,-height,-length,-width,-height,length,//C//D1//D
-width,-height,length,-width,-height,-length,-1.0f/3.0f*width,-height,-length,//D//D1//E1
-width,-height,length,-1.0f/3.0f*width,-height,-length,-1.0f/3.0f*width,-height,length,//D//E1//E\\
-1.0f/3.0f*width,-height,length,-1.0f/3.0f*width,-height,-length,-2.0f/15.0f*width,-2.0f/5.0f*height,-length,//E\\//E1//F1
-1.0f/3.0f*width,-height,length,-2.0f/15.0f*width,-2.0f/5.0f*height,-length,-2.0f/15.0f*width,-2.0f/5.0f*height,length,//E\\//F1//F
-2.0f/15.0f*width,-2.0f/5.0f*height,length,-2.0f/15.0f*width,-2.0f/5.0f*height,-length,2.0f/15.0f*width,-2.0f/5.0f*height,-length,//F//F1//G1
-2.0f/15.0f*width,-2.0f/5.0f*height,length,2.0f/15.0f*width,-2.0f/5.0f*height,-length,2.0f/15.0f*width,-2.0f/5.0f*height,length,//F//G1//G
2.0f/15.0f*width,-2.0f/5.0f*height,length,2.0f/15.0f*width,-2.0f/5.0f*height,-length,1.0f/3.0f*width,-height,-length,//G//G1//H1
2.0f/15.0f*width,-2.0f/5.0f*height,length,1.0f/3.0f*width,-height,-length,1.0f/3.0f*width,-height,length,//G//H1//H
1.0f/3.0f*width,-height,length,1.0f/3.0f*width,-height,-length,width,-height,-length,//H//H1//I1
1.0f/3.0f*width,-height,length,width,-height,-length,width,-height,length,//H//I1//I
width,-height,length,width,-height,-length,17.0f/15.0f*width,-3.0f/5.0f*height,-length,//I//I1//J1
width,-height,length,17.0f/15.0f*width,-3.0f/5.0f*height,-length,17.0f/15.0f*width,-3.0f/5.0f*height,length,//I//J1//J
17.0f/15.0f*width,-3.0f/5.0f*height,length,17.0f/15.0f*width,-3.0f/5.0f*height,-length,17.0f/15.0f*width,3.0f/5.0f*height,-length,//J//J1//K1
17.0f/15.0f*width,-3.0f/5.0f*height,length,17.0f/15.0f*width,3.0f/5.0f*height,-length,17.0f/15.0f*width,3.0f/5.0f*height,length,//J//K1//K
17.0f/15.0f*width,3.0f/5.0f*height,length,17.0f/15.0f*width,3.0f/5.0f*height,-length,width,height,-length,//K//K1//L1
17.0f/15.0f*width,3.0f/5.0f*height,length,width,height,-length,width,height,length,//K//L1//L
width,height,length,width,height,-length,0,height,-length,//L//L1//O1
width,height,length,0,height,-length,0,height,length,//L//o1//O
0,height,length,0,height,-length,0,height,-length,//oo1a1
0,height,length,0,height,-length,0,height,length,//oo1a
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为int型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//顶点纹理数据的初始化================begin============================
float textures[]=new float[]
{
//上表面
0.488f,0.0040f,0.051f,0.0080f,0.0f,0.051f,
0.488f,0.0040f,0.0f,0.051f,0.0f,0.203f,
0.488f,0.0040f,0.0f,0.203f,0.055f,0.23f,
0.488f,0.0040f,0.055f,0.23f,0.344f,0.223f,
0.488f,0.0040f,0.344f,0.223f,0.391f,0.168f,
0.488f,0.0040f,0.391f,0.168f,0.582f,0.164f,
0.488f,0.0040f,0.582f,0.164f,0.664f,0.211f,
0.488f,0.0040f,0.664f,0.211f,0.938f,0.203f,
0.488f,0.0040f,0.938f,0.203f,0.98f,0.164f,
0.488f,0.0040f,0.98f,0.164f,0.984f,0.059f,
0.488f,0.0040f,0.984f,0.059f,0.914f,0.0040f,
//下表面
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
//侧面
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
0.0040f,0.277f,0.0040f,0.391f,0.137f,0.352f,
};
//创建顶点纹理数据缓冲
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTextureBuffer= tbb.asFloatBuffer();//转换为Float型缓冲
mTextureBuffer.put(textures);//向缓冲区中放入顶点着色数据
mTextureBuffer.position(0);//设置缓冲区起始位置
}
//初始化着色器的initShader方法
public void initShader()
{
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点纹理坐标属性引用id
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//获取程序中总变换矩阵引用id
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId)
{
MatrixState.pushMatrix();
MatrixState.rotate(mAngleX, 1, 0, 0);
MatrixState.popMatrix();
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入顶点纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTextureBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制纹理矩形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
}
@@ -0,0 +1,205 @@
package com.bn.tankemodel;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import android.content.res.Resources;
import android.util.Log;
import com.bn.core.Normal;
public class MoXingJiaZai
{
//求两个向量的叉积
public static float[] getCrossProduct(float x1,float y1,float z1,float x2,float y2,float z2)
{
//求出两个矢量叉积矢量在XYZ轴的分量ABC
float A=y1*z2-y2*z1;
float B=z1*x2-z2*x1;
float C=x1*y2-x2*y1;
return new float[]{A,B,C};
}
//向量规格化
public static float[] vectorNormal(float[] vector)
{
//求向量的模
float module=(float)Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]+vector[2]*vector[2]);
return new float[]{vector[0]/module,vector[1]/module,vector[2]/module};
}
//从obj文件中加载携带顶点信息的物体,并自动计算每个顶点的平均法向量
public static Model loadFromFileVertexOnly
(String fname, Resources r,int mProgram)
{
//加载后物体的引用
Model lo=null;
//原始顶点坐标列表--直接从obj文件中加载
ArrayList<Float> alv=new ArrayList<Float>();
//顶点组装面索引列表--根据面的信息从文件中加载
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();
//结果顶点坐标列表--按面组织好
ArrayList<Float> alvResult=new ArrayList<Float>();
//平均前各个索引对应的点的法向量集合Map
//此HashMap的key为点的索引, value为点所在的各个面的法向量的集合
HashMap<Integer,HashSet<Normal>> hmn=new HashMap<Integer,HashSet<Normal>>();
//原始纹理坐标列表
ArrayList<Float> alt=new ArrayList<Float>();
//纹理坐标结果列表
ArrayList<Float> altResult=new ArrayList<Float>();
try
{
InputStream in=r.getAssets().open(fname);
InputStreamReader isr=new InputStreamReader(in);
BufferedReader br=new BufferedReader(isr);
String temps=null;
//扫面文件,根据行类型的不同执行不同的处理逻辑
while((temps=br.readLine())!=null)
{
//用空格分割行中的各个组成部分
String[] tempsa=temps.split("[ ]+");
if(tempsa[0].trim().equals("v"))
{//此行为顶点坐标
//若为顶点坐标行则提取出此顶点的XYZ坐标添加到原始顶点坐标列表中
alv.add(Float.parseFloat(tempsa[1]));
alv.add(Float.parseFloat(tempsa[2]));
alv.add(Float.parseFloat(tempsa[3]));
}
else if(tempsa[0].trim().equals("vt"))
{//此行为纹理坐标行
//若为纹理坐标行则提取ST坐标并添加进原始纹理坐标列表中
alt.add(Float.parseFloat(tempsa[1]));
alt.add(Float.parseFloat(tempsa[2]));
}
else if(tempsa[0].trim().equals("f"))
{//此行为三角形面
/*
*若为三角形面行则根据 组成面的顶点的索引从原始顶点坐标列表中
*提取相应的顶点坐标值添加到结果顶点坐标列表中,同时根据三个
*顶点的坐标计算出此面的法向量并添加到平均前各个索引对应的点
*的法向量集合组成的Map中
*/
int[] index=new int[3];//三个顶点索引值的数组
//计算第0个顶点的索引,并获取此顶点的XYZ三个坐标
index[0]=Integer.parseInt(tempsa[1].split("/")[0])-1;
float x0=alv.get(3*index[0]);
float y0=alv.get(3*index[0]+1);
float z0=alv.get(3*index[0]+2);
alvResult.add(x0);
alvResult.add(y0);
alvResult.add(z0);
//计算第1个顶点的索引,并获取此顶点的XYZ三个坐标
index[1]=Integer.parseInt(tempsa[2].split("/")[0])-1;
float x1=alv.get(3*index[1]);
float y1=alv.get(3*index[1]+1);
float z1=alv.get(3*index[1]+2);
alvResult.add(x1);
alvResult.add(y1);
alvResult.add(z1);
//计算第2个顶点的索引,并获取此顶点的XYZ三个坐标
index[2]=Integer.parseInt(tempsa[3].split("/")[0])-1;
float x2=alv.get(3*index[2]);
float y2=alv.get(3*index[2]+1);
float z2=alv.get(3*index[2]+2);
alvResult.add(x2);
alvResult.add(y2);
alvResult.add(z2);
//记录此面的顶点索引
alFaceIndex.add(index[0]);
alFaceIndex.add(index[1]);
alFaceIndex.add(index[2]);
//通过三角形面两个边向量0-1,0-2求叉积得到此面的法向量
//求0号点到1号点的向量
float vxa=x1-x0;
float vya=y1-y0;
float vza=z1-z0;
//求0号点到2号点的向量
float vxb=x2-x0;
float vyb=y2-y0;
float vzb=z2-z0;
//通过求两个向量的叉积计算法向量
float[] vNormal=getCrossProduct
(
vxa,vya,vza,vxb,vyb,vzb
);
for(int tempInxex:index)
{//记录每个索引点的法向量到平均前各个索引对应的点的法向量集合组成的Map中
//获取当前索引对应点的法向量集合
HashSet<Normal> hsn=hmn.get(tempInxex);
if(hsn==null)
{//若集合不存在则创建
hsn=new HashSet<Normal>();
}
//将此点的法向量添加到集合中
//由于Normal类重写了equals方法,因此同样的法向量不会重复出现在此点
//对应的法向量集合中
hsn.add(new Normal(vNormal[0],vNormal[1],vNormal[2]));
//将集合放进HsahMap中
hmn.put(tempInxex, hsn);
}
//将纹理坐标组织到结果纹理坐标列表中
//第0个顶点的纹理坐标
int indexTex=Integer.parseInt(tempsa[1].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
//第1个顶点的纹理坐标
indexTex=Integer.parseInt(tempsa[2].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
//第2个顶点的纹理坐标
indexTex=Integer.parseInt(tempsa[3].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
}
}
//生成顶点数组
int size=alvResult.size();
float[] vXYZ=new float[size];
for(int i=0;i<size;i++)
{
vXYZ[i]=alvResult.get(i);
}
//生成法向量数组
float[] nXYZ=new float[alFaceIndex.size()*3];
int c=0;
for(Integer i:alFaceIndex)
{
//根据当前点的索引从Map中取出一个法向量的集合
HashSet<Normal> hsn=hmn.get(i);
//求出平均法向量
float[] tn=Normal.getAverage(hsn);
//将计算出的平均法向量存放到法向量数组中
nXYZ[c++]=tn[0];
nXYZ[c++]=tn[1];
nXYZ[c++]=tn[2];
}
//生成纹理数组
size=altResult.size();
float[] tST=new float[size];
for(int i=0;i<size;i++)
{
if(i%2==1){
tST[i]=1-altResult.get(i);
}else{
tST[i]=altResult.get(i);
}
}
//创建3D物体对象
lo=new Model(r,vXYZ,tST,mProgram);
}
catch(Exception e)
{
Log.d("load error", "load error");
e.printStackTrace();
}
return lo;
}
}
@@ -0,0 +1,93 @@
package com.bn.tankemodel;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.content.res.Resources;
import android.opengl.GLES20;
import com.bn.core.MatrixState;
//加载后的物体——携带顶点信息,自动计算面平均法向量
public class Model
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用id
int maPositionHandle; //顶点位置属性引用id
int maTexCoorHandle; //顶点纹理坐标属性引用id
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
int vCount=0;
public Model(Resources r,float[] vertices,float texCoors[],int mProgram)
{
//初始化顶点数据的initVertexData方法
initVertexData(vertices,texCoors);
initShader(mProgram);
}
//初始化顶点数据的initVertexData方法
public void initVertexData(float[] vertices,float texCoors[])
{
//顶点坐标数据的初始化================begin============================
vCount=vertices.length/3;
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//顶点纹理坐标数据的初始化================begin============================
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoors.length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mTexCoorBuffer = tbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(texCoors);//向缓冲区中放入顶点纹理坐标数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
}
//调用初始化着色器的initShader方法
public void initShader(int mProgram)
{
this.mProgram=mProgram;
//获得顶点坐标数据的引用
maPositionHandle=GLES20.glGetAttribLocation(mProgram, "aPosition");
//顶点纹理坐标的引用id
maTexCoorHandle=GLES20.glGetAttribLocation(mProgram, "aTexCoor");
muMVPMatrixHandle=GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void drawSelf(int texId)
{
//使用某套指定的Shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入到Shader程序中
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//传入坐标数据
GLES20.glVertexAttribPointer
(
maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer
);
//传入纹理坐标数据
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//允许顶点位置数据数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制加载的物体
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
}
@@ -0,0 +1,254 @@
package com.bn.tankemodel;
import static com.bn.gameView.Constant.BUTTON_RADAR_BG_WIDTH;
import static com.bn.gameView.Constant.Lock_angle;
import static com.bn.gameView.Constant.Lock_tanke;
import static com.bn.gameView.Constant.MapArray;
import static com.bn.gameView.Constant.PLANE_X;
import static com.bn.gameView.Constant.PLANE_Y;
import static com.bn.gameView.Constant.PLANE_Z;
import static com.bn.gameView.Constant.TANK_MAX_DISTANCE;
import static com.bn.gameView.Constant.WIDTH_LALNDFORM;
import static com.bn.gameView.Constant.directionX;
import static com.bn.gameView.Constant.directionY;
import static com.bn.gameView.Constant.directionZ;
import static com.bn.gameView.Constant.isno_Lock;
import static com.bn.gameView.Constant.mapId;
import static com.bn.gameView.Constant.minimumdistance;
import static com.bn.gameView.Constant.nx;
import static com.bn.gameView.Constant.ny;
import static com.bn.gameView.Constant.nz;
import static com.bn.gameView.Constant.rotationAngle_Plane_Z;
import static com.bn.gameView.Constant.scalMark;
import static com.bn.gameView.Constant.tank_bomb_List;
import static com.bn.gameView.Constant.tank_ratio;
import static com.bn.gameView.GLGameView.cx;
import static com.bn.gameView.GLGameView.cz;
import android.opengl.GLES20;
import com.bn.commonObject.BallTextureByVertex;
import com.bn.commonObject.NumberForDraw;
import com.bn.commonObject.TextureRect;
import com.bn.core.MatrixState;
import com.bn.gameView.BombForControl;
import com.bn.gameView.GLGameView;
public class TanKe
{
Model tanke_body, tanke_barrel;//模型
private BallTextureByVertex bomb_ball;//炮弹球
GLGameView gv;
public float tx,ty,tz;
public float[] tank_position;//坦克的位置
public float barrel_bottom=16;//炮管底部的高度
public float[] barrel_bottom_position=new float[3];//坦克炮管底部的位置
public float barrel_length=30;//炮管的长度
int row;//所在行列
int col;
float tank_barrel_direction=0;//坦克炮管的方向角
float tank_barrel_elevation=0;//坦克炮管的仰角
public float[] bomb_position_init=new float[3];//坦克发射炮弹的初始位置
private float oldTime=0;//用于记录炮弹上次放射的时间
public NumberForDraw nm;//数字引用
public TextureRect backgroundRect;//背景
public float xue_scale=0.6f;//血缩放比例
public int blood=100;//坦克的生命值
int drawblood;
float yAnglexue;
public boolean this_isno_Lock=false;//自己是否被锁定,被锁定就绘制锁定矩形
public TextureRect mark_lock;//标记被锁定的矩形
public TextureRect mark_plane;//标记矩形
//标记军火库位置的颜色矩形位置
float arsenal_x,arsenal_y,arsenal_z;
public TanKe(GLGameView gv,BallTextureByVertex bomb_ball,Model tanke_body,Model tanke_barrel,float[] tank_position,int col,int row,
TextureRect backgroundRect,NumberForDraw nm,TextureRect mark_plane,TextureRect mark_lock
)
{
this.nm=nm;
this.backgroundRect=backgroundRect;
this.gv=gv;
this.bomb_ball=bomb_ball;//炮弹
this.tanke_body=tanke_body;
this.tanke_barrel=tanke_barrel;
this.tank_position=tank_position;//初始化坦克的位置
this.barrel_bottom_position[0]=tank_position[0];
this.barrel_bottom_position[1]=tank_position[1]+barrel_bottom;
this.barrel_bottom_position[2]=tank_position[2];
this.col=col;
this.row=row;
tx=tank_position[0];
ty=tank_position[1];
tz=tank_position[2];
this.mark_plane=mark_plane;
arsenal_x=-scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-tx)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
arsenal_y=scalMark*BUTTON_RADAR_BG_WIDTH*(MapArray[mapId].length*WIDTH_LALNDFORM/2-tz)/(MapArray[mapId].length*WIDTH_LALNDFORM/2);
this.mark_lock=mark_lock;
}
public void drawSelf(int texId,int ii,int jj,int rowR,int colR,
int backgroundRectId,int numberID,int locktexId
)
{
if(row<ii||row>rowR||col<jj||col>colR)
{
return;
}
drawblood=blood;
MatrixState.pushMatrix();
MatrixState.translate(tank_position[0], tank_position[1], tank_position[2]);
MatrixState.scale(tank_ratio, tank_ratio, tank_ratio);
tanke_body.drawSelf(texId);
MatrixState.translate(0, barrel_bottom, 0);
MatrixState.rotate(tank_barrel_direction, 0, 1, 0);
MatrixState.rotate(tank_barrel_elevation, 1, 0, 0);
tanke_barrel.drawSelf(texId);
MatrixState.popMatrix();
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
if(drawblood>=0)
{
MatrixState.pushMatrix();
MatrixState.translate(tank_position[0], tank_position[1]+70, tank_position[2]);
MatrixState.scale(xue_scale, xue_scale, xue_scale);
MatrixState.rotate(yAnglexue, 0,1, 0);
backgroundRect.bloodValue=drawblood*2-100+6;
backgroundRect.drawSelf(backgroundRectId);
MatrixState.popMatrix();
}
if(this_isno_Lock)
{
MatrixState.pushMatrix();//绘制锁定的
MatrixState.translate(tank_position[0], tank_position[1]+20, tank_position[2]);
MatrixState.rotate(yAnglexue, 0,1, 0);
MatrixState.rotate(rotationAngle_Plane_Z, 0,0, 1);
MatrixState.scale(tank_ratio, tank_ratio, tank_ratio);
mark_lock.drawSelf(locktexId);
MatrixState.popMatrix();
}
GLES20.glDisable(GLES20.GL_BLEND);
}
public void drawSelfMark(int texId)
{
MatrixState.pushMatrix();
MatrixState.translate(arsenal_x,arsenal_y,0);
mark_plane.drawSelf(texId);
MatrixState.popMatrix();
}
//这里计算标志板的朝向
public void calculateBillboardDirection()
{//根据摄像机位置计算焰火粒子面朝向
float currX_span=tx-cx;
float currZ_span=tz-cz;
if(currZ_span<0)
{
yAnglexue=(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}else if(currZ_span==0)
{
yAnglexue=currX_span>0?90:-90;
}
else
{
yAnglexue=180+(float)Math.toDegrees(Math.atan(currX_span/currZ_span));
}
if(isno_Lock)//如果已经有被锁定的目标了
{
this_isno_Lock=false;
return;
}
//计算其是否被锁定
float x1,y1,z1,x2,y2,z2;
x1=tx-PLANE_X;
y1=ty-PLANE_Y;
z1=tz-PLANE_Z;
float distance1=(float) Math.sqrt(x1*x1+y1*y1+z1*z1);
if(distance1>minimumdistance){//如果距离超出范围,或者已经有一个被锁定了,则自己不能被锁定
this_isno_Lock=false;
return;
}//计算飞机飞行的方向向量
x2=directionX;//-(float) (Math.cos(Math.toRadians(rotationAngle_Plane_X))*Math.sin(Math.toRadians(rotationAngle_Plane_Y)));
y2=directionY;//(float) (Math.sin(Math.toRadians(rotationAngle_Plane_X)));
z2=directionZ;//-(float) (Math.cos(Math.toRadians(rotationAngle_Plane_X))*Math.cos(Math.toRadians(rotationAngle_Plane_Y)));
float cosa=(float) Math.acos((x1*x2+y1*y2+z1*z2)/(distance1*1));
if(cosa<Lock_angle)
{
if(Lock_tanke!=null)
{
Lock_tanke.this_isno_Lock=false;
}
this.this_isno_Lock=true;
minimumdistance=distance1;//最小距离设置为该距离
nx=x1;ny=y1+20;nz=z1;//发射子弹方向向量
isno_Lock=true;//已经被锁定
Lock_tanke=this;//自己被锁定
}
else
{
this_isno_Lock=false;
}
}
//时时改变坦克炮管的角度
public void tank_go()
{
calculateBillboardDirection();//计算血纹理的朝向
//这里获取飞机的位置
float curr_planeX=PLANE_X;
float curr_planeY=PLANE_Y;
float curr_planeZ=PLANE_Z;
//计算当前高射炮的目标点和飞机之间的距离 这里是 平方
float curr_distance=(curr_planeX-barrel_bottom_position[0])*(curr_planeX-barrel_bottom_position[0])+
(curr_planeY-barrel_bottom_position[1])*(curr_planeY-barrel_bottom_position[1])+
(curr_planeZ-barrel_bottom_position[2])*(curr_planeZ-barrel_bottom_position[2]);
//如果超出高射炮的扫面范围,那么直接返回
if(curr_distance>TANK_MAX_DISTANCE*TANK_MAX_DISTANCE)
{
return;
}
//这里计算高度差
float curr_y_span=curr_planeY-barrel_bottom_position[1];
if(curr_y_span<=0)
{
return;//如果小于0,那么直接返回
}
//这里计算出距离的平方根
curr_distance=(float) Math.sqrt(curr_distance);
//这里计算高射炮的仰角和方位角
float curr_elevation=(float) Math.toDegrees( Math.asin(curr_y_span/curr_distance));
tank_barrel_elevation=curr_elevation;//仰角
//根据反正切计算方位角
float curr_x_span=curr_planeX-barrel_bottom_position[0];
float curr_z_span=curr_planeZ-barrel_bottom_position[2];
float curr_direction=(float)Math.toDegrees(Math.atan(curr_x_span/curr_z_span));
if(curr_x_span==0&&curr_z_span==0)
{
tank_barrel_direction=curr_direction=0;
}
else if(curr_z_span>=0)
{
tank_barrel_direction=curr_direction=curr_direction+180;
}
else
{
tank_barrel_direction=curr_direction;
}
//---------------如何可以发炮
//这里计算高射炮炮弹的初始位置
if(System.nanoTime()-oldTime>2000000000)//每隔2秒发射一次炮弹
{
bomb_position_init[0]=(float) (barrel_bottom_position[0]-Math.cos(Math.toRadians(tank_barrel_elevation))*
Math.sin(Math.toRadians(tank_barrel_direction))*barrel_length);//X
bomb_position_init[1]=(float) (barrel_bottom_position[1]+Math.sin(Math.toRadians(tank_barrel_elevation))*
barrel_length);//Y
bomb_position_init[2]=(float) (barrel_bottom_position[2]-Math.cos(Math.toRadians(tank_barrel_elevation))*
Math.cos(Math.toRadians(tank_barrel_direction))*barrel_length);//Z
//发射炮弹
tank_bomb_List.add(new BombForControl(gv,bomb_ball,bomb_position_init,tank_barrel_elevation,
tank_barrel_direction));
gv.activity.playSound(1,0);
oldTime=System.nanoTime();
}
}
}