记录学习的第一天。
今天花了很多时间把android 最近上课的内容补完了。
1)运用android 多线程编程开发一个运动小球的游戏。
游戏内容如下:1.使用按钮控制游戏开始和结束;
2.用户自己设定游戏总时长,单位:秒;
3.启动游戏后,有背景音乐;停止游戏后,关闭背景音乐;
4游戏开始后,随机从屏幕上方产生小球,位置、大小、颜色、透明度都随机,下落到屏幕下方后,重新在屏幕上方出现,Y坐标值不变;
5.小球下落过程中,可以使用鼠标点击,击中后小球消失;
6.在线显示剩余时长和击落数字。
简单样式如图:
运动小球界面
做这个作业不能逃过对线程的认知,线程是进程的重要组成部分,进程不能没有线程,而多线程处理能让一个进程同时执行多个任务。
在这里 ,我们需要执行多个任务,分别是背景音乐的播放,小球的随机增加,小球位置的移动和倒计时共四个任务。那么理论上需要4个次线程和一个主线程。那么由于我上学期学了Service组件,因而在背景音乐这里我用了Service组件。那么也就是1个Service和4个Thread。
除此之外,我们也需要懂得简单绘图的基本步骤。话不多说,上代码。
BallView的构建
public class BallViewextends View {
private Listbb=new ArrayList();
private int ballCount=0;
public BallView(Context context, AttributeSet attrs)
{
super(context,attrs);
bb.add(new Ball());
}
public void deleteBall(int bx,int by)//删除小球,用点击的坐标和圆心的距离来判断
{
for(int i=0;i
{
int x=bb.get(i).x;
int y=bb.get(i).y;
int r=bb.get(i).r;
int dd=(int )Math.sqrt((bx-x)*(bx-x)+(by-y)*(by-y));
if(dd
{
bb.remove(i);
ballCount++;
}
}
}
public int getBallCount()
{
return ballCount;
}
public void initBallCount()
{
ballCount=0;
}
public void moveXY(){
for(int i=0;i
{
bb.get(i).change();
}
invalidate();
}
public void addBall(Ball aa)
{
bb.add(aa);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);//设置背景
Paint paint=new Paint();//定义画笔
paint.setAntiAlias(true);//去锯齿
for(int i=0;i
{
paint.setColor(bb.get(i).GetColor());
paint.setAlpha(bb.get(i).alpha);
canvas.drawCircle(bb.get(i).x,bb.get(i).y,bb.get(i).r,paint);
}
}
}
为了优化写法,我把其中的数据类分离出来即Ball类
public class Ball {
public int x=0,y=0,r=0,alpha=0;
public int []colors={Color.RED,Color.YELLOW,Color.BLACK,Color.GREEN,Color.GRAY,Color.BLUE};
public int Index=0;
public Ball ()
{
int max=1500,min=100;
long ran=System.currentTimeMillis();
x=(int) (ran%(max-min)+min);
max=600;min=200;
y=(int) (ran%(max-min)+min);
max=60;min=30;
r=(int)(ran%(max-min)+min);
max=6;min=0;
Index=(int)(ran%(max-min)+min);
max=255;min=20;
alpha=(int)(ran%(max-min)+min);
}
public int GetColor()
{
return colors[Index];
}
public void change()
{
y+=50;
if(y>900)y=0;
}
}
之后是背景音乐Myservice类(其中参考了不少https://www.jianshu.com/p/877e921005ee该作者的写法)
public class MySrviceextends Service {
private MediaPlayermediaPlayer;
private boolean isStop =true;
@Nullable
@Override
public IBinderonBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
if (mediaPlayer ==null) {
mediaPlayer =new MediaPlayer();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Intent intent =new Intent();
intent.setAction("com.complete");
sendBroadcast(intent);
}
});
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
switch (intent.getIntExtra("type",-1)){
case 1:
if (isStop){
mediaPlayer.reset();
// mediaPlayer=MediaPlayer.create(this,);
// mediaPlayer=MediaPlayer.create();
mediaPlayer=MediaPlayer.create(this,R.raw.music);
mediaPlayer.start();
mediaPlayer.setLooping(false);
isStop=false;
}else if (!isStop&&mediaPlayer.isPlaying()&&mediaPlayer!=null){
mediaPlayer.start();
}
break;
case 2:
if (mediaPlayer!=null){
mediaPlayer.stop();
isStop=true;
}
break;
}
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
小球运动的线程
public class Workextends Thread
{
@Override
public void run() {
while(!stop)
{
try{
Thread.sleep(100);
Message msg=new Message();
msg.what=1;
handler.sendMessage(msg);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
增加小球的线程
public class CreateBallextends Thread
{
@Override
public void run() {
while(!stop)
{
try{
int max=1500,min=100;
long ran=System.currentTimeMillis();
int kk=(int) (ran%(max-min)+min);
Thread.sleep(kk);
mvb.addBall(new Ball());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
倒计时线程
public class Timeextends Thread
{
@Override
public void run() {
while(Second>0)
{
try{
Thread.sleep(1000);
Message msg=new Message();
msg.what=2;
handler.sendMessage(msg);
Second--;
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
处理线程的Handler
private Handlerhandler=new Handler()
{
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what)
{
case 1:
mvb.moveXY();
tv2.setText("击落个数:"+mvb.getBallCount());
break;
case 2:
btn4.setText("退出("+Second+")");
tv1.setText("剩余时间:"+Second+"秒");
if(Second==0) {
stop=true;
playingmusic(2);
btn1.setEnabled(true);
}
break;
}
}
};
点击小球要用到的View.OnTouchListener和重写
@Override
public boolean onTouch(View v, MotionEvent event) {
int bx=(int)event.getX();
int by=(int)event.getY();
mvb.deleteBall(bx,by);
return super.onTouchEvent(event);
}