代码改变世界

团队博客 magicTower

2019-05-15 16:51  20189203梓航  阅读(127)  评论(0编辑  收藏  举报

一、为游戏添加背景音

方法是利用android中的service来开启,也就是进去的时候就播放出,退出就停止。
首先,在AndroidManifest中的application节点下添加:

[java] view plain copy

    <activity  
                android:name=".MainActivity"  
                android:label="@string/app_name" >  
                <intent-filter>  
                    <action android:name="android.intent.action.MAIN" />  
      
                    <category android:name="android.intent.category.LAUNCHER" />  
                </intent-filter>  
            </activity>  
  • 然后,再在项目中new出一个类,MusicServer:
[java] view plain copy

    package com.example.flybird_anla;  
      
    import android.app.Service;  
    import android.content.Intent;  
    import android.media.MediaPlayer;  
    import android.os.IBinder;  
      
    public class MusicServer extends Service {  
      
        private MediaPlayer mediaPlayer;  
      
        @Override  
        public IBinder onBind(Intent intent) {  
            // TODO Auto-generated method stub  
            return null;  
        }  
      
        @Override  
        public void onStart(Intent intent, int startId) {  
            super.onStart(intent, startId);  
      
            if (mediaPlayer == null) {  
      
                // R.raw.mmp是资源文件,MP3格式的  
                mediaPlayer = MediaPlayer.create(this, R.raw.paopao);  
                mediaPlayer.setLooping(true);  
                mediaPlayer.start();  
      
            }  
        }  
      
        @Override  
        public void onDestroy() {  
            // TODO Auto-generated method stub  
            super.onDestroy();  
            mediaPlayer.stop();  
        }  
    }  

  • 最后,在在activity中,写两个函数:
[java] view plain copy

    protected void onCreate(Bundle savedInstanceState) {  
            Intent intent = new Intent(MainActivity.this,MusicServer.class);  
            super.onCreate(savedInstanceState);  
            startService(intent);  
            manu();  
        }  
          
        protected void onStop(){  
            Intent intent = new Intent(MainActivity.this,MusicServer.class);  
            stopService(intent);  
            super.onStop();  
              
        }  
  • 然后,就ok了。

二、 Android onTouch()和onTouchEvent()区别

1、onTouch()方法:

  onTouch方式是View的OnTouchListener接口中定义的方法。

  当一个View绑定了OnTouchListener后,当有Touch事件触发时,就会调用onTouch方法。

  (当把手放到View上后,onTouch方法被一遍一遍的调用)

2、onTouchEvent()方法:

  onTouchEvent方法时重载的Activity的方法

  重写了Acitivity的onTouchEvent方法后,当屏幕有Touch事件时,此方法就会被调用。

  (当把手放到Activity上时,onTouchEvent方法会一遍一遍的被调用)

3、Touch事件的传递:

  在一个Activity里面放一个TextView的实例tv,并且这个tv的属性设定为march_parent

  在这种情况下,当手放到屏幕上的时候,首先会是tv响应Touch事件,执行onTouch方法。

 

  如果onTouch返回值为true,表示这个Touch事件被onTouch方法处理完毕,不会把Touch事件再传递给Activity

  也就是说onTouchEvent方法不会被调用

  (手放到屏幕上后,onTouch方法会被一遍一遍的调用)

  如果onTouch返回值为false,表示这个Touch事件没有被tv完全处理,onTouch返回以后,Touch事件被传递给Activity,

  onTouchEvent方法调用

  (当把手放到屏幕上后,onTouch方法调用一次后,onTouchEvent方法被一遍一遍的调用)
部分代码如下:

 public boolean onTouchEvent(MotionEvent event)
    {
        int x = (int) event.getX();
        int y = (int) event.getY();
        int type = 0;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 记录触摸点坐标
                if (MySet.touchUp(x,y) )
                {
                    pre();
                }
                else if (MySet.touchDown(x,y))
                {
                    next();
                }
                else if (MySet.touchOK(x,y))
                {
                    dealItem();
                }
                else if (MySet.touchDZH(x,y))
                {
                    dealItem();
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return true;
    }

三、使用Canvas绘图

  • 画布Canvas

  在Android下进行2D绘图需要Canvas类的支持,它位于"android.graphics.Canvas"包下,直译过来为画布的意思,用于完成在View上的绘图。    

  Canvas为提供了两个构造函数:

Canvas():创建一个空的Canvas对象。
Canvas(Bitmap bitmap):创建一个以bitmap位图为背景的Canvas。

  既然Canvas主要用于2D绘图,那么它也提供了很多相应的drawXxx()方法,方便我们在Canvas对象上画画,drawXxx()具有多种类型,可以画出:点、线、矩形、圆形、椭圆、文字、位图等的图形,这里就不再一一介绍了,只介绍几个Canvas中常用的方法:

void drawBitmap(Bitmap bitmap,float left,float top,Paint paint):在指定坐标绘制位图。
void drawLine(float startX,float startY,float stopX,float stopY,Paint paint):根据给定的起始点和结束点之间绘制连线。
void drawPath(Path path,Paint paint):根据给定的path,绘制连线。
void drawPoint(float x,float y,Paint paint):根据给定的坐标,绘制点。
void drawText(String text,int start,int end,Paint paint):根据给定的坐标,绘制文字。
int getHeight():得到Canvas的高度。
int getWidth():得到Canvas的宽度。
  • 画笔Paint

  从上面列举的几个Canvas.drawXxx()的方法看到,其中都有一个类型为paint的参数,可以把它理解为一个"画笔",通过这个画笔,在Canvas这张画布上作画。 它位于"android.graphics.Paint"包下,主要用于设置绘图风格,包括画笔颜色、画笔粗细、填充风格等。

  Paint中提供了大量设置绘图风格的方法,这里仅列出一些常用的,高级的内容有时间再详细讲解:

setARGB(int a,int r,int g,int b):设置ARGB颜色。
setColor(int color):设置颜色。
setAlpha(int a):设置透明度。
setPathEffect(PathEffect effect):设置绘制路径时的路径效果。
setShader(Shader shader):设置Paint的填充效果。
setAntiAlias(boolean aa):设置是否抗锯齿。
setStrokeWidth(float width):设置Paint的笔触宽度。
setStyle(Paint.Style style):设置Paint的填充风格。
setTextSize(float textSize):设置绘制文本时的文字大小。

使用Canvas绘图Demo

  既然已经简单讲解了Android下2D绘图的两个重要类,Canvas和Paint,那么下面通过一个简单的Demo来演示一下,这样加深大家的理解。

  在这个Demo中,将实现一个画图板的功能,当用户在触摸屏上移动的时候,即可在屏幕上绘制任意的图形。实现手绘功能其实是一种假象:表面上看起来可以随着用户在触摸屏上自由地画线,实际上依然利用的是Canvas的drawLine()方法画直线,每条直线都是从上一个移动事件发生点画到本次移动事件的的发生点。当用户在触摸屏上连续移动的时候,每次移动点之间的距离很小,多此极短的连线,肉眼看起来就是一个依照手指触摸移动的轨迹的连线。

  需要指出的是,如果程序每次都只是从上次移动事件的发生点绘制一条直线到本次拖动事件的发生点,那么当用户手指一旦离开触摸屏,再次引发触摸移动事件的时候,会导致前面绘制的内容被丢失。为了保留用户之前绘制的内容,程序需要借助于一个"双缓冲"的机制。

  之前讲解SurfaceView的时候,有讲到SurfaceView会自己维护一个双缓冲的缓冲区,但是在这里使用ImageView来展示绘图效果,它需要我们去维护双缓冲的机制。当用户在ImageView上进行"绘制"的时候,程序并不直接"绘制"到该ImageView组件上,而是先绘制到一个内存中的Bitmap对象(缓冲)上,等到内存中的Bitmap绘制好之后,再一次性的将Bitmap对象"绘制"到ImageView上。

  在这个Demo中,会监听ImageView的View.OnTouchListener事件的发生,它主要用户监听在View上的触摸事件。其中需要重写onTouch()方法,当用户触摸View的时候会调用这个方法,以下是它的完整签名:

    boolean onTouch(View v,MotionEvent event)

  它的返回值用于指定是否连续捕获触摸事件,而在它的参数中,View为当前引发触摸事件的View,而MotionEvent是当前引发触摸事件一些属性,这个类中定义了一系列的静态常量,用于表示当前触摸的动作,比如:

MotionEvent.ACTION_DOWN:手指触摸屏幕。
MotionEvent.ACTION_MOVE:手指移动。
MotionEvent.ACTION_UP:手指离开屏幕。

部分实际代码如下:

protected void onDraw(Canvas canvas)
    {
        paint.setColor(Color.BLACK);
        MySet.fillRect(canvas, 0, 0, MySet.SCREENW, MySet.SCREENH, paint);
        drawCont(canvas);
        MySet.drawImage(canvas, mImgMenuBG, (MySet.SCREENW - mImgMenuBG.getWidth()) / 2, 60);
        drawItem(canvas);
        y = (curItem + 1) * split + borderY + 600;

        paint.setARGB(255, 255, 0, 0);

        MySet.drawString(canvas, menu[curItem], borderX + (MySet.BORDERW - paint.measureText(menu[curItem])) / 2, y, paint);
    }

    private void drawCont(Canvas canvas) //操作栏
    {
        MySet.drawImage(canvas, getImage(GameScreen.IMAGE_WHEEL), 160, 1350, 400, 400, 0, 0);
        MySet.drawImage(canvas, getImage(GameScreen.IMAGE_BTNA), 600, 1380, 240, 240, 0, 0);
        MySet.drawImage(canvas, getImage(GameScreen.IMAGE_BTNA), 600, 1140, 240, 240, 0, 0);
        MySet.drawImage(canvas, getImage(GameScreen.IMAGE_BTNB), 800, 1520, 240, 240, 0, 0);
    }

四、创建String 的构造简析

  • 1、String string = new String ();

这个方案是创建了一个空的String,在内存空间中开辟了一个空内容的地址,实际上也没有什么用,源代码中有这种描写叙述

/**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     */
    public String() {
        this.value = "".value;
    }

尽管是空的String(是""而不是null。“”出是占有内存空间,仅仅只是内容是空的) 。但在其构造方法中依旧调用了value方法。也就是空字符串的value,
所谓value

 /** The value is used for character storage. */
    private final char value[];
  • 2、String string = new String (" test ");

这样的方法来创建String,与我们经常使用创建方式分析中的思路一至,声明变量,开辟空间。赋值引用

源代码中这样操作

public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

毫无疑问,它的构造方法中首先将其转为了相应的字节数组中的数据。
同一时候 获取其相应的Hash值

 /** Cache the hash code for the string */
    private int hash; // Default to 0
  • 3、将char数组中的内容构造为String类型
 char[] chars = new char[]{"q","e","e","q","e","e"};
        //将char数组中的内容构造为String类型
        String string = new String(chars);

        //构造的字符串为 qeeqee

这里是依赖字符数组来创建构造String 。从源代码的角度来看,毫无疑问在其相应的构造中首先将其转为了相应字符数组

 public String(char value[]) {
            this.value = Arrays.copyOf(value, value.length);
        }

能够看到这里并没有直接通过 Arrays的copyOf创建了一个新的字符数组,并赋值 于this.value,

public static char[] copyOf(char[] original, int newLength) {
            char[] copy = new char[newLength];
            System.arraycopy(original, 0, copy, 0,
                            Math.min(original.length, newLength));
            return copy;
        }
  • 4、 将字符数组中的部分数据构造为String
 char[] chars = new char[]{"q","e","e","q","e","e"};
        //构造字符串
        String string = new String(chars,0,2);

        //构造的字符串为 qe 
        //也就是说将字符数组中的部分字符 构造成String 

从其构造源代码来看 :

public String(char value[], int offset, int count) {
            if (offset < 0) {
                throw new StringIndexOutOfBoundsException(offset);
            }
             if (count <= 0) {
                 if (count < 0) {
                    throw new StringIndexOutOfBoundsException(count);
                }
            if (offset <= value.length) {
                    this.value = "".value;
                    return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
                throw new StringIndexOutOfBoundsException(offset + count);
            }
            this.value = Arrays.copyOfRange(value, offset, offset+count);
        }

也就是说当我们通过这样的方法来构造String 的时候 , 传入的參数中构造字符起始位置 offset小于零。那么将会出异常,构造字符个数 count 小于0,

那么意味取出的字符数组中的长度为0,也就是构造一个 ""字符串,同一时候赋值其字符数组。

当构造起始位置 字符个娄都不小于0的时候 ,当起始位置与取出的字符长度设置不合理(所谓不合理指的是 例 字符数组长度为 5,

构造字符串的时候传入的 起始位置 为3 。构造长度为5,也就是说在字符数组中从3号位置取值,向后延取5个值,原字符数组长度必定不够)的时候,

抛出异常

当传入的參数合理的时候。则通过Arrays的copyOfRange方法创建一个新的字符数组空间,并赋值 this.value

public static char[] copyOfRange(char[] original, int from, int to) {
            int newLength = to - from;
            if (newLength < 0)
                throw new IllegalArgumentException(from + " > " + to);
            char[] copy = new char[newLength];
            System.arraycopy(original, from, copy, 0,
                            Math.min(original.length - from, newLength));
            return copy;
        }