4시간 삽질... 책한권 없이 만들긴 만들었어요..
OpenGL 이라 엄청난 속도로 화면 처리 해준다는게 참 좋은거 같습니다.
일단 클레쓰 11개 정도 만들었는데요.
OpenGLView 엑티비티를 상속받은 메인.
MyRenderer 렌더러를 상속받은 기본 렌더러.
MyTexture 비트멥을 얻기위한 텍스쳐.
요기까지는 기본적으로 인터넷 검색하면 자료가 많더군요.
비트멥 한장 스크롤 시켜보고 감 잡았습니다.
IMyTexture 컨버스에 비트멥을 드로잉하기위한 메서드 와, 터치 이벤트 처리를 위한 메서드.
MyResource 이미지리소스 와, 아래 컨트롤 클래쓰 리스트를 공유하기 위한 싱글턴.
BbTan 총알 1개
BbTanGroup 총알 여러개,
MyRoket 아군,
NyRoket 적군,
NyRoketGroup 적군 집단
MyLevel 전광판.
아래는 파일 하나 하나 풀 소스 입니다.
테스트 하던 그대로 올려요.
테스트니깐.
주석은 지금부터 함 달아 볼게요..
2d 라 머 그닥 어려운게 없어서, 어려운게 있으려나 모르겠어요...
모든 컨트롤은 펙토리페턴으로 유연하게 처리되요.
아~! 가장 힘들었던 부분은. 좌표
package com.example.opengl;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
public class OpenGLView extends Activity {
private GLSurfaceView mGLView;
private MyResource Rs;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
Rs = MyResource.getInstance(this); // 싱글턴이라 초기 한번 세팅해줘죠.
mGLView = new GLSurfaceView(this);
//mGLView.setEGLConfigChooser(false);
//mGLView.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR | GLSurfaceView.DEBUG_LOG_GL_CALLS);
mGLView.setRenderer(new MyRenderer(this));
mGLView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
for(IMyTexture mt : MyResource.mControls) {
mt.setOnTouch(event); // 요렇게 해주면 터치가 필요한 컨트롤에서 바로 사용하면 되겟죠.
}
return true;
}
});
setContentView(mGLView);
}
@Override
protected void onPause(){
super.onPause();
mGLView.onPause();
}
@Override
protected void onResume(){
super.onResume();
mGLView.onResume();
}
}// End Class
package com.example.opengl;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLES10;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
public class MyRenderer implements GLSurfaceView.Renderer {
private MyTexture nQuad2 = null;
private float mAngle = 0;
private Context context;
public MyRenderer(Context context){
nQuad2 = new MyTexture();
this.context = context;
}
float zm = 4.4f;
@Override
public void onDrawFrame(GL10 gl) {
// OpenGL 의 기본 쓰레드를 사용해요.
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
// 아래를 주석 해제하면 위 실행화면 처럼 처음에 세로로 전체 회전하면서 등장합니다.
//if(mAngle<320){zm=5.4f; mAngle += 1.0f;}
gl.glTranslatef(0.0f, 0.0f, -zm);
gl.glRotatef(mAngle, 45, 0.0f, 0.0f);
nQuad2.draw(gl); // 텍스쳐 한장만 있으면 되니까. 요걸로 끝.
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES10.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45.0f, (float)width/height, 1.0f, 10.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
nQuad2.initTexture(gl, context);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
}
}// End Class
package com.example.opengl;
import java.io.InputStream;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader.TileMode;
import android.opengl.GLUtils;
import com.example.mygame001.R;
public class MyTexture {
float vertices[] = { // 정사각형으로 나와서 1.6 으로 강제 세팅 했습니다. 1.6배로 나올듯해서.
-1.0f, 1.6f, 0.0f, // LT
1.0f, 1.6f, 0.0f, // RT
1.0f, -1.6f, 0.0f, // RB
-1.0f, -1.6f, 0.0f, // LB
};
float texture[] = {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
short[] index = {
0, 1, 2,
0, 2, 3
};
FloatBuffer verticesBuffer;
ShortBuffer indexBuffer;
FloatBuffer textureBuffer;
private int[] textures;
public MyTexture(){
textures = new int[1];
verticesBuffer = MyUtil.getFloatBuffer(vertices);
indexBuffer = MyUtil.getShortBuffer(index);
textureBuffer = MyUtil.getFloatBuffer(texture);
}
// 비트멥 한장만 나와라.. 하고 요래 해보고 저렇게 해보고..
// 검색해서 하라는대로 다 했는데도 안되더라구요...
// 저사람은 되는데 나는 왜 안될까... 그럼, 될 때까지 해야지
public void draw(GL10 gl){
CreateBitmapTexture(gl, textBitmap); // 요걸로 텍스쳐 메핑을 위한 텍스쳐를 반복해서 만들어요.
gl.glFrontFace(GL10.GL_CCW);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, index.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_BLEND);
}
// 해서 비트멥 한장 출력하는데 성공했습니다.
// 야호~~ 이제 2D 는 끝.
private Bitmap textBitmap;
public void initTexture(GL10 gl, Context context){
InputStream is = context.getResources().openRawResource(R.drawable.image);
textBitmap = BitmapFactory.decodeStream(is);
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
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);
CreateBitmapTexture(gl, textBitmap);
//textBitmap.recycle(); // 요거 풀면 배경 안나와요...
// textBitmap 는 시작부터 완전 종료시점까지 살려둬야 합니다. 여기에 동적으로 텍스쳐를 만들거니까요.
}
// 한장이 나왔으니
// 텍스쳐를 동적으로 생성하고,
// 움직여 봐야 겟죠.
// 배경스크롤 처리 시작.
// 그냥 아무 생각없이 지난번 올렷던 배경스크롤 소스 붙였어요.
// 흠냐. 왜케 느리게 움직일까요... 객체 생성부분을 한번만 생성하도록 바꾸니 날라가네요...야호~!!
private float dy = 0;
private Matrix matrix;
private Bitmap newBitmap;
private BitmapShader bs;
private Paint paint;
private Canvas canvas;
private float speed = 0;
private void CreateBitmapTexture(GL10 gl, Bitmap bitmap){
speed = (bitmap.getHeight()/100)*0.6f;
dy += speed;
dy = (dy>bitmap.getHeight()-speed)? 0: dy;
matrix = new Matrix();
matrix.postTranslate(0, dy);
if(newBitmap==null) newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
if(bs==null) bs = new BitmapShader(bitmap, TileMode.REPEAT, TileMode.REPEAT);
bs.setLocalMatrix(matrix);
if(paint==null) paint = new Paint();
paint.setShader(bs);
if(canvas==null) canvas = new Canvas(newBitmap);
canvas.drawPaint(paint);
for(IMyTexture mt : MyResource.mControls) {
// 메인의 터치 처리처럼. 드로잉 처리도 요렇게 하면 끝입니다.
// 적군, 아군, 총알, 전광판 순서대로 배경위에 드로잉 합니다.
mt.setDraw(canvas, bitmap.getWidth(), bitmap.getHeight());
}
// 마지막으로 생성된 비트멥을 메핑.
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, newBitmap, 0);
//newBitmap.recycle();
}
} // End Class
// 컨트롤은 위 인터페이스를 상속받아 만들어서. MyResource 의 컨트롤 리스트에 추가 해주면 끝 입니다.
package com.example.opengl;
import java.util.LinkedList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import com.example.mygame001.R;
public class MyResource {
private static MyResource instance;
// 이미지들을 한곳에 넣어두고 재활용 합니다.
// 안드로이드가 기본으로 제공하는 이미지만 사용했습니다. 테스트니깐.
public static Drawable Img_NyRoket = null;
public static Drawable Img_MyRoket = null;
public static Drawable Img_BbTan = null;
public static Drawable Img_Bg = null;
public static Bitmap bitmap_Bg = null;
public static float bgScrollTime = 0;
public static List<IMyTexture> mControls;
public static List<NyRoket> mRoketControls;
public static MyResource getInstance(Context context)
{
if(instance==null) instance = new MyResource();
Img_NyRoket = context.getResources().getDrawable(R.drawable.ic_launcher);
Img_MyRoket = context.getResources().getDrawable(R.drawable.ic_launcher);
Img_BbTan = context.getResources().getDrawable(R.drawable.ic_launcher);
Img_Bg = context.getResources().getDrawable(R.drawable.bg03);
bitmap_Bg = BitmapFactory.decodeResource(context.getResources(), R.drawable.bg03);
// 적군이 집단이죠. 스킨쉽 체크시 필요.
mRoketControls = new LinkedList<NyRoket>();
// 모든 컨틀롤은 여기로 집어 넣어요..
// 넣는 순서에 따라 드로잉 순서가 바껴요.
// 가장 나중에 넣은 것이 위로 보이고, 가장 먼저 넣은 것이 아래로 깔려 보입니다.
mControls = new LinkedList<IMyTexture>();
mControls.add(new MyRoket());
mControls.add(new BbTanGroup());
mControls.add(new NyRoketGroup());
mControls.add(new MyLevel());
return instance;
}
}// End Class
package com.example.opengl;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
public class BbTan { // 총알 입니다. 어릴때 가지고 놀던 BB탄이 생각나서. 이렇게 이름을
private Drawable mBallImg;
private int mBallWidth;
private int mBallHeight;
private double mX;
private double mY;
private int mXLeft;
private int mYTop;
private int myType = 0;
private double mAngle;
private boolean mHit=false;
private int mCanvasHeight = 0;
public BbTan(int x, int type, int sh, int angle) {
myType = type;
mBallImg = MyResource.Img_BbTan;
mBallWidth = mBallImg.getIntrinsicWidth();
mBallHeight = mBallImg.getIntrinsicHeight();
mCanvasHeight = sh;
init(x, type, angle);
}
public void init(int x, int type, int angle) {
mX = x;
mHit = false;
if(type==0){
mAngle = 180; // 요건 부채꼴 모양으로 총알을 쏘기위해서.
mY = mCanvasHeight-180;
}else if(type==1){
mAngle = 180+angle; // 아군을 터치하고 좌우이동 뒤로 앞으로 이동시 부채각이 넓어지고 좁아지고.
mY = mCanvasHeight-170;
}else if(type==2){
mAngle = 180-angle;
mY = mCanvasHeight-170;
}
}
public void setDraw(Canvas canvas) {
if(mHit==true)return;
setUpdate();
Paint p = new Paint();
p.setColor((myType==0)? Color.rgb(255, 255, 0): Color.rgb(255, 255, 255));
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(5f);
canvas.drawCircle(mXLeft+mBallWidth/2, mYTop+mBallHeight/2, (myType==0)? 8: 4, p);
}
private void setUpdate() {
double diff = 12d;//총알 이동 속도.
double radians = mAngle * (Math.PI / 180);
mX += diff * Math.sin(radians);
mY += diff * Math.cos(radians);
mYTop = (int) mY + mBallHeight / 2;
mXLeft = (int) mX - mBallWidth / 2;
for(NyRoket ctrl : MyResource.mRoketControls){
mHit = ctrl.checkHit(mX,mY); // 총알하고 적군하고 스킨쉽하는지 여부 쳌크.
if(mHit) break;
}
}
} // End Class
package com.example.opengl;
import java.util.LinkedList;
import java.util.List;
import android.graphics.Canvas;
import android.view.MotionEvent;
public class BbTanGroup implements IMyTexture{
private List<BbTan> mControls;
private int myRoketGetX = 0;
public BbTanGroup() {
mControls = new LinkedList<BbTan>();
}
private int btc = 0;
private int angle = 0;
private int roketY = 0;
@Override
public void setDraw(Canvas canvas, int sw, int sh) {
roketY = sh - 100;
if(btc++>1){
mControls.add(new BbTan(myRoketGetX, 0, sh, angle));
mControls.add(new BbTan(myRoketGetX-16, 1, sh, angle));
mControls.add(new BbTan(myRoketGetX+16, 2, sh, angle));
btc = 0;
}
if(mControls.size() > 40){
mControls.remove(0);
mControls.remove(0);
mControls.remove(0);
}
for(BbTan ctrl : mControls){
ctrl.setDraw(canvas);
}
}
@Override
public void setOnTouch(MotionEvent event) {
myRoketGetX = (int)(event.getX()/1.85); // 터치 위치에 따른 총알 좌/우 위치.
float y = event.getY()/2.2f-70; // 터치상하 위치에 따른 총알 각도.
double ty = y - roketY;
if(y>roketY){
angle = (int)(0.45 * ty);
}
}
}// End Class
package com.example.opengl;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.drawable.Drawable;
public class NyRoket { // 적군 하나.
private Drawable img;
private int tx = 0;
private int ty = 0;
private int lives = 30; // 한방에 가니 재미 없어서 ..
public NyRoket(int x) {
img = MyResource.Img_NyRoket;
tx = x;
ty = -120;
}
public void reset(){
ty = -120;
lives = 30;
}
public void setDraw(Canvas canvas) {
if(lives<=0)return;
int imgWidth = (int)(tx+img.getIntrinsicWidth()*0.6);
int imgHeight = (int)(ty+img.getIntrinsicHeight()*0.6);
img.setBounds(tx, ty, imgWidth, imgHeight);
img.draw(canvas);
Paint p = new Paint();
p.setColor(Color.GREEN);
p.setStrokeWidth(2f);
p.setStyle(Style.STROKE);
//canvas.drawRect(new Rect(tx, ty, tx+54, ty+50), p);
drawText(canvas, String.valueOf(lives), tx+18, ty+36);
}
public void setUpdate() {
ty += 5;
if(getY() > mCanvasHeight){
reset();
}
}
// 스킨쉽 체크..
public boolean checkHit(double x, double y) {
int mx = tx+27;
int my = ty-50;
if (Math.abs(x-mx)>30 || Math.abs(y-my)>10){
return false;
}
if(lives-->0){
return true;
}
return false;
}
private int mCanvasHeight=800;
public void setScreenSize(int sw, int sh) {
mCanvasHeight = sh;
}
// 테두리 문자
// 적군의 lives 를 문자로 표시 합니다.
private void drawText(Canvas canvas, String text, int x, int y){
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.BLACK);
p.setTextSize(12.0f);
p.setTextScaleX(1.5f);
p.setStrokeWidth(4.0f);
p.setStyle(Style.FILL_AND_STROKE);
canvas.drawText(text, x, y, p);
p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.RED);
p.setTextSize(12.0f);
p.setTextScaleX(1.5f);
p.setStrokeWidth(1.0f);
p.setStyle(Style.FILL_AND_STROKE);
canvas.drawText(text, x, y, p);
}
}// End Class
package com.example.opengl;
import android.graphics.Canvas;
import android.view.MotionEvent;
public class NyRoketGroup implements IMyTexture{ // 적군 집단 생성.
public NyRoketGroup() {
int nw = 54;
MyResource.mRoketControls.add(new NyRoket(nw*0));
MyResource.mRoketControls.add(new NyRoket(nw*1));
MyResource.mRoketControls.add(new NyRoket(nw*2));
MyResource.mRoketControls.add(new NyRoket(nw*3));
MyResource.mRoketControls.add(new NyRoket(nw*4));
MyResource.mRoketControls.add(new NyRoket(nw*5));
MyResource.mRoketControls.add(new NyRoket(nw*6));
}
@Override
public void setDraw(Canvas canvas, int sw, int sh) {
for(NyRoket ctrl : MyResource.mRoketControls){
ctrl.setScreenSize(sw,sh);
ctrl.setUpdate();
ctrl.setDraw(canvas);
}
}
@Override
public void setOnTouch(MotionEvent event) { // 적군에겐 필요치 않으니. 무시.
// TODO Auto-generated method stub
}
}// End Class
package com.example.opengl;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
public class MyRoket implements IMyTexture { // 아군.
private Drawable img;
public MyRoket(){
img = MyResource.Img_MyRoket;
}
private float tx = 0;
private float ty = 0;
@Override
public void setOnTouch(MotionEvent event) {
switch(event.getAction()){ // 아군은 좌우로 이동시켜야 하니.
case MotionEvent.ACTION_DOWN :
case MotionEvent.ACTION_UP :
case MotionEvent.ACTION_MOVE :
tx = (float)(event.getX()/1.85-24);
break;
}
}
@Override
public void setDraw(Canvas canvas, int sw, int sh) { // 터치 위치값에 따른 아군 드로잉.
ty = sh-100;
float imgWidth = tx+img.getIntrinsicWidth()/2;
float imgHeight = ty+img.getIntrinsicHeight()/2;
img.setBounds((int)tx, (int)ty, (int)imgWidth, (int)imgHeight);
img.draw(canvas);
}
}// End Class
package com.example.opengl;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Shader.TileMode;
import android.view.MotionEvent;
public class MyLevel implements IMyTexture { // 전광판.
private float tx = 0;
private float ty = 0;
private String action;
@Override
public void setOnTouch(MotionEvent event) {
// TODO Auto-generated method stub
// 터치 정보를 뿌려보기 위해.
tx = event.getX();
ty = event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN : action = "action_down"; break;
case MotionEvent.ACTION_UP : action = "action_up"; break;
case MotionEvent.ACTION_MOVE : action = "action_move"; break;
}
}
private int cnt = 0;
private int speed = 3;
@Override
public void setDraw(Canvas canvas, int sw, int sh) {
Rect topRect = new Rect(5, 5, sw-5, 50);
int bh = 50;
Rect bottomRect = new Rect(5, sh-bh, sw-5, sh-5);
drawRoundRect(canvas, topRect);
cnt++;
// 얼마나 빨리 드로잉 될까 체감하기위해.. 60fps 나오는듯 해요.
drawText(canvas, "거리 : "+String.valueOf(cnt)+" Km", 15, topRect.top+18*1);
cnt = (cnt>Integer.MAX_VALUE-1)? 0: cnt;
// 아직 별로 표시 할게 없어서. 배경 스크롤 속도 찍어 봅니다.
drawText(canvas, "속도 : "+String.valueOf(speed)+" Pixel", 15, topRect.top+18*2);
drawRoundRect(canvas, bottomRect);
drawText(canvas, "터치 : "+String.valueOf(tx)+" / "+String.valueOf(ty), 15, bottomRect.top+18*1);
drawText(canvas, "엑션 : "+action, 15, bottomRect.top+18*2);
// 터치 한곳에 빨간색 원이 찍히게.
drawCircle(canvas, tx, ty);
}
private void drawCircle(Canvas canvas, float x, float y){
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.argb(120, 255, 0, 0));
p.setStrokeWidth(4.0f);
p.setStyle(Style.FILL_AND_STROKE);
float nx = (float)(x/1.85);
float ny = (float)(y/2.2);
canvas.drawCircle(nx, ny-40, 10, p);
}
// 전광판 배경으로 사용할 라운드, 그라디언트 박스 입니다.
private void drawRoundRect(Canvas canvas, Rect r){
Shader shader = new LinearGradient(r.left, r.top, 0, r.bottom, Color.argb(190, 220, 220, 220), Color.argb(255, 60, 60, 60), TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(shader);
//paint.setShadowLayer(10.0f, 0.0f, 5.0f, Color.BLUE);
canvas.drawRoundRect(new RectF(r), 10, 10, paint);
}
// 요런 드로인 메서드들은 스테틱으로 한곳에 모아두고
// 필요할때 가져 쓰도록 클레쓰화 해두면 좋을 듯요. 흠.
private void drawText(Canvas canvas, String text, int x, int y){
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.BLACK);
p.setTextSize(12.0f);
p.setTextScaleX(1.5f);
p.setStrokeWidth(4.0f);
p.setStyle(Style.FILL_AND_STROKE);
//p.setShadowLayer(1.0f, 1.0f, 1.0f, Color.argb(255, 0, 0, 0));
canvas.drawText(text, x, y, p);
p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.WHITE);
p.setTextSize(12.0f);
p.setTextScaleX(1.5f);
p.setStrokeWidth(1.0f);
p.setStyle(Style.FILL_AND_STROKE);
//p.setShadowLayer(1.0f, 1.0f, 1.0f, Color.argb(255, 0, 0, 0));
canvas.drawText(text, x, y, p);
}
}
이상 끝입니다.
OpenGL 처음 접하시는 분들에게 좋은 참조가 되였으면 합니다.
이게임 파일좀 받을수있을까요??
pdy7986@nate.com 으로 보내주시면 감사하겠습니다..