当前位置:  编程技术>移动开发
本页文章导读:
    ▪寨子腾讯“爱消除”游戏7日教程        山寨腾讯“爱消除”游戏7日教程 【前言】 最近,“爱消除”游戏异常的火爆,它正是山寨之王的作品。从今天开始,我们将连续7天,每天一个小时,用OpenGL ES技术,按照解决一般问题的.........
    ▪ ViewPager上下滑动效果        ViewPager左右滑动效果1.下载PagerSlidingTabStrip这个库文件,用来滑动导航栏下载地址  https://github.com/astuetz/PagerSlidingTabStrip 2.导入自己创建的项目中,在导入的过程中可能会出错,一是因为support..........
    ▪ 华为手机打开Logcat的步骤       华为手机打开Logcat的方法华为手机默认是关闭logcat信息的,这在开发调试时当然很不方便,打开log信息的方法如下 1. 进入拨号界面输入:*#*#2846579#*#* 2、2. 依次选择ProjectMenu---后台设置----L.........

[1]寨子腾讯“爱消除”游戏7日教程
    来源: 互联网  发布时间: 2014-02-18
山寨腾讯“爱消除”游戏7日教程


【前言】

最近,“爱消除”游戏异常的火爆,它正是山寨之王的作品。从今天开始,我们将连续7天,每天一个小时,用OpenGL ES技术,按照解决一般问题的思路,进入有趣的山寨之旅。

 

学习本教程最好的方法,就是运行附件的代码,对于不理解的地方再看看课程是如何解释的。

 

 

 

第一天

【课程内容】

今天我们将基于OpenGL ES搭建一个简单的游戏框架,并绘制出第一个图案。

【源代码下载地址】http://download.csdn.net/detail/elong_2009/6444773

 

1、设计程序框架

实现这个游戏的框架非常简单,仅包含一个activity,一个渲染视图及若干个渲染类对象。主框架代码加起来只有120行。

1.1 CrazyLinkActivity 类

该类通过创建OpenGL ES渲染视图,实现OpenGL图形的显示。

package elong.CrazyLink;

 

import android.app.Activity;

import android.os.Bundle;

 

public class CrazyLinkActivity extends Activity {

CrazyLinkGLSurfaceView mGLSurfaceView;

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        mGLSurfaceView = new CrazyLinkGLSurfaceView(this);

        setContentView(mGLSurfaceView);

        mGLSurfaceView.requestFocus();

        mGLSurfaceView.setFocusableInTouchMode(true);

    }

 

@Override

protected void onResume() {

// TODO Auto-generated method stub

super.onResume();

mGLSurfaceView.onResume();

}

 

@Override

protected void onPause() {

// TODO Auto-generated method stub

super.onPause();

mGLSurfaceView.onPause();

}

}

 

1.2 CrazyLinkGLSurfaceView 类

该类提供了一个OpenGL ES场景渲染器,通过onDrawFrame 方法,将要绘制的图案渲染后输出。

 

package elong.CrazyLink;

 

import java.io.IOException;

import elong.CrazyLink.Draw.DrawAnimal;

import java.io.InputStream;

import javax.microedition.khronos.egl.EGLConfig;

import javax.microedition.khronos.opengles.GL10;

 

import elong.CrazyLink.R;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.opengl.GLSurfaceView;

import android.opengl.GLUtils;

 

public class CrazyLinkGLSurfaceView extends GLSurfaceView{

    private SceneRenderer mRenderer;//场景渲染器

    

    static int animalTextureId;//动物素材纹理id    

public CrazyLinkGLSurfaceView(CrazyLinkActivity activity) {

        super(activity);

        mRenderer = new SceneRenderer();//创建场景渲染器

        setRenderer(mRenderer); //设置渲染器

        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染                   

    }   

private class SceneRenderer implements GLSurfaceView.Renderer 

    { 

DrawAnimal drawAnimal;

        public void onDrawFrame(GL10 gl) {  

         gl.glShadeModel(GL10.GL_SMOOTH);//着色模式为平滑着色

         gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);//清除颜色缓冲区及深度缓冲区

         gl.glMatrixMode(GL10.GL_MODELVIEW);//设置矩阵为模式矩阵

         gl.glLoadIdentity(); //设置当前矩阵为单位矩阵

         gl.glTranslatef(0f, 0f, -2.0f); //调整Z轴,可以调整图像显示的大小 

         drawAnimal.draw(gl,1,0,0); //在这里绘制需要显示的素材对象        

        }  

        

        public void onSurfaceChanged(GL10 gl, int width, int height) {

       

         gl.glViewport(0, 0, width, height);         //设置当前矩阵为投影矩阵

            gl.glMatrixMode(GL10.GL_PROJECTION);        //设置当前矩阵为单位矩阵

            gl.glLoadIdentity();             //计算透视投影的比例

            float ratio = (float) width / height;       //调用此方法计算产生透视投影矩阵

            gl.glFrustumf(-ratio, ratio, -1, 1, 1, 100);        

        }

 

        public void onSurfaceCreated(GL10 gl, EGLConfig config) {

         gl.glDisable(GL10.GL_DITHER);//关闭抗抖动

            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);//设置特定Hint项目的模式,这里为设置为使用快速模式

            gl.glClearColor(0,0,0,0);             //设置屏幕背景色黑色RGBA   

            gl.glShadeModel(GL10.GL_SMOOTH);        //设置着色模型为平滑着色

            gl.glEnable(GL10.GL_DEPTH_TEST);//启用深度测试

        

         animalTextureId = initTexture(gl, R.drawable.animal);//初始化纹理对象

         drawAnimal = new DrawAnimal(animalTextureId);//参加动物素材对象

        }

    }

public int initTexture(GL10 gl, int drawableId)

{

int[] textures = new int[1];

gl.glGenTextures(1, textures, 0);

int currTextureId = textures[0];

gl.glBindTexture(GL10.GL_TEXTURE_2D, currTextureId);

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);//指定缩小过滤方法

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);//指定放大过滤方法

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);//指定S坐标轴贴图模式

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);//指定T坐标轴贴图模式

InputStream is = this.getResources().openRawResource(drawableId);

Bitmap bitmapTmp;

try{

bitmapTmp = BitmapFactory.decodeStream(is);

}

finally{

try{

is.close();

}

catch (IOException e) {

e.printStackTrace();

}

}

GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0);

bitmapTmp.recycle();

return currTextureId;

}

}

 

以上实现了游戏框架的主要内容。今后的课程,都会基于这个基本框架来设计代码。

 

1.3 DrawAnimal 类

本课程专门设计一系列的渲染类,用于对特定对象或场景的绘制,凡是Draw打头的类,都是渲染类。后续课程还会陆续提到更多的渲染类。所有渲染类,都集中放在package elong.CrazyLink.Draw包中。

渲染类的核心用途就是将一个对象或动作抽象出来,通过渲染类对象,实现特定对象或动作的绘制。在后续的应用中,我们会将多个渲染类合并一起使用,以达到显示特定场景或特效的目的。

每一个渲染类都会有一个draw方法,该方法实现对特定对象或场景的绘制。要实现一个新的场景或效果,您只需用设计好渲染类的draw方法即可。

DrawAnimal 类的代码请参考附件。部分代码在下节还会有讲解。

 

 

 

2、绘制第一个图案

 

我们要绘制的第一个图案效果如下图,这是素材图片animal.png中7个素材中的其中一个。

 

 

 

2.1基本原理

很显然,我们要绘制的是一张正方形的图片,通过纹理贴图,可以很容易地实现。需要注意的是,在OpenGL ES中,并没用提供绘制正方形的操作,绘制一个正方形,需要转换成绘制两个三角形。

这里需要关注的一个技术细节是背面裁剪,这是OpenGL ES的一项功能,含义是,打开此功能后,视角在三角形的背面时不渲染此三角形(即无法看到此三角形),该功能可以提高渲染的效率。

因此,我们需要保证在观察方向上渲染三角形,否则就有可能会看不到所绘制的图像。很多初学者经常会遇到这个问题,如果您绘制的三角形没有按预期出现,您可能需要检查是不是这个原因引起的。

以下是确定一个三角形正反面的方法:通常情况下,当面对一个三角形时,如果顶点的顺序是逆时针的,则位于三角形的正面;反之就是反面。

如下图所示:

 

 

2.2顶点坐标数据

知道了这个原理之后,我们就可以设计正方形的顶点数据了,如下就是顶点坐标数据的定义:

        int vertices[]=new int[]//顶点坐标数据数组

        {

            -32*UNIT_SIZE,32*UNIT_SIZE,0,

         -32*UNIT_SIZE,-32*UNIT_SIZE,0,

         32*UNIT_SIZE,-32*UNIT_SIZE,0,

         32*UNIT_SIZE,-32*UNIT_SIZE,0,

         32*UNIT_SIZE,32*UNIT_SIZE,0,

         -32*UNIT_SIZE,32*UNIT_SIZE,0

   };

附件的代码中还根据显示位置(col,row)计算了偏移量        

int deltaX = ((col-3)*64*UNIT_SIZE);

    int deltaY = ((row-3)*64*UNIT_SIZE);

为了清晰起见,这里的定义没有加上偏移量deltaX及deltaY。

注意:顶点坐标数据采用的笛卡尔坐标系,其坐标值得范围是任意的;而纹理顶点数据所采用的S-T坐标系,其坐标取值范围是0.0~1.0

 

2.3 纹理顶点坐标数据

对应的,我们需要为正方形的每个顶点设置对应的纹理顶点坐标,如下定义:

        float textureCoors[]=new float[]//顶点纹理S、T坐标值数组

    {

         (witch - 1) * textureRatio,0,

         (witch - 1) * textureRatio,1,

         witch * textureRatio,1,

         witch * textureRatio,1,

         witch * textureRatio,0,        

         (witch - 1) * textureRatio,0

}; 

值得一提的是,由于我们将7个动物素材集中在一张图片(animal.png)中加载进来(为了满足OpenGL ES对像素的要求,实际空出了一个素材的位置,在OpenGL ES中进行纹理映射时对纹理图片的尺寸是有要求的,纹理图片的宽度和高度必须为2n (2的n次方),即32x32,256x512等。)

而实际显示的时候,我们仅想显示其中的一个素材,因此引入了一个变量textureRatio,该变量的值是textureRatio = (float)(1/8.0f),用来精确控制每个动物素材(witch:有效地范围为1~7)对应的纹理坐标。通过传入不同的witch可以渲染不同的对象。

如下图示:

 

 

2.4 渲染类的核心方法draw

最后,介绍一下DrawAnimal类中得draw方法。在后续的课程中,用DrawXxxx命名的类都是用来渲染某个特定场景的,这种类中都会有一个公有的方法draw。

DrawAnimal中的draw方法是这样定义的:

public void draw(GL10 gl, int witch, int col, int row)

该方法可以将witch素材绘制在x=col, y=row的位置。

 

在这里,我们把draw方法的实现贴出来,具体含义直接参考代码的注释。在后续的课程当中,只会将新提到的知识点将代码贴出。完整的代码请参考对应的附件,不再啰嗦。

 

    public void draw(GL10 gl, int witch, int col, int row)

    {   

     initVertexBuffer(col, row); //根据col,row初始化顶点坐标

     initTextureBuffer(witch); //根据witch来初始化纹理顶点数据

     //gl.glTranslatef(col * textureRatio, row * textureRatio, 0);//在x=col,y=row的位置绘制选定的素材对象        

        //顶点坐标,允许使用顶点数组

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//为画笔指定顶点坐标数据

        gl.glVertexPointer

        (

     3, //每个顶点的坐标数量为3  xyz 

     GL10.GL_FIXED, //顶点坐标值的类型为 GL_FIXED

     0,  //连续顶点坐标数据之间的间隔

     mVertexBuffer //顶点坐标数据

        );

        

        //纹理坐标,开启纹理

        gl.glEnable(GL10.GL_TEXTURE_2D);   

        //允许使用纹理数组

        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        //为画笔指定纹理uv坐标数据

        gl.glTexCoordPointer

        (

     2,  //每个顶点两个纹理坐标数据 S、T

     GL10.GL_FLOAT,  //数据类型

     0,  //连续纹理坐标数据之间的间隔

     mTextureBuffer //纹理坐标数据

        );        

        gl.glBindTexture(GL10.GL_TEXTURE_2D,textureId);//为画笔绑定指定名称ID纹理   

        

        //绘制图形

        gl.glDrawArrays

        (

     GL10.GL_TRIANGLES, 

     0, 

     vCount

        );

        gl.glDisable(GL10.GL_TEXTURE_2D);//关闭纹理

    }

 

2.5考虑字节序的问题

这里额外强调的一点是:不同平台其字节序有可能不同,如果数据单元不是字节的,就一定要经过ByteBuffer进行转换,转换的关键就是要通过ByteOrder设置为nativeOrder(),以适应对应平台的字节序,否则就有可能会出现问题。

ByteBuffer cbb = ByteBuffer.allocateDirect(textureCoors.length*4);

cbb.order(ByteOrder.nativeOrder());//设置本地字节顺序


    
[2] ViewPager上下滑动效果
    来源: 互联网  发布时间: 2014-02-18
ViewPager左右滑动效果

1.下载PagerSlidingTabStrip这个库文件,用来滑动导航栏下载地址  https://github.com/astuetz/PagerSlidingTabStrip

2.导入自己创建的项目中,在导入的过程中可能会出错,一是因为support.v4.jar包冲突,将其中的一个删掉,并引入另一个的support.v4.jar;二是因为项目的版本问题,修改一下创建的项目版本就可以了,项目版本越高越好。

3.简单使用:(1)在main_activity.xml文件中:  

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.kgcyy.app"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <com.astuetz.viewpager.extensions.PagerSlidingTabStrip
            android:id="@+id/pagertab"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_alignParentTop="true"
            android:layout_centerInParent="true"
            android:saveEnabled="true"
            app:tabPaddingLeftRight="20dp"
            android:background="#6699FF"
            app:indicatorColor="@color/indicator_color" />
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/pagertab"
        android:layout_gravity="center" >
    </android.support.v4.view.ViewPager>
</RelativeLayout>

(2)在activity中

public class MainActivity extends Activity{

private ViewPager mViewPager;

private PagerSlidingTabStrip mPagerSlidingTabStrip;

private View view1,view2,view3;

private List<View> viewList = new ArrayList<View>;//用来添加需要滑动的view

private List<String> titleList = new ArrayList<String>;//用来添加导航栏的标题

private MyAdapter mAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout..main_activity);

LayoutInflater inflater = getLayoutInflater();

//layout  的定义不在此显示

view1 = inflater.inflate(R.layout.layout1,null);
view2 = inflater.inflate(R.layout.layout2,null);

view2 = inflater.inflate(R.layout.layout3,null);
viewList.add(view1);

viewList.add(view2);

viewList.add(view3);

titleList.add("A");

titleList.add("B");

titleList.add("C");

mViewPager = (ViewPager) findViewById(R.id.viewpager);
mPagerSlidingTabStrip = (PagerSlidingTabStrip) findViewById(R.id.pagertab);

mAdapter = new MyAdapter();

mViewPager.setAdapter(mAdapter);

mPagerSlidingTabStrip.setViewPager(mViewPager);

mPagerTabStrip.setOnPageChangeListener(new PageChangeListener());

}


class PageChangeListener implements OnPageChangeListener {


@Override
public void onPageScrollStateChanged(int arg0) {


}


@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {


}


@Override
public void onPageSelected(int arg0) {
//page滑动时的事件
}


}

class MyPagerAdapter extends PagerAdapter {

@Override
public int getCount() {
return viewList.size();
}


@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}


@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView(viewList.get(position));
}


@Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}


@Override
public CharSequence getPageTitle(int position) {
return titleList.get(position);
}


@Override
public Object instantiateItem(ViewGroup container, int position) {
((ViewPager) container).addView(viewList.get(position), 0);
return viewList.get(position);
}

}

}

4.此项目能够实现基本的滑动,但是界面不太美观,尤其是导航栏,需要自己动手改变库文件的内容。


    
[3] 华为手机打开Logcat的步骤
    来源: 互联网  发布时间: 2014-02-18
华为手机打开Logcat的方法

华为手机默认是关闭logcat信息的,这在开发调试时当然很不方便,打开log信息的方法如下

1. 进入拨号界面输入:*#*#2846579#*#*


2、2. 依次选择ProjectMenu---后台设置----LOG设置---LOG开关 点击打开, 然后在LOG级别选VERBOSE

3、 重新启动手机


    
最新技术文章:
编程技术其它 iis7站长之家
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3