Android游戏开发之360°半透明摇杆。。。。

照着PDF做了个摇杆并实现了 摇杆控制角色行走, 在这里贴下代码做下笔记。

首先新建了一个VIEW  继承SurfaceView   实现相关接口

<pre name="code" class="java">

public class PlayerView extends MapView implements Callback,Runnable

 

相关变量声明与初始化设置

protected final int DIR_LEFT = 0;
	protected final int DIR_RIGHT = 1;
	private int dir = DIR_RIGHT;
	private int robotX,robotY;
	private boolean isUp=false,isDown=false,isLeft=false,isRight=false;
	//摇杆的圆半径
	private float smallCenterX = 120,smallCenterY=120,smallCenterR = 20;
	private float BigCenterX = 120,BigCenterY = 120,BigCenterR = 40;
	//圆运动角度
	private double angle;
	
	public PlayerView(Context context) {
		super(context);
		holder = getHolder();
		holder.addCallback(this);//设置监听
		paint = new Paint();
		paint.setColor(Color.BLACK);
		setFocusable(true);//设置焦点
	}
	
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		bitmap = BitmapFactory.decodeResource(this.getResources(),
				R.drawable.robot);
		bmpX = -bitmap.getWidth()+this.getWidth();
		bmpY = this.getHeight() - bitmap.getHeight();
		Thread thread = new Thread(this);
		thread.start();
		
		//设置摇杆初始位置
		smallCenterX = 40;
		smallCenterY = this.getHeight()-40;
		BigCenterX = 40;
		BigCenterY = this.getHeight()-40;
	}


接下来是 摇杆和 角色的绘制, 都放一起了


private void drawFrame(){
		canvas = holder.lockCanvas();
		canvas.drawColor(Color.WHITE);
		int frameW = bitmap.getWidth()/6; //获得每一帧的宽
		int frameH = bitmap.getHeight()/2; //获得每一帧的高
		int col = bitmap.getWidth()/frameW; //获得位图列数
		int x = cureentFrame%col * frameW;
		int y = cureentFrame /col * frameH;
		paint.setAlpha(255);//不透明
		canvas.save();
		//paint.setColor(Color.RED);//设置画笔颜色
		//设置每帧可见区域为角色一样大小
		canvas.clipRect(robotX,robotY,robotX+bitmap.getWidth()/6,robotY+bitmap.getHeight()/2);
		if(dir==DIR_LEFT){
			//如果向左移动则设置角色翻转
			canvas.scale(-1,1,robotX-x+bitmap.getWidth()/2,robotY-y+bitmap.getHeight()/2);
		}
		canvas.drawBitmap(bitmap, robotX-x,robotY-y, paint);
		canvas.restore();
		//摇杆绘制
		paint.setAlpha(0x77); //设置摇杆透明度
		canvas.drawCircle(BigCenterX, BigCenterY, BigCenterR, paint);//大圆
		canvas.drawCircle(smallCenterX, smallCenterY, smallCenterR, paint);//小圆
		
		holder.unlockCanvasAndPost(canvas);
	}


计算余弦

	/**
	 * Math.cos 返回余弦  
	 * @param centerX 围绕大圆中心点X
	 * @param centerY 围绕大圆中心点Y
	 * @param R	围绕大圆半径
	 * @param rad   旋转弧度
	 * 方法: 设置小圆中心点的坐标位置
	 */
	private void setSmallCircleXY(float centerX,float centerY,float R,double rad){
		smallCenterX = (float)(R*Math.cos(rad))+centerX;
		smallCenterY = (float)(R*Math.sin(rad))+centerY;
	}


剩下的代码直接贴吧  都有注释的

	public void logic(){
		cureentFrame++;//渲染帧数
		if(cureentFrame>=12) //超过12帧 则重置
			cureentFrame = 0;
		if(isUp)
			robotY -=5;
		if(isDown)
			robotY+=5;
		if(isLeft)
			robotX-=5;
		if(isRight)
			robotX+=5;
		//angle++;
		/*if(angle>=360)
			angle=0;
		setSmallCircleXY(BigCenterX, BigCenterY, BigCenterR, angle*Math.PI/180);//Math.PI 圆的周长与直径之比
		
*/	}
	
	/**
	 * 得到两点之间弧度
	 * @param px1
	 * @param py1
	 * @param px2
	 * @param py2
	 * @return
	 */
	public double getRad(float px1,float py1,float px2,float py2){
		float x = px2 - px1;//得到两点X的距离
		float y = py1 -py2; //y
		//算出斜边长
		float Hypotenuse = (float) Math.sqrt(Math.pow(x, 2)+Math.pow(y, 2));
		float cosAngle = x/Hypotenuse; //得到角度的余弦值
		//通过反余弦获得角度弧度
		float rad = (float)Math.acos(cosAngle);
		if(py2<py1)
			rad = -rad;
		return rad;
	}
	
	private void stopMove(){
		isUp = false;
		isDown = false;
		isLeft = false;
		isRight = false;
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		//用户抬起小圆恢复初始位置
		if(event.getAction()==MotionEvent.ACTION_UP){
			smallCenterX = BigCenterX;
			smallCenterY = BigCenterY;
			stopMove();//停止移动
		}else{
			int pointX = (int)event.getX();
			int pointY = (int)event.getY();
			//判断用户点击位置是否在大圆内
			if(Math.sqrt(Math.pow((BigCenterX-(int)event.getX()),2)+Math.pow((BigCenterY-(int)event.getY()), 2))<=BigCenterR){
				smallCenterX = pointX;//让小圆跟随用户点击位置
				smallCenterY = pointY;
			}else{
				setSmallCircleXY(BigCenterX, BigCenterY, BigCenterR, getRad(BigCenterX, BigCenterY, pointX, pointY));
			}
			
			double radian = getRad(BigCenterX, BigCenterY, pointX, pointY);
			
			angle = radian/Math.PI*180;
			Log.v("角度:", "============>"+angle+"   radian:"+radian);
			stopMove();
			if(angle<-67.5&&angle>-112.5){ //上
				isUp = true;
			}else if(angle<-22.5&&angle>-67.5){ //右上
				isUp=true;
				isRight = true;
				dir = DIR_RIGHT;
			}else if(angle>-167.5&&angle<-112.5){  //左上
				dir=DIR_LEFT;
				isLeft =true;
				isUp = true;
			}else if(angle>67.5&&angle<112.5){ //下
				isDown = true;
			}else if(angle<167.5&&angle>112.5){ //左下
				dir=DIR_LEFT;
				isDown = true;
				isLeft = true;
			}else if(angle>-22.5&&angle<22.5){  //右
				dir = DIR_RIGHT;
				isRight = true;
			}else if(angle>22.5&&angle<67.5){//右下
				dir=DIR_RIGHT;
				isDown = true;
				isRight = true;
			}else if((angle>-212.5&&angle<-167.5)||(angle<212.5&&angle>167.5)){ //下
				dir = DIR_LEFT;
				isLeft = true;
			}
				
				
				
		}
		return true;
	}

	@Override
	public void run() {
		while (flag) {
			long start = System.currentTimeMillis();
			drawFrame();
			logic();
			long end = System.currentTimeMillis();
			try {
				if (end - start < 50) {
					Thread.sleep(50 - (end - start));
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值