以前 『背景が動く中で飛ぶ鳥』を作りました
everydayisagoodday.hatenadiary.com
これは横方向に背景が動いてそこに鳥のアニメーションを表示するものでした
今回はこれを応用して 縦方向に背景を動かしそこにタッチ入力によって動くUFOを表示したいと思います
1.res/drawableに背景とUFOの画像を準備
2.activity_main.xmlの編集
画面全体をSurfaceViewにします
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <SurfaceView android:id="@+id/surfaceview" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="1.0" /> </androidx.constraintlayout.widget.ConstraintLayout>
3.MainActivity.ktの編集
import android.content.Context import android.content.res.Resources import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas import android.os.Bundle import android.util.DisplayMetrics import android.view.MotionEvent import android.view.SurfaceHolder import android.view.SurfaceView import android.view.WindowManager import androidx.appcompat.app.AppCompatActivity import androidx.core.view.MotionEventCompat var SCREEN_WIDTH = 0 var SCREEN_HEIGHT = 0 var isRunning = false var flag_ufo = 0 //+:右 -:左 0:停止 class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val surfaceView: SurfaceView = findViewById(R.id.surfaceview) PlayView(this, surfaceView) //SurfaceViewのインスタンスを生成 GetScreenSize(this) //スクリーンサイズの取得 } override fun onTouchEvent(event: MotionEvent): Boolean { val action: Int = MotionEventCompat.getActionMasked(event) return when (action) { MotionEvent.ACTION_DOWN -> { if(event.x > SCREEN_WIDTH/2){ flag_ufo = 10 } else{ flag_ufo = -10 } true } MotionEvent.ACTION_UP -> { flag_ufo = 0 true } else -> super.onTouchEvent(event) } } //スクリーンサイズの取得 fun GetScreenSize(context: Context) { val vm: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager val display = vm.defaultDisplay val metric = DisplayMetrics() display.getMetrics(metric) SCREEN_WIDTH = metric.widthPixels SCREEN_HEIGHT = metric.heightPixels } } // SurfaceViewを継承したクラス class PlayView: SurfaceView, SurfaceHolder.Callback { private var surfaceHolder: SurfaceHolder? = null constructor(context: Context, surfaceView: SurfaceView) : super(context) { surfaceHolder = surfaceView.holder // コールバック surfaceHolder!!.addCallback(this) } override fun surfaceCreated(p0: SurfaceHolder) { val playgame = PlayGame(surfaceHolder!!, resources) //ゲームスタート isRunning = true playgame.start() } override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) { } override fun surfaceDestroyed(p0: SurfaceHolder) { } } //ゲームのThreadクラス class PlayGame:Thread{ private var holder : SurfaceHolder private var resources : Resources private var backBitmap : Bitmap //背景のビットマップ private var ufoBitmap : Bitmap //UFOのビットマップ private var ufoPosx = 0 //UFOのx座標 private var ufoPosy = 0 //UFOのy座標 constructor(holder: SurfaceHolder, resources: Resources) { this.holder = holder this.resources = resources backBitmap = BitmapFactory.decodeResource(resources, R.drawable.sky) ufoBitmap = BitmapFactory.decodeResource(resources, R.drawable.ufo) ufoPosx = SCREEN_WIDTH/2-ufoBitmap.width/2 ufoPosy = SCREEN_HEIGHT-ufoBitmap.height-100 } private var backPosx = 0 //背景のx座標 private var backPosy = 0 //背景のy座標 override fun run() { while(isRunning){ if(holder == null) return val canvas = holder.lockCanvas() if(canvas != null){ try { synchronized(holder){ BackGround(canvas) //背景を表示 UfoMove(canvas) //UFOを表示 } } finally { holder.unlockCanvasAndPost(canvas) } } } } //UFO描画 private fun UfoMove(canvas: Canvas) { val ufoVerocity = 20 //UFO移動速度 val ufoMargin = 50 //UFOビットマップの余白 if(flag_ufo > 0){ //右へ ufoPosx += ufoVerocity }else if(flag_ufo < 0){ //左へ ufoPosx -= ufoVerocity }else{ //停止 ufoPosx = ufoPosx } if(ufoPosx > SCREEN_WIDTH-ufoBitmap.width+ufoMargin){ ufoPosx = SCREEN_WIDTH-ufoBitmap.width+ufoMargin } if(ufoPosx < -ufoMargin){ ufoPosx = -ufoMargin } canvas.drawBitmap(ufoBitmap,ufoPosx.toFloat(),ufoPosy.toFloat(),null) } //背景描画 private fun BackGround(canvas: Canvas){ val backVelocity = 15 //背景の移動速度 backPosy = backPosy + backVelocity if(backPosy > backBitmap.height){ backPosy = 0 } canvas.drawBitmap(backBitmap,backPosx.toFloat(),backPosy.toFloat(),null) //背景をloop表示 if(backPosy > 0) { canvas.drawBitmap(backBitmap,backPosx.toFloat(), (backPosy - backBitmap.height).toFloat(),null) } } }
実行すると
画面右側をタッチするとUFOが右に 画面左側をタッチするとUFOが左に移動します
タッチをやめるとその場にとどまります
また新しいゲームができそうです