記錄學(xué)習(xí)的第一天。
今天花了很多時間把android 最近上課的內(nèi)容補完了。
1)運用android 多線程編程開發(fā)一個運動小球的游戲。
? ? ? ? ? ? 游戲內(nèi)容如下:1.使用按鈕控制游戲開始和結(jié)束;
????????????????????????????????????2.用戶自己設(shè)定游戲總時長,單位:秒;
????????????????????????????????????3.啟動游戲后,有背景音樂;停止游戲后,關(guān)閉背景音樂;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 4游戲開始后,隨機從屏幕上方產(chǎn)生小球,位置、大小、顏色、透明度都隨機,下落到屏幕下方后,重新在屏幕上方出現(xiàn),Y坐標值不變;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 5.小球下落過程中,可以使用鼠標點擊,擊中后小球消失;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6.在線顯示剩余時長和擊落數(shù)字。
簡單樣式如圖:

? ? ? ? ? 做這個作業(yè)不能逃過對線程的認知,線程是進程的重要組成部分,進程不能沒有線程,而多線程處理能讓一個進程同時執(zhí)行多個任務(wù)。
? ? ? ? ? 在這里 ,我們需要執(zhí)行多個任務(wù),分別是背景音樂的播放,小球的隨機增加,小球位置的移動和倒計時共四個任務(wù)。那么理論上需要4個次線程和一個主線程。那么由于我上學(xué)期學(xué)了Service組件,因而在背景音樂這里我用了Service組件。那么也就是1個Service和4個Thread。
? ? ? ? ? ? 除此之外,我們也需要懂得簡單繪圖的基本步驟。話不多說,上代碼。
? ? ? ? ? ? ? ?BallView的構(gòu)建
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);//設(shè)置背景
? ? ? ? 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);
? ? ? ? }
}
}
為了優(yōu)化寫法,我把其中的數(shù)據(jù)類分離出來即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類(其中參考了不少http://www.itdecent.cn/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("擊落個數(shù):"+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);
}