手游app开发入门教程之飞机小游戏

小编最近想玩一下射击类的空战飞机游戏,看到新手游里有几款,索性下载玩了玩,真是感觉垃圾啊,满屏的首充啊、礼包啊在晃荡,如下图:

手游app开发入门教程之飞机小游戏插图1左、右两款类似的空战类手游

这样的游戏品质和幕后公司啊,越操心玩家的钱包越赚不到钱,可能也就骗骗无知的小朋友充值吧。

以后没有好网游攻略的时候,超仔给大家陆续提供一些简单的安卓手游app开发入门教程,咱们今天就来个飞机小游戏的制作吧。

工具还是AndroidStudio(超仔用的版本3.6.2),首先我们新建一个项目(Create Android Project或者Start a new Android Studio Project):

手游app开发入门教程之飞机小游戏插图3

新建java类guanqia1,采用默认设置即可:

手游app开发入门教程之飞机小游戏插图5

guanqia1.java代码如下,大家复制就行:

package com.example.myplane;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.RectF;

import android.view.MotionEvent;

import android.view.View;

import java.util.Vector;

/**

* Created by chaozai on 2020/4/25.

*/

class my{//新建一个类 里面的东西都是静态的 当全局变量用

public static int js=0;//击杀数

public static int w,h;//屏幕的宽高

public static float bili;//比例,用于适应不同屏幕

public static Vector

public static Vector

public static Bitmap myhj,drhj,bj,myzd;//图片:我的飞机、敌人、背景、我的子弹

public static myhj my;//我的飞机

public static bj b;//背景

}

public class guanqia1 extends View{//画

private Paint p=new Paint();//画笔

private float x,y;//按下屏幕时的坐标

private float myx,myy;//按下屏幕时玩家飞机的坐标

public guanqia1(Context context) {

super(context);

//添加事件控制玩家飞机

setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View view, MotionEvent e) {

if(e.getAction()==MotionEvent.ACTION_DOWN){

x=e.getX();

y=e.getY();

myx=my.my.r.left;

myy=my.my.r.top;

}

float xx=myx+e.getX()-x;

float yy=myy+e.getY()-y;

//我的飞机不能飞出屏幕

xx=xx

xx=xx>-my.my.w/2?xx:-my.my.w/2;

yy=yy

yy=yy>-my.my.h/2?yy:-my.my.h/2;

my.my.setX(xx);

my.my.setY(yy);

return true;

}

});

setBackgroundColor(Color.BLACK);//设背景颜色为黑色

my.myhj= BitmapFactory.decodeResource(getResources(),R.mipmap.biyao1);//加载图片

my.drhj=BitmapFactory.decodeResource(getResources(),R.mipmap.xueqi1);

my.myzd=BitmapFactory.decodeResource(getResources(),R.mipmap.shixuezhu1);

my.bj=BitmapFactory.decodeResource(getResources(), R.mipmap.backgroundp1);

new Thread(new re()).start();//新建一个线程 让画布自动重绘

new Thread(new loaddr()).start();//新建一个 加载敌人的线程

}

@Override

protected void onDraw(Canvas g) {//这个相当于swing的paint方法吧 用于绘制屏幕上的所有物体

super.onDraw(g);

g.drawBitmap(my.b.img,null,my.b.r,p);//画背景 我没有把背景添加到list里

for(int i=0;i

hj h=my.list.get(i); //然后在这里用一个for循环画出来

g.drawBitmap(h.img,null,h.r,p);

}

g.drawText(“已击杀:”+my.js,0,my.h-50,p);

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {//这个方法用来获取屏幕宽高的

super.onSizeChanged(w, h, oldw, oldh);

my.w=w;//获取宽

my.h=h;//高

//获取分辨率和1920*1080的比例

my.bili= (float) (Math.sqrt(my.w * my.h)/ Math.sqrt(1920 * 1080));

p.setTextSize(50*my.bili);//设置字体大小,击杀的大小

p.setColor(Color.WHITE);//设为白色

//好了 到这里游戏开始了

my.b=new bj();//初始化背景

my.my=new myhj();//初始化 我的飞机

}

private class re implements Runnable {

@Override

public void run() {

//每10ms刷新一次界面

while(true){

try { Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}

postInvalidate();//刷新画布

}

}

}

private class loaddr implements Runnable{

@Override

public void run() {

while(true){

//每300ms刷一个敌人

try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}

try {

new drhj();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

}

class hj{//游戏内所有物体的父类

public RectF r=new RectF();//这个是用来确定位置的

public int hp;//生命

public float w,h;//宽高

public Bitmap img;//图片

//这里的画图方法和swing的不太一样

//设两个方法来设置x,y的坐标

public void setX(float x){

r.left=x;

r.right=x+w;

}

public void setY(float y){

r.top=y;

r.bottom=y+h;

}

public boolean pengzhuang(hj obj,float px) {//判断碰撞 判断时忽略px个像素

px*=my.bili;//凡是涉及到像素的 都乘一下分辨率比例my.bili

if (r.left+px – obj.r.left <= obj.w && obj.r.left – this.r.left+px <= this.w-px-px)

if (r.top+px – obj.r.top <= obj.h && obj.r.top – r.top+px <= h-px-px) {

return true;

}

return false;

}

}

class bj extends hj implements Runnable{//背景

public bj(){

w=my.w;

h=my.h*2;//背景的高是 屏幕高的两倍

img=my.bj;

setX(0);

setY(-my.h);

new Thread(this).start();

}

@Override

public void run() {

//这里控制背景一直向下移

while(true){

try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}

if(r.top+2<=0){

setY(r.top+2);

}else{

setY(-my.h);

}

}

}

}

class drhj extends hj implements Runnable{//敌人灰机

private long sd0=(long) (Math.random()*10)+10;//生成一个[10,20)的随机数 用来控制敌人速度 敌人速度是不一样的

public drhj(){

// w=my.w/5.4f;

// h=my.h/9.6f;

w=h=200*my.bili;

//敌人刷出来的位置

setX((float)( Math.random()*(my.w-w)));//x是随机的

setY(-h);//在屏幕外 刚好看不到的位置

img=my.drhj;

hp=12;//生命=12

my.list.add(this);//添加到集合里 这样才能被画出来

my.drlist.add(this);//添加到敌人的集合 添加进这个集合子弹才打得到

new Thread(this).start();

}

@Override

public void run() {

while(hp>0){//如果生命>0就继续向前飞

try {Thread.sleep(sd0);} catch (InterruptedException e) {e.printStackTrace();}

setY(r.top+2*my.bili);

if(r.top>=my.h)break;//敌人飞出屏幕 跳出循环

}

//从集合删除

my.list.remove(this);

my.drlist.remove(this);

}

}

class myhj extends hj implements Runnable{//我的灰机

public myhj(){

w=h=200*my.bili;//凡是涉及到像素的 都乘一下分辨率比例my.bili

//设置初始位置

setX(my.w/2-w/2);

setY(my.h*0.7f-h/2);

img=my.myhj;//初始化图片

my.list.add(this);//添加到集合里 这样才能被画出来

new Thread(this).start();//发射子弹的线程

}

@Override

public void run() {

while(true){

//90毫秒发射一发子弹

try {Thread.sleep(90);} catch (InterruptedException e) {e.printStackTrace();}

new myzd(this);

}

}

}

class myzd extends hj implements Runnable{//我的子弹

private int dps;

private float sd0;

public myzd(hj hj){

w=h=90*my.bili;//凡是涉及到像素的 都乘一下分辨率比例my.bili

img=my.myzd;//图片

sd0=6*my.bili;//速度=6

dps=6;//伤害=6

//设在玩家中心的偏上一点

setX(hj.r.left+hj.w/2-w/2);

setY(hj.r.top-h/2);

my.list.add(this);//添加到集合里 这样才能被画出来

new Thread(this).start();//新建一个子弹向上移动的线程

}

@Override

public void run() {

boolean flag=false;//一个标记 用来跳出嵌套循环

while(true){

try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}

setY(r.top-sd0);//向上移sd0个像素,sd0=6

try {//try一下 怕出错

//这里判断有没有和集合里的敌人发生碰撞

for(int i=0;i

hj h=my.drlist.get(i);

if(pengzhuang(h,30)){//判断碰撞

h.hp-=dps;//敌人生命-子弹伤害

flag=true;//一个标记 用来跳出嵌套循环

my.js++;//击杀+1

break;

}

}

} catch (Exception e) {

e.printStackTrace();

break;

}

if(flag || r.top+h<=0)break;//如果子弹击中过敌人 或者超出屏幕范围 跳出循环

}

my.list.remove(this);//从集合删除

}

}

上边这就完了。

返回修改一下MainActivity.java,第二个也是最后一个,程序如下:

手游app开发入门教程之飞机小游戏插图7

package com.example.myplane;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import android.view.KeyEvent;

import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

private long time;//用于检测按两次 “再按一次可退出游戏”

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

getSupportActionBar().hide();//隐藏标题栏

setContentView(new guanqia1(this));

//setContentView()跟swing的add()差不多吧,不过这里只能添加一个控件,默认铺满屏幕

}

public boolean onKeyDown(int keyCode,KeyEvent event) { //返回键

if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0){

long t=System.currentTimeMillis();//获取系统时间

if(t-time<=500){

exit(); //如果500毫秒内按下两次返回键则退出游戏

}else{

time=t;

Toast.makeText(getApplicationContext(),”再按一次可退出游戏”,Toast.LENGTH_SHORT).show();

}

return true;

}

return false;

}

public void exit(){

MainActivity.this.finish();

new Thread(new Runnable(){

@Override

public void run() {

try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}

System.exit(0);

}

}).start();

}

}

手游app开发入门教程之飞机小游戏插图9

把用到的biyao1、xueqi1、shixuezhu1、backgroundp1等png图片放入res下mipmap文件夹。

大功告成,build生成apk安卓安装文件,用qq等传至手机安装就可以玩了。因为手边正好有几个游戏图片,就随便选了几个,app简单就叫《碧瑶大战陆雪琪》吧,主要就是我方飞机碧瑶发出嗜血珠打敌人陆雪琪,大家领会精神即可:

手游app开发入门教程之飞机小游戏插图11

我们今天做的小游戏一共涉及俩程序和几个图片,非常简单也比较简陋。以后感兴趣的朋友可以加上技能、boss、关卡和动画剧情等功能。

推荐大家以后可以采用SurfaceView(属于View的子类),它是专门为制作游戏而产生的,它的功能非常强大,最重要的是它支持OpenGL ES库,2D和3D的效果都可以较好的实现。

<完>

举报/反馈

原创文章 手游app开发入门教程之飞机小游戏,版权所有
如若转载,请注明出处:https://www.itxiaozhan.cn/20229220.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注