ソースとAPKはこちら
ボタンは見えませんが、画面の左半分を触るとキャラクターが左右に移動します。
画面右側を押すとジャンプします。
地面から落ちると、落ち続けます・・・・・
大雑把な雛形です。自分で設計したものなので効率的であるかはわかりません。
すべてJAVAで書かれています。
キャラクターや障害物を増やすにはデータ作成管理クラスが必要になります。
戻るボタンで終了します。
大まかな構造としては
タッチスレッドでパラメーターを変更。
・移動ならXをプラス
・ジャンプなら慣性のFをプラス
描画スレッドで位置や慣性を計算。
・障害物に触れていないなら空中
・空中なら落下
//ゲーム画面呼び出しクラス
public class MainActivity extends Activity {
private GameView gameView;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
gameView=new GameView(this);
setContentView(gameView);
}
}
//画面クラス
public class GameView extends SurfaceView{
private GameViewCallBack cb;
private long time;
public GameView(Context context) {
super(context);
SurfaceHolder holder = getHolder();
cb = new GameViewCallBack();
cb.setContext(context);
holder.addCallback(cb);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//連続タップ防止
if(time+100<System.currentTimeMillis()){
time=System.currentTimeMillis();
float x = event.getX(); // X座標を取得
float y = event.getY(); // Y座標を取得
cb.setTouchPoint( x , y );
}
return true;
}
// キーイベント発生時、呼び出されます
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) { // キーが離された時
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_HOME:
case KeyEvent.KEYCODE_BACK:
cb.teisi();
return false;
default:
}
}
return super.dispatchKeyEvent(event);
}
}
//描画スレッド
public class GameViewCallBack implements SurfaceHolder.Callback, Runnable{
private SurfaceHolder holder = null;
private Thread thread = null;
//スレッドの管理
private boolean isAttached = true;
//コントローラー
private Controler cl;
//プレイヤー情報
private PlayCharcter pc;
//障害物
private Syougai sg;
private float w, h;
//中心位置
private int cx, cy;
private Context context;
public void setContext(Context rr){
context=rr;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
this.w = width;
this.h = height;
this.cx=(int)(w*0.50);
this.cy=(int)(h*0.50);
cl=new Controler(width, height);
pc =new PlayCharcter(cx,cy,context);
//左、下、幅、高さ
sg = new Syougai(50,(int) (h-100),1000,100);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
this.holder = holder;
thread = new Thread(this);
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isAttached = false;
thread = null;
}
private long t1 = 0, t2 = 0;
@Override
public void run() {
while( isAttached ){
t1 = System.currentTimeMillis();
hyouji();
atari();
byouga();
// スリープ 60fpsの確保
t2 = System.currentTimeMillis();
if(t2 - t1 < 16){
try {
Thread.sleep(16 - (t2 - t1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void teisi(){
isAttached=false;
thread = null;
}
//コントロール
public void setTouchPoint(float x, float y) {
int tmp =cl.getTouthActionProt((int)x,(int)y);
if(tmp==100){
pc.btnAction(1);
}else{
pc.moveAction(tmp);
}
}
public void byouga(){
//描画処理を開始
Canvas canvas = holder.lockCanvas();
if(canvas==null){
return;
}
//背景
canvas.drawColor(0,PorterDuff.Mode.CLEAR );
Paint paint = new Paint();//かり
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
canvas.drawRect(new RectF(sg.l, sg.t, sg.r, sg.b), paint);
pc.byouga(canvas, cx, cy);
//描画処理を終了
holder.unlockCanvasAndPost(canvas);
}
//各データの計算 キャラの状態 あたり判定
private void atari(){
//慣性移動計算 障害物への移動適応
pc.kansei();
//キャラと足場が接触 pc.y仮
if(cx>=sg.l && cx<=sg.r && pc.y>=sg.t&&cy<=sg.b){
//if(pc.x>=sg.l && pc.x<=sg.r && pc.y>=sg.t&&pc.y<=sg.b){
pc.s=0;//立ち
pc.y=sg.t;//位置補正 めり込み防止
}else{//こちらへ来ないとジャンプできない
pc.s=-1;//浮び
}
sg.sukuro(pc.x,pc.y);
}
//表示領域に存在する? hFLをたてる
private void hyouji(){
sg.hFL=true;
}
}
//コントローラーくらす
public class Controler {
private int w,h,ox=0,oy=0;
private int hidari,migi,a,j,m;
public Controler(int ww,int hh){
w=ww;
h=hh;
j= (int) (w*0.75);
a= (int) (w*0.50);
migi= (int) (w*0.25);
//hidari= (int) (w*0.75);
}
public int getTouthActionProt(int xx,int yy){
int action=0;
if(xx>=j){
action=100;
}else if(xx>=a){
action =200;
}else if(xx>=migi){
action=20;
}else{
action=-20;
}
return action;
}
}
//キャラクタークラス
public class PlayCharcter {
private Paint paint;
//慣性 重力
private int kt=0,ky=0,kp=0,kf=0;
//座標を管理
public int x=0,y=0,w=0,h=0;//当たり判定計算用
public Bitmap gazo;
public int s=-1;//状態 0 地上 -1 空中
private Context context;
//コンストラクタ
public PlayCharcter(int xx,int yy,Context c){
paint = new Paint();
paint.setColor(Color.WHITE);
x=xx;//初期位置
y=yy;
context =c;
gazo = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
w=gazo.getWidth();
h=gazo.getHeight();
y-=h;
}
public void byouga(Canvas canvas,int xx,int yy){
canvas.drawBitmap(gazo, xx, yy-h, null);
}
//右手操作
public void btnAction(int aa){
if(s==0){
kf=7;//ジャンプの実験
y-=3;
}
}
//左手操作
public void moveAction(int aa){
x+=aa;
}
public void kansei(){
if(s==-1){
kt=ky;
ky+=(ky-kp)+kf;
kp=kt;
kf=-1;
//慣性を適応
y-=ky;
}else{
ky=0;
kp=0;
}
}
}
//障害物くらす
public class Syougai {
public int x,y,w,h,t,b,r,l,T,B,R,L;
//表示フラグ
public boolean hFL=false;
private Paint paint;
public Syougai(int xx,int yy,int ww,int hh){
x=xx;
y=yy;
w=ww;
h=hh;
//絶対座標
T=y;
L=x;
R=x+w;
B=y+h;
t=y;
l=x;
r=x+w;
b=y+h;
paint = new Paint();
paint.setColor(Color.GREEN);
}
//プレイヤーの移動情報を適応
public void sukuro(int xx,int yy){
t=T-yy;
l=L-xx;
r=R-xx;
b=B-yy;
}
//描画処理
public void byouga(Canvas canvas){
canvas.drawRect(new RectF(l, t, r, b), paint);
}
}
権限は必要ありません。APILEVELは9以上
アクションゲームさえ作れれば大抵のゲームは作れると思います。
設計書は再設計後に記事にします。
0 件のコメント:
コメントを投稿