移动互联网开发教学案例学习-1

本文详细介绍了如何使用SurfaceView在Android平台上开发经典游戏FlappyBird。从SurfaceView的使用方法,到在MainActivity中显示SurfaceView,再到绘制背景、鸟和管道的步骤,逐一讲解了游戏的基本构建过程。开发者需要掌握SurfaceView的生命周期回调,以及如何在Canvas上进行图像绘制,以实现游戏画面的流畅更新。
摘要由CSDN通过智能技术生成

2021SC@SDUSC


目录

案例——Flappybird

1.SurfaceView的使用方法

2.在MainActivity中显示SurfaceView

3.绘制背景

4.绘制鸟 

5.绘制管道 


案例——Flappybird

绘制结果展示:

 

1.SurfaceView的使用方法

使用方法:

1、继承SurfaceView,实现SurfaceHolder.Callback接口

2、重写以下方法:

surfaceChanged:在surface大小或者格式发生变化时触发,在surfaceCreated调用后至少会被调用一次。

surfaceCreated:surface创建时触发,一般在此函数中开启绘图线程(新的线程,不要再这个线程中绘制surface)

surfaceDestoryed:销毁时触发,一般不可见时就会销毁。

3、利用getHolder()获取SurfaceHolder对象,调用SurfaceHolder.addCallback添加回调。

4、SurfaceHolder.lockCanvas获取Canvas对象并锁定画布,调用Canvas绘图,SurfaceHolder.unlockCanvasAndPost结束锁定画布,提交改变。

SurfaceView vs View

它和View有一个很大的区别,View在UI线程去更新自己;而SurfaceView则在一个子线程中去更新自己;这也显示出了它的优势,当制作游戏等需要不断刷新View时,因为是在子线程,避免了对UI线程的阻塞。

2.在MainActivity中显示SurfaceView

public class B_MainActivity extends AppCompatActivity {
    GameFlappyBird mGame;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        checkPermission();
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        mGame=new GameFlappyBird(this);
        setContentView(mGame);
    }
}

 MainActivity 作为主界面,通过setContentView(mGame);来设置SurfaceView为主页面展示。

3.绘制背景

(1)成员变量

    //背景相关
    private Bitmap mBackgroud_bitmap;
    private int mWidth,mHeight;
    private RectF mGamePanelRect=new RectF();

Bitmap背景图成员;

需要获取当前View的尺寸 width,height;

 设置绘画区域的RecF类成员。

(2)加载图片、初始化图片的方法

 //加载图片
    private Bitmap loadBitmapByResId(int resId){
        return BitmapFactory.decodeResource(getResources(), resId);
    }
    //初始化图片
    private void initBitmap(){
        mBackgroud_bitmap=loadBitmapByResId(R.drawable.bg1);
        mBird_bitmap=loadBitmapByResId(R.drawable.b1);
        mPipeTop=loadBitmapByResId(R.drawable.g2);
        mPipeBottom=loadBitmapByResId(R.drawable.g1);
    }

(3)在Surface创建时初始化Bitmap

initBitmap();

(4)设置背景长宽,初始化尺寸

 protected void onSizeChanged(int w, int h, int oldw, int oldh){
        super.onSizeChanged(w, h, oldw, oldh);

        mWidth = w;
        mHeight = h;
        mGamePanelRect.set(0, 0, w, h);

    }

(5)画背景

 //画背景
private void drawBg(){
    mCanvas.drawBitmap(mBackgroud_bitmap,null,mGamePanelRect,null);
}

private void draw()
    {
        try
        {
            // 获得canvas
            mCanvas = mHolder.lockCanvas();
            if (mCanvas != null)
            {
                // drawSomething..
                drawBg();

            }
        } catch (Exception e)
        {
        } finally
        {
            if (mCanvas != null)
                mHolder.unlockCanvasAndPost(mCanvas);
        }
    }

4.绘制鸟 

(1)鸟的变量

  //鸟相关
    private Bird bird;
    private Bitmap mBird_bitmap;

(2)初始化鸟的对象

 public Bird(Context context,int gameWidth,int gameHeight,Bitmap bitmap){
        this.bitmap=bitmap;
        //鸟的位置
        x=(gameWidth/2)-(bitmap.getWidth()/2);
        y=(int)(gameHeight*RADIO_POS_HEIGHT);

        //计算鸟的宽度和高度
        mWidth=Util.dp2px(context,BIRD_SIZE);
        mHeight=(int)(mWidth*1.0f/bitmap.getWidth()*bitmap.getHeight());

    }

鸟在屏幕高度2/3的位置。 

(3)画鸟

 //画鸟
    private void drawBird(){
        bird.draw(mCanvas);
    }

5.绘制管道 

(1)变量

上管道的高度(管道长度时随机生成的,设置一个最大值、最小值);

上管道最大高度4/5F,上管道最小高度1/5F;

管道间隙长度;

下管道长度:用背景长度-(上管道长度+管道间隙长度)计算;

上下管道的图片;

管道横坐标

(2)为管道随机生成一个高度

 private void randomHeight(int gameHeight){
        height=random.nextInt((int)(gameHeight*(RADIO_MAX_HEIGHT-RASIO_MIN_HEIGHT)));
        height=(int)(height+gameHeight*RASIO_MIN_HEIGHT);
    }

(3)构造函数

public Pipe(Context context,int gameWidth,int gameHeight,Bitmap top,Bitmap bottom){
        //间隙是默认值
        margin=(int)(gameHeight*RADIO_BETWEEN_UP_DOWN);
        //默认从最右边出现
        x=gameWidth;
        //图片参数
        mTop=top;
        mBottom=bottom;
        //随机设置上管道高度
        randomHeight(gameHeight);

    }

(4)画自己

   public void draw(Canvas mCanvas, RectF rectF){
        mCanvas.save();
        //rect为整个管道
        mCanvas.translate(x,-(rectF.bottom-height));
        mCanvas.drawBitmap(mTop,null,rectF,null);
        //下管道
        mCanvas.translate(0,(rectF.bottom-height)+height+margin);
        mCanvas.drawBitmap(mBottom,null,rectF,null);
        mCanvas.restore();
    }

(5)在主类中初始化自己

 private void drawPipes(){
        //画出管道List中的每一个
        for(Pipe pipe:mPipes){
            pipe.setX(pipe.getX()-mSpeed);
            pipe.draw(mCanvas,mPipeRect);
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值