| 使用画像 |
![]() |
|
ファイル名「Robo1Activity.java」
package and.roid.robo1;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager;
public class Robo1Activity extends Activity {
public float disp_w,disp_h;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
Window window = getWindow();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
WindowManager manager = window.getWindowManager();
Display disp = manager.getDefaultDisplay();
disp_w = disp.getWidth();
disp_h = disp.getHeight();
setContentView(new MainLoop(this));
//setContentView(R.layout.main);
}
}
|
Activityファイルは、一番下の段のコードがたまに変わるだけでいつもこのまま使っています。 完全フルスクリーン仕様&画面の幅、高さを取得しています。 |
ファイル名「MainLoop.java」
package and.roid.robo1;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
public class MainLoop extends SurfaceView implements SurfaceHolder.Callback,Runnable{
public static final int GAME_START = 0;//ゲーム状態固定値
public static final int GAME_PLAY = 1;//ゲーム状態固定値
private int game_state;//ゲーム状態決定変数
private Thread thread;
private SurfaceHolder holder;
private float disp_w,disp_h;//画面の幅高さ
private Robo1Activity robo1;//Activityクラス登録
private int sleep;//遅延時間
//変数設定
private Drawable buckimg;
private Object buck;
private Drawable roboimg;
private Object robo;
private Object line;
private boolean robomovekeystate;//タップ長押し処理用
//変数設定ここまで
public MainLoop(Context context) {
super(context);
init(context);
}
public MainLoop(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public void init(Context context){
holder = getHolder();
holder.addCallback(this);
holder.setFixedSize(getWidth(), getHeight());
robo1 = (Robo1Activity)context;
disp_w = robo1.disp_w;//画面幅取得
disp_h = robo1.disp_h;//画面高さ取得
game_state = 1;//ゲーム状態
//ここから初期化
this.setSleep(50);//ループ中遅延時間
robomovekeystate = false;
Resources resources = context.getResources();//画像登録準備
buckimg = resources.getDrawable(R.drawable.buck);//背景画像取り込み
buck = new Object(disp_w,disp_h);//背景画像をオブジェクト登録
buck.Drawableinit(buckimg,disp_w/2,disp_h/2,854,480);//背景画像初期設定
roboimg = resources.getDrawable(R.drawable.robo);//ロボ画像取り込み
robo = new Object(disp_w,disp_h);//ロボ画像をオブジェクト登録
robo.Drawableinit(roboimg,425,350,85,100);//ロボを初期設定
float[] lxy = {100,400,754,400};//ライン座標
line = new Object(disp_w,disp_h);//ラインオブジェクト登録
line.Lineinit(lxy,Color.CYAN,2,Paint.Style.FILL);//ラインオブジェクト初期設定
//初期化ここまで
}
public void run() {
Canvas c;
Paint p = new Paint();
p.setAntiAlias(true);
while(thread != null){
c = holder.lockCanvas();
//ゲーム状態によってスイッチ処理
switch(game_state){
case GAME_START:
StartDraw(c);
break;
case GAME_PLAY:
PlayDraw(c,p);
break;
}
holder.unlockCanvasAndPost(c);
try {
Thread.sleep(sleep);
} catch (Exception e){}
}
}
//タッチ処理
public boolean onTouchEvent(MotionEvent event){
int action = event.getAction();
int x = (int)event.getX();
int y = (int)event.getY();
float time = event.getDownTime();
switch(action){
case MotionEvent.ACTION_DOWN:
switch(game_state){
case GAME_START:
break;
case GAME_PLAY:
if(robomovekeystate==false)robomovekeystate=true;
break;
}
break;
case MotionEvent.ACTION_UP:
switch(game_state){
case GAME_START:
break;
case GAME_PLAY:
if(robomovekeystate==true) robomovekeystate=false;
break;
}
break;
case MotionEvent.ACTION_MOVE:
switch(game_state){
case GAME_START:
break;
case GAME_PLAY:
if(robomovekeystate==true) robo.DrawableJump();
break;
}
break;
}
return true;
}
public boolean RectTap(int x,int y,Drawable[] gazou,int keystate){
return gazou[keystate].getBounds().left < x && gazou[keystate].getBounds().top < y &&
gazou[keystate].getBounds().right > x && gazou[keystate].getBounds().bottom > y;
}
public void StartDraw(Canvas c){
}
public void PlayDraw(Canvas c,Paint p){
//プレイ画面表示
buck.Drawabledraw(c, p);
robo.Drawabledraw(c, p);
if(robomovekeystate==true) robo.DrawableJump();
line.Linedraw(c, p);
drawString("kye:"+robomovekeystate,50,100,20,Color.WHITE,c,p);
}
public void drawString(String str,int x,int y,int size,int col,Canvas c,Paint p){
p.setColor(col);
p.setTextSize(size);
c.drawText(str, x, y, p);
}
public void setSleep(int s){sleep=s;}
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}
public void surfaceCreated(SurfaceHolder arg0) {thread = new Thread(this);thread.start();}
public void surfaceDestroyed(SurfaceHolder arg0) {thread = null;}
}
|
MainLoopクラスです。動きのあるゲームは、ほぼループ必須なのでSurfaceViewを使用しています。run() 内がループ処理です。 その中で、ゲーム状態(スタート画面、プレイ画面)をgamestateでswitch処理しています。タップのところもswitch処理です。 処理内容run()内に書いてもいいのですが、ごちゃごちゃするので別のメソッドに飛ぶようにしています。 drawString()メソッドは、開発中に表示したい変数などをどこからでも表示できるようにしたメソッドです。 setSleep()は、run()後にあるThread.sleep()のループ遅延の設定メソッドです。いつか使うときがくるかもなので一応。 最後の3つのメソッドは、SurfaceViewを使用すると自動的に生成されるメソッドで、わたしはこう書くものだと割り切っています・・・ |
ファイル名「Object.java」
package and.roid.robo1;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
public class Object {
private float px,py; //Rect,画像の中心座標
private int w,h; //Rect,画像の横幅縦幅
private float wh,hh; //Rect,画像の大きさ/2
private Rect rect; //Rect,画像ののRect
private float[] linexy; //Lineスタート座標エンド座標
private int lw; //Lineの太さ
private Style style; //Lineのスタイル
private int col; //オブジェクトカラー
private int alpha; //オブジェクト透過度
private Drawable obj; //Drawable型の画像
private float speedx,speedy;//オブジェクトスピード
private double disp_w,disp_h;
//コンストラクタ
public Object(double ww,double hh){
disp_w = ww;disp_h=hh;
}
//四角形を作成したいときの初期設定
public void Rectinit(float px,float py,int w, int h,int col,int alpha){
this.px = px;
this.py = py;
this.w = w;
this.h = h;
rect = setgetRectSize(new Rect((int)(px-w/2),(int)(py-h/2),(int)(px+w/2),(int)(py+h/2)));
this.px = rect.left;
this.py = rect.top;
this.w = rect.right;
this.h = rect.bottom;
this.col = col;
this.alpha = alpha;
}
//ラインを作成したいときの初期設定
public void Lineinit(float[] lxy,int col,int w,Style style){
linexy = new float[4];
linexy = setgetLineSize(lxy);
this.col = col;
this.lw = w;
this.style = style;
}
//Drawable型の画像を作成したいときの初期設定
public void Drawableinit(Drawable img,float px,float py,int w, int h){
this.obj = img;
this.px = px;
this.py = py;
this.w = w;
this.h = h;
setgetDrawableSize();
this.speedy = -50;
}
//四角形表示
public void Rectdraw(Canvas c,Paint p){
wh = w/2;hh=h/2;
rect = new Rect((int)(px-wh), (int)(py-hh), (int)(px+wh), (int)(py+hh));
p.setAlpha(alpha);
p.setColor(col);
c.drawRect(rect, p);
}
//ライン表示
public void Linedraw(Canvas c,Paint p){
p.setStrokeWidth(lw);
p.setStyle(style);
p.setColor(col);
c.drawLines(linexy, p);
}
//Drawable型の画像表示
public void Drawabledraw(Canvas c,Paint p){
wh = w/2;hh=h/2;
rect = new Rect((int)(px-wh), (int)(py-hh), (int)(px+wh), (int)(py+hh));
obj.setBounds(rect);
obj.draw(c);
}
//オブジェクトのジャンプ処理
public void DrawableJump(){
py += speedy;
}
//String型表示
public void Stringdraw(String str,int x,int y,int size,int col,Canvas c,Paint p){
p.setColor(col);
p.setTextSize(size);
c.drawText(str, x, y, p);
}
//このクラスのRect短形を取り出せるメソッド
public Rect getRect(){return rect;}
//このクラスのライン座標配列を取り出せるメソッド
public float[] getLinexy(){return linexy;}
//どのスマホの機種でもうまく表示出来るように、Rect短形座標変換
public Rect setgetRectSize(Rect rect){
this.rect = rect;
double dw = disp_w / 854f;
double dh = disp_h / 480f;
int w;int h;
w = this.rect.right;
h = this.rect.bottom;
this.rect.left *= dw;
this.rect.top *= dh;
w *= dw;
h *= dh;
this.rect.right = this.rect.left + w;
this.rect.bottom = this.rect.top + h;
return this.rect;
}
//どのスマホの機種でもうまく表示出来るように、ライン座標変換
public float[] setgetLineSize(float[] lxy){
linexy = new float[4];
linexy = lxy;
double dw = disp_w / 854f;
double dh = disp_h / 480f;
linexy[0] *= dw;
linexy[1] *= dh;
linexy[2] *= dw;
linexy[3] *= dh;
return linexy;
}
//どのスマホの機種でもうまく表示出来るように、座標変換
public void setgetDrawableSize(){
double dw = disp_w / 854f;
double dh = disp_h / 480f;
px *= dw;
py *= dh;
w *= dw;
h *= dh;
}
}
|
Objectクラスです。 今回決めゴトとして、画面に表示させるオブジェクトはすべてクラスのインスタンスで生成すると決めました。なので背景、ロボ、ラインもすべてこのクラスで作成されています。 内容としては、コンストラクタ(一番最初に呼び出されるもの)で画面の大きさを取得しています。 本当は、作成するオブジェクト別にinit()ではなくコンストラクタで初期設定する予定でしたが、画面大きさ取得を先にしたい、というのと、画面取得までコンストラクタでやると、なんか長くなってカッコ悪くなってしまうので、オブジェクトの初期設定はinit()に分けました。 実はこんなやり方では、間違ったメソッドを呼び出される可能性があるわけですし、ダメなのはわかっているのです。もっとインターフェースやオーバーライドとかそんなヤツを使用したいのはやまやまなのですが、残念ながらまだキッチリ理解していないので楽な方法に走ってしいました。 それはそれとして、これに円や点なども付け加えれば、なんでもオブジェクトを表示できるので当分これでいきます。 最後のメソッド3つは、書いてある通りで、わたしは使用しているスマホのXperiaでの画像の大きさなどを決定しているので、それを使用スマホの画面の大きさとxperiaの画面との比率をうまい具合に調整して表示させるようにしています。 |
| 実行結果 |
![]() |
ただ単にタップ押しっぱなしでどんどん上に行くだけのプログラムです。 タップ長押し専用コードなども本当はあるのですが、使用しなくてもできたのでOKとしました。 これをどんどん発展させて行く予定です。しかし発展といってもゴールなどはまだ決めていません。 これを骨組みとして次はジャンプしたら降りてくる、線との当たり判定、線がなかったら落ちる、とかこまごまとしたアルゴリズム的な基礎を勉強していこうと思います。
|
骨組み作成、簡単な画像表示、タップ処理 |
|
その1をちょっとした変更で劇的に変化 |
|
アニメーション |
|
タップ方向に動かし、画像も回転 |
|
Androidプログラミング日記 (仮)

