Android游戏开发之绘制游戏主菜单与进度条加载进度(十三)

雨松MOMO带你走进游戏开发的世界之主菜单与进度条



雨松MOMO原创文章如转载,请注明:转载至我的独立域名博客雨松MOMO程序研究院,原文地址:http://www.xuanyusong.com/archives/271




本例中出现的资源图片全部源于互联网,本文仅供个人学习。






        由于Android开发 横竖屏的切换会给游戏开发造成非常麻烦的事情 所以在游戏的制作当中会强制手机屏幕横屏或者竖屏避免横竖屏切换造成的数据重置 即使让程序不在切换屏幕后调用onCreat()方法 也会带来屏幕自适应的麻烦 所以Android的游戏一般都会强制横屏或者强制竖屏。

强制横屏的方法


	//强制为横屏
	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

强制竖屏的方法

//强制竖屏
	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);


后期的博文我会详细介绍 可以切换屏幕的情况下开发游戏和软件,废话不多说了。


1.游戏主菜单
        游戏中的菜单在游戏开发中虽然在程序员的眼力不是最难的开发难点但是它在玩家眼力确实很重要的一部分,因为任何一款游戏第一个进入玩家眼帘的就是游戏的主菜单,制作一个漂亮的界面对于游戏品质来说会提高很多。现在主流的游戏主菜单都是使用漂亮的背景加上一些动画效果而构成,今天雨松MOMO用自己写的一个Demo向大家介绍如何制作一个漂亮的游戏菜单。


Demo中这个游戏界面一共是又3个部件组成的
1.游戏背景图
2. 图片按钮 教学 与 设置,  在程序中须要对点击图片按钮进行事件的处理
3.动画效果 红框中的小鱼是一组游戏动画 ,从一进游戏菜单界面开始小鱼就从屏幕的右边向左边游让界面动了起来, 游戏菜单中可以多加一些这样的动画效果会使游戏界面活灵活现起来,给玩家一种视觉的冲击,游戏动画绘制的方法我已经在前几篇博客详细的说明 如果看到这里你还是不太清楚动画如何来绘制请阅读我前几篇博客。






        为了方便使用图片按钮 所以我写了一个ImageButton类 专门来处理图片按钮的绘制以及监听,这个类是非常有存在必要的 用对象去处理 会比在代码中写死坐标点来处理方便很多可以更好地管理这些图片按钮。用户点击屏幕后程序只需要调用ImageButton成员方法IsClick() 根据返回值 就可以确定用户点击的范围是否在这个图片按钮中。

public class ImageButton {
  
    /**按钮图片**/
    private Bitmap mBitButton = null;
    
    /**图片绘制的XY坐标**/
    private int mPosX =0;
    private int mPosY =0;
    /**图片绘制的宽高**/
    private int mWidth =0;
    private int mHeight =0;
  
    public ImageButton(Context context, int frameBitmapID, int x, int y) {
	mBitButton = ReadBitMap(context,frameBitmapID);
	mPosX = x;
	mPosY = y;
	mWidth = mBitButton.getWidth();
	mHeight = mBitButton.getHeight();
    }

    /**
     * 绘制图片按钮
     * @param canvas
     * @param paint
     */
    public void DrawImageButton(Canvas canvas, Paint paint) {
	canvas.drawBitmap(mBitButton, mPosX, mPosY, paint);
    }
    
    /**
     * 判断是否点中图片按钮
     * @param x
     * @param y
     */
    public boolean IsClick(int x, int y) {
	boolean isClick = false;
	if (x >= mPosX && x <= mPosX + mWidth && y >= mPosY
		&& y <= mPosY + mHeight) {
	    isClick = true;
	}
	return isClick;
    }
    
    /**
     * 读取图片资源
     * @param context
     * @param resId
     * @return
     */
    public Bitmap ReadBitMap(Context context, int resId) {
	BitmapFactory.Options opt = new BitmapFactory.Options();
	opt.inPreferredConfig = Bitmap.Config.RGB_565;
	opt.inPurgeable = true;
	opt.inInputShareable = true;
	// 获取资源图片
	InputStream is = context.getResources().openRawResource(resId);
	return BitmapFactory.decodeStream(is, null, opt);
    }
}

2.游戏进度条的实现

        我相信读我博文的朋友 应该都玩过游戏吧, 进度条机制基本上是个游戏都有,要想做一个完全百分百以按读取进度比例的进度条就需要使用线程检测文件的读取进度来确定当前的进度信息,我觉得这么做完全没必要,纯属多余,而且基本上没有游戏公司这么做,为什么呢?我相信大家玩游戏的时候都会发现有时候进度条读取的很不均匀 比如说进度条从左边给右边走 在中间某一个点卡住了一小会儿,这就表明游戏的进度是通过读取文件结束以后才计算出来的,卡住的时候刚好是在读较多文件的时候。下面我向大家分享一下我在游戏开发中如何来计算进度信息。







       在读取进度的界面我会调用Loading()这个方法,每次调用mProgress 就会++  ,在switch 中就可以分布式读取资源,每个case中会加载 不同的资源 所以读取的时间是不一样的,读取的总数 和 当前读取mProgress的值 就  可以计算出进度的百分比值,最后根据计算出来的百分比在屏幕中显示进度信息。


我在强调一下下面代码中的sleep(200)须要替换成真正需要加载的资源,由于本例中没有大量的资源 所以我临时写成Sleep去等待 将进度显示在UI中。

	public void Loading() {
	    // 这里应该是去读取资源, 由于没有大量的资源 这里我暂时只用线程去等待
	    try {
		switch (mProgress) {
		case 0:
		    Thread.sleep(200);
		    break;
		case 1:
		    Thread.sleep(200);
		    break;
		case 2:
		    Thread.sleep(200);
		    break;
		case 3:
		    Thread.sleep(200);
		    break;
		case 4:
		    Thread.sleep(200);
		    break;
		case 5:
		    Thread.sleep(200);
		    break;
		case 6:
		    Thread.sleep(200);
		    break;
		case 7:
		    Thread.sleep(200);
		    break;
		case 8:
		    Thread.sleep(200);
		    break;
		case 9:
		    Thread.sleep(200);
		    break;
		case 10:
		    Thread.sleep(200);
		    break;
		case 11:
		    Thread.sleep(200);
		    break;
		}
		mProgressBar = (100 / 12) * mProgress;
		mProgress++;
	    } catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
}

在Loading状态中实时监测mProgress的值, 未读取到100在UI中绘制进度信息,读取到100则修改游戏状态机状态 转跳读取成功界面。


	    /** 这里表示进度加载完成 **/
	    if (mProgressBar >= 100) {
		setGameState(GAME_TEACH);
	    }




3.游戏状态机

       游戏状态机的实现方式的是通过变量来控制当前游戏状态,在游戏主线程中只更新绘制当前游戏状态下的内容,这就是游戏状态机的原理。
      下面的代码中一共有4个游戏状态 分别是 游戏菜单状态,读取进度状态,读取成功教学状态 ,游戏设置状态。在程序执行的过程中根据须要的时候去更改游戏状态。

	protected void Draw() {
	    switch (mState) {
	    case GAME_MENU:
		/**计算鱼动画的X坐标向左超出屏幕后在还原保持一直在屏幕上游动**/
		mMenuAnimPosX-= 5;
		if(mMenuAnimPosX + MENU_ANIM_WIDTH <= 0) {
		    mMenuAnimPosX = mScreenWidth;
		}
		/**绘制背景**/
		mCanvas.drawBitmap(mBitMenuBG, 0, 0, mPaint);
		mCanvas.drawBitmap(mBitMenuTitle, (mScreenWidth - mBitMenuTitle.getWidth()) >> 1,0, mPaint);
		mMenuAnim.DrawAnimation(mCanvas, mPaint, mMenuAnimPosX , 100);
		
		/**绘制按钮**/
		mButtonTeach.DrawImageButton(mCanvas, mPaint);
		mButtonOption.DrawImageButton(mCanvas, mPaint);
		
		
		break;
	    case GAME_LOAD:
		
		mCanvas.drawBitmap(mBitMenuBG, 0, 0, mPaint);
		mCanvas.drawBitmap(mBitMenuTitle, (mScreenWidth - mBitMenuTitle.getWidth()) >> 1,0, mPaint);
		mButtonTeach.DrawImageButton(mCanvas, mPaint);
		mButtonOption.DrawImageButton(mCanvas, mPaint);

		mCanvas.drawBitmap(mLoadBack, (mScreenWidth - mLoadBack.getWidth()) >> 1, mScreenHeight >> 1, mPaint);
		//这里计算进度条进度
		Loading();
		break;
	    case GAME_TEACH:
		mCanvas.drawBitmap(mBitTeach, 0, 0, mPaint);
		mCanvas.drawBitmap(mMomo, (mScreenWidth >> 1) - (mMomo.getWidth()>> 1), 20, mPaint);
		
		String str1 = "欢迎光临雨松MOMO的博客 资源已经全部加载完成";
		drawRimString(mCanvas,str1,Color.BLACK,(mScreenWidth >> 1) - (((int)mPaint.measureText(str1)) >> 1), mScreenHeight >> 1);
		break;
	    case GAME_OPTION:
		mCanvas.drawBitmap(mBitTeach, 0, 0, mPaint);
		mCanvas.drawBitmap(mMomo, (mScreenWidth >> 1) - (mMomo.getWidth()>> 1), 20, mPaint);
		String str2 = "设置界面暂未 开放 雨松MOMO:xuanyusong@gmail.com";
		drawRimString(mCanvas,str2,Color.BLACK,(mScreenWidth >> 1) - (((int)mPaint.measureText(str2)) >> 1), mScreenHeight >> 1);
		break;
	    }
	}


如图:我们实现点击设置按钮 游戏状态机跳转到 游戏状态页面




      在拿到玩家触摸屏幕后的的X Y坐标 判断是否在游戏主菜单界面 点击设置按钮 状态机切换到GAME_OPTION 游戏设置界面。

	public void UpdateTouchEvent(int x, int y) {
	    switch(mState) {
	    case GAME_MENU:
		if(mButtonTeach.IsClick(x, y)) {
		   //教学图片按钮被按下
		    setGameState(GAME_LOAD);
		}else if(mButtonOption.IsClick(x, y)) {
		   //设置图片按钮被按下   
		    setGameState(GAME_OPTION);
		}
		break;
	    }
	}

后期我还会详细介绍游戏状态机,今天只是先简单给大家介绍一下,希望孩童们快速跟进雨松MOMO的博客。



最后由于代码较多我就不贴在博客中了 , 老规矩每一篇博文都会附带我写的源代码,下面给出Demo源码的下载地址欢迎大家下载阅读互相学习,互相研究,互相讨论 雨松MOMO希望可以和大家一起进步。

下载地址:http://www.xuanyusong.com/archives/271
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页