surfaceholder和surfaceview回调关系

初学者今天接触了回调接口,大致是上层类a中引用的下层类b通过接口c回调类a的方法d,再看surfaceholder.addcallback(surfaceview)后可以使用holder中的方法surfacechanged,那在这里 谁是abcd,忘解答,新人,可能理解存在错误

1个回答

holder顾名思义是占位符。 surfaceholder翻过来调用surfaceview

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
Android surfaceview控件高度超过8192就不回调surfaceCreated( )函数
**一、问题:** 自己自定义了一个surfaceview,在onMeasurea方法中设置该控件的高度,发现一旦超过8192就不会回调surfaceCreated( )函数,是什么原因造成的?一直想不通为什么会不回调...有这个限制吗? **二、测试的例子:** 这里把surfaceview放到scrollview中,可以上下滑动查看。(把scrollview去掉也出现同样的问题) 当高度大于8192时,查看log打印的信息,发现没有调用surfaceCreated( )。 ``` **1、自定义的TestSurfaceView.java** package com.hebei.textviewdemo6; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class TestSurfaceView extends SurfaceView implements SurfaceHolder.Callback{ public TestSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub SurfaceHolder holder = getHolder(); holder.addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub Log.d("surfaceCreated", "created"); Log.d("surfaceCreated", "widht = "+this.getWidth()+" height = "+this.getHeight()); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub Log.d("surfaceChanged", "changed"); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub Log.d("surfaceDestoryed", "destoryed"); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = 8193; Log.d("onMeasure", "Width = "+width+" Height = "+height); setMeasuredDimension(width, height); } } **2、xml文件** <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.hebei.textviewdemo6.MainActivity" > <ScrollView android:id="@+id/scrollview_demo6" android:layout_width="120dp" android:layout_height="120dp" android:background="#FF0000" android:fadingEdge="vertical" android:scrollbars="vertical" > <com.hebei.textviewdemo6.TestSurfaceView android:layout_width="match_parent" android:layout_height="wrap_content" /> </ScrollView> </RelativeLayout> **3、MainActivity.java** public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d("onCreate", "create"); } } ```
surfaceview自定义显示效果,在小米mix2上显示默认背景色黑色问题
一下是控件代码 ``` import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import com.voiceai.voicekey.R; public class VolumeView extends SurfaceView implements Runnable { private SurfaceHolder mSurfaceHolder; private Paint paint; private int highVolColor = 0xFF4500, midVolColor = 0xFB90F, lowVolColor = 0x32CD32, edgeColor = 0xffffff; private int volValue, maxVolume; private float unitSize; private int width, height, edgeSize; /*** * 是否在绘制:用于关闭子线程:true则表示一直循环 */ private boolean isDrawing = true; public VolumeView(Context context) { this(context, null); } public VolumeView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public VolumeView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs, defStyleAttr); initSurface(); } private void init(AttributeSet attrs, int defStyleAttr) { paint = new Paint(); TypedArray array = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable .VolumeBar, defStyleAttr, 0); int n = array.getIndexCount(); for (int i = 0; i < n; i++) { int attr = array.getIndex(i); switch (attr) { case R.styleable.VolumeBar_HighVolumeColor: highVolColor = array.getColor(attr, 0xFF4500); break; case R.styleable.VolumeBar_LowVolumeColor: lowVolColor = array.getColor(attr, 0x32CD32); break; case R.styleable.VolumeBar_MidVolumeColor: midVolColor = array.getColor(attr, 0xFB90F); break; case R.styleable.VolumeBar_VolumeValue: volValue = array.getInt(attr, 50); break; case R.styleable.VolumeBar_MaxVolume: maxVolume = array.getInt(attr, 100); break; case R.styleable.VolumeBar_EdgeColor: edgeColor = array.getColor(attr, 0xffffff); break; case R.styleable.VolumeBar_EdgeSize: edgeSize = array.getDimensionPixelSize(attr, 0); break; } } } private void initSurface() { /**通过holder去申请绘图表面的画布,surfaceview其实draw()或dispathDraw()都只是一块默认的黑色区域,并不是用作宿主 * 真正要做的事情由开发者自行绘制,绘制之前就是通过holder获取一块内存区域的画布, * 然后可在UI线程或工作线程在这个画布上进行绘制所需要的视图,最后还是通过holder提交这个画布就可以显示 * * * 生命周期自动和activity一起 * */ mSurfaceHolder = getHolder(); setZOrderOnTop(true); //回调 mSurfaceHolder.addCallback(new SurfaceHolder.Callback() { /*** * surfaceview的绘图表面(就是activity宿主创建一个透明的表面用于surfaceView绘制)被创建时执行 * 在updateWindow()创建宿主(activity的窗口)的绘图表面时会回调,虽然surfaceView是独立于一个线程但还是离不开宿主窗口, * 最后还是要粘贴到window中 * * surfaceCreated方法,是当SurfaceView被显示时会调用的方法,所以你需要再这边开启绘制的线 程 * * @param holder */ @Override public void surfaceCreated(SurfaceHolder holder) { isDrawing = true; new Thread(VolumeView.this).start(); Log.e("VolumeView", "SurfaceHolder生命周期surfaceCreated"); } /** * 创建、更新会认为发生变化也会回调这个方法 * @param holder * @param format * @param width * @param height */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.e("VolumeView", "SurfaceHolder生命周期surfaceChanged"); } /*** *surfaceDestroyed方法是当SurfaceView被隐藏会销毁时调用的方法,在这里你可以关闭绘制的线程 * @param holder */ @Override public void surfaceDestroyed(SurfaceHolder holder) { isDrawing = false; Log.e("VolumeView", "SurfaceHolder生命周期surfaceDestroyed"); } }); } public void setDrawing(boolean drawing) { isDrawing = drawing; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); height = measureHeight(heightMeasureSpec); width = measureWidth(widthMeasureSpec); setMeasuredDimension(width, height); } private int measureHeight(int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); // Default size if no limits are specified. int result = 500; if (specMode == MeasureSpec.AT_MOST) { result = specSize; } else if (specMode == MeasureSpec.EXACTLY) { result = specSize; } return result; } private int measureWidth(int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); // Default size if no limits are specified. int result = 500; if (specMode == MeasureSpec.AT_MOST) { result = specSize; } else if (specMode == MeasureSpec.EXACTLY) { result = specSize; } return result; } @Override public void run() { while (isDrawing) { draw(); } } //设置音量 public void setVolValue(int value) { if (value > maxVolume) { value = maxVolume; } this.volValue = value; } /*** * 注意这个是在子线程中绘制的,surface支持子线程更新ui,所以 */ private void draw() { Canvas canvas = null; //给画布加锁,防止线程安全,防止该内存区域被其他线程公用 try { synchronized (mSurfaceHolder) { canvas = mSurfaceHolder.lockCanvas(); if (null != canvas) { //清屏操作或者设置背景 onDrawPic(canvas); Thread.sleep(50); } } } catch (Exception e){ Log.e("VolumeView", "VolumeView异常:"+e.getMessage()); }finally { //提交显示视图并解锁,防止长期占用此内存 if (null != mSurfaceHolder) mSurfaceHolder.unlockCanvasAndPost(canvas); } } protected void onDrawPic(Canvas canvas) { final Rect rect = new Rect(0, 0, this.width, this.width); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); unitSize = (float) (width - 2 * edgeSize) / (float) maxVolume; int drawSize = Math.round(volValue * unitSize); //颜色渐变原则:当音量小于50时,R值递增/递减(根据指定的low、mid颜色值来判断),G值不变,B值递增/递减, //当音量大于50时,R值不变,G值递减/递增(),B值递增/递减 float redColorUnitFirstStage = (float) (((midVolColor & 0xff0000) - (lowVolColor & 0xff0000)) >> 16) / 70; float greenColorUnitFirstStage = (float) (((midVolColor & 0x00ff00) - (lowVolColor & 0x00ff00)) >> 8) / 70; float blueColorUnitFirstStage = (float) (((midVolColor & 0x0000ff) - (lowVolColor & 0x0000ff))) / 70; float redColorUnitSecondStage = (float) (((highVolColor & 0xff0000) - (midVolColor & 0xff0000)) >> 16) / 30; float greenColorUnitSecondStage = (float) (((highVolColor & 0x00ff00) - (midVolColor & 0x00ff00)) >> 8) / 30; float blueColorUnitSecondStage = (float) (((highVolColor & 0x0000ff) - (midVolColor & 0x0000ff))) / 30; int red = (lowVolColor & 0xff0000) >> 16; int green = (lowVolColor & 0x00ff00) >> 8; int blue = (lowVolColor & 0x0000ff); //绘制有颜色区域 for (int i = 0; i < volValue; i++) { if (i <= 70) { //当音量小于50时,更新颜色的R值,递增/递减。 red = red + (int) redColorUnitFirstStage; green = green + (int) greenColorUnitFirstStage; blue = blue + (int) blueColorUnitFirstStage; int colorValue = Color.rgb(red, green, blue); paint.setColor(colorValue); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawRect(i * unitSize, edgeSize, (i + 1) * unitSize + 1, height - edgeSize, paint); } else { //当音量小于50时,更新颜色的G值,递减。 red = red + (int) redColorUnitSecondStage; green = green + (int) greenColorUnitSecondStage; blue = blue + (int) blueColorUnitSecondStage; int colorValue = Color.rgb(red, green, blue); paint.setColor(colorValue); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawRect(i * unitSize, edgeSize, (i + 1) * unitSize + 1, height, paint); } } //绘制边框 paint.setColor(edgeColor); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); //绘制左边框 canvas.drawRect(0, 0, edgeSize, height, paint); //绘制上边框 canvas.drawRect(0, 0, width, edgeSize, paint); //绘制下边框 canvas.drawRect(0, height - edgeSize, width, height, paint); //绘制有边框 canvas.drawRect(width - edgeSize, 0, width, height, paint); //绘制第一个刻度 canvas.drawRect(width / 4, height - 10 * edgeSize, width / 4 + 2 * edgeSize, height, paint); //绘制第二个刻度 canvas.drawRect(width * 4 / 5, height - 10 * edgeSize, width * 4 / 5 + 2 * edgeSize, height, paint); } } ``` 在activity调用了 vVolumeBar.setVolValue(20);然后其他手机都ok就是小米,初次进去就会显示默认黑色背景,再次回到该页面显示效果正常
怎么在ListView的Item里面去用SurfaceView绘制
package com.example.mysurfaceviewdemo; import java.util.Random; import android.graphics.Bitmap; public class BitmapBubble { private Bitmap mBitmap; private int maxX; private int maxY; private int x; private int y; private boolean isRight = true; private boolean isUp = true; Random random = new Random(); private int speedX = random.nextInt(2)+1; private int speedY = random.nextInt(10)+1; public BitmapBubble(Bitmap mBitmap,int x,int y,int maxX,int maxY){ this.mBitmap = mBitmap; this.x = x; this.y = y; this.maxX = maxX - mBitmap.getWidth(); this.maxY = maxY - mBitmap.getHeight(); } public int getMaxX() { return maxX; } public void setMaxX(int maxX) { this.maxX = maxX; } public int getMaxY() { return maxY; } public void setMaxY(int maxY) { this.maxY = maxY; } public int getX() { x+=speedX; return x; } public int getY() { y-=speedY; return y; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public int getSpeedX() { return speedX; } public void setSpeedX(int speedX) { this.speedX = speedX; } public Bitmap getmBitmap() { return mBitmap; } public void setmBitmap(Bitmap mBitmap) { this.mBitmap = mBitmap; } } package com.example.mysurfaceviewdemo; import java.util.ArrayList; import java.util.Random; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff.Mode; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.RelativeLayout; import android.widget.TextView; public class MySurfaceView extends SurfaceView implements Callback,Runnable{ private SurfaceHolder mSurfaceHolder; private Thread mThread; private Canvas canvas; private int ScreenW, ScreenH; private Random random = new Random(); private ArrayList <BitmapBubble> list = new ArrayList<BitmapBubble>(); int maxY; int maxX; int x ; int y ; private boolean hasBitmapBubble = true; private Bitmap mBitmap; private BitmapBubble mBitmapBubble; private int BitmapIds [] = new int []{R.drawable.water,R.drawable.water2,R.drawable.water3,R.drawable.water4}; public MySurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initSurfaceView(context); } public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); initSurfaceView(context); } public MySurfaceView(Context context) { super(context); initSurfaceView(context); } @Override public void run(){ Canvas canvas = mSurfaceHolder.lockCanvas(); maxX = canvas.getWidth(); maxY = canvas.getHeight(); x = 30; y = maxY-80; mSurfaceHolder.unlockCanvasAndPost(canvas); while(true){ canvas = mSurfaceHolder.lockCanvas(); if(canvas==null){ return; } canvas.drawColor(Color.TRANSPARENT,Mode.CLEAR); for(int j=0; j<list.size();j++){ mBitmapBubble = list.get(j); canvas.drawBitmap(mBitmapBubble.getmBitmap(),mBitmapBubble.getX(), mBitmapBubble.getY(), null); if(mBitmapBubble.getX()>mBitmapBubble.getMaxX()){ list.remove(mBitmapBubble); } if(mBitmapBubble.getY()<0){ list.remove(mBitmapBubble); } } mSurfaceHolder.unlockCanvasAndPost(canvas); try { Thread.sleep(150); } catch (InterruptedException e) { e.printStackTrace(); } } } public void initSurfaceView(Context context){ mSurfaceHolder = this.getHolder(); mSurfaceHolder.addCallback(this); this.setZOrderOnTop(true);//设置画布 背景透明 this.getHolder().setFormat(PixelFormat.TRANSLUCENT); drawBubble(); mThread = new Thread(this); } @Override public void surfaceCreated(SurfaceHolder holder) { mThread.start(); //生产冒泡 new Thread(){ public void run() { while(true){ int position = random.nextInt(4); int resId = BitmapIds[position]; mBitmap = BitmapFactory.decodeResource(getResources(),resId); Bitmap bitmap = Bitmap.createScaledBitmap(mBitmap, 50, 50, false); list.add(new BitmapBubble(bitmap, x, y, maxX, maxY)); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { mThread.stop(); } public ArrayList<BitmapBubble> getList() { return list; } public void setList(ArrayList<BitmapBubble> list) { this.list = list; } public void drawBubble(){ mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); Bitmap bitmap = Bitmap.createScaledBitmap(mBitmap, 40, 40, false); list.add(new BitmapBubble(bitmap, x, y, maxX, maxY)); } } package com.example.mysurfaceviewdemo; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; public class MyAdapter extends BaseAdapter{ Context mContext; public MyAdapter(Context mContext){ this.mContext = mContext; } @Override public int getCount() { return 10; } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = LayoutInflater.from(mContext).inflate(R.layout.activity_main, null); final MySurfaceView mySurfaceView = (MySurfaceView)view.findViewById(R.id.mysurfaceview); Button btn = (Button) view.findViewById(R.id.btn); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mySurfaceView.drawBubble(); } }); return view; } } package com.example.mysurfaceviewdemo; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ListView; public class MainActivity extends Activity { MySurfaceView mySurfaceView; Button btn; ListView listview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout); // setContentView(R.layout.activity_main); // mySurfaceView = (MySurfaceView) findViewById(R.id.mysurfaceview); // btn = (Button) findViewById(R.id.btn); // btn.setOnClickListener(new OnClickListener() { // @Override // public void onClick(View v) { // mySurfaceView.drawBubble(); // } // }); listview = (ListView)findViewById(R.id.listview); listview.setAdapter(new MyAdapter(getApplicationContext())); } } 求大牛教育 ,为什么我在绘制的时候,它的回调不走,但是SurfaceView的宿主是Activity的时候就可以去绘
SurfaceView缩放、拖拽、涂鸦功能,进行坐标换算
改写了一个surfaceView,之前有缩放、拖拽功能,根据我的应用需求,我需要加上涂鸦功能, 在这个过程中,我可以再上面画矩形。画矩形没有问题,但是在画好图形进行缩放的时候,画的矩形来回抖动,不能固定,在坐标换算的时候出问题了,一直找不到问题在哪里,求高人指点。 这里坐标换算,是换算成相对于bitmap的坐标,因为bitmap是等比例缩放的,不是铺满整个surfaceview的 调用源码: ``` public MySurfaceView3 msvZoom; Bitmap bm = BitmapFactory.decodeFile(imgPath); msvZoom.setBitmap(bm); ``` 自定义SurfaceView代码 ``` import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.Rect; import android.text.TextUtils; import android.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import com.github.niqdev.mjpeg.OnDrawCompleteListener; import com.github.niqdev.mjpeg.bean.Data; /** * @Author hyj * @Date 2017/10/19 19:16 */ public class MySurfaceView3 extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener { private static final int NONE = 0;// 原始 private static final int DRAG = 1;// 拖动 private static final int ZOOM = 2;// 放大 private int mStatus = NONE; private static final float MAX_ZOOM_SCALE = 5f; private static final float MIN_ZOOM_SCALE = 1.0f; private static final float FLOAT_TYPE = 1.0f; private float mCurrentMaxScale = MAX_ZOOM_SCALE; private float mCurrentScale = 1.0f; private Rect mRectSrc = new Rect(); // used for render image. //要绘图的位置 private Rect mRectDes = new Rect(); // used for store size of monitor. 要画图的部分 private int mCenterX, mCenterY; int mSurfaceHeight, mSurfaceWidth, mImageHeight, mImageWidth; private PointF mStartPoint = new PointF(); private float mStartDistance = 0f; private SurfaceHolder mSurHolder = null; private Bitmap mBitmap; /********************画图部分********************/ private Paint shapePaint; private String paintColor = "FA1418";//当前画笔颜色 private int paintWidth = 3;//画笔宽度 private String action = Data.ACTION_DRAW;//画图动作 private String style = Data.STYLE_RECTANGLE;//画图形状 private float startX = 0, startY = 0, endX = 0, endY = 0;//位置比例 private float sx = 0, sy = 0, ex = 0, ey = 0; //计算出来当前屏幕中真实位置 private boolean isDrawShape = false;//当前是否处于画图状态 private ArrayMap<String, Data> amShape; private Data tempShape; private OnDrawCompleteListener<Data> onDrawCompleteListener;//标记绘制完成 /** * 还原所有画图的参数 */ private void restoreDrawParams() { startX = startY = endX = endY = 0; sx = sy = ex = ey = 0; isDrawShape = false; amShape.clear(); } /** * 获得画图状态 * * @return */ public boolean isDrawShape() { return isDrawShape; } /** * 设置画图状态 * * @param drawShape */ public void setDrawShape(boolean drawShape) { isDrawShape = drawShape; } /** * 清空所所有标记、注解 */ public void addMarker(Data dataMarker) { if (null == dataMarker || TextUtils.isEmpty(dataMarker.getAction())) { return; } switch (dataMarker.getAction()) { case Data.ACTION_DRAW: amShape.put(dataMarker.getId(), dataMarker); break; case Data.ACTION_DEL: //TODO 删除指定的图形,预留接口 break; case Data.ACTION_DELALL: restoreDrawParams(); break; } showBitmap(); } /** * 一个图形画完之后的回调事件 * * @param onDrawCompleteListener */ public void setOnDrawCompleteListener(OnDrawCompleteListener onDrawCompleteListener) { this.onDrawCompleteListener = onDrawCompleteListener; } /** * 初始化画图属性 */ private void initDrawShape() { amShape = new ArrayMap<String, Data>(); shapePaint = new Paint(); shapePaint.setAntiAlias(false); shapePaint.setStyle(Paint.Style.STROKE); shapePaint.setStrokeCap(Paint.Cap.ROUND); shapePaint.setStrokeJoin(Paint.Join.ROUND); shapePaint.setColor(Color.parseColor("#" + paintColor)); shapePaint.setStrokeWidth(paintWidth); } /** * 计算点X到图片左上角距离与图片宽度的比值 * * @param bmW 图片宽 * @param pointX 点相对于屏幕左上角的X距离 * @return */ private float pointScreen2ImageX(int bmW, float pointX) { return (pointX / mWidthScale - mRectDes.left + mRectSrc.left) * 1.0f / (bmW); } /** * 计算点Y到图片左上角与图片高度的比值 * * @param bmH 图片高度 * @param pointY 点相对于屏幕左上角的Y距离 * @return */ private float pointScreen2ImageY(int bmH, float pointY) { return (pointY / mHeightScale - mRectDes.top + mRectSrc.top) * 1.0f / (bmH); } /** * 把相对于图片的宽比值转换成相对于屏幕上具体的点 * * @param bmW 图片宽度 * @param scaleX 点的X值相对于图片宽度的比值 * @return */ private float pointImage2ScreenX(int bmW, float scaleX) { return (scaleX * bmW + mRectDes.left - mRectSrc.left) * mWidthScale; } /** * 把相对于图片的高度壁纸转换成相对于屏幕上具体的点 * * @param bmH 图片高度 * @param scaleY 点的Y值相对于图片高度的比值 * @return */ private float pointImage2ScreenY(int bmH, float scaleY) { return (scaleY * bmH + mRectDes.top - mRectSrc.top) * mHeightScale; } /********************画图部分********************/ public MySurfaceView3(Context context, AttributeSet attrs) { super(context, attrs); mSurHolder = getHolder(); mSurHolder.addCallback(this); this.setOnTouchListener(this); } private void init() { mCurrentMaxScale = Math.max(MIN_ZOOM_SCALE, 4 * Math.min(FLOAT_TYPE * mImageHeight / mSurfaceHeight, 1.0f * mImageWidth / mSurfaceWidth)); mCurrentScale = MIN_ZOOM_SCALE; mCenterX = mImageWidth / 2; mCenterY = mImageHeight / 2; initDrawShape(); calcRect(); } private void adjustCenter() { int w = mRectSrc.right - mRectSrc.left; int h = mRectSrc.bottom - mRectSrc.top; if (mCenterX - w / 2 < 0) { mCenterX = w / 2; mRectSrc.left = 0; mRectSrc.right = w; } else if (mCenterX + w / 2 >= mImageWidth) { mCenterX = mImageWidth - w / 2; mRectSrc.right = mImageWidth; mRectSrc.left = mRectSrc.right - w; } else { mRectSrc.left = mCenterX - w / 2; mRectSrc.right = mRectSrc.left + w; } if (mCenterY - h / 2 < 0) { mCenterY = h / 2; mRectSrc.top = 0; mRectSrc.bottom = h; } else if (mCenterY + h / 2 >= mImageHeight) { mCenterY = mImageHeight - h / 2; mRectSrc.bottom = mImageHeight; mRectSrc.top = mRectSrc.bottom - h; } else { mRectSrc.top = mCenterY - h / 2; mRectSrc.bottom = mRectSrc.top + h; } } private float mWidthScale = 1.0f;//当前宽的缩放比例 private float mHeightScale = 1.0f;//当前高的缩放比例 float distanceX; float distancY; private void calcRect() { int w, h; float imageRatio, surfaceRatio; imageRatio = FLOAT_TYPE * mImageWidth / mImageHeight; surfaceRatio = FLOAT_TYPE * mSurfaceWidth / mSurfaceHeight; if (imageRatio < surfaceRatio) { h = mSurfaceHeight; w = (int) (h * imageRatio); } else { w = mSurfaceWidth; h = (int) (w / imageRatio); } if (mCurrentScale > MIN_ZOOM_SCALE) { //如果显示区域超过屏幕宽高,则取屏幕宽高 w = Math.min(mSurfaceWidth, (int) (w * mCurrentScale)); h = Math.min(mSurfaceHeight, (int) (h * mCurrentScale)); } else { mCurrentScale = MIN_ZOOM_SCALE; } String msg = "imageRatio:" + imageRatio + " surfaceRatio:" + surfaceRatio + " mCurrentScale:" + mCurrentScale + " w:" + w + " h:" + h + " mSurfaceWidth:" + mSurfaceWidth + " mSurfaceHeight:" + mSurfaceHeight + " mImageWidth:" + mImageWidth + " mImageHeight:" + mImageHeight; Log.i("TAG radio", msg); mRectDes.left = (mSurfaceWidth - w) / 2; mRectDes.top = (mSurfaceHeight - h) / 2; mRectDes.right = mRectDes.left + w; mRectDes.bottom = mRectDes.top + h; float curImageRatio = FLOAT_TYPE * w / h; int h2, w2; if (curImageRatio > imageRatio) { h2 = (int) (mImageHeight / mCurrentScale); w2 = (int) (h2 * curImageRatio); } else { w2 = (int) (mImageWidth / mCurrentScale); h2 = (int) (w2 / curImageRatio); } mRectSrc.left = mCenterX - w2 / 2; mRectSrc.top = mCenterY - h2 / 2; mRectSrc.right = mRectSrc.left + w2; mRectSrc.bottom = mRectSrc.top + h2; distanceX = (mSurfaceWidth - w) / 2 - (mCenterX - w2 / 2); distancY = (mSurfaceHeight - h) / 2 - (mCenterY - h2 / 2); mWidthScale = w * FLOAT_TYPE / w2;//计算当前宽度缩放比例 mHeightScale = h * FLOAT_TYPE / h2;//计算当前高度缩放比例 } public void setMaxZoom(float value) { mCurrentMaxScale = value; } public void setBitmap(Bitmap b) { if (b == null) { return; } synchronized (MySurfaceView3.class) { mBitmap = b; if (mImageHeight != mBitmap.getHeight() || mImageWidth != mBitmap.getWidth()) { mImageHeight = mBitmap.getHeight(); mImageWidth = mBitmap.getWidth(); init(); } showBitmap(); } } private void showBitmap() { synchronized (MySurfaceView3.class) { Canvas c = getHolder().lockCanvas(); if (c != null && mBitmap != null) { c.drawColor(Color.GRAY); c.drawBitmap(mBitmap, mRectSrc, mRectDes, null); drawShape2Bitmap(c); getHolder().unlockCanvasAndPost(c); } } } private void drawShape2Bitmap(Canvas c) { if (amShape != null && amShape.size() > 0) { for (Data obj : amShape.values()) { shapePaint.setStrokeWidth(obj.getBorderWidth()); shapePaint.setColor(Color.parseColor(obj.getColor2Paint())); switch (obj.getStyle()) { case Data.STYLE_RECTANGLE: sx = pointImage2ScreenX(mImageWidth, obj.getStartPointX()); sy = pointImage2ScreenY(mImageHeight, obj.getStartPointY()); ex = pointImage2ScreenX(mImageWidth, obj.getEndPointX()); ey = pointImage2ScreenY(mImageHeight, obj.getEndPointY()); c.drawRect(sx, sy, ex, ey, shapePaint); break; case Data.STYLE_CIRCLE: //TODO 预留接口画圆 break; } } } //将图片上的点转换为屏幕上的点 if (startX != endX || startY != endY) { sx = pointImage2ScreenX(mImageWidth, startX); sy = pointImage2ScreenY(mImageHeight, startY); ex = pointImage2ScreenX(mImageWidth, endX); ey = pointImage2ScreenY(mImageHeight, endY); c.drawRect(sx, sy, ex, ey, shapePaint); String msg = "mRectSrc:" + mRectSrc.left + "," + mRectSrc.top + "," + mRectSrc.right + "," + mRectSrc.bottom; Log.i("TAG mRectSrc", msg); msg = "mRectDes:" + mRectDes.left + "," + mRectDes.top + "," + mRectDes.right + "," + mRectDes.bottom; Log.i("TAG mRectDes", msg); msg = "pintScale: " + startX + "," + startY + "," + endX + "," + endY; Log.i("TAG pintScale", msg); msg = "point:" + sx + "," + sy + "," + ex + "," + ey; Log.i("TAG point", msg); msg = "bitmap:" + mBitmap.getWidth() + "," + mBitmap.getHeight() + ",放大倍数:" + mCurrentScale + ",mWidthScale:" + mWidthScale + ",mHeightScale:" + mHeightScale; Log.i("TAG bitmap", msg); } } private void dragAction(MotionEvent event) { final int dragScale = 3;//放慢拖动速率 synchronized (MySurfaceView3.class) { PointF currentPoint = new PointF(); currentPoint.set(event.getX(), event.getY()); int offsetX = (int) (currentPoint.x - mStartPoint.x) / dragScale; int offsetY = (int) (currentPoint.y - mStartPoint.y) / dragScale; mStartPoint = currentPoint; mCenterX -= offsetX; mCenterY -= offsetY; adjustCenter(); showBitmap(); } } private void zoomAcition(MotionEvent event) { synchronized (MySurfaceView3.class) { float newDist = spacing(event); float scale = newDist / mStartDistance; mStartDistance = newDist; mCurrentScale *= scale; mCurrentScale = Math.max(FLOAT_TYPE, Math.min(mCurrentScale, mCurrentMaxScale)); calcRect(); adjustCenter(); showBitmap(); } } @Override public boolean onTouch(View v, MotionEvent event) { if (isDrawShape) { if (mRectDes.left > event.getX() || mRectDes.right < event.getX()) { return false; } else if (mRectDes.top > event.getY() || mRectDes.bottom < event.getY()) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startX = pointScreen2ImageX(mImageWidth, event.getX()); startY = pointScreen2ImageY(mImageHeight, event.getY()); endX = startX; endY = startY; tempShape = new Data(action, style, paintColor, paintWidth); break; case MotionEvent.ACTION_MOVE: endX = pointScreen2ImageX(mImageWidth, event.getX()); endY = pointScreen2ImageY(mImageHeight, event.getY()); break; case MotionEvent.ACTION_UP: endX = pointScreen2ImageX(mImageWidth, event.getX()); endY = pointScreen2ImageY(mImageHeight, event.getY()); tempShape.setStartPoint(startX, startY); tempShape.setEndPoint(endX, endY); if (null != onDrawCompleteListener) { tempShape = onDrawCompleteListener.onDrawCoomplete(tempShape); } amShape.put(tempShape.getId(), tempShape.clone()); break; } showBitmap(); return true; } //缩放部分 switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mStartPoint.set(event.getX(), event.getY()); mStatus = DRAG; break; case MotionEvent.ACTION_POINTER_DOWN: float distance = spacing(event); if (distance > 10f) { mStatus = ZOOM; mStartDistance = distance; } break; case MotionEvent.ACTION_MOVE: if (mStatus == DRAG) { dragAction(event); } else { if (event.getPointerCount() == 1) return true; zoomAcition(event); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mStatus = NONE; break; } return true; } private float spacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub } // 初始化 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { synchronized (MySurfaceView3.class) { mRectDes.set(0, 0, width, height); mSurfaceHeight = height; mSurfaceWidth = width; init(); if (mBitmap != null) { showBitmap(); } } } @Override public void surfaceDestroyed(SurfaceHolder holder) { } } ``` XML文件代码 ``` <MySurfaceView3 android:id="@+id/calledMsvZoom" android:layout_width="match_parent" android:layout_height="match_parent" /> ```
使用MediaRecorder录制视频 录完后没有生成文件
代码如下:package com.example.meadiarecorder3; import java.io.File; import java.io.IOException; import android.app.Activity; import android.content.pm.ActivityInfo; import android.graphics.PixelFormat; import android.hardware.Camera; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements SurfaceHolder.Callback{ private SurfaceView mSurfaceView; private SurfaceHolder mSurfaceHolder; private TextView tvTime; private TextView tvSize; private Button btnStart; private Button btnStop; private Button btnCancel; private MediaRecorder recorder; private Handler handler; private Camera camera; private boolean recording; // 记录是否正在录像,fasle为未录像, true 为正在录像 private int minute = 0; private int second = 0; private String time = ""; private String size = ""; private String name; private File viodFile; private Runnable timeRun = new Runnable() { @Override public void run() { long fileLength = viodFile.length(); if (fileLength < 1024 && fileLength > 0) { size = String.format("%dB/10M", fileLength); } else if (fileLength >= 1024 && fileLength < (1024 * 1024)) { fileLength = fileLength / 1024; size = String.format("%dK/10M", fileLength); } else if (fileLength > (1024 * 1024 * 1024)) { fileLength = (fileLength / 1024) / 1024; size = String.format("%dM/10M", fileLength); } second++; if (second == 60) { minute++; second = 0; } time = String.format("%02d:%02d", minute, second); tvSize.setText(viodFile.getAbsolutePath()); tvTime.setText(time); handler.postDelayed(timeRun, 1000); } }; private Button start;// 开始录制按钮 private Button stop;// 停止录制按钮 private MediaRecorder mediarecorder;// 录制视频的类 private SurfaceView surfaceview;// 显示视频的控件 // 用来显示视频的一个接口,我靠不用还不行,也就是说用mediarecorder录制视频还得给个界面看 // 想偷偷录视频的同学可以考虑别的办法。。嗯需要实现这个接口的Callback接口 private SurfaceHolder surfaceHolder; private String fileName; private SurfaceHolder holder; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏 // 设置横屏显示 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); // 选择支持半透明模式,在有surfaceview的activity中使用。 getWindow().setFormat(PixelFormat.TRANSLUCENT); setContentView(R.layout.activity_main); fileName = Environment.getExternalStorageDirectory().getAbsolutePath(); name = "video_" + System.currentTimeMillis() + ".mp4"; fileName += File.separator + File.separator + "Ruanko_Jobseeker" + File.separator + name; name = "video_" + System.currentTimeMillis() + ".mp4"; tvSize = (TextView) findViewById(R.id.tv_video_size); tvTime = (TextView) findViewById(R.id.tv_video_time); handler= new Handler(); init(); } private void init() { start = (Button) this.findViewById(R.id.start); stop = (Button) this.findViewById(R.id.stop); start.setOnClickListener(new TestVideoListener()); stop.setOnClickListener(new TestVideoListener()); surfaceview = (SurfaceView) this.findViewById(R.id.surfaceview); holder = surfaceview.getHolder(); holder.addCallback(this); // holder加入回调接口 // setType必须设置,要不出错. holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } class TestVideoListener implements OnClickListener { private static final String TAG = "MainActivity"; @Override public void onClick(View v) { if (v == start) { try { viodFile = new File(Environment.getExternalStorageDirectory().getCanonicalFile() + "/myvideo.mp4"); if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { Toast.makeText(getApplicationContext(), "SD卡不存在,请插卡", 0).show(); return; }else{ if(!viodFile.exists()){ viodFile.getParentFile().mkdirs(); viodFile.createNewFile(); } } mediarecorder = new MediaRecorder();// 创建mediarecorder对象 // 设置录制视频源为Camera(相机) mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 设置从麦克风采集声音 mediarecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置录制完成后视频的封装格式THREE_GPP为3gp.MPEG_4为mp4 mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 设置录制的视频编码h263 h264 mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediarecorder.setAudioEncoder(MediaRecorder.VideoEncoder.DEFAULT); // 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错 mediarecorder.setVideoSize(176, 144); // 设置录制的视频帧率。必须放在设置编码和格式的后面,否则报错 mediarecorder.setVideoFrameRate(20); mediarecorder.setPreviewDisplay(holder.getSurface()); // 设置视频文件输出的路径 mediarecorder.setOutputFile(viodFile.getAbsolutePath()); System.out.println("viodFile.getAbsolutePath()的值为:"+viodFile.getAbsolutePath()); // 准备录制 mediarecorder.prepare(); // 开始录制 mediarecorder.start(); handler.post(timeRun); } catch (IOException e2) { e2.printStackTrace(); } } if (v == stop) { Log.i(TAG, viodFile.toString()); if (mediarecorder != null) { handler.removeCallbacks(timeRun); // 停止录制 mediarecorder.stop(); // 释放资源 mediarecorder.release(); mediarecorder = null; } } } } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 将holder,这个holder为开始在oncreat里面取得的holder,将它赋给surfaceHolder surfaceHolder = holder; } public void surfaceCreated(SurfaceHolder holder) { // 将holder,这个holder为开始在oncreat里面取得的holder,将它赋给surfaceHolder surfaceHolder = holder; } public void surfaceDestroyed(SurfaceHolder holder) { // surfaceDestroyed的时候同时对象设置为null surfaceview = null; holder = null; mediarecorder = null; } } 代码是没问题的 可以运行 可以录制和暂停 设置录制视频地址的代码是 viodFile = new File(Environment.getExternalStorageDirectory().getCanonicalFile() + "/myvideo.mp4"); mediarecorder.setOutputFile(viodFile.getAbsolutePath()); 这两行已经把地址设置好了 按道理来说 录完之后就可以找到文件了 但是没有! 求助各位大神,到底是哪里出了问题,有录制视频的号框架推荐就指点一二,或者有更好的代码就发小弟一份,不胜感激。。
Android想将图片间隔改一下,以为很简单弄了一天,求思路
![图片说明](https://img-ask.csdn.net/upload/201709/26/1506359899_11872.jpg) 请GitHub搜“EhViewer”,提问秒删不知道是不是不能发地址 - 漫画app,登录时请点击最下面的“免登陆”,入口选择第一个"e-hexxai"。 - 现在只想改一个地方,就是看漫画两页之间的黑条去掉,形成无缝连接。为了这一个小改动,从昨晚搞到现在,android学得稀烂,基础较薄弱,很久没敲代码了,现在都不知道这个黑条间隔到底是在哪个位置添加的,求思路 - 首先,我用ddms看了下,发现整个图片内容显示都是一个自定义view - 找到布局文件activity gallery.xml中发现是一个命名GLRootView的自定义控件 - 因为不同页及黑条都在同一个控件内,所以应该不是activity中代码实现,直接定位到GLRootView,继承自GLSurfaceView - 看了下构造函数,里面有一些方法看不懂,搜了下都是surfaceview相关,而GLSurfaceView就继承的surfaceview - 然后顺着GLSurfaceView的构造找下去,发现就一个初始化方法里面有个SurfaceHolder的回调,简单研究了下serfaceview,没搞懂 然后我该怎么办? 回过头去,我以为漫画应该是recylerview或listview展示的,发现GLRootView和GLSurfaceView的java文件中都没有写入布局相关的代码, 我该怎么定位到那个给两页漫画间增加间隔的代码中去?求具体的思路
android采集图像并通过(Server端)socket发送时,只能发一次数据,为什么呢?
``` public class MainActivity extends ActionBarActivity { private EditText edOwnPort; private TextView tvOwnIP; SurfaceView sView; SurfaceHolder surfaceHolder; int screenWidth,screenHeight; Camera camera; boolean isPreview=false; private String ipname; @Override protected void onCreate(Bundle savedInstanceState) { //设置全屏 requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); edOwnPort=(EditText)findViewById(R.id.edOwnPort); tvOwnIP=(TextView)findViewById(R.id.tvOwnIP); sView=(SurfaceView)findViewById(R.id.sView); surfaceHolder=sView.getHolder();//获得surfaceview的surfaceHolder screenWidth=640; screenHeight=480; ipname=getLocalIpAddress(); tvOwnIP.setText(ipname); //为surfaceHolder添加一个回调监听器 surfaceHolder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { initCamera();//初始化摄像头,并打开摄像头 } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { //如果camera不为null,释放摄像头 if (camera!=null){ if (isPreview) camera.stopPreview(); camera.release(); camera=null; } System.exit(0);//退出程序 } }); //设置该SurfaceView自己不维护缓冲 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } private String getLocalIpAddress() { //获取本机IP地址 try{ for (Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();en.hasMoreElements();){ NetworkInterface intf=en.nextElement(); for (Enumeration<InetAddress> enumlpAddr=intf.getInetAddresses();enumlpAddr.hasMoreElements();){ InetAddress inetAddress=enumlpAddr.nextElement(); if (!inetAddress.isLoopbackAddress()){ return inetAddress.getHostAddress().toString(); } } } }catch (SocketException ex){ Log.e("WifiPreference Ip",ex.toString()); } return null; } private void initCamera(){ if (!isPreview){ camera=Camera.open();//打开摄像头 } if (camera!=null&&!isPreview){//摄像头已打开,但还没有进行预览 try{ Camera.Parameters parameters=camera.getParameters(); parameters.setPreviewSize(screenWidth, screenHeight);//设置预览照片的大小 parameters.setPreviewFpsRange(20, 30);//设置每秒显示20~30帧 parameters.setPictureFormat(ImageFormat.NV21);//设置图片格式 parameters.setPictureSize(screenWidth, screenHeight);//设置照片的大小 parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);//设置对焦模式 camera.setPreviewDisplay(surfaceHolder);//通过SurfaceView显示取景画面 camera.setPreviewCallback(new StreamIt(ipname));//设置回调 的类 camera.setDisplayOrientation(90);//让预览图像旋转90°,手机camera sensor默认是横屏 camera.startPreview();//开始预览 }catch (Exception e){ e.printStackTrace(); } isPreview=true;//开启预览后,给预览标志符true } } class StreamIt implements Camera.PreviewCallback{ private String ipname; public StreamIt(String ipname){ this.ipname=ipname; } @Override public void onPreviewFrame(byte[] data,Camera camera){ Size size=camera.getParameters().getPreviewSize(); try{ YuvImage image=new YuvImage(data,ImageFormat.NV21,size.width,size.height,null); if (image!=null){ ByteArrayOutputStream outstream=new ByteArrayOutputStream(); image.compressToJpeg(new Rect(0,0,size.width,size.height),80,outstream); outstream.flush(); Thread th=new MyThread(outstream,ipname); th.start(); } }catch (Exception ex){ Log.e("Sys", "Error:" + ex.getMessage()); } } } class MyThread extends Thread{ private int Port=Integer.parseInt(edOwnPort.getText().toString()); private byte byteBuffer[]=new byte[1024]; private OutputStream outsocket; private ByteArrayOutputStream myoutputstream; private String ipname; private ServerSocket ss; private Socket tempSocket; public MyThread(ByteArrayOutputStream myoutputstream,String ipname){ this.myoutputstream=myoutputstream; this.ipname=ipname; try{ myoutputstream.close(); }catch (IOException e){ e.printStackTrace(); } } public void run(){ try{ ss=new ServerSocket(Port); tempSocket = ss.accept(); outsocket = tempSocket.getOutputStream();//socket获得输出流 ByteArrayInputStream inputStream=new ByteArrayInputStream(myoutputstream.toByteArray()); int amount; while ((amount=inputStream.read(byteBuffer))!=-1){ //这个方法是先规定一个数组长度,将这个流中的字节缓冲到数组byteBuffer中,返回的是这个数组中的字节个数,这个缓冲区没有满的话,则返回真实的字节个数,到未尾时都返回-1 outsocket.write(byteBuffer,0,amount); //write(byte[] b, int off, int len): 将指定 byteBuffer数组中从偏移量 off 开始的 len 个字节写入此输出流,此处是: 上面把myoutputstream->inputStream->byteBuffer,并获得长度amount->把byteBuffer写入输出流outsocket } myoutputstream.flush(); //myoutputstream.reset(); myoutputstream.close(); //tempSocket.close(); }catch(IOException e){ e.printStackTrace(); } } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } } ``` 想实现的是,一启动程序就进入一直预览的状态,并等待socket的连接请求,一旦有请求过来,server端新建立一个socket去通信,然后将获取的每一帧图像,完整的通过socket发送出去,现在是可以实现预览,但连上socket后只发一次图像数据就没动静了,这时什么原因,在run()那段代码里调试了很久还是不行,求解 ?
相机预览按多任务键再返回应用黑屏问题,异常fail connect camera service
package com.yssh.myapplication; import android.app.Activity; import android.hardware.Camera; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import java.util.Collections; import java.util.Comparator; import java.util.List; public class MainActivity extends Activity implements SurfaceHolder.Callback{ private SurfaceView mCameraView; // 视频显示控件 private SurfaceHolder currentHolder = null; private boolean mIsSufaceCreated = false; private Camera mCamera; private Camera.Size mSize; public final int CAMERA_FACING_BACK = 0; // 0代表前置摄像头 @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.video_frame); mCameraView = (SurfaceView) findViewById(R.id.surface_local); currentHolder = mCameraView.getHolder();// 取得holder currentHolder.addCallback(this); // holder加入回调接口 // // setType必须设置,要不出错. if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB){ currentHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); releaseCamera(); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); releaseCamera(); } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub initCamera(); } @Override public void surfaceCreated(SurfaceHolder arg0) { // TODO Auto-generated method stub mIsSufaceCreated = true; currentHolder = arg0; } @Override public void surfaceDestroyed(SurfaceHolder arg0) { // TODO Auto-generated method stub mIsSufaceCreated = false; } private void initCamera() { //保证只有一个Camera对象 if (mCamera != null || !mIsSufaceCreated) { return; } try{ mCamera = Camera.open(CAMERA_FACING_BACK); CameraSizeComparator sizeComparator = new CameraSizeComparator(); Camera.Parameters parameters = mCamera.getParameters(); if (mSize == null) { List<Camera.Size> vSizeList = parameters.getSupportedPreviewSizes(); Collections.sort(vSizeList, sizeComparator); for (int num = 0; num < vSizeList.size(); num++) { Camera.Size size = vSizeList.get(num); if (size.width >= 800 && size.height >= 480) { this.mSize = size; break; } } mSize = vSizeList.get(0); List<String> focusModesList = parameters.getSupportedFocusModes(); //增加对聚焦模式的判断 if (focusModesList.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); } else if (focusModesList.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } mCamera.setParameters(parameters); } mCamera.setPreviewDisplay(currentHolder); mCamera.startPreview(); }catch (Exception e){ Log.d("mCamera", e.getMessage()); e.printStackTrace(); } } private class CameraSizeComparator implements Comparator<Camera.Size> { public int compare(Camera.Size lhs, Camera.Size rhs) { if (lhs.width == rhs.width) { return 0; } else if (lhs.width > rhs.width) { return 1; } else { return -1; } } } private void releaseCamera() { try { if (mCamera != null) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.unlock(); mCamera.release(); } } catch (RuntimeException e) { } finally { mCamera = null; } } }
Android拍视频预览的界面被拉伸
最近 Android 需要做一个拍视频保存然后上传的功能,基本功能实现了,但是有一个小 bug,就是预览的时候界面明显被拉长了,但是各种预览设置的参数也都试过了,都没有用,来请教一下。 #代码如下: ##1. Activity ``` public class RecordActivity extends AppCompatActivity implements SurfaceHolder.Callback { private SurfaceView mSurfaceView; private SurfaceHolder mSurfaceHolder; private Button btnStartStop; private boolean isRecording = false; // 标记是否已经在录制 private MediaRecorder mRecorder; // 音视频录制类 private Camera mCamera = null; // 相机 private List<Camera.Size> mSupportedPreviewSizes = null; private Camera.Size mPreviewSize; private Camera.Size mSize = null;// 相机的尺寸 private int mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK; // 默认后置摄像头 private static final SparseIntArray orientations = new SparseIntArray(); // 手机旋转对应的调整角度 static { orientations.append(Surface.ROTATION_0, 90); orientations.append(Surface.ROTATION_90, 0); orientations.append(Surface.ROTATION_180, 270); orientations.append(Surface.ROTATION_270, 180); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initWindow(); setContentView(R.layout.activity_record); initViews(); } /** * 初始化窗口 */ private void initWindow() { requestWindowFeature(Window.FEATURE_NO_TITLE); // 去掉标题栏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // 设置全屏 // 设置竖屏显示 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); // 选择支持半透明模式,在有 surfaceView 的 activity 中使用。 getWindow().setFormat(PixelFormat.TRANSLUCENT); } /** * 视图对象初始化 */ private void initViews() { mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview); btnStartStop = (Button) findViewById(R.id.btnStartStop); btnStartStop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!isRecording) { startRecord(); } else { stopRecord(); } } }); SurfaceHolder holder = mSurfaceView.getHolder(); // 取得holder holder.setFormat(PixelFormat.TRANSPARENT); holder.setKeepScreenOn(true); holder.addCallback(this); // holder加入回调接口 } /** * 初始化相机 */ private void initCamera() { /** * 默认打开后置摄像头 */ if (Camera.getNumberOfCameras() == 2) { mCamera = Camera.open(mCameraFacing); } else { mCamera = Camera.open(); } CameraSizeComparator sizeComparator = new CameraSizeComparator(); Camera.Parameters parameters = mCamera.getParameters(); if (mSize == null) { mSupportedPreviewSizes = parameters.getSupportedPreviewSizes(); Collections.sort(mSupportedPreviewSizes, sizeComparator); for (int num = 0; num < mSupportedPreviewSizes.size(); num++) { Camera.Size size = mSupportedPreviewSizes.get(num); if (size.width >= 1000 && size.height >= 1000) { this.mSize = size; break; } } mSize = mSupportedPreviewSizes.get(0); /** * 增加对聚焦模式的判断 */ List<String> focusModesList = parameters.getSupportedFocusModes(); if (focusModesList.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); } else if (focusModesList.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } mCamera.setParameters(parameters); } int rotation = getWindowManager().getDefaultDisplay().getRotation(); int orientation = orientations.get(rotation); mCamera.setDisplayOrientation(orientation); } @Override protected void onResume() { super.onResume(); initCamera(); } @Override public void onPause() { releaseCamera(); super.onPause(); } /** * 开始录制 */ private void startRecord() { if (mRecorder == null) { mRecorder = new MediaRecorder(); // 创建MediaRecorder } if (mCamera != null) { mCamera.stopPreview(); mCamera.unlock(); mRecorder.setCamera(mCamera); } try { // 设置音频采集方式 mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); // 设置视频的采集方式 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); /* mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 设置文件的输出格式 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 设置audio的编码格式 mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置video的编码格式 mRecorder.setVideoEncodingBitRate(10 * 1024 * 1024); // 设置录制的视频编码比特率 mRecorder.setVideoFrameRate(30); // 设置录制的视频帧率 mRecorder.setVideoSize(1920, 1080); // 设置相机分辨率 */ // 设置要捕获的视频的宽度和高度 // mSurfaceHolder.setFixedSize(optimalSize.width, optimalSize.height); mRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); // 设置记录会话的最大持续时间(毫秒) mRecorder.setMaxDuration(180 * 1000); mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); /** * 获取外部路径,然后将视频保存进去 */ String path = Environment.getExternalStorageDirectory().getPath(); if (path != null) { File dir = new File(path + "/crafts_videos"); if (!dir.exists()) { dir.mkdir(); } /** * 将 currentTimeMillis() 作为文件名 */ path = dir + "/" + System.currentTimeMillis() + ".mp4"; mRecorder.setOutputFile(path); //设置输出文件的路径 mRecorder.prepare(); //准备录制 mRecorder.start(); //开始录制 isRecording = true; btnStartStop.setText("停止"); } } catch (Exception e) { e.printStackTrace(); } } /** * 停止录制 */ private void stopRecord() { try { mRecorder.stop(); // 停止录制 mRecorder.reset(); // 重置 btnStartStop.setText("开始"); } catch (Exception e) { e.printStackTrace(); } isRecording = false; } /** * 释放 MediaRecorder */ private void releaseMediaRecorder() { if (mRecorder != null) { mRecorder.release(); mRecorder = null; } } /** * 释放相机资源 */ private void releaseCamera() { try { if (mCamera != null) { mCamera.stopPreview(); mCamera.setPreviewCallback(null); mCamera.unlock(); mCamera.release(); } } catch (RuntimeException e) { } finally { mCamera = null; } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 将holder,这个holder为开始在onCreate里面取得的holder,将它赋给mSurfaceHolder mSurfaceHolder = holder; if (mCamera == null) { return; } try { //设置显示 mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (Exception e) { e.printStackTrace(); releaseCamera(); finish(); } } @Override public void surfaceCreated(SurfaceHolder holder) { // 将holder,这个holder为开始在onCreate里面取得的holder,将它赋给mSurfaceHolder mSurfaceHolder = holder; try { mCamera.setPreviewDisplay(mSurfaceHolder); mCamera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { // surfaceDestroyed的时候同时对象设置为null if (isRecording && mCamera != null) { mCamera.lock(); } mSurfaceView = null; mSurfaceHolder = null; releaseMediaRecorder(); releaseCamera(); } private class CameraSizeComparator implements Comparator<Camera.Size> { public int compare(Camera.Size lhs, Camera.Size rhs) { if (lhs.width == rhs.width) { return 0; } else if (lhs.width > rhs.width) { return 1; } else { return -1; } } } } ``` ##2. 布局 ``` <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <SurfaceView android:id="@+id/surfaceview" android:layout_width="match_parent" android:layout_height="match_parent" /> <Button android:id="@+id/btnStartStop" android:layout_width="60dp" android:layout_height="40dip" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:text="开始" /> </RelativeLayout> ``` ##3. 权限 ``` <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 求大神解答
怎样给三个大小不同圆加一个线速度,并且停止的时候会因为角速度的不同,停止的时间不一样
public class LuckyPanView extends SurfaceView implements Callback, Runnable { private SurfaceHolder mHolder; // SurfaceView是 SurfaceHolder对象完成的 private Canvas mCanvas; //与SurfaceHolder这个对象绑定的Canvas private Thread t; //用于绘制的线程 private boolean isRunning; //线程的控制开关 private boolean rotateEnabled = false; public RotateListener listern; public String[] mStrs = new String[] { "0", "1", "2", "3", //转盘上的的数字 "4", "5","6","7","8","9" }; public int[] mColors = new int[] { 0xFFFFC300, 0xFFF17E01, 0xff00ffff, //每个盘块的颜色 0xFFFFA500, 0xFF7FFF00, 0xFFB0C4DE,0xFFF08080,0xFFB0E0E6, 0xFF444444, 0xFF008B8B, }; private int mItemCount = 10;//盘块的个数 private RectF mRange = new RectF();// 绘制盘块的范围 private RectF mRange1 = new RectF(); private RectF mRange2 = new RectF(); private float mRadius;//圆的半径 private float mRadius1; private float mRadius2; private Paint mArcPaint;//绘制盘块的画笔 private Paint mTextPaint;//绘制文字的画笔 private double mSpeed; //滚动的速度 private volatile float mStartAngle = 0; private boolean isShouldEnd;//是否点击了停止 private int mPadding; //控件的padding, /** * 文字的大小 */ private float mTextSize = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 15, getResources().getDisplayMetrics()); public LuckyPanView(Context context) { this(context, null);//初始化,设置生命周期回调方法?? } public LuckyPanView(Context context, AttributeSet attrs)//设置Surface生命周期回调 { super(context, attrs); mHolder = getHolder(); mHolder.addCallback(this);//设置Surface生命周期回调 setFocusable(true); setFocusableInTouchMode(true); this.setKeepScreenOn(true); } /** * 设置控件为正方形 View在屏幕上显示出来要先经过measure(计算)和layout(布局). */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)//调用onMeasure方法 然后传入两个参数——widthMeasureSpec和 // heightMeasureSpec 来确定占多大的地方 { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = Math.min(getMeasuredWidth(), getMeasuredHeight()); //int width=width1/2; mRadius = (width - getPaddingLeft()+30 )/2;// 获取圆形的直径 mRadius1 = (width - getPaddingLeft() - getPaddingRight())/4; mRadius2 = (width - getPaddingLeft() - getPaddingRight()+50)/6; mPadding = getPaddingLeft();// padding值 } @Override public void surfaceCreated(SurfaceHolder holder) { // 初始化绘制圆弧的画笔 mArcPaint = new Paint(); mArcPaint.setAntiAlias(true); mArcPaint.setDither(true); // 初始化绘制文字的画笔 mTextPaint = new Paint(); mTextPaint.setColor(0xFFffffff); mTextPaint.setTextSize(mTextSize); // 圆的四个顶点绘制范围 虚拟机上的比例 mRange = new RectF(getPaddingLeft()-35, getPaddingRight()-40, mRadius + getPaddingLeft()-35, mRadius + getPaddingLeft()-40); mRange1=new RectF(getPaddingLeft()+400, getPaddingRight()+590, mRadius1 + getPaddingLeft()+400, mRadius1 + getPaddingLeft()+590); mRange2=new RectF(getPaddingLeft()+200, getPaddingRight()+595, mRadius2 + getPaddingLeft()+200, mRadius2 + getPaddingLeft()+595); // 圆的四个顶点绘制范围 /** mRange = new RectF(getPaddingLeft()-35, getPaddingRight()-40, mRadius + getPaddingLeft()-35, mRadius + getPaddingLeft()-40); mRange1=new RectF(getPaddingLeft()+80, getPaddingRight()+800, mRadius1 + getPaddingLeft()+80, mRadius1 + getPaddingLeft()+800); mRange2=new RectF(getPaddingLeft()+360, getPaddingRight()+460, mRadius2 + getPaddingLeft()+360, mRadius2 + getPaddingLeft()+460); **/ // 开启线程 isRunning = true; t = new Thread(this); t.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, //初始化了绘制需要用到的变量, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { // 通知关闭线程 isRunning = false; } @Override public void run() { // 不断的进行draw 控制转速 while (isRunning) { long start = System.currentTimeMillis(); //System.currentTimeMillis(); 是获得当前时间 距离 起始时间的经过毫秒数 draw(); long end = System.currentTimeMillis(); try { if (end - start < 50)// 数值越大 越慢 { Thread.sleep(50- (end - start)); } } catch (InterruptedException e) { e.printStackTrace(); } } } private void draw() { try { // 使用通过 mHolder.lockCanvas();获得Canvas,然后就可以绘制了 mCanvas = mHolder.lockCanvas(); if (mCanvas != null) { // 绘制背景图 drawBg(); /** * 绘制每个块块,每个块块上的文本, */ float tmpAngle = mStartAngle; float sweepAngle = (float) (360 / mItemCount); //每一块的角度 for (int i = 0; i < mItemCount; i++) { // 绘制块块 mArcPaint.setColor(mColors[i]); //画扇形 mCanvas.drawArc(mRange, tmpAngle, sweepAngle, true, mArcPaint); mCanvas.drawArc(mRange1, tmpAngle, sweepAngle, true, mArcPaint); mCanvas.drawArc(mRange2, tmpAngle, sweepAngle, true, mArcPaint); // 绘制文本 drawText(tmpAngle, sweepAngle, mStrs[i]); tmpAngle += sweepAngle; //生成全部的扇形块 } // 如果mSpeed不等于0,则相当于在滚动 mStartAngle += mSpeed; // 点击停止时,设置mSpeed为递减,为0值转盘停止 if (isShouldEnd) { mSpeed -= 1; } if (mSpeed <= 0) { mSpeed = 0; isShouldEnd = false; } // 根据当前旋转的mStartAngle计算当前滚动到的区域 calInExactArea(mStartAngle); } } catch (Exception e) { e.printStackTrace(); } finally { if (mCanvas != null) mHolder.unlockCanvasAndPost(mCanvas); } } /** * 根据当前旋转的mStartAngle计算当前滚动到的区域 绘制背景 绘制一个棕色的圆盘 */ private void drawBg() { mCanvas.drawColor(0xffccccc); //背景灰色 } /** * 根据当前旋转的mStartAngle计算当前滚动到的区域 */ public void calInExactArea(float startAngle) { // 让指针从水平向右开始计算 float rotate = startAngle + 90; rotate %= 360.0; for (int i = 0; i < mItemCount; i++) // for循环,且角度每次递增(360 / mItemCount);就是绘制每个盘块以及盘块上的字体和图标了。 { // 每个的中奖范围 float from = 360 - (i + 1) * (360 / mItemCount); float to = from + 360 - (i) * (360 / mItemCount); if ((rotate > from) && (rotate < to)) { listern.showEndRotate(mStrs[i]); Log.d("TAG", mStrs[i]); return; } } } /** * 绘制文本 * * @param startAngle * @param sweepAngle * @param string */ private void drawText(float startAngle, float sweepAngle, String string) { Path path = new Path(); path.addArc(mRange, startAngle, sweepAngle);//利用Path,添加入一个Arc,然后设置水平和垂直的偏移量, // 垂直偏移量就是当前Arc朝着圆心移动的距离;水平偏移量,就是顺时针去旋转 Path path1 = new Path(); path1.addArc(mRange1, startAngle, sweepAngle); Path path2 = new Path(); path2.addArc(mRange2, startAngle, sweepAngle); float textWidth = mTextPaint.measureText(string); /*偏移 (mRadius * Math.PI / mItemCount / 2 - textWidth / 2);目的是为了文字居中。mRadius * Math.PI 是圆的周长; 周长/ mItemCount / 2 是每个Arc的一半的长度;拿Arc一半的长度减去textWidth / 2,就把文字设置居中了。最后,用过path去绘制文本 */ float hOffset = (float) (mRadius * Math.PI / mItemCount / 2 - textWidth / 2);// 利用水平偏移让文字居中 float vOffset = mRadius / 2 / 4;// 垂直偏移 mCanvas.drawTextOnPath(string, path, hOffset, vOffset, mTextPaint); float hOffset1 = (float) (mRadius1 * Math.PI / mItemCount / 2 - textWidth/2 );// 利用水平偏移让文字居中 float vOffset1= mRadius1 / 6;// 垂直偏移 mCanvas.drawTextOnPath(string, path1, hOffset1, vOffset1, mTextPaint); float hOffset2 = (float) (mRadius2 * Math.PI / mItemCount / 2 - textWidth/2 );// 利用水平偏移让文字居中 float vOffset2= mRadius2 / 6;// 垂直偏移 mCanvas.drawTextOnPath(string, path2, hOffset2, vOffset2, mTextPaint); } public void setRotateListener(RotateListener ln) { listern = ln; } /** * 点击开始旋转 * * @param luckyIndex */ public void luckyStart(int luckyIndex) { // 每项角度大小 float angle = (float) (360 / mItemCount); // 中奖角度范围(因为指针向上,所以水平第一项旋转到指针指向,需要旋转72-144;) float from = 144 - (luckyIndex + 1) * angle; float to = from + angle; // 停下来时旋转的距离 float targetFrom = 2 *10 + from;//targetFrom是决定你点击停止的时候转多长距离 4圈多 多的用from和to调整 float v1 = (float) (Math.sqrt(1 * 1 + 8 * 1 * targetFrom) - 1) / 2; float targetTo = 2 * 360 + to; float v2 = (float) (Math.sqrt(1 * 1 + 8 * 1 * targetTo) - 1) / 2; mSpeed = (float) (v1 + Math.random() * (v2 - v1)); isShouldEnd = false; } public void luckyEnd()//让圆盘停止滚动 { mStartAngle = 0; isShouldEnd = true; } public boolean isStart() { return mSpeed != 0; } public boolean isShouldEnd() { return isShouldEnd; } public boolean isRotateEnabled() { return rotateEnabled; } }
Android 怎么将主程序添加到欢迎界面里面
我做好了一个欢迎界面,并且做了下按钮触发,里面什么都还没有,我这边有一个游戏主程序,应该怎么样才能合理的添加进去呢? 添加的结果就是 点击这个按钮 就进入这个主程序。下面是代码 这个是我的欢迎界面的代码 package sen.tan; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; public class dazhuankuaiActivity extends Activity { BallView myview; public static int screenWidth ; public static int screenHeight; private TextView textview; Button kaishi,jieshu,guanyu; ImageView image; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String string = "欢迎进入疯狂打砖块游戏"; image = (ImageView) this.findViewById(R.id.image); image.setImageResource(R.drawable.img1); textview =(TextView) this.findViewById(R.id.textview); textview.setTextSize(20); textview.setTextColor(Color.GREEN); textview.setBackgroundColor(Color.RED); textview.setText(string); kaishi=(Button)findViewById(R.id.button1); guanyu=(Button)findViewById(R.id.button2); jieshu=(Button)findViewById(R.id.button3); kaishi.setWidth(250); guanyu.setWidth(200); jieshu.setWidth(150); kaishi.setTextSize(35); guanyu.setTextSize(29); jieshu.setTextSize(24); jieshu.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v) { dazhuankuaiActivity.this.finish(); } }); guanyu.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ textview.setText("本游戏由xxx制作,此游戏控制左右按键,来回移动挡板,不让小球掉落,当小球把上方砖块全部打完时,游戏胜利"); } }); kaishi.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v) { } }); 下面是我找到的主程序 package ab.cc; import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Window; import android.view.WindowManager; public class BaomingActivity extends Activity { BallView myView; static int screenWidth; static int screenHeight; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* 定义DisplayMetrics对象 */ DisplayMetrics dm = new DisplayMetrics(); /* 取得窗口属性 */ getWindowManager().getDefaultDisplay().getMetrics(dm); /* 窗口的宽度 */ screenWidth = dm.widthPixels; /* 窗口的高度 */ screenHeight = dm.heightPixels; // setTitle("宽"+screenWidth+" 高"+screenHeight); /* 设置为无标题栏 */ requestWindowFeature(Window.FEATURE_NO_TITLE); /* 设置为全屏模式 */ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); myView = new BallView(this); //设置显示GameSurfaceView视图 setContentView(myView); }//end of onCreate() //触笔事件 public boolean onTouchEvent(MotionEvent event) { return true; } //按键按下事件 public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { //菜单按键-设为初始菜单 case KeyEvent.KEYCODE_MENU: myView.resetGame(); //重新开始 break; //中间按键 case KeyEvent.KEYCODE_DPAD_CENTER: myView.ball_isRun = !myView.ball_isRun;//开始//暂停 break; //左方向键 case KeyEvent.KEYCODE_DPAD_LEFT: if(myView.ball_isRun){ if(myView.board_left<=myView.board_x_move) { myView.board_left=0; myView.board_right=myView.board_length; }else{ myView.board_left-=myView.board_x_move; myView.board_right-=myView.board_x_move;} } break; //右方向键 case KeyEvent.KEYCODE_DPAD_RIGHT: if(myView.ball_isRun){ if(screenWidth-myView.board_right<=myView.board_x_move ) { myView.board_left=screenWidth-myView.board_length; myView.board_right=screenWidth; }else{ myView.board_left+=myView.board_x_move; myView.board_right+=myView.board_x_move; } } break; //上方向键 case KeyEvent.KEYCODE_DPAD_UP: if(myView.ball_isRun){ if( myView.board_alterable_top==myView.board_default_top) { myView.board_alterable_top-=myView.boardYadd; myView.board_alterable_bottom-=myView.boardYadd; } } break; //下方向键 case KeyEvent.KEYCODE_DPAD_DOWN: if(myView.ball_isRun){ if( myView.board_alterable_top==myView.board_default_top-myView.boardYadd ) { myView.board_alterable_top=myView.board_default_top; myView.board_alterable_bottom=myView.board_alterable_top+myView.board_thickness; } } break; //返回键 case KeyEvent.KEYCODE_BACK: this.finish(); break; }//end switch return false; } //按键弹起事件 public boolean onKeyUp(int keyCode, KeyEvent event) { return true; } public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { return true; } } package ab.cc; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RadialGradient; import android.graphics.Shader; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class BallView extends SurfaceView implements SurfaceHolder.Callback, Runnable { //线程延时控制 final int ball_sleep=1;//毫秒,延时越大,球速越慢 final int ball_r= 8;//小球半径 final float ball2_r= 8;//底下滚珠小球半径 final int ballXorYadd = 4;//小球的基本位移。测试可行值:2,4 //获取屏幕宽度和高度 int screen_width;//320; int screen_height;//480; //砖的属性 int brick_width;//每块砖宽 int brick_height;//每块砖高 boolean brick_exist[];//砖是否存在 int k ;// 列//到for循环里才初始化 int j ;// 行 int brick_left = brick_width*(k-1);//到判断语句才初始化 int brick_right = brick_width*k; int brick_top = brick_height*j; int brick_bottom = brick_height*(j+1); //挡板的属性 int board_length;//挡板长度:80比较合适,可以随意修改,但别超过screen_width final int boardYadd = 16;//按上下键时挡板y方向位移量。经验证4、8、16可以,12不行 final int board_x_move = 30;//挡板x方向位移量:可以随意自定义 int board_left;//挡板左侧(可变) int board_right;//挡板右侧(可变) int board_thickness;//挡板厚度 int board_default_top;//即435,挡板的top面初始位置 int board_alterable_top;//挡板上侧(可变) int board_alterable_bottom;//挡板下侧(可变) int ball_default_x;//球的初始x坐标 int ball_default_y;//球的初始y坐标 //球的即时坐标(可变): int ball_x;//球心横坐标 int ball_y;//球心纵坐标 //球的前一步的y坐标 int ball_previous_y; int ball_x_speed;//球的横向偏移量//可变 int ball_y_speed;//球的纵向偏移量//可变 boolean ball_isRun;//球是否在动 // 控制循环 boolean mbLoop; // 定义SurfaceHolder对象 SurfaceHolder mSurfaceHolder = null; //获得分数 int score; /* 唤醒渐变渲染 */ Shader mRadialGradient = null; //------------------------------------------------------------------------------------------------------// public BallView(Context context) { super(context); // 实例化SurfaceHolder mSurfaceHolder = this.getHolder(); // 添加回调 mSurfaceHolder.addCallback(this); this.setFocusable(true); //获取屏幕宽度和高度 screen_width = BaomingActivity.screenWidth;//320 screen_height = BaomingActivity.screenHeight;//480 //砖的属性 brick_width = screen_width/5;//每块砖宽64 brick_height = screen_height/15;//每块砖高32 //挡板的属性 board_length = screen_width/4;//挡板长度:80比较合适,可以随意修改,但别超过screen_width board_left = (screen_width-board_length)/2;//挡板左侧(可变) board_right = (screen_width+board_length)/2;//挡板右侧(可变) board_thickness = 5;//挡板厚度 board_default_top = 13*screen_height/15;//即435,挡板的top面初始位置 board_alterable_top = board_default_top;//挡板上侧(可变) board_alterable_bottom = board_alterable_top+board_thickness;//挡板下侧(可变) ball_default_x = screen_width/2;//球的初始x坐标 ball_default_y = board_default_top - ball_r;//球的初始y坐标 //球的即时坐标(可变): ball_x = ball_default_x; ball_y = ball_default_y; //球的前一步的y坐标 ball_previous_y = 0; ball_x_speed = ballXorYadd;//球的横向偏移量 ball_y_speed = ballXorYadd;//球的纵向偏移量 mbLoop = true; ball_isRun = false; score=0; brick_exist = new boolean[25]; for (int i = 0; i < 25; i++) { brick_exist[i] = true; } /* 构建RadialGradient对象,设置半径的属性 */ mRadialGradient = new RadialGradient(ball_x, ball_y, ball_r,//球中心坐标x,y,半径r new int[]{Color.WHITE,Color.BLUE,Color.GREEN,Color.RED,Color.YELLOW},//颜色数组 null,//颜色数组中每一种颜色对应的相对位置,为空的话就是平均分布,由中心向外排布 Shader.TileMode.REPEAT);//渲染模式:重复 } public void resetGame(){ ball_isRun = false; score =0;//分数 ball_x_speed = ballXorYadd;//球的横向偏移量 ball_y_speed = ballXorYadd;//球的纵向偏移量 ball_x = screen_width/2;//球心起始横坐标 ball_y = board_default_top - ball_r;//球心起始纵坐标 board_left = (screen_width-board_length)/2;//挡板左侧 board_right = (screen_width+board_length)/2;//挡板右侧 board_alterable_top = board_default_top;//挡板上侧 board_alterable_bottom = board_alterable_top+board_thickness;//挡板下侧 for (int i = 0; i < 25; i++) { brick_exist[i] = true; } } //---------------------------------绘图循环开始---------------------------------- public void run() { while (mbLoop&&!Thread.currentThread().isInterrupted()) { try { Thread.sleep(ball_sleep); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } //球的前一步y坐标 ball_previous_y = ball_y; if (ball_isRun) { ballRunning();// 让小球移动 boardPositionCheck();//检测挡板是否处于“中线”位置,是就随小球上升一步,直至到“上线” hitWallCheck();//墙壁碰撞检测 hitBoardCheck();//挡板碰撞检测 hitBrickCheck();//砖块碰撞检测 } synchronized (mSurfaceHolder) { Draw(); } } } //---------------------------------绘图循环结束---------------------------------- //------------------------------------------------------------------------------ //让小球移动 public void ballRunning() { ball_x += ball_x_speed; ball_y -= ball_y_speed; } //朝左或朝右碰撞后小球水平方向逆向 public void ballLeftOrRightHit() { ball_x_speed *= -1; } //朝上或朝下碰撞后小球竖直方向逆向 public void ballUpOrDownHit() { ball_y_speed *= -1; } public void ballcornerHit() { ball_x_speed *= -1; ball_y_speed *= -1; } public void ballStraightUp() {//功能没实现,这是多余代码 ball_x_speed = 0;//注意在其他地方恢复 ball_y_speed *= -1; } //-------------------墙壁碰撞检测开始------------------------------------- public void hitWallCheck() { // 左碰墙 if (ball_x <= ball_r && ball_y >= ball_r && ball_y <= screen_height) { ballLeftOrRightHit(); // 右碰墙 } if (ball_x >= screen_width - ball_r && //不能写为 else if,因为可能恰好碰到角落。 ball_y >= ball_r && ball_y <= screen_height) { ballLeftOrRightHit(); } // 上碰墙 if (ball_x >= ball_r && ball_x <= screen_width - ball_r && ball_y <= ball_r + brick_height) //、、、、、、、、、、、、、、、25号修改 { ballUpOrDownHit(); } // 下碰墙 if (ball_x >= ball_r && ball_x <= screen_width - ball_r && ball_y >= screen_height-ball_r) { ballUpOrDownHit(); if(score<=10){ score = 0; } else score-=10; } } //-------------------墙壁碰撞检测结束------------------------------------- //-----------------------------挡板碰撞检测开始--------------------------- public void hitBoardCheck() { // 下碰挡板正面 if (ball_x >= ball_r && ball_x <= screen_width - ball_r && //在屏幕内,起码条件 ball_x >= board_left && ball_x <= board_right && //在挡板X域上方 ball_y == board_alterable_top - ball_r &&//球面与挡板相切 ball_previous_y <= board_alterable_top - ball_r //确定球是从上方下落 ) { if(board_alterable_top==board_default_top-boardYadd ){//如果弹簧伸张,挡板位于上线 ballHitBoardlower();//作用:ball_y_move减小;挡板被打下;小球Y向运动反向 } else if(board_alterable_top==board_default_top){//如果弹簧压缩,挡板位于下线 boardHitBallHigher();//作用:ball_y_move增加;挡板弹上;小球Y向运动反向 } } //斜碰挡板右上角//经验证有效 else if(Math.pow(board_right-ball_x, 2)+Math.pow(board_alterable_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>board_right && ball_y<board_alterable_top) { ballcornerHit(); } //斜碰挡板的左上角//经验证有效 else if(Math.pow(board_left-ball_x, 2)+Math.pow(board_alterable_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x<board_left && ball_y<board_alterable_top) { ballcornerHit(); } } //-----------------------------挡板碰撞检测结束-------------------------- private void boardHitBallHigher() {//增强 ballUpOrDownHit();//小球Y方向反向,ball_y_speed变为正数 if(ball_y_speed == ballXorYadd ){ ball_y_speed += ballXorYadd;//离开挡板后小球Y方向速度增强 } if( boardYadd > ball_y_speed ){//在线程这一轮,小球上升多少,挡板就上升多少。 board_alterable_top = board_default_top - ball_y_speed; board_alterable_bottom= board_alterable_top+board_thickness;//挡板下层面 } } //检测挡板是否处于“中线”位置,是就随小球上升一步,直至到“上线” private void boardPositionCheck() {//还可直接利用球的位置刷新,board_top与球心相差ball_r if(board_alterable_top < board_default_top && board_alterable_top > board_default_top-boardYadd){ //挡板随球上升 if(board_alterable_top - ball_y_speed >= board_default_top-boardYadd){ board_alterable_top -= ball_y_speed;//挡板上层面 board_alterable_bottom= board_alterable_top+board_thickness;//挡板下层面 } else{ board_alterable_top = board_default_top-boardYadd;//挡板上层面 board_alterable_bottom= board_alterable_top+board_thickness;//挡板下层面 } } } private void ballHitBoardlower() {//减弱 board_alterable_top=board_default_top; board_alterable_bottom=board_default_top+board_thickness;//挡板被打退 ballUpOrDownHit();//小球Y方向反向 if(ball_y_speed==2*ballXorYadd){ ball_y_speed -= ballXorYadd;//小球Y方向速度减弱 } } //砖块碰撞检测开始----------------------------------------------------------- public void hitBrickCheck() { for (int i = 0; i <25 ; i++) { if (brick_exist[i]) { k = i % 5+1;// 1,2,3,4,5循环 j = i / 5+1;// 1,1,1,1,1;2,2,2,2,2,;...;5,5,5,5,5 brick_left = brick_width*(k-1); brick_right = brick_width*k; brick_top = brick_height*j; brick_bottom = brick_height*(j+1); //朝下碰砖的top面 AAAAAAAAAAAAAAAAAAAAA if(ball_x >= brick_left && ball_x <= brick_right && ball_y >= brick_top-ball_r && ball_y < brick_top) { ballUpOrDownHit(); brick_exist[i] = false; score+=4; //朝下正碰2砖中间,i砖右上角检测 if(k!=5 && ball_x == brick_right)//如果不是第5列砖的右侧边 { //如果砖[i+1]存在 if(brick_exist[i+1]){ brick_exist[i+1] = false; score+=4; } } //朝下正碰2砖中间,i砖左上角检测 else if(k!=1 && ball_x == brick_left)//如果不是第1列砖的左侧边 { //如果砖[i-1]存在 if(brick_exist[i-1]){ brick_exist[i-1] = false; score+=4; } } } //朝上碰砖的bottom面 BBBBBBBBBBBBBBBBB else if(ball_x >= brick_left && ball_x <= brick_right && ball_y > brick_bottom&& ball_y <= brick_bottom + ball_r ) { ballUpOrDownHit(); brick_exist[i] = false; score+=4; //朝上正碰2块砖中间--i砖的右下角检测 if(k!=5 && ball_x == brick_right) //如果不是第5列砖的右侧边 { if(brick_exist[i+1]){//如果砖[i+1]存在 brick_exist[i+1] = false; score+=4; } } //朝上正碰2块砖中间--i砖的左下角检测 else if(k!=1 && ball_x == brick_left) //如果不是第1列砖的左侧边 { if(brick_exist[i-1]){//如果砖[i-1]存在 brick_exist[i-1] = false; score+=4; } } } //朝右碰砖的left面CCCCCCCCCCCCCCCCC else if(ball_x >= brick_left -ball_r&&ball_x < brick_left&& ball_y >= brick_top && ball_y <= brick_bottom) { ballLeftOrRightHit(); brick_exist[i] = false; score+=4; //朝右正碰2块砖中间,左下角检测 if(j!=5 && ball_y == brick_bottom)//如果不是第5行砖的下侧边 { if(brick_exist[i+5]){//如果砖[i+5]存在 brick_exist[i+5] = false; score+=4; } } //朝右正碰2块砖中间,左上角检测 else if(j!=1 && ball_y == brick_top)//如果不是第1行砖的上侧边 { if(brick_exist[i-5]){//如果砖[i-5]存在 brick_exist[i-5] = false; score+=4; } } } //朝左碰砖的right面DDDDDDDDDDDDDDDDDD else if(ball_x >= brick_right && ball_x <= brick_right+ball_r&& ball_y >= brick_top && ball_y <= brick_bottom) { ballLeftOrRightHit(); brick_exist[i] = false; score+=4; //朝左正碰2块砖中间,右下角检测 if(j!=5 && ball_y == brick_bottom )//如果不是第5行砖的下侧边 { if(brick_exist[i+5]){//如果砖[i+5]存在 brick_exist[i+5] = false; score+=4; } } //朝左正碰2块砖中间,右上角检测 else if(j!=1 && ball_y == brick_top )//如果不是第1行砖上侧边 { if(brick_exist[i-5]){//如果砖[i-5]存在 brick_exist[i-5] = false; score+=4; } } } ///////////////////////////////////////// //斜碰i砖的左下角EEEEEEEEEEEEEEEEEEEEEEEE else if(( i-1<0||(i-1>=0&&!brick_exist[i-1]) ) && (i+5>=25||(i+5<25&&!brick_exist[i+5]) )&& Math.pow(brick_left-ball_x, 2)+Math.pow(brick_bottom-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_left-ball_r && ball_x<brick_left && ball_y>brick_bottom && ball_y<brick_bottom+ball_r ) { ballcornerHit(); brick_exist[i] = false; score+=4; } //斜碰i砖的右下角FFFFFFFFFFFFFFFFFFFFFFFFFF else if( (i+1>=25||(i+1<25&&!brick_exist[i+1]) )&& (i+5>=25||(i+5<25&&!brick_exist[i+5]) )&& Math.pow(brick_right-ball_x, 2)+Math.pow(brick_bottom-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_right&&ball_x<brick_right+ball_r&& ball_y>brick_bottom&&ball_y<brick_bottom+ball_r ) { Log.v("----------", "right bottom hit"+i+":"+brick_exist[i]); ballcornerHit(); brick_exist[i] = false; score+=4; } //斜碰i砖的右上角GGGGGGGGGGGGGGGGGGGGGGGG else if( (i+1>=25||(i+1<25&&!brick_exist[i+1]) )&& (i-5<0||(i-5>0&&!brick_exist[i-5]) )&& Math.pow(brick_right-ball_x, 2)+Math.pow(brick_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_right && ball_x<brick_right+ball_r&& ball_y>brick_top-ball_r && ball_y<brick_top) { ballcornerHit(); brick_exist[i] = false; score+=4; } //斜碰i砖的左上角HHHHHHHHHHHHHHHHHHHHHHHHHH else if((i-1<0||(i-1>=0&&!brick_exist[i-1])) && (i-5<0||(i-5>=0&&!brick_exist[i-5])) && Math.pow(brick_left-ball_x, 2)+Math.pow(brick_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_left-ball_x && ball_x<brick_left && ball_y>brick_top-ball_r && ball_y<brick_top ) { ballcornerHit(); brick_exist[i] = false; score+=4; } }//end if }//end for }//end hitBrickCheck() //砖块碰撞检测结束----------------------------------------------------------- //------------------------------------------ public boolean gameOver(){ int count = 0; for(boolean s:brick_exist){ if(!s){ count++; } } if(count == 25){ return true; }else{ return false; } } //------------------------------------------ //---------------绘图方法开始------------------------ public void Draw() { // 锁定画布,得到canvas Canvas canvas = mSurfaceHolder.lockCanvas(); if (mSurfaceHolder == null || canvas == null) { return; } // 绘图 Paint mPaint = new Paint(); // 设置取消锯齿效果 mPaint.setAntiAlias(true); mPaint.setColor(Color.GREEN); // 绘制矩形--背景 canvas.drawRect(0, 0, screen_width, brick_height-2, mPaint); mPaint.setColor(Color.MAGENTA); // 绘制矩形--背景 canvas.drawRect(0, brick_height-2, screen_width, screen_height, mPaint); mPaint.setColor(Color.RED);//设置字体颜色 mPaint.setTextSize(brick_height-7);//设置字体大小 canvas.drawText("得分:"+score, 0, brick_height-7, mPaint); // 绘制顶层挡板````````````````````````````````````````````````````````25号修改 mPaint.setColor(Color.BLACK);//设置颜色 mPaint.setStrokeWidth(4);//设置粗细 canvas.drawLine(0, brick_height-2, screen_width, brick_height-2, mPaint); for (int i = 0; i <25 ; i++) { if (brick_exist[i]) { k = i % 5+1;// 1,2,3,4,5循环 j = i / 5+1;// 1,1,1,1,1;2,2,2,2,2,;...;5,5,5,5,5 brick_left = brick_width*(k-1); brick_right = brick_width*k; brick_top = brick_height*j; brick_bottom = brick_height*(j+1); mPaint.setStyle(Paint.Style.FILL);// 设置实心画笔 mPaint.setColor(Color.BLACK); canvas.drawRect(brick_left+1, brick_top+1, brick_right-1,brick_bottom-1, mPaint); mPaint.setStyle(Paint.Style.STROKE);// 设置空心画笔 mPaint.setStrokeWidth(2);//设置粗细 mPaint.setColor(Color.RED); canvas.drawRect(brick_left+3, brick_top+3, brick_right-3,brick_bottom-3, mPaint); } } // 设置实心画笔 mPaint.setStyle(Paint.Style.FILL); { mPaint.setShader(mRadialGradient); canvas.drawCircle(ball_x, ball_y, ball_r, mPaint); } Paint mPaint2 = new Paint(); // 设置取消锯齿效果 mPaint2.setAntiAlias(true); // 设置实心画笔 mPaint2.setStyle(Paint.Style.FILL); { mPaint2.setColor(Color.BLACK); /* 绘制矩形挡板 */ canvas.drawRect(board_left, board_alterable_top, board_right, board_alterable_bottom,mPaint2); float board2_bottom = screen_height - 2*ball2_r;//164 float board2_top = board2_bottom - 4;//160 //线段端点坐标数组 float x0 = board_left+(board_right-board_left)/4; float y0 = board_alterable_bottom;//440或者444 float springAdd = (board2_top- board_alterable_bottom)/8;//即2.5或者2:弹簧小线段的y向长度 float springWidth = 5.0f;//弹簧小线段的x向长度 float x1 = x0 - springWidth; float y1 = y0 + springAdd; float x2 = x0 + springWidth; float y2 = y0 + 3*springAdd; float x3 = x1 ; float y3 = y0 + 5*springAdd; float x4 = x2; float y4 = y0 + 7*springAdd; float x5 = x0 ; float y5 = board2_top;//即460 float between_spring = (board_right-board_left)/2; float pts[] = { x0,y0,x1,y1, x1,y1,x2,y2, x2,y2,x3,y3, x3,y3,x4,y4, x4,y4,x5,y5}; float pts2[] = {x0+between_spring,y0, x1+between_spring,y1, x1+between_spring,y1, x2+between_spring,y2, x2+between_spring,y2, x3+between_spring,y3, x3+between_spring,y3, x4+between_spring,y4, x4+between_spring,y4, x5+between_spring,y5}; mPaint2.setStrokeWidth(2);//设置弹簧粗细 //绘制2个弹簧 canvas.drawLines(pts, mPaint2); canvas.drawLines(pts2, mPaint2); //绘制下层挡板 canvas.drawRect(board_left, board2_top, board_right, board2_bottom,mPaint2); mPaint2.setColor(Color.BLACK);// // 绘制最下面的两个“轮子”(圆心x,圆心y,半径r,p) canvas.drawCircle(board_left+ball2_r, screen_height-ball2_r, ball2_r, mPaint2);//圆 canvas.drawCircle(board_right-ball2_r, screen_height-ball2_r, ball2_r, mPaint2); mPaint2.setColor(Color.WHITE);// }//实心画笔mPaint2结束 if(gameOver()){ // mbLoop = false;//注释掉的话GAME OVER后也可重启 ball_isRun = false; mPaint2.setColor(Color.BLACK);//设置字体颜色 mPaint2.setTextSize(40.0f);//设置字体大小 canvas.drawText("GAME OVER", screen_width/32+40, screen_height/16*9-70, mPaint2); mPaint2.setTextSize(20.0f);//设置字体大小 canvas.drawText("Press \"MENU\" button to restart,", screen_width/32, //320/32=10 screen_height/16*9, //480/16=30,30*9=270 mPaint2); canvas.drawText("Press \"BACK\" button to exit.", screen_width/32, //320/32=10 screen_height/16*10, //480/16=30,30*10=300 mPaint2); } // 绘制后解锁,绘制后必须解锁才能显示 mSurfaceHolder.unlockCanvasAndPost(canvas); }// end of Draw() //---------------------绘图方法结束----------------------------------------------- // 在surface的大小发生改变时激发 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } // 在surface创建时激发 public void surfaceCreated(SurfaceHolder holder) { new Thread(this).start();// 开启绘图线程 } // 在surface销毁时激发 public void surfaceDestroyed(SurfaceHolder holder) { // 停止循环 mbLoop = false; } } 能否回答的详细一点,学的时间短,求帮忙
重力感应控制画布小球问题
import android.app.Activity; import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.Window; import android.view.WindowManager; import android.view.SurfaceHolder.Callback; public class SurfaceViewAcitvity extends Activity { MyView mAnimView = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 全屏显示窗口 requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //强制横屏 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // 显示自定义的游戏View mAnimView = new MyView(this); setContentView(mAnimView); } public class MyView extends SurfaceView implements Callback,Runnable ,SensorEventListener{ /**每50帧刷新一次屏幕**/ public static final int TIME_IN_FRAME = 50; /** 游戏画笔 **/ Paint mPaint = null; Paint mTextPaint = null; SurfaceHolder mSurfaceHolder = null; /** 控制游戏更新循环 **/ boolean mRunning = false; /** 游戏画布 **/ Canvas mCanvas = null; /**控制游戏循环**/ boolean mIsRunning = false; /**SensorManager管理器**/ private SensorManager mSensorMgr = null; Sensor mSensor = null; /**手机屏幕宽高**/ int mScreenWidth = 0; int mScreenHeight = 0; /**小球资源文件越界区域**/ private int mScreenBallWidth = 0; private int mScreenBallHeight = 0; /**游戏背景文件**/ private Bitmap mbitmapBg; /**小球资源文件**/ private Bitmap mbitmapBall; /**小球的坐标位置**/ private float mPosX = 200; private float mPosY = 0; /**重力感应X轴 Y轴 Z轴的重力值**/ private float mGX = 0; private float mGY = 0; private float mGZ = 0; public MyView(Context context) { super(context); /** 设置当前View拥有控制焦点 **/ this.setFocusable(true); /** 设置当前View拥有触摸事件 **/ this.setFocusableInTouchMode(true); /** 拿到SurfaceHolder对象 **/ mSurfaceHolder = this.getHolder(); /** 将mSurfaceHolder添加到Callback回调函数中 **/ mSurfaceHolder.addCallback(this); /** 创建画布 **/ mCanvas = new Canvas(); /** 创建曲线画笔 **/ mPaint = new Paint(); mPaint.setColor(Color.WHITE); /**加载小球资源**/ mbitmapBall = BitmapFactory.decodeResource(this.getResources(), R.drawable.ball); /**加载游戏背景**/ mbitmapBg = BitmapFactory.decodeResource(this.getResources(), R.drawable.bg); /**得到SensorManager对象**/ mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE); mSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); // 注册listener,第三个参数是检测的精确度 //SENSOR_DELAY_FASTEST 最灵敏 因为太快了没必要使用 //SENSOR_DELAY_GAME 游戏开发中使用 //SENSOR_DELAY_NORMAL 正常速度 //SENSOR_DELAY_UI 最慢的速度 mSensorMgr.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_GAME); } private void Draw() { /**绘制游戏背景**/ mCanvas.drawBitmap(mbitmapBg,0,0, mPaint); /**绘制小球**/ mCanvas.drawBitmap(mbitmapBall, mPosX,mPosY, mPaint); /**X轴 Y轴 Z轴的重力值**/ mCanvas.drawText("X轴重力值 :" + mGX, 0, 20, mPaint); mCanvas.drawText("Y轴重力值 :" + mGY, 0, 40, mPaint); mCanvas.drawText("Z轴重力值 :" + mGZ, 0, 60, mPaint); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { /**开始游戏主循环线程**/ mIsRunning = true; new Thread(this).start(); /**得到当前屏幕宽高**/ mScreenWidth = this.getWidth(); mScreenHeight = this.getHeight(); /**得到小球越界区域**/ mScreenBallWidth = mScreenWidth - mbitmapBall.getWidth(); mScreenBallHeight = mScreenHeight - mbitmapBall.getHeight(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mIsRunning = false; } @Override public void run() { while (mIsRunning) { /** 取得更新游戏之前的时间 **/ long startTime = System.currentTimeMillis(); /** 在这里加上线程安全锁 **/ synchronized (mSurfaceHolder) { /** 拿到当前画布 然后锁定 **/ mCanvas = mSurfaceHolder.lockCanvas(); Draw(); /** 绘制结束后解锁显示在屏幕上 **/ mSurfaceHolder.unlockCanvasAndPost(mCanvas); } /** 取得更新游戏结束的时间 **/ long endTime = System.currentTimeMillis(); /** 计算出游戏一次更新的毫秒数 **/ int diffTime = (int) (endTime - startTime); /** 确保每次更新时间为50帧 **/ while (diffTime <= TIME_IN_FRAME) { diffTime = (int) (System.currentTimeMillis() - startTime); /** 线程等待 **/ Thread.yield(); } } } @Override public void onAccuracyChanged(Sensor arg0, int arg1) { // TODO Auto-generated method stub } @Override public void onSensorChanged(SensorEvent event) { mGX = event.values[SensorManager.DATA_X]; mGY= event.values[SensorManager.DATA_Y]; mGZ = event.values[SensorManager.DATA_Z]; //这里乘以2是为了让小球移动的更快 mPosX -= mGX * 2; mPosY += mGY * 2; //检测小球是否超出边界 if (mPosX < 0) { mPosX = 0; } else if (mPosX > mScreenBallWidth) { mPosX = mScreenBallWidth; } if (mPosY < 0) { mPosY = 0; } else if (mPosY > mScreenBallHeight) { mPosY = mScreenBallHeight; } } } } 这时用重力感应器控制小球移动的一个demo,但是现在我想自己画一个圆充当小球,而不是用图片替代,我该怎么改这段代码?求指教!
所做Android打砖块代码其中 出错 求教
下面是代码 可其中出现了一个错误(做了标记),不知道怎么解决,可否有高手帮我看看,能不能稍作修改一下,做成正确的。 就是这句错了 myview = new BallView(this); package sen.tan; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; public class dazhuankuaiActivity extends Activity { BallView myview; public static int screenWidth ; public static int screenHeight; private TextView textview; Button kaishi,jieshu,guanyu; ImageView image; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String string = "欢迎进入疯狂打砖块游戏"; image = (ImageView) this.findViewById(R.id.image); image.setImageResource(R.drawable.img1); textview =(TextView) this.findViewById(R.id.textview); textview.setTextSize(20); textview.setTextColor(Color.GREEN); textview.setBackgroundColor(Color.RED); textview.setText(string); kaishi=(Button)findViewById(R.id.button1); guanyu=(Button)findViewById(R.id.button2); jieshu=(Button)findViewById(R.id.button3); kaishi.setWidth(250); guanyu.setWidth(200); jieshu.setWidth(150); kaishi.setTextSize(35); guanyu.setTextSize(29); jieshu.setTextSize(24); jieshu.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v) { dazhuankuaiActivity.this.finish(); } }); guanyu.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ textview.setText("本游戏由xxx制作,此游戏控制左右按键,来回移动挡板,不让小球掉落,当小球把上方砖块全部打完时,游戏胜利"); } }); kaishi.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); screenWidth = dm.widthPixels; screenHeight = dm.heightPixels; setTitle("宽"+screenWidth+" 高"+screenHeight); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); `myview = new BallView(this);` //错误在这里 setContentView(myview); } public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_MENU: myview.resetGame(); break; case KeyEvent.KEYCODE_DPAD_CENTER: myview.ball_isRun = !myview.ball_isRun; break; case KeyEvent.KEYCODE_DPAD_LEFT: if(myview.ball_isRun){ if(myview.board_left<=myview.board_x_move) { myview.board_left=0; myview.board_right=myview.board_length; }else{ myview.board_left-=myview.board_x_move; myview.board_right-=myview.board_x_move;} } break; case KeyEvent.KEYCODE_DPAD_RIGHT: if(myview.ball_isRun){ if(screenWidth-myview.board_right<=myview.board_x_move ) { myview.board_left=screenWidth-myview.board_length; myview.board_right=screenWidth; }else{ myview.board_left+=myview.board_x_move; myview.board_right+=myview.board_x_move; } } break; case KeyEvent.KEYCODE_DPAD_UP: if(myview.ball_isRun){ if( myview.board_alterable_top==myview.board_default_top) { myview.board_alterable_top-=myview.boardYadd; myview.board_alterable_bottom-=myview.boardYadd; } } break; case KeyEvent.KEYCODE_DPAD_DOWN: if(myview.ball_isRun){ if( myview.board_alterable_top==myview.board_default_top-myview.boardYadd ) { myview.board_alterable_top=myview.board_default_top; myview.board_alterable_bottom=myview.board_alterable_top+myview.board_thickness; } } break; case KeyEvent.KEYCODE_BACK: dazhuankuaiActivity.this.finish(); break; }//end switch return false; } //按键弹起事件 } ); } } package sen.tan; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RadialGradient; import android.graphics.Shader; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class BallView extends SurfaceView implements SurfaceHolder.Callback, Runnable { //线程延时控制 final int ball_sleep=1;//毫秒,延时越大,球速越慢 final int ball_r= 8;//小球半径 final float ball2_r= 8;//底下滚珠小球半径 final int ballXorYadd = 4;//小球的基本位移。测试可行值:2,4 //获取屏幕宽度和高度 int screen_width;//320; int screen_height;//480; //砖的属性 int brick_width;//每块砖宽 int brick_height;//每块砖高 boolean brick_exist[];//砖是否存在 int k ;// 列//到for循环里才初始化 int j ;// 行 int brick_left = brick_width*(k-1);//到判断语句才初始化 int brick_right = brick_width*k; int brick_top = brick_height*j; int brick_bottom = brick_height*(j+1); //挡板的属性 int board_length;//挡板长度:80比较合适,可以随意修改,但别超过screen_width final int boardYadd = 16;//按上下键时挡板y方向位移量。经验证4、8、16可以,12不行 final int board_x_move = 30;//挡板x方向位移量:可以随意自定义 int board_left;//挡板左侧(可变) int board_right;//挡板右侧(可变) int board_thickness;//挡板厚度 int board_default_top;//即435,挡板的top面初始位置 int board_alterable_top;//挡板上侧(可变) int board_alterable_bottom;//挡板下侧(可变) int ball_default_x;//球的初始x坐标 int ball_default_y;//球的初始y坐标 //球的即时坐标(可变): int ball_x;//球心横坐标 int ball_y;//球心纵坐标 //球的前一步的y坐标 int ball_previous_y; int ball_x_speed;//球的横向偏移量//可变 int ball_y_speed;//球的纵向偏移量//可变 boolean ball_isRun;//球是否在动 // 控制循环 boolean mbLoop; // 定义SurfaceHolder对象 SurfaceHolder mSurfaceHolder = null; //获得分数 int score; /* 唤醒渐变渲染 */ Shader mRadialGradient = null; //------------------------------------------------------------------------------------------------------// public BallView(Context context) { super(context); // 实例化SurfaceHolder mSurfaceHolder = this.getHolder(); // 添加回调 mSurfaceHolder.addCallback(this); this.setFocusable(true); //获取屏幕宽度和高度 screen_width = dazhuankuaiActivity.screenWidth;//320 screen_height = dazhuankuaiActivity.screenHeight;//480 //砖的属性 brick_width = screen_width/5;//每块砖宽64 brick_height = screen_height/15;//每块砖高32 //挡板的属性 board_length = screen_width/4;//挡板长度:80比较合适,可以随意修改,但别超过screen_width board_left = (screen_width-board_length)/2;//挡板左侧(可变) board_right = (screen_width+board_length)/2;//挡板右侧(可变) board_thickness = 5;//挡板厚度 board_default_top = 13*screen_height/15;//即435,挡板的top面初始位置 board_alterable_top = board_default_top;//挡板上侧(可变) board_alterable_bottom = board_alterable_top+board_thickness;//挡板下侧(可变) ball_default_x = screen_width/2;//球的初始x坐标 ball_default_y = board_default_top - ball_r;//球的初始y坐标 //球的即时坐标(可变): ball_x = ball_default_x; ball_y = ball_default_y; //球的前一步的y坐标 ball_previous_y = 0; ball_x_speed = ballXorYadd;//球的横向偏移量 ball_y_speed = ballXorYadd;//球的纵向偏移量 mbLoop = true; ball_isRun = false; score=0; brick_exist = new boolean[25]; for (int i = 0; i < 25; i++) { brick_exist[i] = true; } /* 构建RadialGradient对象,设置半径的属性 */ mRadialGradient = new RadialGradient(ball_x, ball_y, ball_r,//球中心坐标x,y,半径r new int[]{Color.WHITE,Color.BLUE,Color.GREEN,Color.RED,Color.YELLOW},//颜色数组 null,//颜色数组中每一种颜色对应的相对位置,为空的话就是平均分布,由中心向外排布 Shader.TileMode.REPEAT);//渲染模式:重复 } public void resetGame(){ ball_isRun = false; score =0;//分数 ball_x_speed = ballXorYadd;//球的横向偏移量 ball_y_speed = ballXorYadd;//球的纵向偏移量 ball_x = screen_width/2;//球心起始横坐标 ball_y = board_default_top - ball_r;//球心起始纵坐标 board_left = (screen_width-board_length)/2;//挡板左侧 board_right = (screen_width+board_length)/2;//挡板右侧 board_alterable_top = board_default_top;//挡板上侧 board_alterable_bottom = board_alterable_top+board_thickness;//挡板下侧 for (int i = 0; i < 25; i++) { brick_exist[i] = true; } } //---------------------------------绘图循环开始---------------------------------- public void run() { while (mbLoop&&!Thread.currentThread().isInterrupted()) { try { Thread.sleep(ball_sleep); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } //球的前一步y坐标 ball_previous_y = ball_y; if (ball_isRun) { ballRunning();// 让小球移动 boardPositionCheck();//检测挡板是否处于“中线”位置,是就随小球上升一步,直至到“上线” hitWallCheck();//墙壁碰撞检测 hitBoardCheck();//挡板碰撞检测 hitBrickCheck();//砖块碰撞检测 } synchronized (mSurfaceHolder) { Draw(); } } } //---------------------------------绘图循环结束---------------------------------- //------------------------------------------------------------------------------ //让小球移动 public void ballRunning() { ball_x += ball_x_speed; ball_y -= ball_y_speed; } //朝左或朝右碰撞后小球水平方向逆向 public void ballLeftOrRightHit() { ball_x_speed *= -1; } //朝上或朝下碰撞后小球竖直方向逆向 public void ballUpOrDownHit() { ball_y_speed *= -1; } public void ballcornerHit() { ball_x_speed *= -1; ball_y_speed *= -1; } public void ballStraightUp() {//功能没实现,这是多余代码 ball_x_speed = 0;//注意在其他地方恢复 ball_y_speed *= -1; } //-------------------墙壁碰撞检测开始------------------------------------- public void hitWallCheck() { // 左碰墙 if (ball_x <= ball_r && ball_y >= ball_r && ball_y <= screen_height) { ballLeftOrRightHit(); // 右碰墙 } if (ball_x >= screen_width - ball_r && //不能写为 else if,因为可能恰好碰到角落。 ball_y >= ball_r && ball_y <= screen_height) { ballLeftOrRightHit(); } // 上碰墙 if (ball_x >= ball_r && ball_x <= screen_width - ball_r && ball_y <= ball_r + brick_height) //、、、、、、、、、、、、、、、25号修改 { ballUpOrDownHit(); } // 下碰墙 if (ball_x >= ball_r && ball_x <= screen_width - ball_r && ball_y >= screen_height-ball_r) { ballUpOrDownHit(); if(score<=10){ score = 0; } else score-=10; } } //-------------------墙壁碰撞检测结束------------------------------------- //-----------------------------挡板碰撞检测开始--------------------------- public void hitBoardCheck() { // 下碰挡板正面 if (ball_x >= ball_r && ball_x <= screen_width - ball_r && //在屏幕内,起码条件 ball_x >= board_left && ball_x <= board_right && //在挡板X域上方 ball_y == board_alterable_top - ball_r &&//球面与挡板相切 ball_previous_y <= board_alterable_top - ball_r //确定球是从上方下落 ) { if(board_alterable_top==board_default_top-boardYadd ){//如果弹簧伸张,挡板位于上线 ballHitBoardlower();//作用:ball_y_move减小;挡板被打下;小球Y向运动反向 } else if(board_alterable_top==board_default_top){//如果弹簧压缩,挡板位于下线 boardHitBallHigher();//作用:ball_y_move增加;挡板弹上;小球Y向运动反向 } } //斜碰挡板右上角//经验证有效 else if(Math.pow(board_right-ball_x, 2)+Math.pow(board_alterable_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>board_right && ball_y<board_alterable_top) { ballcornerHit(); } //斜碰挡板的左上角//经验证有效 else if(Math.pow(board_left-ball_x, 2)+Math.pow(board_alterable_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x<board_left && ball_y<board_alterable_top) { ballcornerHit(); } } //-----------------------------挡板碰撞检测结束-------------------------- private void boardHitBallHigher() {//增强 ballUpOrDownHit();//小球Y方向反向,ball_y_speed变为正数 if(ball_y_speed == ballXorYadd ){ ball_y_speed += ballXorYadd;//离开挡板后小球Y方向速度增强 } if( boardYadd > ball_y_speed ){//在线程这一轮,小球上升多少,挡板就上升多少。 board_alterable_top = board_default_top - ball_y_speed; board_alterable_bottom= board_alterable_top+board_thickness;//挡板下层面 } } //检测挡板是否处于“中线”位置,是就随小球上升一步,直至到“上线” private void boardPositionCheck() {//还可直接利用球的位置刷新,board_top与球心相差ball_r if(board_alterable_top < board_default_top && board_alterable_top > board_default_top-boardYadd){ //挡板随球上升 if(board_alterable_top - ball_y_speed >= board_default_top-boardYadd){ board_alterable_top -= ball_y_speed;//挡板上层面 board_alterable_bottom= board_alterable_top+board_thickness;//挡板下层面 } else{ board_alterable_top = board_default_top-boardYadd;//挡板上层面 board_alterable_bottom= board_alterable_top+board_thickness;//挡板下层面 } } } private void ballHitBoardlower() {//减弱 board_alterable_top=board_default_top; board_alterable_bottom=board_default_top+board_thickness;//挡板被打退 ballUpOrDownHit();//小球Y方向反向 if(ball_y_speed==2*ballXorYadd){ ball_y_speed -= ballXorYadd;//小球Y方向速度减弱 } } //砖块碰撞检测开始----------------------------------------------------------- public void hitBrickCheck() { for (int i = 0; i <25 ; i++) { if (brick_exist[i]) { k = i % 5+1;// 1,2,3,4,5循环 j = i / 5+1;// 1,1,1,1,1;2,2,2,2,2,;...;5,5,5,5,5 brick_left = brick_width*(k-1); brick_right = brick_width*k; brick_top = brick_height*j; brick_bottom = brick_height*(j+1); //朝下碰砖的top面 AAAAAAAAAAAAAAAAAAAAA if(ball_x >= brick_left && ball_x <= brick_right && ball_y >= brick_top-ball_r && ball_y < brick_top) { ballUpOrDownHit(); brick_exist[i] = false; score+=4; //朝下正碰2砖中间,i砖右上角检测 if(k!=5 && ball_x == brick_right)//如果不是第5列砖的右侧边 { //如果砖[i+1]存在 if(brick_exist[i+1]){ brick_exist[i+1] = false; score+=4; } } //朝下正碰2砖中间,i砖左上角检测 else if(k!=1 && ball_x == brick_left)//如果不是第1列砖的左侧边 { //如果砖[i-1]存在 if(brick_exist[i-1]){ brick_exist[i-1] = false; score+=4; } } } //朝上碰砖的bottom面 BBBBBBBBBBBBBBBBB else if(ball_x >= brick_left && ball_x <= brick_right && ball_y > brick_bottom&& ball_y <= brick_bottom + ball_r ) { ballUpOrDownHit(); brick_exist[i] = false; score+=4; //朝上正碰2块砖中间--i砖的右下角检测 if(k!=5 && ball_x == brick_right) //如果不是第5列砖的右侧边 { if(brick_exist[i+1]){//如果砖[i+1]存在 brick_exist[i+1] = false; score+=4; } } //朝上正碰2块砖中间--i砖的左下角检测 else if(k!=1 && ball_x == brick_left) //如果不是第1列砖的左侧边 { if(brick_exist[i-1]){//如果砖[i-1]存在 brick_exist[i-1] = false; score+=4; } } } //朝右碰砖的left面CCCCCCCCCCCCCCCCC else if(ball_x >= brick_left -ball_r&&ball_x < brick_left&& ball_y >= brick_top && ball_y <= brick_bottom) { ballLeftOrRightHit(); brick_exist[i] = false; score+=4; //朝右正碰2块砖中间,左下角检测 if(j!=5 && ball_y == brick_bottom)//如果不是第5行砖的下侧边 { if(brick_exist[i+5]){//如果砖[i+5]存在 brick_exist[i+5] = false; score+=4; } } //朝右正碰2块砖中间,左上角检测 else if(j!=1 && ball_y == brick_top)//如果不是第1行砖的上侧边 { if(brick_exist[i-5]){//如果砖[i-5]存在 brick_exist[i-5] = false; score+=4; } } } //朝左碰砖的right面DDDDDDDDDDDDDDDDDD else if(ball_x >= brick_right && ball_x <= brick_right+ball_r&& ball_y >= brick_top && ball_y <= brick_bottom) { ballLeftOrRightHit(); brick_exist[i] = false; score+=4; //朝左正碰2块砖中间,右下角检测 if(j!=5 && ball_y == brick_bottom )//如果不是第5行砖的下侧边 { if(brick_exist[i+5]){//如果砖[i+5]存在 brick_exist[i+5] = false; score+=4; } } //朝左正碰2块砖中间,右上角检测 else if(j!=1 && ball_y == brick_top )//如果不是第1行砖上侧边 { if(brick_exist[i-5]){//如果砖[i-5]存在 brick_exist[i-5] = false; score+=4; } } } ///////////////////////////////////////// //斜碰i砖的左下角EEEEEEEEEEEEEEEEEEEEEEEE else if(( i-1<0||(i-1>=0&&!brick_exist[i-1]) ) && (i+5>=25||(i+5<25&&!brick_exist[i+5]) )&& Math.pow(brick_left-ball_x, 2)+Math.pow(brick_bottom-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_left-ball_r && ball_x<brick_left && ball_y>brick_bottom && ball_y<brick_bottom+ball_r ) { ballcornerHit(); brick_exist[i] = false; score+=4; } //斜碰i砖的右下角FFFFFFFFFFFFFFFFFFFFFFFFFF else if( (i+1>=25||(i+1<25&&!brick_exist[i+1]) )&& (i+5>=25||(i+5<25&&!brick_exist[i+5]) )&& Math.pow(brick_right-ball_x, 2)+Math.pow(brick_bottom-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_right&&ball_x<brick_right+ball_r&& ball_y>brick_bottom&&ball_y<brick_bottom+ball_r ) { Log.v("----------", "right bottom hit"+i+":"+brick_exist[i]); ballcornerHit(); brick_exist[i] = false; score+=4; } //斜碰i砖的右上角GGGGGGGGGGGGGGGGGGGGGGGG else if( (i+1>=25||(i+1<25&&!brick_exist[i+1]) )&& (i-5<0||(i-5>0&&!brick_exist[i-5]) )&& Math.pow(brick_right-ball_x, 2)+Math.pow(brick_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_right && ball_x<brick_right+ball_r&& ball_y>brick_top-ball_r && ball_y<brick_top) { ballcornerHit(); brick_exist[i] = false; score+=4; } //斜碰i砖的左上角HHHHHHHHHHHHHHHHHHHHHHHHHH else if((i-1<0||(i-1>=0&&!brick_exist[i-1])) && (i-5<0||(i-5>=0&&!brick_exist[i-5])) && Math.pow(brick_left-ball_x, 2)+Math.pow(brick_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_left-ball_x && ball_x<brick_left && ball_y>brick_top-ball_r && ball_y<brick_top ) { ballcornerHit(); brick_exist[i] = false; score+=4; } }//end if }//end for }//end hitBrickCheck() //砖块碰撞检测结束----------------------------------------------------------- //------------------------------------------ public boolean gameOver(){ int count = 0; for(boolean s:brick_exist){ if(!s){ count++; } } if(count == 25){ return true; }else{ return false; } } //------------------------------------------ //---------------绘图方法开始------------------------ public void Draw() { // 锁定画布,得到canvas Canvas canvas = mSurfaceHolder.lockCanvas(); if (mSurfaceHolder == null || canvas == null) { return; } // 绘图 Paint mPaint = new Paint(); // 设置取消锯齿效果 mPaint.setAntiAlias(true); mPaint.setColor(Color.BLACK); // 绘制矩形--背景 canvas.drawRect(0, 0, screen_width, brick_height-2, mPaint); mPaint.setColor(Color.GREEN); // 绘制矩形--背景 canvas.drawRect(0, brick_height-2, screen_width, screen_height, mPaint); mPaint.setColor(Color.RED);//设置字体颜色 mPaint.setTextSize(brick_height-7);//设置字体大小 canvas.drawText("得分:"+score, 0, brick_height-7, mPaint); // 绘制顶层挡板````````````````````````````````````````````````````````25号修改 mPaint.setColor(Color.BLACK);//设置颜色 mPaint.setStrokeWidth(4);//设置粗细 canvas.drawLine(0, brick_height-2, screen_width, brick_height-2, mPaint); for (int i = 0; i <25 ; i++) { if (brick_exist[i]) { k = i % 5+1;// 1,2,3,4,5循环 j = i / 5+1;// 1,1,1,1,1;2,2,2,2,2,;...;5,5,5,5,5 brick_left = brick_width*(k-1); brick_right = brick_width*k; brick_top = brick_height*j; brick_bottom = brick_height*(j+1); mPaint.setStyle(Paint.Style.FILL);// 设置实心画笔 mPaint.setColor(Color.YELLOW); canvas.drawRect(brick_left+1, brick_top+1, brick_right-1,brick_bottom-1, mPaint); mPaint.setStyle(Paint.Style.STROKE);// 设置空心画笔 mPaint.setStrokeWidth(2);//设置粗细 mPaint.setColor(Color.BLUE); canvas.drawRect(brick_left+3, brick_top+3, brick_right-3,brick_bottom-3, mPaint); } } // 设置实心画笔 mPaint.setStyle(Paint.Style.FILL); { mPaint.setShader(mRadialGradient); canvas.drawCircle(ball_x, ball_y, ball_r, mPaint); } Paint mPaint2 = new Paint(); // 设置取消锯齿效果 mPaint2.setAntiAlias(true); // 设置实心画笔 mPaint2.setStyle(Paint.Style.FILL); { mPaint2.setColor(Color.BLACK); /* 绘制矩形挡板 */ canvas.drawRect(board_left, board_alterable_top, board_right, board_alterable_bottom,mPaint2); float board2_bottom = screen_height - 2*ball2_r;//164 float board2_top = board2_bottom - 4;//160 //线段端点坐标数组 float x0 = board_left+(board_right-board_left)/4; float y0 = board_alterable_bottom;//440或者444 float springAdd = (board2_top- board_alterable_bottom)/8;//即2.5或者2:弹簧小线段的y向长度 float springWidth = 5.0f;//弹簧小线段的x向长度 float x1 = x0 - springWidth; float y1 = y0 + springAdd; float x2 = x0 + springWidth; float y2 = y0 + 3*springAdd; float x3 = x1 ; float y3 = y0 + 5*springAdd; float x4 = x2; float y4 = y0 + 7*springAdd; float x5 = x0 ; float y5 = board2_top;//即460 float between_spring = (board_right-board_left)/2; float pts[] = { x0,y0,x1,y1, x1,y1,x2,y2, x2,y2,x3,y3, x3,y3,x4,y4, x4,y4,x5,y5}; float pts2[] = {x0+between_spring,y0, x1+between_spring,y1, x1+between_spring,y1, x2+between_spring,y2, x2+between_spring,y2, x3+between_spring,y3, x3+between_spring,y3, x4+between_spring,y4, x4+between_spring,y4, x5+between_spring,y5}; mPaint2.setStrokeWidth(2);//设置弹簧粗细 //绘制2个弹簧 canvas.drawLines(pts, mPaint2); canvas.drawLines(pts2, mPaint2); //绘制下层挡板 canvas.drawRect(board_left, board2_top, board_right, board2_bottom,mPaint2); mPaint2.setColor(Color.BLACK);// // 绘制最下面的两个“轮子”(圆心x,圆心y,半径r,p) canvas.drawCircle(board_left+ball2_r, screen_height-ball2_r, ball2_r, mPaint2);//圆 canvas.drawCircle(board_right-ball2_r, screen_height-ball2_r, ball2_r, mPaint2); mPaint2.setColor(Color.WHITE);// canvas.drawPoint(board_left+ball2_r, screen_height-ball2_r, mPaint2);//绘制左轮轮心 canvas.drawPoint(board_right-ball2_r, screen_height-ball2_r, mPaint2);//绘制右轮轮心 }//实心画笔mPaint2结束 if(gameOver()){ // mbLoop = false;//注释掉的话GAME OVER后也可重启 ball_isRun = false; mPaint2.setColor(Color.BLACK);//设置字体颜色 mPaint2.setTextSize(40.0f);//设置字体大小 canvas.drawText("GAME OVER", screen_width/32+40, screen_height/16*9-70, mPaint2); mPaint2.setTextSize(20.0f);//设置字体大小 canvas.drawText("Press \"MENU\" button to restart,", screen_width/32, //320/32=10 screen_height/16*9, //480/16=30,30*9=270 mPaint2); canvas.drawText("Press \"BACK\" button to exit.", screen_width/32, //320/32=10 screen_height/16*10, //480/16=30,30*10=300 mPaint2); } // 绘制后解锁,绘制后必须解锁才能显示 mSurfaceHolder.unlockCanvasAndPost(canvas); }// end of Draw() //---------------------绘图方法结束----------------------------------------------- // 在surface的大小发生改变时激发 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } // 在surface创建时激发 public void surfaceCreated(SurfaceHolder holder) { new Thread(this).start();// 开启绘图线程 } // 在surface销毁时激发 public void surfaceDestroyed(SurfaceHolder holder) { // 停止循环 mbLoop = false; } } 下个界面的代码是 package ab.cc; import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Window; import android.view.WindowManager; public class BaomingActivity extends Activity { BallView myView; static int screenWidth; static int screenHeight; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* 定义DisplayMetrics对象 */ DisplayMetrics dm = new DisplayMetrics(); /* 取得窗口属性 */ getWindowManager().getDefaultDisplay().getMetrics(dm); /* 窗口的宽度 */ screenWidth = dm.widthPixels; /* 窗口的高度 */ screenHeight = dm.heightPixels; // setTitle("宽"+screenWidth+" 高"+screenHeight); /* 设置为无标题栏 */ requestWindowFeature(Window.FEATURE_NO_TITLE); /* 设置为全屏模式 */ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); myView = new BallView(this); //设置显示GameSurfaceView视图 setContentView(myView); }//end of onCreate() //触笔事件 public boolean onTouchEvent(MotionEvent event) { return true; } //按键按下事件 public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { //菜单按键-设为初始菜单 case KeyEvent.KEYCODE_MENU: myView.resetGame(); //重新开始 break; //中间按键 case KeyEvent.KEYCODE_DPAD_CENTER: myView.ball_isRun = !myView.ball_isRun;//开始//暂停 break; //左方向键 case KeyEvent.KEYCODE_DPAD_LEFT: if(myView.ball_isRun){ if(myView.board_left<=myView.board_x_move) { myView.board_left=0; myView.board_right=myView.board_length; }else{ myView.board_left-=myView.board_x_move; myView.board_right-=myView.board_x_move;} } break; //右方向键 case KeyEvent.KEYCODE_DPAD_RIGHT: if(myView.ball_isRun){ if(screenWidth-myView.board_right<=myView.board_x_move ) { myView.board_left=screenWidth-myView.board_length; myView.board_right=screenWidth; }else{ myView.board_left+=myView.board_x_move; myView.board_right+=myView.board_x_move; } } break; //上方向键 case KeyEvent.KEYCODE_DPAD_UP: if(myView.ball_isRun){ if( myView.board_alterable_top==myView.board_default_top) { myView.board_alterable_top-=myView.boardYadd; myView.board_alterable_bottom-=myView.boardYadd; } } break; //下方向键 case KeyEvent.KEYCODE_DPAD_DOWN: if(myView.ball_isRun){ if( myView.board_alterable_top==myView.board_default_top-myView.boardYadd ) { myView.board_alterable_top=myView.board_default_top; myView.board_alterable_bottom=myView.board_alterable_top+myView.board_thickness; } } break; //返回键 case KeyEvent.KEYCODE_BACK: this.finish(); break; }//end switch return false; } //按键弹起事件 public boolean onKeyUp(int keyCode, KeyEvent event) { return true; } public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { return true; } }
android做的俄罗斯方块,其他界面在手机撒谎能够看都是正常的,就游戏界面不能满屏
package com.comon; //启动游戏 import java.io.InputStream; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; public class StarSurfaceView extends SurfaceView implements Runnable,SurfaceHolder.Callback,View.OnKeyListener { //SurfaceHolder用来完成对绘制的画布进行裁剪,控制其大小 SurfaceHolder sHolder=null; Canvas canvas; Paint paint; showPage tm; contro cm; int face; boolean flag; boolean onlyone=true; boolean next = false; Store a; Store c; int x; int y; int kk; // int action; //创建图片对象 Bitmap store1 = null; Bitmap store2 = null; Bitmap store3 = null; Bitmap store4 = null; Bitmap store5 = null; Bitmap store6 = null; Bitmap store7 = null; Bitmap border1 = null; Bitmap border2 = null; Bitmap record = null; Bitmap num0 = null; Bitmap num1 = null; Bitmap num2 = null; Bitmap num3 = null; Bitmap num4 = null; Bitmap num5 = null; Bitmap num6 = null; Bitmap num7 = null; Bitmap num8 = null; Bitmap num9 = null; Bitmap blg = null; // Bitmap fire = null; Bitmap conti=null; Bitmap goon = null; Bitmap good = null; Bitmap happy = null; Bitmap bbk = null; public StarSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); //实例化sHolder sHolder = this.getHolder(); //addCallback:给SurfaceView添加一个回调函数 sHolder.addCallback(this); this.setFocusable(true); // sHolder = this.getHolder(); // sHolder.addCallback(this); paint=new Paint(); tm = new showPage(); cm = new contro(); a = new Store(); c = new Store(); // action=0; face = 0; x=-2; y=4; kk=0; //获得对象 bbk = this.getBitmapById(R.drawable.bbk); blg = this.getBitmapById(R.drawable.tetris); store1 = this.getBitmapById(R.drawable.block0); store2 = this.getBitmapById(R.drawable.block1); store3 = this.getBitmapById(R.drawable.block2); store4 = this.getBitmapById(R.drawable.block3); store5 = this.getBitmapById(R.drawable.block4); store6 = this.getBitmapById(R.drawable.block5); store7 = this.getBitmapById(R.drawable.block6); border1 = this.getBitmapById(R.drawable.border); border2 = this.getBitmapById(R.drawable.border_sm); num0 = this.getBitmapById(R.drawable.a0); num1 = this.getBitmapById(R.drawable.a1); num2 = this.getBitmapById(R.drawable.a2); num3 = this.getBitmapById(R.drawable.a3); num4 = this.getBitmapById(R.drawable.a4); num5 = this.getBitmapById(R.drawable.a5); num6 = this.getBitmapById(R.drawable.a6); num7 = this.getBitmapById(R.drawable.a7); num8 = this.getBitmapById(R.drawable.a8); num9 = this.getBitmapById(R.drawable.a9); record = this.getBitmapById(R.drawable.record); // fire = this.getBitmapById(R.drawable.fire); conti=this.getBitmapById(R.drawable.conti); goon = this.getBitmapById(R.drawable.goon); good = this.getBitmapById(R.drawable.good); happy = this.getBitmapById(R.drawable.happy); } //从资源中装载图片 public Bitmap getBitmapById(int id) { Bitmap image = null; Context currentCtx = this.getContext();//得到当前设备环境 Resources res = currentCtx.getResources();//得到图片资源 InputStream is = res.openRawResource(id);//打开图片资源 image = BitmapFactory.decodeStream(is);//获取图片资源 return image; } //绘制方法 public void draw() { //// Canvas c = null;//声明画布 // c = sHolder.lockCanvas();//锁定画布 //// Paint p;//声明画笔 // p = new Paint(); // // c.drawBitmap(bbk, 0, 0, p); // c.drawBitmap(border1, 2, 1, p);//绘制游戏主背景 // c.drawBitmap(border2, 240, 20, p);//绘制产生下一个方块的背景 // c.drawBitmap(record, 240, 270, p);//绘制计分榜背景 // showFace(c,p); // showC(c,p); // showT(c,p); // showP(c,p); // sHolder.unlockCanvasAndPost(c);//解锁画布 try { canvas= sHolder.lockCanvas(); if (canvas!= null) { canvas.drawBitmap(bbk,0,0,paint); canvas.drawBitmap(border1, 2,1 ,paint); canvas.drawBitmap(border2,240,20, paint); canvas.drawBitmap(record,240, 270,paint); showFace(canvas,paint); showC(canvas,paint); showT(canvas,paint); showP(canvas,paint); // sHolder.unlockCanvasAndPost(c); } } catch (Exception e) { System.out.println("error"); } finally { if (canvas!= null) sHolder.unlockCanvasAndPost(canvas); } } boolean left = false; boolean right = false; boolean up = false; boolean down = false; // boolean back=false; public void run() { if(onlyone){ // int x = -2; // int y = 4; // boolean next = false; // Store a = new Store(); // Store b = new Store(); c.Sttore(-1);//随机为下一个方块区域生成一个方块 a.Sttore(-1);//随机为游戏区域生成一个方块 tm.putS(c);//在下一个方块区域产生一个方块 onlyone=false; // int kk = 0; //用来控制方块的变形次数,在一行内 } while(flag){ if(next) { tm.delS(c);//删除下一个方块区域的方块 a.Sttore(c.kind);//把存储下一个方块区域的方块的数组传递给游戏区域的方块数组 c.Sttore(-1);//为下一个方块区域随机生成一个方块 x = -2; y = 4; next = false; tm.putS(c); } draw();//绘制方块 //控制方块下降速度 try { Thread.sleep(400 - cm.speed); } catch (InterruptedException e) { e.printStackTrace(); } // if(back){ // Intent intent1 = new Intent(); // intent1.setClass( ActivityGame.acGame, TTetris.class); // ActivityGame.acGame.startActivity(intent1); // ActivityGame.acGame.finish(); // break; // } if(left) { tm.delStore(a, x, y);//删除游戏区域的方块 if(tm.leftM(a, x, y)) { y--; //如果方块可以左移,把方块左移 } tm.putStore(a, x, y);//重新生成左移后的方块 left = false; kk++; if(kk < 3) { continue; } } //方块右移 else if(right) { tm.delStore(a, x, y); if(tm.rightM(a, x, y)) { y++; } tm.putStore(a, x, y); right = false; kk++; if(kk < 3) { continue; } } //方块变形 else if(up) { int tv; if( (a.kind+1)%4 == 0) { //每种方块有1,2,3,4这四种状态,如果处于第4种状态,按上就变回第一种状态 tv = a.kind -3; //否则把没按一次上,1变成2,2变成3,3变成4 } else { tv = a.kind + 1; } Store b = new Store(); b.Sttore(tv); tm.delStore(a, x, y); if(tm.fit(b, x, y)) { //如果方块变形后不会碰壁,则生成一个变形后的方块,否则生成原来的方块 a = b; tm.putStore(a, x, y); up = false; kk++; if(kk < 3) { continue; } } else { tm.putStore(a, x, y); up = false; } } else if(down) { tm.delStore(a, x, y); while(tm.fit(a, x, y)) { x++; } tm.putStore(a, x, y); down = false; } tm.delStore(a, x, y); kk = 0; if(tm.fit(a, x, y)) {//使方块下落 x++; tm.putStore(a, x, y); } else { int t; tm.putStore(a, x, y); if(tm.outM(a, x, y)) {//如果方块触顶了,结束游戏,转换到游戏结束界面 Intent intent = new Intent(); intent.setClass( ActivityGame.acGame, ActGameover.class); ActivityGame.acGame.startActivity(intent); ActivityGame.acGame.finish(); break; } t = tm.flood(a, x, y);//消行,并返回消除的行数,不可以消行返回0; // putface(t); face=t; cm.tscore(t); //计分 cm.passWar(); System.out.println(cm.score); tm.pSco(cm.sco); next = true; } } } public void showFace(Canvas canvas,Paint paint) {//通过face控制人物的表情 if(face == 0) { canvas.drawBitmap(goon, 240,120, paint); } else if(face == 1) { canvas.drawBitmap(conti, 240,120, paint); } else if(face == 2||face==3) { canvas.drawBitmap(good, 240,120, paint); } else if(face==4) { canvas.drawBitmap(happy, 240,120, paint); } } // public void putface(int fa) { //生成face的值 // if(fa == 0) { // face = (int)(Math.random()*2); // } // else { // face = fa+1; // } // } public void showC(Canvas canvas,Paint paint) { //绘制分数的图片 for(int i = 0; i <4; i++) { if(tm.co[i] == 0) { canvas.drawBitmap(num0, i*20+240, 330, paint); } else if(tm.co[i] == 1) { canvas.drawBitmap(num1, i*20+240, 330, paint); } else if(tm.co[i] == 2) { canvas.drawBitmap(num2, i*20+240, 330, paint); } else if(tm.co[i] == 3) { canvas.drawBitmap(num3, i*20+240, 330, paint); } else if(tm.co[i] == 4) { canvas.drawBitmap(num4, i*20+240, 330, paint); } else if(tm.co[i] == 5) { canvas.drawBitmap(num5, i*20+240, 330, paint); } else if(tm.co[i] == 6) { canvas.drawBitmap(num6, i*20+240, 330, paint); } else if(tm.co[i] == 7) { canvas.drawBitmap(num7, i*20+240, 330, paint); } else if(tm.co[i] == 8) { canvas.drawBitmap(num8, i*20+240, 330, paint); } else if(tm.co[i] == 9) { canvas.drawBitmap(num9, i*20+240, 330, paint); } } } public void showT(Canvas canvas,Paint paint) {//下一个方块生成区域的方块绘制不同颜色的方块图片 for(int i = 0 ;i < 4; i++) { for(int j = 0; j < 4; j++) { if(tm.brray[i][j] == 1){ canvas.drawBitmap(store1, j*tm.w+240, i*tm.w+20, paint); } else if(tm.brray[i][j] == 2){ canvas.drawBitmap(store2, j*tm.w+240, i*tm.w+20, paint); } else if(tm.brray[i][j] == 3){ canvas.drawBitmap(store3, j*tm.w+240, i*tm.w+20, paint); } else if(tm.brray[i][j] == 4){ canvas.drawBitmap(store4, j*tm.w+240, i*tm.w+20, paint); } else if(tm.brray[i][j] == 5){ canvas.drawBitmap(store5, j*tm.w+240, i*tm.w+20, paint); } else if(tm.brray[i][j] == 6){ canvas.drawBitmap(store6, j*tm.w+240, i*tm.w+20, paint); } else if(tm.brray[i][j] == 7){ canvas.drawBitmap(store7, j*tm.w+240, i*tm.w+20, paint); } } } } public void showP(Canvas canvas,Paint paint) { //为游戏区域的方块绘制不同颜色的图片 for(int i = 0 ;i < tm.array.length; i++){ for(int j = 0; j < tm.array[0].length; j++){ if(tm.array[i][j] == 1){ canvas.drawBitmap(store1, j*tm.w-1, i*tm.w-2, paint); } else if(tm.array[i][j] == 2){ canvas.drawBitmap(store2, j*tm.w-1, i*tm.w-2, paint); } else if(tm.array[i][j] == 3){ canvas.drawBitmap(store3, j*tm.w-1, i*tm.w-2, paint); } else if(tm.array[i][j] == 4){ canvas.drawBitmap(store4, j*tm.w-1, i*tm.w-2, paint); } else if(tm.array[i][j] == 5){ canvas.drawBitmap(store5, j*tm.w-1, i*tm.w-2, paint); } else if(tm.array[i][j] == 6){ canvas.drawBitmap(store6, j*tm.w-1, i*tm.w-2, paint); } else if(tm.array[i][j] == 7){ canvas.drawBitmap(store7, j*tm.w-1, i*tm.w-2, paint); } } } } public boolean onKeyDown(int k, KeyEvent event) { return false; } public boolean onKeyUp(int k,KeyEvent event){ switch (k) { case KeyEvent.KEYCODE_DPAD_UP: up=true; break; case KeyEvent.KEYCODE_DPAD_DOWN: down=true; break; case KeyEvent.KEYCODE_DPAD_LEFT: left=true; break; case KeyEvent.KEYCODE_DPAD_RIGHT: right=true; break; } return false; } public boolean onKey(View v, int k, KeyEvent e) { return false; } public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) { } public void surfaceCreated(SurfaceHolder holder) { flag=true; Thread th = new Thread(this); th.start(); } public void surfaceDestroyed(SurfaceHolder holder) { flag=false; } } main()的代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation = "vertical" > <com.comon.StarSurfaceView android:layout_width="fill_parent" android:layout_height="fill_parent" ></com.comon.StarSurfaceView> </LinearLayout>
Android打砖块代码 其中系统说格式错误 求帮助
我这边有一个打砖块代码,我将它移植到我的按钮事件触发里 提示我格式错误 下面前两个是打砖块代码 ,后两个是转到我的里面之后的, 标注了,请帮忙。 package ab.cc; import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Window; import android.view.WindowManager; public class BaomingActivity extends Activity { BallView myView; static int screenWidth; static int screenHeight; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* 定义DisplayMetrics对象 */ DisplayMetrics dm = new DisplayMetrics(); /* 取得窗口属性 */ getWindowManager().getDefaultDisplay().getMetrics(dm); /* 窗口的宽度 */ screenWidth = dm.widthPixels; /* 窗口的高度 */ screenHeight = dm.heightPixels; // setTitle("宽"+screenWidth+" 高"+screenHeight); /* 设置为无标题栏 */ requestWindowFeature(Window.FEATURE_NO_TITLE); /* 设置为全屏模式 */ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); myView = new BallView(this); //设置显示GameSurfaceView视图 setContentView(myView); }//end of onCreate() //触笔事件 public boolean onTouchEvent(MotionEvent event) { return true; } //按键按下事件 public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { //菜单按键-设为初始菜单 case KeyEvent.KEYCODE_MENU: myView.resetGame(); //重新开始 break; //中间按键 case KeyEvent.KEYCODE_DPAD_CENTER: myView.ball_isRun = !myView.ball_isRun;//开始//暂停 break; //左方向键 case KeyEvent.KEYCODE_DPAD_LEFT: if(myView.ball_isRun){ if(myView.board_left<=myView.board_x_move) { myView.board_left=0; myView.board_right=myView.board_length; }else{ myView.board_left-=myView.board_x_move; myView.board_right-=myView.board_x_move;} } break; //右方向键 case KeyEvent.KEYCODE_DPAD_RIGHT: if(myView.ball_isRun){ if(screenWidth-myView.board_right<=myView.board_x_move ) { myView.board_left=screenWidth-myView.board_length; myView.board_right=screenWidth; }else{ myView.board_left+=myView.board_x_move; myView.board_right+=myView.board_x_move; } } break; //上方向键 case KeyEvent.KEYCODE_DPAD_UP: if(myView.ball_isRun){ if( myView.board_alterable_top==myView.board_default_top) { myView.board_alterable_top-=myView.boardYadd; myView.board_alterable_bottom-=myView.boardYadd; } } break; //下方向键 case KeyEvent.KEYCODE_DPAD_DOWN: if(myView.ball_isRun){ if( myView.board_alterable_top==myView.board_default_top-myView.boardYadd ) { myView.board_alterable_top=myView.board_default_top; myView.board_alterable_bottom=myView.board_alterable_top+myView.board_thickness; } } break; //返回键 case KeyEvent.KEYCODE_BACK: this.finish(); break; }//end switch return false; } //按键弹起事件 public boolean onKeyUp(int keyCode, KeyEvent event) { return true; } public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { return true; } } package ab.cc; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RadialGradient; import android.graphics.Shader; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class BallView extends SurfaceView implements SurfaceHolder.Callback, Runnable { //线程延时控制 final int ball_sleep=1;//毫秒,延时越大,球速越慢 final int ball_r= 8;//小球半径 final float ball2_r= 8;//底下滚珠小球半径 final int ballXorYadd = 4;//小球的基本位移。测试可行值:2,4 //获取屏幕宽度和高度 int screen_width;//320; int screen_height;//480; //砖的属性 int brick_width;//每块砖宽 int brick_height;//每块砖高 boolean brick_exist[];//砖是否存在 int k ;// 列//到for循环里才初始化 int j ;// 行 int brick_left = brick_width*(k-1);//到判断语句才初始化 int brick_right = brick_width*k; int brick_top = brick_height*j; int brick_bottom = brick_height*(j+1); //挡板的属性 int board_length;//挡板长度:80比较合适,可以随意修改,但别超过screen_width final int boardYadd = 16;//按上下键时挡板y方向位移量。经验证4、8、16可以,12不行 final int board_x_move = 30;//挡板x方向位移量:可以随意自定义 int board_left;//挡板左侧(可变) int board_right;//挡板右侧(可变) int board_thickness;//挡板厚度 int board_default_top;//即435,挡板的top面初始位置 int board_alterable_top;//挡板上侧(可变) int board_alterable_bottom;//挡板下侧(可变) int ball_default_x;//球的初始x坐标 int ball_default_y;//球的初始y坐标 //球的即时坐标(可变): int ball_x;//球心横坐标 int ball_y;//球心纵坐标 //球的前一步的y坐标 int ball_previous_y; int ball_x_speed;//球的横向偏移量//可变 int ball_y_speed;//球的纵向偏移量//可变 boolean ball_isRun;//球是否在动 // 控制循环 boolean mbLoop; // 定义SurfaceHolder对象 SurfaceHolder mSurfaceHolder = null; //获得分数 int score; /* 唤醒渐变渲染 */ Shader mRadialGradient = null; //------------------------------------------------------------------------------------------------------// public BallView(Context context) { super(context); // 实例化SurfaceHolder mSurfaceHolder = this.getHolder(); // 添加回调 mSurfaceHolder.addCallback(this); this.setFocusable(true); //获取屏幕宽度和高度 screen_width = BaomingActivity.screenWidth;//320 screen_height = BaomingActivity.screenHeight;//480 //砖的属性 brick_width = screen_width/5;//每块砖宽64 brick_height = screen_height/15;//每块砖高32 //挡板的属性 board_length = screen_width/4;//挡板长度:80比较合适,可以随意修改,但别超过screen_width board_left = (screen_width-board_length)/2;//挡板左侧(可变) board_right = (screen_width+board_length)/2;//挡板右侧(可变) board_thickness = 5;//挡板厚度 board_default_top = 13*screen_height/15;//即435,挡板的top面初始位置 board_alterable_top = board_default_top;//挡板上侧(可变) board_alterable_bottom = board_alterable_top+board_thickness;//挡板下侧(可变) ball_default_x = screen_width/2;//球的初始x坐标 ball_default_y = board_default_top - ball_r;//球的初始y坐标 //球的即时坐标(可变): ball_x = ball_default_x; ball_y = ball_default_y; //球的前一步的y坐标 ball_previous_y = 0; ball_x_speed = ballXorYadd;//球的横向偏移量 ball_y_speed = ballXorYadd;//球的纵向偏移量 mbLoop = true; ball_isRun = false; score=0; brick_exist = new boolean[25]; for (int i = 0; i < 25; i++) { brick_exist[i] = true; } /* 构建RadialGradient对象,设置半径的属性 */ mRadialGradient = new RadialGradient(ball_x, ball_y, ball_r,//球中心坐标x,y,半径r new int[]{Color.WHITE,Color.BLUE,Color.GREEN,Color.RED,Color.YELLOW},//颜色数组 null,//颜色数组中每一种颜色对应的相对位置,为空的话就是平均分布,由中心向外排布 Shader.TileMode.REPEAT);//渲染模式:重复 } public void resetGame(){ ball_isRun = false; score =0;//分数 ball_x_speed = ballXorYadd;//球的横向偏移量 ball_y_speed = ballXorYadd;//球的纵向偏移量 ball_x = screen_width/2;//球心起始横坐标 ball_y = board_default_top - ball_r;//球心起始纵坐标 board_left = (screen_width-board_length)/2;//挡板左侧 board_right = (screen_width+board_length)/2;//挡板右侧 board_alterable_top = board_default_top;//挡板上侧 board_alterable_bottom = board_alterable_top+board_thickness;//挡板下侧 for (int i = 0; i < 25; i++) { brick_exist[i] = true; } } //---------------------------------绘图循环开始---------------------------------- public void run() { while (mbLoop&&!Thread.currentThread().isInterrupted()) { try { Thread.sleep(ball_sleep); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } //球的前一步y坐标 ball_previous_y = ball_y; if (ball_isRun) { ballRunning();// 让小球移动 boardPositionCheck();//检测挡板是否处于“中线”位置,是就随小球上升一步,直至到“上线” hitWallCheck();//墙壁碰撞检测 hitBoardCheck();//挡板碰撞检测 hitBrickCheck();//砖块碰撞检测 } synchronized (mSurfaceHolder) { Draw(); } } } //---------------------------------绘图循环结束---------------------------------- //------------------------------------------------------------------------------ //让小球移动 public void ballRunning() { ball_x += ball_x_speed; ball_y -= ball_y_speed; } //朝左或朝右碰撞后小球水平方向逆向 public void ballLeftOrRightHit() { ball_x_speed *= -1; } //朝上或朝下碰撞后小球竖直方向逆向 public void ballUpOrDownHit() { ball_y_speed *= -1; } public void ballcornerHit() { ball_x_speed *= -1; ball_y_speed *= -1; } public void ballStraightUp() {//功能没实现,这是多余代码 ball_x_speed = 0;//注意在其他地方恢复 ball_y_speed *= -1; } //-------------------墙壁碰撞检测开始------------------------------------- public void hitWallCheck() { // 左碰墙 if (ball_x <= ball_r && ball_y >= ball_r && ball_y <= screen_height) { ballLeftOrRightHit(); // 右碰墙 } if (ball_x >= screen_width - ball_r && //不能写为 else if,因为可能恰好碰到角落。 ball_y >= ball_r && ball_y <= screen_height) { ballLeftOrRightHit(); } // 上碰墙 if (ball_x >= ball_r && ball_x <= screen_width - ball_r && ball_y <= ball_r + brick_height) //、、、、、、、、、、、、、、、25号修改 { ballUpOrDownHit(); } // 下碰墙 if (ball_x >= ball_r && ball_x <= screen_width - ball_r && ball_y >= screen_height-ball_r) { ballUpOrDownHit(); if(score<=10){ score = 0; } else score-=10; } } //-------------------墙壁碰撞检测结束------------------------------------- //-----------------------------挡板碰撞检测开始--------------------------- public void hitBoardCheck() { // 下碰挡板正面 if (ball_x >= ball_r && ball_x <= screen_width - ball_r && //在屏幕内,起码条件 ball_x >= board_left && ball_x <= board_right && //在挡板X域上方 ball_y == board_alterable_top - ball_r &&//球面与挡板相切 ball_previous_y <= board_alterable_top - ball_r //确定球是从上方下落 ) { if(board_alterable_top==board_default_top-boardYadd ){//如果弹簧伸张,挡板位于上线 ballHitBoardlower();//作用:ball_y_move减小;挡板被打下;小球Y向运动反向 } else if(board_alterable_top==board_default_top){//如果弹簧压缩,挡板位于下线 boardHitBallHigher();//作用:ball_y_move增加;挡板弹上;小球Y向运动反向 } } //斜碰挡板右上角//经验证有效 else if(Math.pow(board_right-ball_x, 2)+Math.pow(board_alterable_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>board_right && ball_y<board_alterable_top) { ballcornerHit(); } //斜碰挡板的左上角//经验证有效 else if(Math.pow(board_left-ball_x, 2)+Math.pow(board_alterable_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x<board_left && ball_y<board_alterable_top) { ballcornerHit(); } } //-----------------------------挡板碰撞检测结束-------------------------- private void boardHitBallHigher() {//增强 ballUpOrDownHit();//小球Y方向反向,ball_y_speed变为正数 if(ball_y_speed == ballXorYadd ){ ball_y_speed += ballXorYadd;//离开挡板后小球Y方向速度增强 } if( boardYadd > ball_y_speed ){//在线程这一轮,小球上升多少,挡板就上升多少。 board_alterable_top = board_default_top - ball_y_speed; board_alterable_bottom= board_alterable_top+board_thickness;//挡板下层面 } } //检测挡板是否处于“中线”位置,是就随小球上升一步,直至到“上线” private void boardPositionCheck() {//还可直接利用球的位置刷新,board_top与球心相差ball_r if(board_alterable_top < board_default_top && board_alterable_top > board_default_top-boardYadd){ //挡板随球上升 if(board_alterable_top - ball_y_speed >= board_default_top-boardYadd){ board_alterable_top -= ball_y_speed;//挡板上层面 board_alterable_bottom= board_alterable_top+board_thickness;//挡板下层面 } else{ board_alterable_top = board_default_top-boardYadd;//挡板上层面 board_alterable_bottom= board_alterable_top+board_thickness;//挡板下层面 } } } private void ballHitBoardlower() {//减弱 board_alterable_top=board_default_top; board_alterable_bottom=board_default_top+board_thickness;//挡板被打退 ballUpOrDownHit();//小球Y方向反向 if(ball_y_speed==2*ballXorYadd){ ball_y_speed -= ballXorYadd;//小球Y方向速度减弱 } } //砖块碰撞检测开始----------------------------------------------------------- public void hitBrickCheck() { for (int i = 0; i <25 ; i++) { if (brick_exist[i]) { k = i % 5+1;// 1,2,3,4,5循环 j = i / 5+1;// 1,1,1,1,1;2,2,2,2,2,;...;5,5,5,5,5 brick_left = brick_width*(k-1); brick_right = brick_width*k; brick_top = brick_height*j; brick_bottom = brick_height*(j+1); //朝下碰砖的top面 AAAAAAAAAAAAAAAAAAAAA if(ball_x >= brick_left && ball_x <= brick_right && ball_y >= brick_top-ball_r && ball_y < brick_top) { ballUpOrDownHit(); brick_exist[i] = false; score+=4; //朝下正碰2砖中间,i砖右上角检测 if(k!=5 && ball_x == brick_right)//如果不是第5列砖的右侧边 { //如果砖[i+1]存在 if(brick_exist[i+1]){ brick_exist[i+1] = false; score+=4; } } //朝下正碰2砖中间,i砖左上角检测 else if(k!=1 && ball_x == brick_left)//如果不是第1列砖的左侧边 { //如果砖[i-1]存在 if(brick_exist[i-1]){ brick_exist[i-1] = false; score+=4; } } } //朝上碰砖的bottom面 BBBBBBBBBBBBBBBBB else if(ball_x >= brick_left && ball_x <= brick_right && ball_y > brick_bottom&& ball_y <= brick_bottom + ball_r ) { ballUpOrDownHit(); brick_exist[i] = false; score+=4; //朝上正碰2块砖中间--i砖的右下角检测 if(k!=5 && ball_x == brick_right) //如果不是第5列砖的右侧边 { if(brick_exist[i+1]){//如果砖[i+1]存在 brick_exist[i+1] = false; score+=4; } } //朝上正碰2块砖中间--i砖的左下角检测 else if(k!=1 && ball_x == brick_left) //如果不是第1列砖的左侧边 { if(brick_exist[i-1]){//如果砖[i-1]存在 brick_exist[i-1] = false; score+=4; } } } //朝右碰砖的left面CCCCCCCCCCCCCCCCC else if(ball_x >= brick_left -ball_r&&ball_x < brick_left&& ball_y >= brick_top && ball_y <= brick_bottom) { ballLeftOrRightHit(); brick_exist[i] = false; score+=4; //朝右正碰2块砖中间,左下角检测 if(j!=5 && ball_y == brick_bottom)//如果不是第5行砖的下侧边 { if(brick_exist[i+5]){//如果砖[i+5]存在 brick_exist[i+5] = false; score+=4; } } //朝右正碰2块砖中间,左上角检测 else if(j!=1 && ball_y == brick_top)//如果不是第1行砖的上侧边 { if(brick_exist[i-5]){//如果砖[i-5]存在 brick_exist[i-5] = false; score+=4; } } } //朝左碰砖的right面DDDDDDDDDDDDDDDDDD else if(ball_x >= brick_right && ball_x <= brick_right+ball_r&& ball_y >= brick_top && ball_y <= brick_bottom) { ballLeftOrRightHit(); brick_exist[i] = false; score+=4; //朝左正碰2块砖中间,右下角检测 if(j!=5 && ball_y == brick_bottom )//如果不是第5行砖的下侧边 { if(brick_exist[i+5]){//如果砖[i+5]存在 brick_exist[i+5] = false; score+=4; } } //朝左正碰2块砖中间,右上角检测 else if(j!=1 && ball_y == brick_top )//如果不是第1行砖上侧边 { if(brick_exist[i-5]){//如果砖[i-5]存在 brick_exist[i-5] = false; score+=4; } } } ///////////////////////////////////////// //斜碰i砖的左下角EEEEEEEEEEEEEEEEEEEEEEEE else if(( i-1<0||(i-1>=0&&!brick_exist[i-1]) ) && (i+5>=25||(i+5<25&&!brick_exist[i+5]) )&& Math.pow(brick_left-ball_x, 2)+Math.pow(brick_bottom-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_left-ball_r && ball_x<brick_left && ball_y>brick_bottom && ball_y<brick_bottom+ball_r ) { ballcornerHit(); brick_exist[i] = false; score+=4; } //斜碰i砖的右下角FFFFFFFFFFFFFFFFFFFFFFFFFF else if( (i+1>=25||(i+1<25&&!brick_exist[i+1]) )&& (i+5>=25||(i+5<25&&!brick_exist[i+5]) )&& Math.pow(brick_right-ball_x, 2)+Math.pow(brick_bottom-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_right&&ball_x<brick_right+ball_r&& ball_y>brick_bottom&&ball_y<brick_bottom+ball_r ) { Log.v("----------", "right bottom hit"+i+":"+brick_exist[i]); ballcornerHit(); brick_exist[i] = false; score+=4; } //斜碰i砖的右上角GGGGGGGGGGGGGGGGGGGGGGGG else if( (i+1>=25||(i+1<25&&!brick_exist[i+1]) )&& (i-5<0||(i-5>0&&!brick_exist[i-5]) )&& Math.pow(brick_right-ball_x, 2)+Math.pow(brick_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_right && ball_x<brick_right+ball_r&& ball_y>brick_top-ball_r && ball_y<brick_top) { ballcornerHit(); brick_exist[i] = false; score+=4; } //斜碰i砖的左上角HHHHHHHHHHHHHHHHHHHHHHHHHH else if((i-1<0||(i-1>=0&&!brick_exist[i-1])) && (i-5<0||(i-5>=0&&!brick_exist[i-5])) && Math.pow(brick_left-ball_x, 2)+Math.pow(brick_top-ball_y,2)<=Math.pow(ball_r, 2)&& ball_x>brick_left-ball_x && ball_x<brick_left && ball_y>brick_top-ball_r && ball_y<brick_top ) { ballcornerHit(); brick_exist[i] = false; score+=4; } }//end if }//end for }//end hitBrickCheck() //砖块碰撞检测结束----------------------------------------------------------- //------------------------------------------ public boolean gameOver(){ int count = 0; for(boolean s:brick_exist){ if(!s){ count++; } } if(count == 25){ return true; }else{ return false; } } //------------------------------------------ //---------------绘图方法开始------------------------ public void Draw() { // 锁定画布,得到canvas Canvas canvas = mSurfaceHolder.lockCanvas(); if (mSurfaceHolder == null || canvas == null) { return; } // 绘图 Paint mPaint = new Paint(); // 设置取消锯齿效果 mPaint.setAntiAlias(true); mPaint.setColor(Color.BLACK); // 绘制矩形--背景 canvas.drawRect(0, 0, screen_width, brick_height-2, mPaint); mPaint.setColor(Color.GREEN); // 绘制矩形--背景 canvas.drawRect(0, brick_height-2, screen_width, screen_height, mPaint); mPaint.setColor(Color.RED);//设置字体颜色 mPaint.setTextSize(brick_height-7);//设置字体大小 canvas.drawText("得分:"+score, 0, brick_height-7, mPaint); // 绘制顶层挡板````````````````````````````````````````````````````````25号修改 mPaint.setColor(Color.BLACK);//设置颜色 mPaint.setStrokeWidth(4);//设置粗细 canvas.drawLine(0, brick_height-2, screen_width, brick_height-2, mPaint); for (int i = 0; i <25 ; i++) { if (brick_exist[i]) { k = i % 5+1;// 1,2,3,4,5循环 j = i / 5+1;// 1,1,1,1,1;2,2,2,2,2,;...;5,5,5,5,5 brick_left = brick_width*(k-1); brick_right = brick_width*k; brick_top = brick_height*j; brick_bottom = brick_height*(j+1); mPaint.setStyle(Paint.Style.FILL);// 设置实心画笔 mPaint.setColor(Color.YELLOW); canvas.drawRect(brick_left+1, brick_top+1, brick_right-1,brick_bottom-1, mPaint); mPaint.setStyle(Paint.Style.STROKE);// 设置空心画笔 mPaint.setStrokeWidth(2);//设置粗细 mPaint.setColor(Color.BLUE); canvas.drawRect(brick_left+3, brick_top+3, brick_right-3,brick_bottom-3, mPaint); } } // 设置实心画笔 mPaint.setStyle(Paint.Style.FILL); { mPaint.setShader(mRadialGradient); canvas.drawCircle(ball_x, ball_y, ball_r, mPaint); } Paint mPaint2 = new Paint(); // 设置取消锯齿效果 mPaint2.setAntiAlias(true); // 设置实心画笔 mPaint2.setStyle(Paint.Style.FILL); { mPaint2.setColor(Color.BLACK); /* 绘制矩形挡板 */ canvas.drawRect(board_left, board_alterable_top, board_right, board_alterable_bottom,mPaint2); float board2_bottom = screen_height - 2*ball2_r;//164 float board2_top = board2_bottom - 4;//160 //线段端点坐标数组 float x0 = board_left+(board_right-board_left)/4; float y0 = board_alterable_bottom;//440或者444 float springAdd = (board2_top- board_alterable_bottom)/8;//即2.5或者2:弹簧小线段的y向长度 float springWidth = 5.0f;//弹簧小线段的x向长度 float x1 = x0 - springWidth; float y1 = y0 + springAdd; float x2 = x0 + springWidth; float y2 = y0 + 3*springAdd; float x3 = x1 ; float y3 = y0 + 5*springAdd; float x4 = x2; float y4 = y0 + 7*springAdd; float x5 = x0 ; float y5 = board2_top;//即460 float between_spring = (board_right-board_left)/2; float pts[] = { x0,y0,x1,y1, x1,y1,x2,y2, x2,y2,x3,y3, x3,y3,x4,y4, x4,y4,x5,y5}; float pts2[] = {x0+between_spring,y0, x1+between_spring,y1, x1+between_spring,y1, x2+between_spring,y2, x2+between_spring,y2, x3+between_spring,y3, x3+between_spring,y3, x4+between_spring,y4, x4+between_spring,y4, x5+between_spring,y5}; mPaint2.setStrokeWidth(2);//设置弹簧粗细 //绘制2个弹簧 canvas.drawLines(pts, mPaint2); canvas.drawLines(pts2, mPaint2); //绘制下层挡板 canvas.drawRect(board_left, board2_top, board_right, board2_bottom,mPaint2); mPaint2.setColor(Color.BLACK);// // 绘制最下面的两个“轮子”(圆心x,圆心y,半径r,p) canvas.drawCircle(board_left+ball2_r, screen_height-ball2_r, ball2_r, mPaint2);//圆 canvas.drawCircle(board_right-ball2_r, screen_height-ball2_r, ball2_r, mPaint2); mPaint2.setColor(Color.WHITE);// canvas.drawPoint(board_left+ball2_r, screen_height-ball2_r, mPaint2);//绘制左轮轮心 canvas.drawPoint(board_right-ball2_r, screen_height-ball2_r, mPaint2);//绘制右轮轮心 }//实心画笔mPaint2结束 if(gameOver()){ // mbLoop = false;//注释掉的话GAME OVER后也可重启 ball_isRun = false; mPaint2.setColor(Color.BLACK);//设置字体颜色 mPaint2.setTextSize(40.0f);//设置字体大小 canvas.drawText("GAME OVER", screen_width/32+40, screen_height/16*9-70, mPaint2); mPaint2.setTextSize(20.0f);//设置字体大小 canvas.drawText("Press \"MENU\" button to restart,", screen_width/32, //320/32=10 screen_height/16*9, //480/16=30,30*9=270 mPaint2); canvas.drawText("Press \"BACK\" button to exit.", screen_width/32, //320/32=10 screen_height/16*10, //480/16=30,30*10=300 mPaint2); } // 绘制后解锁,绘制后必须解锁才能显示 mSurfaceHolder.unlockCanvasAndPost(canvas); }// end of Draw() //---------------------绘图方法结束----------------------------------------------- // 在surface的大小发生改变时激发 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } // 在surface创建时激发 public void surfaceCreated(SurfaceHolder holder) { new Thread(this).start();// 开启绘图线程 } // 在surface销毁时激发 public void surfaceDestroyed(SurfaceHolder holder) { // 停止循环 mbLoop = false; } } package sen.tan; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; public class dazhuankuaiActivity extends Activity { BallView myview; public static int screenWidth ; public static int screenHeight; private TextView textview; Button kaishi,jieshu,guanyu; ImageView image; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String string = "欢迎进入疯狂打砖块游戏"; image = (ImageView) this.findViewById(R.id.image); image.setImageResource(R.drawable.img1); textview =(TextView) this.findViewById(R.id.textview); textview.setTextSize(20); textview.setTextColor(Color.GREEN); textview.setBackgroundColor(Color.RED); textview.setText(string); kaishi=(Button)findViewById(R.id.button1); guanyu=(Button)findViewById(R.id.button2); jieshu=(Button)findViewById(R.id.button3); kaishi.setWidth(250); guanyu.setWidth(200); jieshu.setWidth(150); kaishi.setTextSize(35); guanyu.setTextSize(29); jieshu.setTextSize(24); jieshu.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v) { dazhuankuaiActivity.this.finish(); } }); guanyu.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ textview.setText("本游戏由邵明森和谭明星制作,此游戏控制左右按键,来回移动挡板,不让小球掉落,当小球把上方砖块全部打完时,游戏胜利"); } }); kaishi.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ public void onCreate(Bundle savedInstanceState)这里显示的错误 显示的是上面两个括号标示不对。 { super.onCreate(savedInstanceState); DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); screenWidth = dm.widthPixels; screenHeight = dm.heightPixels; setTitle("宽"+screenWidth+" 高"+screenHeight); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); myview = new BallView(this); setContentView(myview); } } public boolean onTouchEvent(MotionEvent event) { return true; } public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_MENU: myview.resetGame(); break; case KeyEvent.KEYCODE_DPAD_CENTER: myview.ball_isRun = !myview.ball_isRun; break; case KeyEvent.KEYCODE_DPAD_LEFT: if(myview.ball_isRun){ if(myview.board_left<=myview.board_x_move) { myview.board_left=0; myview.board_right=myview.board_length; }else{ myview.board_left-=myview.board_x_move; myview.board_right-=myview.board_x_move;} } break; case KeyEvent.KEYCODE_DPAD_RIGHT: if(myview.ball_isRun){ if(screenWidth-myview.board_right<=myview.board_x_move ) { myview.board_left=screenWidth-myview.board_length; myview.board_right=screenWidth; }else{ myview.board_left+=myview.board_x_move; myview.board_right+=myview.board_x_move; } } break; case KeyEvent.KEYCODE_DPAD_UP: if(myview.ball_isRun){ if( myview.board_alterable_top==myview.board_default_top) { myview.board_alterable_top-=myview.boardYadd; myview.board_alterable_bottom-=myview.boardYadd; } } break; case KeyEvent.KEYCODE_DPAD_DOWN: if(myview.ball_isRun){ if( myview.board_alterable_top==myview.board_default_top-myview.boardYadd ) { myview.board_alterable_top=myview.board_default_top; myview.board_alterable_bottom=myview.board_alterable_top+myview.board_thickness; } } break; case KeyEvent.KEYCODE_BACK: this.finish(); break; } return false; } public boolean onKeyUp(int keyCode, KeyEvent event) { return true; } public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { return true; } } ); } }
动态规划入门到熟悉,看不懂来打我啊
持续更新。。。。。。 2.1斐波那契系列问题 2.2矩阵系列问题 2.3跳跃系列问题 3.1 01背包 3.2 完全背包 3.3多重背包 3.4 一些变形选讲 2.1斐波那契系列问题 在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n&gt;=2,n∈N*)根据定义,前十项为1, 1, 2, 3...
终于明白阿里百度这样的大公司,为什么面试经常拿ThreadLocal考验求职者了
点击上面↑「爱开发」关注我们每晚10点,捕获技术思考和创业资源洞察什么是ThreadLocalThreadLocal是一个本地线程副本变量工具类,各个线程都拥有一份线程私...
对计算机专业来说学历真的重要吗?
我本科学校是渣渣二本,研究生学校是985,现在毕业五年,校招笔试、面试,社招面试参加了两年了,就我个人的经历来说下这个问题。 这篇文章很长,但绝对是精华,相信我,读完以后,你会知道学历不好的解决方案,记得帮我点赞哦。 先说结论,无论赞不赞同,它本质就是这样:对于技术类工作而言,学历五年以内非常重要,但有办法弥补。五年以后,不重要。 目录: 张雪峰讲述的事实 我看到的事实 为什么会这样 ...
Java学习的正确打开方式
在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次就是国内的书籍,博客次之,这又是一个层次了,这里暂时不提后面再谈。博主将为各位入门java保驾护航,各位只管冲鸭!!!上天是公平的,只要不辜负时间,时间自然不会辜负你。 何谓学习?博主所理解的学习,它是一个过程,是一个不断累积、不断沉淀、不断总结、善于传达自己的个人见解以及乐于分享的过程。
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
Python 植物大战僵尸代码实现(2):植物卡片选择和种植
这篇文章要介绍的是: - 上方植物卡片栏的实现。 - 点击植物卡片,鼠标切换为植物图片。 - 鼠标移动时,判断当前在哪个方格中,并显示半透明的植物作为提示。
防劝退!数据结构和算法难理解?可视化动画带你轻松透彻理解!
大家好,我是 Rocky0429,一个连数据结构和算法都不会的蒟蒻… 学过数据结构和算法的都知道这玩意儿不好学,没学过的经常听到这样的说法还没学就觉得难,其实难吗?真难! 难在哪呢?当年我还是个小蒟蒻,初学数据结构和算法的时候,在忍着枯燥看完定义原理,之后想实现的时候,觉得它们的过程真的是七拐八绕,及其难受。 在简单的链表、栈和队列这些我还能靠着在草稿上写写画画理解过程,但是到了数论、图...
【搞定 Java 并发面试】面试最常问的 Java 并发基础常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star!【Java学习 面试指南】 一份涵盖大部分Java程序员所需要掌握的核心知识。欢迎 Star!)。 另外推荐一篇原创:终极推荐!可能是最适合你的Java学习路线 方法 网站 书籍推荐! Java 并发基础常见面试题总结 1. 什么是线程和进程? 1.1. 何为进程? 进程是程...
西游记团队中如果需要裁掉一个人,会先裁掉谁?
2019年互联网寒冬,大批企业开始裁员,下图是网上流传的一张截图: 裁员不可避免,那如何才能做到不管大环境如何变化,自身不受影响呢? 我们先来看一个有意思的故事,如果西游记取经团队需要裁员一名,会裁掉谁呢,为什么? 西游记团队组成: 1.唐僧 作为团队teamleader,有很坚韧的品性和极高的原则性,不达目的不罢休,遇到任何问题,都没有退缩过,又很得上司支持和赏识(直接得到唐太宗的任命,既给
shell脚本:备份数据库、代码上线
备份MySQL数据库 场景: 一台MySQL服务器,跑着5个数据库,在没有做主从的情况下,需要对这5个库进行备份 需求: 1)每天备份一次,需要备份所有的库 2)把备份数据存放到/data/backup/下 3)备份文件名称格式示例:dbname-2019-11-23.sql 4)需要对1天以前的所有sql文件压缩,格式为gzip 5)本地数据保留1周 6)需要把备份的数据同步到远程备份中心,假如...
iOS Bug 太多,苹果终于坐不住了!
开源的 Android 和闭源的 iOS,作为用户的你,更偏向哪一个呢? 整理 | 屠敏 出品 | CSDN(ID:CSDNnews) 毋庸置疑,当前移动设备操作系统市场中,Android 和 iOS 作为两大阵营,在相互竞争的同时不断演进。不过一直以来,开源的 Android 吸引了无数的手机厂商涌入其中,为其生态带来了百花齐放的盛景,但和神秘且闭源的 iOS 系统相比,不少网友...
神经⽹络可以计算任何函数的可视化证明
《Neural Networks and Deep Learning》读书笔记第四篇本章其实和前面章节的关联性不大,所以大可将本章作为小短文来阅读,当然基本的深度学习基础还是要有的。主要介绍了神经⽹络拥有的⼀种普遍性,比如说不管目标函数是怎样的,神经网络总是能够对任何可能的输入,其值(或者说近似值)是网络的输出,哪怕是多输入和多输出也是如此,我们大可直接得出一个结论:不论我们想要计算什么样的函数,...
聊聊C语言和指针的本质
坐着绿皮车上海到杭州,24块钱,很宽敞,在火车上非正式地聊几句。 很多编程语言都以 “没有指针” 作为自己的优势来宣传,然而,对于C语言,指针却是与生俱来的。 那么,什么是指针,为什么大家都想避开指针。 很简单, 指针就是地址,当一个地址作为一个变量存在时,它就被叫做指针,该变量的类型,自然就是指针类型。 指针的作用就是,给出一个指针,取出该指针指向地址处的值。为了理解本质,我们从计算机模型说起...
为什么你学不过动态规划?告别动态规划,谈谈我的经验
动态规划难吗?说实话,我觉得很难,特别是对于初学者来说,我当时入门动态规划的时候,是看 0-1 背包问题,当时真的是一脸懵逼。后来,我遇到动态规划的题,看的懂答案,但就是自己不会做,不知道怎么下手。就像做递归的题,看的懂答案,但下不了手,关于递归的,我之前也写过一篇套路的文章,如果对递归不大懂的,强烈建议看一看:为什么你学不会递归,告别递归,谈谈我的经验 对于动态规划,春招秋招时好多题都会用到动态...
程序员一般通过什么途径接私活?
二哥,你好,我想知道一般程序猿都如何接私活,我也想接,能告诉我一些方法吗? 上面是一个读者“烦不烦”问我的一个问题。其实不止是“烦不烦”,还有很多读者问过我类似这样的问题。 我接的私活不算多,挣到的钱也没有多少,加起来不到 20W。说实话,这个数目说出来我是有点心虚的,毕竟太少了,大家轻喷。但我想,恰好配得上“一般程序员”这个称号啊。毕竟苍蝇再小也是肉,我也算是有经验的人了。 唾弃接私活、做外...
字节跳动面试官这样问消息队列:分布式事务、重复消费、顺序消费,我整理了一下
你知道的越多,你不知道的越多 点赞再看,养成习惯 GitHub上已经开源 https://github.com/JavaFamily 有一线大厂面试点脑图、个人联系方式和人才交流群,欢迎Star和完善 前言 消息队列在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在消息队列的使用和原理方面对小伙伴们进行360°的刁难。 作为一个在互联网公司面一次拿一次Offer的面霸...
如何安装 IntelliJ IDEA 最新版本——详细教程
IntelliJ IDEA 简称 IDEA,被业界公认为最好的 Java 集成开发工具,尤其在智能代码助手、代码自动提示、代码重构、代码版本管理(Git、SVN、Maven)、单元测试、代码分析等方面有着亮眼的发挥。IDEA 产于捷克,开发人员以严谨著称的东欧程序员为主。IDEA 分为社区版和付费版两个版本。 我呢,一直是 Eclipse 的忠实粉丝,差不多十年的老用户了。很早就接触到了 IDEA...
面试还搞不懂redis,快看看这40道面试题(含答案和思维导图)
Redis 面试题 1、什么是 Redis?. 2、Redis 的数据类型? 3、使用 Redis 有哪些好处? 4、Redis 相比 Memcached 有哪些优势? 5、Memcache 与 Redis 的区别都有哪些? 6、Redis 是单进程单线程的? 7、一个字符串类型的值能存储最大容量是多少? 8、Redis 的持久化机制是什么?各自的优缺点? 9、Redis 常见性...
大学四年自学走来,这些珍藏的「实用工具/学习网站」我全贡献出来了
知乎高赞:文中列举了互联网一线大厂程序员都在用的工具集合,涉及面非常广,小白和老手都可以进来看看,或许有新收获。
为什么要推荐大家学习字节码?
配套视频: 为什么推荐大家学习Java字节码 https://www.bilibili.com/video/av77600176/ 一、背景 本文主要探讨:为什么要学习 JVM 字节码? 可能很多人会觉得没必要,因为平时开发用不到,而且不学这个也没耽误学习。 但是这里分享一点感悟,即人总是根据自己已经掌握的知识和技能来解决问题的。 这里有个悖论,有时候你觉得有些技术没用恰恰是...
互联网公司的裁员,能玩出多少种花样?
裁员,也是一门学问,可谓博大精深!以下,是互联网公司的裁员的多种方法:-正文开始-135岁+不予续签的理由:千禧一代网感更强。95后不予通过试用期的理由:已婚已育员工更有责任心。2通知接下来要过苦日子,让一部分不肯同甘共苦的员工自己走人,以“兄弟”和“非兄弟”来区别员工。3强制996。员工如果平衡不了工作和家庭,可在离婚或离职里二选一。4不布置任何工作,但下班前必须提交千字工作日报。5不给活干+...
【超详细分析】关于三次握手与四次挥手面试官想考我们什么?
在面试中,三次握手和四次挥手可以说是问的最频繁的一个知识点了,我相信大家也都看过很多关于三次握手与四次挥手的文章,今天的这篇文章,重点是围绕着面试,我们应该掌握哪些比较重要的点,哪些是比较被面试官给问到的,我觉得如果你能把我下面列举的一些点都记住、理解,我想就差不多了。 三次握手 当面试官问你为什么需要有三次握手、三次握手的作用、讲讲三次三次握手的时候,我想很多人会这样回答: 首先很多人会先讲下握...
新程序员七宗罪
当我发表这篇文章《为什么每个工程师都应该开始考虑开发中的分析和编程技能呢?》时,我从未想到它会对读者产生如此积极的影响。那些想要开始探索编程和数据科学领域的人向我寻求建议;还有一些人问我下一篇文章的发布日期;还有许多人询问如何顺利过渡到这个职业。我非常鼓励大家继续分享我在这个旅程的经验,学习,成功和失败,以帮助尽可能多的人过渡到一个充满无数好处和机会的职业生涯。亲爱的读者,谢谢你。 -罗伯特。 ...
活到老,学到老,程序员也该如此
全文共2763字,预计学习时长8分钟 图片来源:Pixabay 此前,“网传阿里巴巴要求尽快实现P8全员35周岁以内”的消息闹得沸沸扬扬。虽然很快被阿里辟谣,但苍蝇不叮无缝的蛋,无蜜不招彩蝶蜂。消息从何而来?真相究竟怎样?我们无从而知。我们只知道一个事实:不知从何时开始,程序猿也被划在了“吃青春饭”行业之列。 饱受“996ICU”摧残后,好不容易“头秃了变强了”,即将步入为“高...
Vue快速实现通用表单验证
本文开篇第一句话,想引用鲁迅先生《祝福》里的一句话,那便是:“我真傻,真的,我单单知道后端整天都是CRUD,我没想到前端整天都是Form表单”。这句话要从哪里说起呢?大概要从最近半个月的“全栈工程师”说起。项目上需要做一个城市配载的功能,顾名思义,就是通过框选和拖拽的方式在地图上完成配载。博主选择了前后端分离的方式,在这个过程中发现:首先,只要有依赖jQuery的组件,譬如Kendoui,即使使用...
2019年Spring Boot面试都问了什么?快看看这22道面试题!
Spring Boot 面试题 1、什么是 Spring Boot? 2、Spring Boot 有哪些优点? 3、什么是 JavaConfig? 4、如何重新加载 Spring Boot 上的更改,而无需重新启动服务器? 5、Spring Boot 中的监视器是什么? 6、如何在 Spring Boot 中禁用 Actuator 端点安全性? 7、如何在自定义端口上运行 Sprin...
【图解】记一次手撕算法面试:字节跳动的面试官把我四连击了
字节跳动这家公司,应该是所有秋招的公司中,对算法最重视的一个了,每次面试基本都会让你手撕算法,今天这篇文章就记录下当时被问到的几个算法题,并且每个算法题我都详细着给出了最优解,下面再现当时的面试场景。看完一定让你有所收获 一、小牛试刀:有效括号 大部分情况下,面试官都会问一个不怎么难的问题,不过你千万别太开心,因为这道题往往可以拓展出更多有难度的问题,或者一道题看起来很简单,但是给出最优解,确实很...
关于裁员几点看法及建议
最近网易裁员事件引起广泛关注,昨天网易针对此事,也发了声明,到底谁对谁错,孰是孰非?我们作为吃瓜观众实在是知之甚少,所以不敢妄下定论。身处软件开发这个行业,近一两年来,对...
面试官:关于Java性能优化,你有什么技巧
通过使用一些辅助性工具来找到程序中的瓶颈,然后就可以对瓶颈部分的代码进行优化。 一般有两种方案:即优化代码或更改设计方法。我们一般会选择后者,因为不去调用以下代码要比调用一些优化的代码更能提高程序的性能。而一个设计良好的程序能够精简代码,从而提高性能。 下面将提供一些在JAVA程序的设计和编码中,为了能够提高JAVA程序的性能,而经常采用的一些方法和技巧。 1.对象的生成和大小的调整。 J...
【图解算法面试】记一次面试:说说游戏中的敏感词过滤是如何实现的?
版权声明:本文为苦逼的码农原创。未经同意禁止任何形式转载,特别是那些复制粘贴到别的平台的,否则,必定追究。欢迎大家多多转发,谢谢。 小秋今天去面试了,面试官问了一个与敏感词过滤算法相关的问题,然而小秋对敏感词过滤算法一点也没听说过。于是,有了下下事情的发生… 面试官开怼 面试官:玩过王者荣耀吧?了解过敏感词过滤吗?,例如在游戏里,如果我们发送“你在干嘛?麻痹演员啊你?”,由于“麻痹”是一个敏感词,...
程序员需要了解的硬核知识之汇编语言(一)
之前的系列文章从 CPU 和内存方面简单介绍了一下汇编语言,但是还没有系统的了解一下汇编语言,汇编语言作为第二代计算机语言,会用一些容易理解和记忆的字母,单词来代替一个特定的指令,作为高级编程语言的基础,有必要系统的了解一下汇编语言,那么本篇文章希望大家跟我一起来了解一下汇编语言。 汇编语言和本地代码 我们在之前的文章中探讨过,计算机 CPU 只能运行本地代码(机器语言)程序,用 C 语言等高级语...
GitHub 标星 1.6w+,我发现了一个宝藏项目,作为编程新手有福了!
大家好,我是 Rocky0429,一个最近老在 GitHub 上闲逛的蒟蒻… 特别惭愧的是,虽然我很早就知道 GitHub,但是学会逛 GitHub 的时间特别晚。当时一方面是因为菜,看着这种全是英文的东西难受,不知道该怎么去玩,另一方面是一直在搞 ACM,没有做一些工程类的项目,所以想当然的以为和 GitHub 也没什么关系(当然这种想法是错误的)。 后来自己花了一个星期看完了 Pyt...
java知识体系整理,学会了,月入过万不是梦
欢迎关注个人公众号:程序猿学社 前言: 一转眼,工作4年了,正式写博客也有一年多了,之前就有整理和总结的习惯,只是都记录在有道云,感觉知识点都是很凌乱,花时间系统整理下,该文会一直同步更新,有不足之处,希望各位同行指正,既然,选择做技术这行,就得有分享的精神,而不是抱着别人会超过你的心理。希望各位博友们互相交流,互相进步。 目录 java系统学习 小白也能...
相关热词 c# 数组类型 泛型约束 c#的赛狗日程序 c# 传递数组 可变参数 c# 生成存储过程 c# list 补集 c#获得所有窗体 c# 当前秒数转成年月日 c#中的枚举 c# 计算校验和 连续随机数不重复c#
立即提问