文件名: Android studio赛艇游戏源代码_015.txt
创建时间: 2025-12-31 09:57:14
文件序号: 15/15
原始文件: Android studio赛艇游戏源代码.txt

        vCount=6;
        float vertices[]=new float[]
        {
        	-width,height,0,
        	-width,-height,0,
        	width,-height,0,
        	
        	width,-height,0,
        	width,height,0,
        	-width,height,0
        };
		
        //创建顶点坐标数据缓冲
        //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 texCoor[]=new float[]//顶点颜色值数组,每个顶点4个色彩值RGBA
        {
        		0,0, 0,1, 1,1,
        		1,1, 1,0, 0,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(int mProgramIn)
    {
        mProgram = mProgramIn;
        //获取程序中顶点位置属性引用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); 
    }
}


==========XCSurfaceView.java】 ==========
package com.bn.st.xc;

import java.io.IOException;
import java.io.InputStream;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

//import com.bn.R;
import com.bn.clp.R;
import com.bn.clp.BoatInfo;
import com.bn.core.MatrixState;
import com.bn.st.d2.MyActivity;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.view.MotionEvent;
import static com.bn.st.xc.Constant.*;

public class XCSurfaceView extends GLSurfaceView 
{
	final float TOUCH_SCALE_FACTOR = 180.0f/SCREEN_WIDTH;//角度缩放比例
    SceneRenderer mRenderer;//场景渲染器
    float mPreviousX;//上次的触控位置X坐标
    float mPreviousY;//上次的触控位置Y坐标

    int tex_index=0;//广告纹理id索引   
    
    int textureUpId;//系统分配的游戏前进虚拟按钮纹理id
    int textureDownId;//系统分配的游戏后退虚拟按钮纹理id
    int texWallId[]=new int[3];  //广告墙纹理Id数组
    int texFloorId;//地面纹理id
    
    //船的纹理id数组
    int[] heroBoatTexId;
    int[] quickBoatTexId;
    int[] slowBoatTexId;
    
    //船的纹理图片数组
    static Bitmap[] heroBoatTexBitmap;
    static Bitmap[] quickBoatTexBitmap;
    static Bitmap[] slowBoatTexBitmap;
	
    static Bitmap bmUp;//前进虚拟按钮
    static Bitmap bmDown;//后退虚拟按钮
    static Bitmap[] bmaWall=new Bitmap[3];//广告墙纹理数组
    static Bitmap bmFloor;//地面
    
	private float yAngle=0;//绕Y轴转动角
	private float xAngle=20;//仰角
	//摄像机坐标
	private float cx;
	private float cz;
	private float cy;
	//目标点坐标
	private float tx=0;
	private float tz=0;
	private float ty=-HOUSE_GAO/3;
	//摄像机头顶指向
	private float upX=0;
	private float upY=1;
	private float upZ=0;
	//----创建物体----------------------
	HouseForDraw house;//房间
	DisplayStation displayStation;//展台
	Boat boat[]=new Boat[3];//船
	TextureRect button;//按钮
	LoadedObjectVertexNormalXC rome;//创建罗马柱子
	
	private float half_width_button=0.15f;
//	private float half_height_button=0.1f;
	private float offset_X_Button1=-0.7f;
	private float offset_Y_Button1=-0.8f;
	private float offset_X_Button2=0.7f;
	private float offset_Y_Button2=-0.8f;
	//按钮的范围
	private float[] button1;
	private float[] button2;
	
	public boolean flagForThread=true;//线程标志
	
	public int index_boat=0;//船的索引
	private float ratio;//绘制投影矩阵缩放比例
	
	//--------测试惯性---------------
	private boolean flag_go;//允许惯性标志位 
	final int countGoStepInitValue=35;
	private int countGoStep=0;
	private float acceleratedVelocity=0.06f;
	private float ori_angle_speed=7;//初始角速度
	private float curr_angle_speed;//当前角速度
	private boolean isMoved;//判断是否移动过
	//---------纹理墙墙上的广告---------------
	public boolean flag_display=true;//广告标志位
	public XCSurfaceView(Context context)
	{
        super(context);
        this.setEGLContextClientVersion(2); //设置使用OPENGL ES2.0
        mRenderer = new SceneRenderer();	//创建场景渲染器
        setRenderer(mRenderer);				//设置渲染器		        
        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染   
        this.setKeepScreenOn(true);
        cx=(float)(tx+Math.cos(Math.toRadians(xAngle))*Math.sin(Math.toRadians(yAngle))*XC_DISTANCE);//摄像机x坐标 
        cz=(float)(tz+Math.cos(Math.toRadians(xAngle))*Math.cos(Math.toRadians(yAngle))*XC_DISTANCE);//摄像机z坐标 
        cy=(float)(ty+Math.sin(Math.toRadians(xAngle))*XC_DISTANCE);//摄像机y坐标 
    }
	//触摸事件回调方法
	@Override 
    public boolean onTouchEvent(MotionEvent e) 
	{
        float y = e.getY();//得到按下的XY坐标
        float x = e.getX();
        float domain_span=5;
        switch (e.getAction())
        {
        case MotionEvent.ACTION_MOVE:
            float dx = x - mPreviousX;//计算触控笔X位移
			float dy = y-  mPreviousY;//
        	yAngle -= dx * TOUCH_SCALE_FACTOR;//
        	xAngle -= dy * TOUCH_SCALE_FACTOR/2.0f;//仰角改变
        	if(xAngle>45)//仰角的最大值
        	{
        		xAngle=45;
        	}
        	if(xAngle<10){//仰角的最小值
        		xAngle=10;
        	}

            if(Math.abs(dx)>domain_span)//确定一个阈值
            {
	            isMoved=true;//表示当前移动过
	            //设置当前角速度
	            curr_angle_speed=ori_angle_speed*(-dx/SCREEN_WIDTH);
	            if(dx>20||dx<-20)
	            {
	            	if(curr_angle_speed>0)
		            {
		            	curr_angle_speed=curr_angle_speed+ori_angle_speed;
		            }  
		            else
		            {
		            	curr_angle_speed=curr_angle_speed-ori_angle_speed;
		            }
	            }
	            
	            //设置加速度大小
	            acceleratedVelocity=0.03f;
	            //若当前角速度大于零则加速度置为负
	            if(curr_angle_speed>0)
	            {
	            	acceleratedVelocity=-0.03f;
	            }
            }
            cx=(float)(tx+Math.cos(Math.toRadians(xAngle))*Math.sin(Math.toRadians(yAngle))*XC_DISTANCE);//摄像机x坐标 
            cz=(float)(tz+Math.cos(Math.toRadians(xAngle))*Math.cos(Math.toRadians(yAngle))*XC_DISTANCE);//摄像机z坐标 
            cy=(float)(ty+Math.sin(Math.toRadians(xAngle))*XC_DISTANCE);//摄像机y坐标
            break;
            
        case MotionEvent.ACTION_DOWN :
        	flag_go=false;
        	if(x>button1[0]&&x<button1[1]&&y>button1[2]&&y<button1[3])
        	{
        		index_boat=(index_boat-1+3)%3;
        	}
        	if(x>button2[0]&&x<button2[1]&&y>button2[2]&&y<button2[3])
        	{
        		index_boat=(index_boat+1)%3;
        	}
        	BoatInfo.cuttBoatIndex=index_boat;
        	break;
        case MotionEvent.ACTION_UP: 
        	if(isMoved)
        	{
        		flag_go=true;
        		countGoStep=countGoStepInitValue;
        		isMoved=false;
        	}
        	break;
        }
        mPreviousX = x;//记录触控笔位置   
        mPreviousY=y;
        cx=(float)(tx+Math.cos(Math.toRadians(xAngle))*Math.sin(Math.toRadians(yAngle))*XC_DISTANCE);//摄像机x坐标 
        cz=(float)(tz+Math.cos(Math.toRadians(xAngle))*Math.cos(Math.toRadians(yAngle))*XC_DISTANCE);//摄像机z坐标 
        cy=(float)(ty+Math.sin(Math.toRadians(xAngle))*XC_DISTANCE);//摄像机y坐标
        return true;
    }
	
	//船部件LoadedObjectVertexNormal列表
	static LoadedObjectVertexTexXC[][] parts=new LoadedObjectVertexTexXC[3][];
	static 
	{
		parts[0]=new LoadedObjectVertexTexXC[BoatInfo.boatPartNames[0].length];
		parts[1]=new LoadedObjectVertexTexXC[BoatInfo.boatPartNames[1].length];
		parts[2]=new LoadedObjectVertexTexXC[BoatInfo.boatPartNames[2].length];
	}
	
	static LoadedObjectVertexNormalXC romeData;
	
	public static void loadVertexFromObj(Resources r)
	{
		romeData=LoadUtilXC.loadFromFileVertexOnly("rome.obj",r, 1f, 1f, 1f);
		
		for(int j=0;j<BoatInfo.boatPartNames.length;j++)
		{
			for(int i=0;i<BoatInfo.boatPartNames[j].length;i++)  
			{  
				parts[j][i]=LoadUtilTexXC.loadFromFileVertexOnly
				(
					BoatInfo.boatPartNames[j][i], 
					r,
					ShaderManager.getCommTextureShaderProgram()
			     );			
			}
		}
	}
	
	private class SceneRenderer implements GLSurfaceView.Renderer 
    {
    	//long olds;
    	//long currs;
        public void onDrawFrame(GL10 gl) 
        { 
        	//currs=System.nanoTime();			
			//System.out.println(1000000000.0/(currs-olds)+"FPS");
			//olds=currs;
        	 
        	//清除深度缓冲与颜色缓冲
            GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); 
            MatrixState.setProjectFrustum(-ratio, ratio, -1, 1, 2.5f, 1000);           
            MatrixState.setCamera(cx,cy,cz,tx,ty,tz,upX,upY,upZ);
            MatrixState.copyMVMatrix();
            //初始化光源位置
            MatrixState.setLightLocation(cx, cy+5, cz+3);            
            //--------------------------绘制船在墙壁上的倒影-------------------------------------------            
            drawBoatMirrorOnWall();
           
            //在画透明墙
            GLES20.glEnable(GLES20.GL_BLEND);//开启混合
            GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
            house.drawTransparentWall();
            GLES20.glDisable(GLES20.GL_BLEND); //关闭混合
            
            house.drawFloor(texFloorId);//绘制地板
            //绘制广告墙
            house.drawTexWall(texWallId,tex_index);
            
            //--------------------------绘制船在展台上的倒影-------------------------------------------
            //绘制展台的不透明的圆柱
            MatrixState.pushMatrix();
            MatrixState.translate(0, -Constant.HOUSE_GAO/2, 0);
            displayStation.drawSelfCylinder();
            MatrixState.popMatrix();
            
            //绘制船在展台上的倒影
            MatrixState.pushMatrix();
            drawBoatShadow();
            MatrixState.popMatrix(); 
            
            //绘制透明圆面,开启混合
            GLES20.glEnable(GLES20.GL_BLEND);//开启混合
            GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);//设置混合因子
            displayStation.drawTransparentCircle();
            GLES20.glDisable(GLES20.GL_BLEND); //关闭混合            
            
            //绘制真实船
            drawBoat();
            //绘制柱子
            drawRomeColumn();
            //绘制上一个下一个按钮
            drawButton();
        }  
        public void onSurfaceChanged(GL10 gl, int width, int height)
        {
            //设置视窗大小及位置 
        	GLES20.glViewport(0, 0, width, height); 
        	//计算GLSurfaceView的宽高比
            ratio = (float) width / height;            
            virtualButton();
            new Thread()
            {
				@Override
            	public void run()
            	{
            		while(flagForThread)
            		{
            			try 
            			{
            				//这里进行惯性测试
            				if(flag_go)//如果允许惯性
            				{
            					countGoStep--;
            					if(countGoStep<=0)
            					{
            						curr_angle_speed=curr_angle_speed+acceleratedVelocity;//计算当前角速度
            					}
            					
            					if(Math.abs(curr_angle_speed)>0.1f)
            					{
            						yAngle=yAngle+curr_angle_speed;
                					cx=(float)(tx+Math.cos(Math.toRadians(xAngle))*Math.sin(Math.toRadians(yAngle))*XC_DISTANCE);//摄像机x坐标 
                				    cz=(float)(tz+Math.cos(Math.toRadians(xAngle))*Math.cos(Math.toRadians(yAngle))*XC_DISTANCE);//摄像机z坐标 
                				    cy=(float)(ty+Math.sin(Math.toRadians(xAngle))*XC_DISTANCE);//摄像机y坐标 
            					}
            					else
            					{
            						curr_angle_speed=0;
            						flag_go=false;
            					}
            				}
							Thread.sleep(10);
						}
            			catch (InterruptedException e)
            			{
							e.printStackTrace();
						}
            		}
            	}
            }.start();
        }
        
        
        public void onSurfaceCreated(GL10 gl, EGLConfig config) 
        {	    
        	synchronized(MyActivity.boatInitLock)
        	{        		
            	ShaderManager.compileShaderReal();            	
            	textureUpId=initTextureFromBitmap(bmUp);//上按钮
                textureDownId=initTextureFromBitmap(bmDown);//下按钮
                texWallId[0]=initTextureFromBitmap(bmaWall[0]);//广告纹理图1    
                texWallId[1]=initTextureFromBitmap(bmaWall[1]);//广告纹理图2
                texWallId[2]=initTextureFromBitmap(bmaWall[2]);//广告纹理图3
                texFloorId=initTextureFromBitmap(bmFloor);//地面纹理图3   
                
                heroBoatTexId=new int[heroBoatTexBitmap.length];
                quickBoatTexId=new int[quickBoatTexBitmap.length];
                slowBoatTexId=new int[slowBoatTexBitmap.length];
                
                for(int i=0;i<heroBoatTexBitmap.length;i++)
                {
                	heroBoatTexId[i]=initTextureFromBitmap(heroBoatTexBitmap[i]);
                }
                
                for(int i=0;i<quickBoatTexBitmap.length;i++)
                {
                	quickBoatTexId[i]=initTextureFromBitmap(quickBoatTexBitmap[i]);
                }
                
                for(int i=0;i<slowBoatTexBitmap.length;i++)
                {
                	slowBoatTexId[i]=initTextureFromBitmap(slowBoatTexBitmap[i]);
                }
            	
                //设置屏幕背景色RGBA
                GLES20.glClearColor(1f,1f,1f, 1.0f);
                                
                //立体物体==========================================================
                house=new HouseForDraw();//创建房间
                displayStation=new DisplayStation(RADIUS_DISPLAY, LENGTH_DISPLAY);//创建展台
                boat[0]=new Boat(parts[0],XCSurfaceView.this);//创建船只ltf
                boat[1]=new Boat(parts[1],XCSurfaceView.this);//创建船只cjg
                boat[2]=new Boat(parts[2],XCSurfaceView.this);//创建船只pjh
            	button=new TextureRect(ShaderManager.getCommTextureShaderProgram(), half_width_button, XC_Self_Adapter_Data_TRASLATE[com.bn.clp.Constant.screenId][0]);//绘制相关按钮
            	
             	//创建罗马柱对象
            	romeData.initShader(ShaderManager.getColorshaderProgram());
            	rome=romeData;
            	//开启背面剪裁   
                GLES20.glEnable(GLES20.GL_CULL_FACE);
                //打开深度检测
                GLES20.glEnable(GLES20.GL_DEPTH_TEST);
                //打开抖动
                GLES20.glEnable(GLES20.GL_DITHER);
                MatrixState.setInitStack();
                //--------------------------绘制纹理墙------------------------------------------------
    	          new Thread()
    	          {
    	          	@Override
    	          	public void run()
    	          	{
    	          		while(flag_display)
    	          		{
    	          			tex_index=(tex_index+1)%texWallId.length;//每隔两秒换一幅纹理图
    	          			
    	        			try
    	              		{
    	                          Thread.sleep(2000);
    	              		}
    	              		catch(InterruptedException e)
    	              		{
    	              			e.printStackTrace();
    	              		}
    	          		}
    	          	}
    	          }.start();
              //--------------------------绘制纹理墙------------------------------------------------
        	}
        }
        //绘制柱子
        public void drawRomeColumn()
        {
        	float ratio_column=0.55f;
        	float column_height=-18;
        	float adjust=3f;//调整值
           
            //绘制第一个柱子
            MatrixState.pushMatrix();
            MatrixState.rotate(30, 0, 1, 0);
            MatrixState.translate( 0,column_height, -WALL_WIDHT*2+adjust);
            MatrixState.scale(ratio_column, ratio_column, ratio_column);            
            rome.drawSelf(1.0f);
            MatrixState.popMatrix();
            
            //逆时针绘制第二根柱子,此时为正方向  
            MatrixState.pushMatrix();
            MatrixState.rotate(90, 0, 1, 0);
            MatrixState.translate( 0,column_height, -WALL_WIDHT*2+adjust);
            MatrixState.scale(ratio_column, ratio_column, ratio_column);
            rome.drawSelf(1.0f);
            MatrixState.popMatrix();
            
            //逆时针绘制第三根柱子,此时为正方向
            MatrixState.pushMatrix();
            MatrixState.rotate(150, 0, 1, 0);
            MatrixState.translate( 0,column_height, -WALL_WIDHT*2+adjust);
            MatrixState.scale(ratio_column, ratio_column, ratio_column);
            rome.drawSelf(1.0f);
            MatrixState.popMatrix();
            
            //逆时针绘制第四根柱子,此时为正方向
            MatrixState.pushMatrix();
            MatrixState.rotate(210, 0, 1, 0);  
            MatrixState.translate( 0,column_height, -WALL_WIDHT*2+adjust);
            MatrixState.scale(ratio_column, ratio_column, ratio_column);
            rome.drawSelf(1.0f);
            MatrixState.popMatrix();
            
            //逆时针绘制第五根柱子,此时为正方向
            MatrixState.pushMatrix();
            MatrixState.rotate(270, 0, 1, 0);
            MatrixState.translate( 0,column_height, -WALL_WIDHT*2+adjust);
            MatrixState.scale(ratio_column, ratio_column, ratio_column);
            rome.drawSelf(1.0f);
            MatrixState.popMatrix();
            
            //逆时针绘制第六根柱子,此时为正方向
            MatrixState.pushMatrix();
            MatrixState.rotate(330, 0, 1, 0);
            MatrixState.translate( 0,column_height, -WALL_WIDHT*2+adjust);
            MatrixState.scale(ratio_column, ratio_column, ratio_column);
            rome.drawSelf(1.0f);
            MatrixState.popMatrix();
        }

        //绘制船的方法
        public void drawBoat()
        {
        	 MatrixState.pushMatrix();
             switch(index_boat) 
             {  
             case 0://腾飞的船   
                  MatrixState.translate(0, -10f, 0);             	  
                  MatrixState.scale(RATIO_BOAT, RATIO_BOAT, RATIO_BOAT);
                  boat[0].drawSelf(heroBoatTexId);  
             	break;   
             case 1://大广的船  
            	 MatrixState.translate(0, -10f, 0);
                  MatrixState.scale(RATIO_BOAT, RATIO_BOAT, RATIO_BOAT);
                  boat[1].drawSelf(quickBoatTexId);
             	break;
             case 2://彭彭的船
             	  MatrixState.translate(0, -10f, 0);             	  
                  MatrixState.scale(RATIO_BOAT, RATIO_BOAT, RATIO_BOAT);
                  boat[2].drawSelf(slowBoatTexId);
             	break;
             }
             MatrixState.popMatrix();
        }
        
        //绘制船的倒影的方法
        public void drawBoatShadow()
        {
			//关闭背面剪裁
            GLES20.glDisable(GLES20.GL_CULL_FACE);
            MatrixState.pushMatrix();   
			switch(index_boat) 
            {  
            case 0://腾飞的船  
                 MatrixState.translate(-1f, -14f, 0); 
                 MatrixState.rotate(180, 0, 0, 1);
                 MatrixState.scale(RATIO_BOAT, RATIO_BOAT, RATIO_BOAT);
                 boat[0].drawSelf(heroBoatTexId);  
            	break;   
            case 1://大广的船  
           	 	MatrixState.translate(0.6f, -14f, 0);
           	 	MatrixState.rotate(180, 0, 0, 1);
                MatrixState.scale(RATIO_BOAT, RATIO_BOAT, RATIO_BOAT);
                boat[1].drawSelf(quickBoatTexId);
            	break;
            case 2://彭彭的船
            	MatrixState.translate(0, -14f, 0); 
            	MatrixState.rotate(180, 0, 0, 1);
                MatrixState.scale(RATIO_BOAT, RATIO_BOAT, RATIO_BOAT);
                boat[2].drawSelf(slowBoatTexId);
            	break;
            }
            MatrixState.popMatrix();
            //打开背面剪裁
            GLES20.glEnable(GLES20.GL_CULL_FACE);
        }
        //绘制船在墙中的镜像
        public void drawBoatMirrorOnWall()
        {
        	final float ydistance=6f;
        	final float zdistance=-43f;
        	int k=(int) Math.abs(yAngle)/360+2;
        	float yAngleTemp=(yAngle+360*k)%360;
        	final int span=68;
        	//在第一面墙        	
        	if(yAngleTemp<=span&&yAngleTemp>=0||yAngleTemp>=360-span&&yAngleTemp<=360)
        	{
        		MatrixState.pushMatrix();
            	MatrixState.translate(0, ydistance, zdistance);
            	MatrixState.rotate(180, 0, 1, 0);
            	MatrixState.rotate(-15, 1, 0, 0);
            	drawBoat();
            	MatrixState.popMatrix();   
        	}  
        	     	
        	//逆时针在第二面墙画镜像========================?
        	int bzAngle;
        	
        	//逆时针在第三个墙面镜像  
        	bzAngle=120;
        	if(yAngleTemp>bzAngle-span&&yAngleTemp<bzAngle+span)
        	{
		    	MatrixState.pushMatrix();
		    	MatrixState.rotate(120, 0, 1, 0);
		    	MatrixState.translate(0, ydistance, zdistance);
		    	MatrixState.rotate(-90, 0, 1, 0);
		    	MatrixState.rotate(-15, 0, 0, 1);
		    	drawBoat();
		    	MatrixState.popMatrix();    
        	}
        	//逆时针第五个面
        	bzAngle=240;
        	if(yAngleTemp>bzAngle-span&&yAngleTemp<bzAngle+span)
        	{
	        	MatrixState.pushMatrix();
	        	MatrixState.rotate(240, 0, 1, 0);
	        	MatrixState.translate(0, ydistance, zdistance);
	        	MatrixState.rotate(90, 0, 1, 0);
	        	MatrixState.rotate(15, 0, 0, 1);
	        	drawBoat();
	        	MatrixState.popMatrix();
        	}
        }       
     
        //绘制相关按钮
        public void drawButton()
        {
        	//设置正交矩阵
        	MatrixState.setProjectOrtho(-1,1,-1,1,1,100);
        	//设置摄像机
        	MatrixState.setCamera(0, 0, 0, 0, 0,-1, 0, 1, 0);
        	MatrixState.copyMVMatrix();
        	 //开启混合
            GLES20.glEnable(GLES20.GL_BLEND);  
            //设置混合因子
            GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
        	MatrixState.pushMatrix();
        	MatrixState.translate(-0.7f, -0.8f, -1);
        	button.drawSelf(textureUpId);//绘制后移按钮
            MatrixState.popMatrix();
            MatrixState.pushMatrix();
            MatrixState.translate(0.7f, -0.8f, -1);
            button.drawSelf(textureDownId);//绘制后移按钮
            MatrixState.popMatrix();
            //关闭混合
            GLES20.glDisable(GLES20.GL_BLEND);
        }
    }
	//虚拟按钮的监听方法
	public void virtualButton()
	{
		//按钮1左边所占的比例
		float leftEdge=(float)(1-half_width_button+offset_X_Button1)/2*SCREEN_WIDTH;
		float rightEdge=(float)(1+half_width_button+offset_X_Button1)/2*SCREEN_WIDTH;
		float topEdge=(float)(1-XC_Self_Adapter_Data_TRASLATE[com.bn.clp.Constant.screenId][0]-offset_Y_Button1)/2*SCREEN_HEIGHT;
		float bottomEdge=(float)(1+XC_Self_Adapter_Data_TRASLATE[com.bn.clp.Constant.screenId][0]-offset_Y_Button1)/2*SCREEN_HEIGHT;
		button1=new float[]{leftEdge,rightEdge,topEdge,bottomEdge};
		//按钮2左边所占的比例
		leftEdge=(float)(1-half_width_button+offset_X_Button2)/2*SCREEN_WIDTH;
		rightEdge=(float)(1+half_width_button+offset_X_Button2)/2*SCREEN_WIDTH;
		topEdge=(float)(1-XC_Self_Adapter_Data_TRASLATE[com.bn.clp.Constant.screenId][0]-offset_Y_Button2)/2*SCREEN_HEIGHT;
		bottomEdge=(float)(1+XC_Self_Adapter_Data_TRASLATE[com.bn.clp.Constant.screenId][0]-offset_Y_Button2)/2*SCREEN_HEIGHT;
		button2=new float[]{leftEdge,rightEdge,topEdge,bottomEdge};
		
		
	}
	public int initTextureFromBitmap(Bitmap bitmapTmp)//textureId
	{
		//生成纹理ID
		int[] textures = new int[1];
		GLES20.glGenTextures
		(
				1,          //产生的纹理id的数量
				textures,   //纹理id的数组
				0           //偏移量
		);    
		int textureId=textures[0];    
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_NEAREST);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_REPEAT);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT);    
        
        //实际加载纹理
        GLUtils.texImage2D
        (
        		GLES20.GL_TEXTURE_2D,   //纹理类型,在OpenGL ES中必须为GL10.GL_TEXTURE_2D
        		0, 					  //纹理的层次,0表示基本图像层,可以理解为直接贴图
        		bitmapTmp, 			  //纹理图像
        		0					  //纹理边框尺寸
        );
        
        return textureId;
	}
	
   	public static void loadWelcomeBitmap(Resources r)
	{
		  InputStream is=null;
          try  
          {
        	  is= r.openRawResource(R.drawable.up);	
        	  bmUp=BitmapFactory.decodeStream(is);
        	  is= r.openRawResource(R.drawable.down);	
        	  bmDown=BitmapFactory.decodeStream(is);
        	  is= r.openRawResource(R.drawable.gg1);	
        	  bmaWall[0]=BitmapFactory.decodeStream(is);
        	  is= r.openRawResource(R.drawable.gg2);	
        	  bmaWall[1]=BitmapFactory.decodeStream(is);
        	  is= r.openRawResource(R.drawable.gg3);	
        	  bmaWall[2]=BitmapFactory.decodeStream(is);
        	  is= r.openRawResource(R.drawable.floor);	
        	  bmFloor=BitmapFactory.decodeStream(is); 

    	      heroBoatTexBitmap=new Bitmap[parts[0].length];
        	  quickBoatTexBitmap=new Bitmap[parts[1].length];
        	  slowBoatTexBitmap=new Bitmap[parts[2].length];  
        	  
        	  for(int i=0;i<parts[0].length;i++)
        	  {
        		  is= r.openRawResource(BoatInfo.boatTexIdName[0][i]);	
        		  heroBoatTexBitmap[i]=BitmapFactory.decodeStream(is);
        	  }
        	  
        	  for(int i=0;i<parts[1].length;i++)
        	  {
        		  is= r.openRawResource(BoatInfo.boatTexIdName[1][i]);	
        		  quickBoatTexBitmap[i]=BitmapFactory.decodeStream(is);
        	  }
        	  
        	  for(int i=0;i<parts[2].length;i++)
        	  {
        		  is= r.openRawResource(BoatInfo.boatTexIdName[2][i]);	
        		  slowBoatTexBitmap[i]=BitmapFactory.decodeStream(is);
        	  }
          } 
	      finally 
	      {
            try 
            {
                is.close();
            } 
            catch(IOException e) 
            {
                e.printStackTrace();
            }
	      }	      
	}   
}










d2\app\src\main\res\layout

========== 【activity_main.xml】 ==========
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

========== 【breakrecordornot.xml】 ==========
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/FrameLayout01" 
   android:layout_width="fill_parent" 
   android:layout_height="fill_parent"   >   
	<LinearLayout 
		android:orientation="vertical"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent" 
		android:paddingLeft="10dip"
		android:paddingRight="10dip"
		android:paddingTop="10dip"
		android:paddingBottom="10dip"
		android:gravity="center">
		<LinearLayout
			android:layout_width="fill_parent"
			android:layout_height="wrap_content">
			<TextView
				android:id="@+id/tview"
				android:layout_width="fill_parent"   
				android:layout_height="wrap_content"
				android:text="恭喜您,成功的突破记录!"
				android:textSize="18dip"
				android:textColor="#ffffff"
				android:paddingLeft="10dip"/>
		</LinearLayout> 
		<LinearLayout 
				android:orientation="horizontal"
				android:layout_width="fill_parent"
				android:layout_height="fill_parent"
				android:gravity="center">  
			<Button   
				android:text="确定" 
				android:id="@+id/ok_button" 
				android:layout_width="75dip" 
				android:layout_height="40dip"
				android:textSize="18dip"
				android:gravity="center"/> 
		</LinearLayout> 	
	</LinearLayout>
</LinearLayout>

========== 【checkversion.xml】 ==========
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/FrameLayout01" 
   android:layout_width="fill_parent" 
   android:layout_height="fill_parent"   >   
<LinearLayout 
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent" 
	android:paddingLeft="10dip"
	android:paddingRight="10dip"
	android:paddingTop="10dip"
	android:paddingBottom="10dip"
	android:gravity="center">
<LinearLayout
	android:layout_width="fill_parent"
	android:layout_height="wrap_content">
	<TextView   
		android:layout_width="fill_parent"   
		android:layout_height="wrap_content"
		android:text="对不起,由于您的手机没有支持OpenGL ES 2.0的显卡,不能进入游戏。"
		android:textSize="18dip"
		android:textColor="#ffffff"
		android:paddingLeft="10dip"/>
</LinearLayout> 
<LinearLayout 
		android:orientation="horizontal"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:gravity="center">  
	<Button   
		android:text="确定" 
		android:id="@+id/ok_button" 
		android:layout_width="75dip" 
		android:layout_height="40dip"
		android:textSize="18dip"
		android:gravity="center"/> 
</LinearLayout> 	
</LinearLayout>
</LinearLayout>

========== 【currandroidversion.xml】 ==========
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/FrameLayout01" 
   android:layout_width="fill_parent" 
   android:layout_height="fill_parent"   >   
<LinearLayout 
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent" 
	android:paddingLeft="10dip"
	android:paddingRight="10dip"
	android:paddingTop="10dip"
	android:paddingBottom="10dip"
	android:gravity="center">
<LinearLayout
	android:layout_width="fill_parent"
	android:layout_height="wrap_content">
	<TextView   
		android:layout_width="fill_parent"   
		android:layout_height="wrap_content" 
		android:text="对不起,由于您手机的当前系统低于2.2,不能进入游戏。"
		android:textSize="18dip"
		android:textColor="#ffffff"
		android:paddingLeft="10dip"/>
</LinearLayout> 
<LinearLayout 
		android:orientation="horizontal"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:gravity="center">  
	<Button   
		android:text="确定" 
		android:id="@+id/ok" 
		android:layout_width="75dip" 
		android:layout_height="40dip"
		android:textSize="18dip"
		android:gravity="center"/> 
</LinearLayout> 	
</LinearLayout>
</LinearLayout>

========== 【rankingdialog.xml】 ==========
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/FrameLayout01" 
   android:layout_width="fill_parent" 
   android:layout_height="fill_parent"   >   
	<LinearLayout 
		android:orientation="vertical"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent" 
		android:paddingLeft="10dip"
		android:paddingRight="10dip"
		android:paddingTop="10dip"
		android:paddingBottom="10dip"
		android:gravity="center">
		<LinearLayout
			android:layout_width="fill_parent"
			android:layout_height="wrap_content">
			<TextView
				android:id="@+id/tview"
				android:layout_width="fill_parent"   
				android:layout_height="wrap_content"
				android:text=""
				android:textSize="18dip"
				android:textColor="#ffffff"
				android:paddingLeft="10dip"/>
		</LinearLayout> 
		<LinearLayout 
				android:orientation="horizontal"
				android:layout_width="fill_parent"
				android:layout_height="fill_parent"
				android:gravity="center">  
			<Button   
				android:text="确定" 
				android:id="@+id/ok_button" 
				android:layout_width="75dip" 
				android:layout_height="40dip"
				android:textSize="18dip"
				android:gravity="center"/> 
		</LinearLayout> 	
	</LinearLayout>
</LinearLayout>







d2\app\src\main\res\values

========== 【colors.xml】 ==========
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
</resources>

========== 【strings.xml】 ==========
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">BN赛艇</string>
</resources>


========== 【styles.xml】 ==========
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style 	name="FullHeightDialog"
      	parent="android:style/Theme.Dialog">
      	<item name="android:windowNoTitle">true</item>
      	<item name="android:windowBackground">@drawable/dialog</item>  
    </style>
</resources>


========== 【themes.xml】 ==========
<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.D2" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>
</resources>












app\build.gradle
plugins {
    id 'com.android.application'
}

android {
    namespace "com.bn.clp"
   // 升级到33(解决所有依赖的编译版本要求)
    compileSdk 33
    // 匹配compileSdk 33的稳定Build-Tools
    buildToolsVersion "33.0.2"

    defaultConfig {
        applicationId "com.bn.clp"
        minSdk 25 // 最低兼容版本仍保留25(不影响旧设备安装)
        targetSdk 33 // 同步升级到33(建议与compileSdk一致)
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    // 保持Java 11(AGP 7.4.2推荐版本)
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }

    sourceSets {
        main {
            java.srcDirs = ['src/main/java'] // java源码路径(正确)
            res.srcDirs = ['src/main/res']   // 资源文件路径(正确,若被修改会导致无法找到res目录)
        }
    }

}

dependencies {

    implementation fileTree(dir: "libs", include: ["*.jar"])
    // 升级到适配compileSdk 33的稳定版依赖
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    // 新增:Material Components依赖(必须添加,解决资源缺失问题)
    implementation 'com.google.android.material:material:1.8.0' // 版本可根据compileSdk调整,建议>=1.8.0

    // 测试依赖也适配compileSdk 33
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}




gradle\wrapper\gradle-wrapper.properties
#Tue Dec 30 10:00:44 CST 2025
distributionBase=GRADLE_USER_HOME
distributionUrl=file\:///E:/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME




项目\build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google() // 必须优先配置Google仓库
        mavenCentral() // 替代废弃的jcenter()
    }
    dependencies {
        // AGP 7.4.2 与 Gradle 7.5 完全兼容
        classpath 'com.android.tools.build:gradle:7.4.2'

        // 如需Kotlin插件(如果项目用Kotlin则添加,否则删除)
        // classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0"
    }
}

//allprojects {
//    repositories {
//        google()
//        mavenCentral()
//    }
//}

task clean(type: Delete) {
    delete rootProject.buildDir
}





d2\app\src\main\res\drawable-nodpi

about.png
about_press.png
airship_st.png
airship_wy.png
androidheli.jpg
back.png
back_press.png
background.jpg
bg_bitmap0.jpg
bg_bitmap1.jpg
bg_bitmap2.jpg
bg_bitmap3.jpg
bg_bitmap4.jpg
bg_music.png
bridge_cm.jpg
castle0.jpg
castle1.png
chooseboat.png
chooseboat_press.png
close.png
d0.png
d1.png
d2.png
d3.png
d4.png
d5.png
d6.png
d7.png
d8.png
d9.png
daojishi.png
dialog.9.png
down.png
exit.png
exit_press.png
floor.png
game_end.png
game_music.png
game_start.png
gamehelp.png
gamehelp_press.png
gg1.jpg
gg2.jpg
gg3.jpg
gg_0.png
gg_1.png
gg_2.png
gg_sz.png
go.png
grass.jpg
guanyu.jpg
hd_rock.jpg
heli.jpg
hengxian.png
icon.png
jt_wl.png
load_bj.jpg
load_dt.png
load_fgt.png
maohao.png
mark0.png
mark1.png
mark2.png
mark3.png
mark4.png
mountion_land.png
mountion_land_0.png
next.png
next_page.png
next_page_press.png
number.png
open.png
other_boat.png
play.png
play_press.png
pre_page.png
pre_page_press.png
rador_bg.png
rador_plane.png
record_select.png
record_select_press.png
rmode.png
rock.jpg
shache.png
shrub.png
shrub1.png
shrub2.png
shrub3.png
sky.jpg
soundset.png
soundset_press.png
speed_down.png
speed_mode.png
speed_mode_press.png
speed_up.png
time.png
timer_mode.png
timer_mode_press.png
tmode.png
two_ceyi.png
two_chuanshen.png
two_pentong.png
two_shangmian.png
two_weijia.png
two_weiyi.png
up.png
water.png
wood.png
xd.png
ybp.png

d2\app\src\main\res\raw

houshijing.png
one_chuanshen.png
one_dizuo.png
one_houmian.png
one_qiandizuo.png
one_qianmian.png
three_chuanshen.png
three_liangce.png
three_pentong.png
three_shangmian.png
three_shangmianqian.png
three_weiyi.png
weilang.png

backsound.mp3
boatgo.mp3
daojishi.mp3
eatthings1.mp3
pengzhuang.mp3
start.mp3
zhuangfei.mp3

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐