10-3 イメージを画面上で移動する
一定時間ごとの処理の具体例として、イメージを画面上で移動します。
private int x=60,dx=10,w;
private Handler hd=new Handler();
private GView gv;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
gv=new GView(this);
setContentView(gv);
hd.post(this);
}
public void run() { x+=dx;
if (x<=0 || w-10<=x) dx=-dx;
gv.invalidate();
hd.postDelayed(this,100);
}
class GView extends View { private Bitmap ball;
public GView(Context context) { super(context);
ball=BitmapFactory.decodeResource(getResources(),R.drawable.ball);
}
public void onDraw(Canvas canvas){
w=getWidth();
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(ball,x,60,null);
} } }
「練習問題10-3」ボールを100ミリ秒単位で斜めに移動し、上下壁、左右壁でボールを跳 ね返しなさい。
・MainActivity.java
package com.example.handler6;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.view.*;
import android.graphics.*;
public class MainActivity extends Activity implements Runnable{
private int x=60,y=60,dx=10,dy=10,w,h;
private Handler hd=new Handler();
private GView gv;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
gv=new GView(this);
setContentView(gv);
hd.post(this);
}
public void run() { x+=dx;y+=dy;
if (x<=0 || w-10<=x)
dx=-dx;
if ( ① ) dy=-dy;
gv.invalidate();
hd.postDelayed(this,100);
}
class GView extends View { private Bitmap ball;
public GView(Context context) { super(context);
ball=BitmapFactory.decodeResource(getResources(),R.drawable.ball);
}
public void onDraw(Canvas canvas){
w=getWidth();
h= ②
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(ball,x,y,null);
} } }
☆応用サンプル ラケットゲーム 1
タッチムーブイベントでラケットを移動し、ボールを跳ね返します。「練習問題10-3」
を元にラケットの移動処理とボールをラケットで跳ね返す処理を追加します。ボールがラ ケットに当たったを判定するのにy座標に関する等価比較を行うため、ラケットのy座標 はボールの移動量の10の倍数とします。画面の高さを元に以下で計算します。
ry=(getHeight()/10)*10-100;
ボールとラケットのイメージのサイズは以下で計算します。ボールの高さと幅は同じと仮 定しています。
ballW=ball.getWidth();
barW=bar.getWidth();
・MainActivity.java
package com.example.racket1;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.view.*;
import android.graphics.*;
public class MainActivity extends Activity implements Runnable{
private int x=100,y=100,dx=10,dy=10,rx=100,ry,w,ballW,barW;
private GView gv;
private Handler hd=new Handler();
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
gv=new GView(this);
setContentView(gv);
hd.post(this);
}
public void run() { x+=dx;y+=dy;
if (x<=0 || w-ballW<=x) dx=-dx;
if (y<=0) dy=-dy;
if (rx-ballW<=x && x<=rx+barW && y+ballW==ry) // ラケットで跳ね返す dy=-dy;
gv.invalidate();
hd.postDelayed(this,100);
}
class GView extends View { private Bitmap ball,bar;
public GView(Context context) { super(context);
ball=BitmapFactory.decodeResource(getResources(),R.drawable.ball);
bar=BitmapFactory.decodeResource(getResources(),R.drawable.bar);
ballW=ball.getWidth();
barW=bar.getWidth();
}
public void onDraw(Canvas canvas){
w=getWidth();
ry=(getHeight()/10)*10-100;
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(ball,x,y,null);
canvas.drawBitmap(bar,rx,ry,null);
} }
public boolean onTouchEvent(MotionEvent event) { // ラケットの移動 if (event.getAction()==MotionEvent.ACTION_MOVE){
rx=(int)event.getX()-barW/2;
if (rx<barW/2) rx=0;
if (rx>w-barW) rx=w-barW;
gv.invalidate();
}
return super.onTouchEvent(event);
} }
17-2 複数のテキストを読み上げる
txt[ ]配列の読み上げテキストが行単位で格納されているとき、行間に1秒のサイレント
を入れるには以下のようにします。なお、複数のテキストを連続して読み上げる場合は
「QUEUE_ADD」モードにします。「QUEUE_FLUSH」モードだと最後のテキストしか 読み上げられません。
for (int i=0;i<n;i++){
ts.speak(txt[i],TextToSpeech.QUEUE_ADD,null);
ts.playSilence(1000,TextToSpeech.QUEUE_ADD,null);
}
「例題17-2」複数のテキストを、行間に1秒のサイレントを入れて読み上げます。
・MainActivity.java
package com.example.speech2;
import java.util.Locale;
import android.app.Activity;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.view.MotionEvent;
import android.widget.*;
public class MainActivity extends Activity implements OnInitListener{
private TextToSpeech ts;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ts=new TextToSpeech(this,this);
}
public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_DOWN){
String txt[]={"Good morning","Hello","Good night"};
if (ts.isSpeaking()) ts.stop();
ts.setSpeechRate(1.0f);
for (int i=0;i<txt.length;i++){
ts.speak(txt[i],TextToSpeech.QUEUE_ADD,null);
ts.playSilence(1000,TextToSpeech.QUEUE_ADD,null);
} }
return super.onTouchEvent(event);
}
public void onInit(int status) { if (status==TextToSpeech.SUCCESS){
Locale locale=Locale.ENGLISH;
if (ts.isLanguageAvailable(locale)>=TextToSpeech.LANG_AVAILABLE) ts.setLanguage(locale);
else
Toast.makeText(this,"この言語は未サポートです
",Toast.LENGTH_LONG).show();
} else
Toast.makeText(this,"音声合成できません",Toast.LENGTH_LONG).show();
}
protected void onDestroy(){
super.onDestroy();
if (ts!=null) ts.shutdown();
} }
17-3 通訳アプリ
音声合成機能を使って簡単な通訳アプリを作ることができます。
「例題17-3」ListViewに登録した日本語に対応する英語を読み上げます。
・activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
・MainActivity.java
package com.example.speech3;
import java.util.Locale;
import android.app.Activity;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.view.*;
import android.widget.*;
public class MainActivity extends Activity implements OnInitListener{
private TextToSpeech ts;
private String[] Japanese={
"おはよう","こんにちは","おやすみ","ありがとう", "お名前は","お値段は","すみません","美味しいです", "何時ですか","友達になってください","何をお求めですか",
"病院はどこですか","お茶を飲みましょう","もう一度言って下さい"};
private String[] English={
"Good morning","Hello","Good night","Thank you",
"What is the name?","How much is a price?","I'm sorry","I am delicious", "What time is it?","Please make friends","What is it a request in?", "Where is the hospital?","Let's drink tea","Please say once again"};
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
for (int i=0;i<Japanese.length;i++) adapter.add(Japanese[i]);
ListView lv=(ListView)findViewById(R.id.listview);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
if (ts.isSpeaking()) ts.stop();
ts.setSpeechRate(1.0f);
ts.speak(English[position],TextToSpeech.QUEUE_FLUSH,null);
} });
ts=new TextToSpeech(this,this);
}
public void onInit(int status) { if (status==TextToSpeech.SUCCESS){
Locale locale=Locale.ENGLISH;
if (ts.isLanguageAvailable(locale)>=TextToSpeech.LANG_AVAILABLE) ts.setLanguage(locale);
else
Toast.makeText(this,"この言語は未サポートです", Toast.LENGTH_LONG).show();
}
else
Toast.makeText(this,"音声合成できません", Toast.LENGTH_LONG).show();
}
protected void onDestroy(){
super.onDestroy();
if (ts!=null) ts.shutdown();
} }