今回の質問は少し前の質問に機能を追加したくて、というものです。
前の質問
そこでは、画像を表示するところまで要ったのですが、その次に私はこの画像(障害物)を移動させてみようと考えました。
そこで、どうやればいいか考えていると、回転のクラスを参考にして作ればいいのではないかと思いました。
(ここでの質問は上記「前の質問」の追加として書きますのでそちらを見なければ意味不明だと思います。手間をかけさせるやり方で申し訳ありません。)
とりあえず、前回の質問同様、やりたいことを書きます。
1、まず移動パターンを何個か作りそれぞれにIDでもつける
(例)まっすぐ下に降りてくるだけ→TypeA
2、最後の「_barrList.add(new BarricadeSquare( xx , yy,100, 100, null , bits));// 画面4隅に四角形を配置」の最後にBConfと同じ形(null or new ・・・)で追加したらその障害物がその動きをする。
参考にしたBConf.java
package net.dixq.irairabar;
public class BConf {
public float speed = 0;//回転のスピード
public Barricade.eType type = Barricade.eType.OUT;
public BConf(Barricade.eType atype){
type = atype;
}
public BConf(float aspeed){
speed = aspeed;
}
}
package net.dixq.irairabar;
public class BMove
{
public int MoveType = 0;//移動パターン
public Barricade.eType type = Barricade.eType.OUT;//タイプ(当たってはいけない)
public BMove(Barricade.eType atype)
{
type = atype;
}
public BMove(int mType)
{
MoveType = mType;
}
}
package net.dixq.irairabar;
import android.graphics.PointF;
public class DiagramCalcr {
// centerを中心に角度ang、頂点群ptを回転する
public static void RotateDiagram(PointF pt[], final PointF center, final float ang) {
for (int i = 0; i < pt.length; i++) {
RotatePt(pt[i], center, ang);
}
}
// rotaPtを中心に角度ang、origPtを回転する
public static void RotatePt(PointF rotaPt, final PointF origPt, final float ang) {
float cx = origPt.x;
float cy = origPt.y;
float x = rotaPt.x;
float y = rotaPt.y;
rotaPt.x = (float) (cx + Math.cos(ang) * (x - cx) - Math.sin(ang) * (y - cy));
rotaPt.y = (float) (cy + Math.sin(ang) * (x - cx) + Math.cos(ang) * (y - cy));
}
// 頂点群ptの線分とcirが接触していたらその接触しているベクトルをverに格納してtrueを返す
public static boolean isHit(PointF pt[], final Circle cir, Vec vec) {
if (pt.length < 2) { // 線でなければ
return false;
}
int len = pt.length;
for (int i = 1; i <= len; i++) {//例えば線分0-1,1-2,2-3,3-0とループさせてつなげる為%を使用してループ
Line line = new Line(pt[i - 1].x, pt[i - 1].y, pt[i % len].x, pt[i % len].y);
if (isHitLC(line, cir) == true) {//接触していれば
vec._x= pt[i % len].x - pt[i - 1].x;//その線分のベクトルを格納する
vec._y= pt[i % len].y - pt[i - 1].y;
return true;
}
}
return false;
}
//線分lineと円cirが当たっていればtrueを返す
public static boolean isHitLC(Line L,Circle C){
// 円と線分の当たり判定関数
if((L._sx*(C._x-L._x) + L._sy*(C._y-L._y)) <= 0){
// 始点を通る、線分に垂直な線を置いたとき、円の中心が線分の範囲外にあったとき
// 「線分の始点から円の中心までの距離の2乗」と「円の半径の2乗」との比較
return (C._r*C._r >= (C._x-L._x)*(C._x-L._x)+(C._y-L._y)*(C._y-L._y));
} else if(((-L._sx)*(C._x-(L._x+L._sx)) + (-L._sy)*(C._y-(L._y+L._sy))) <= 0){
// 終点を通る、線分に垂直な線を置いたとき、円の中心が線分の範囲外にあったとき
// 「線分の終点から円の中心までの距離の2乗」と「円の半径の2乗」との比較
return (C._r*C._r >= (C._x-(L._x+L._sx))*(C._x-(L._x+L._sx))+(C._y-(L._y+L._sy))*(C._y-(L._y+L._sy)));
} else {
// 線分の始点終点に垂線を引っ張ったとき、円の中心がその範囲内にあったとき
float e = (float) Math.sqrt(L._sx*L._sx + L._sy*L._sy); // これでx,y成分を割れば単ベクトルになる
float c2 = (C._x-L._x)*(C._x-L._x)+(C._y-L._y)*(C._y-L._y);
float b = (C._x-L._x)*(L._sx/e)+(C._y-L._y)*(L._sy/e); // 内積で算出した、隣辺の長さ
return (C._r*C._r >= c2 - b*b);
}
}
}
(ここがわかりません・・・)
package net.dixq.irairabar;
import android.graphics.PointF;
public class MoveStyle
{
private int process = 0;//竜神録のようにcase文を使いたいため
//「Aスタイル」centerを中心に「下に降りてきて一定位置までいくと右に移動」
public static void MoveAType(PointF pt[] , final PointF center)
{
}
}
前の質問からそのまま、
Barricade.java
(28行目のコンストラクタに「BMove move」とでも付け足します。)
package net.dixq.irairabar;
import android.graphics.Bitmap;//追加
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;//追加
import android.graphics.PointF;
import android.graphics.RectF;//追加
public class Barricade extends Task {
public enum eType{
OUT,
GOAL
}
protected PointF _center = new PointF(0,0); //図形の中心点
protected PointF _pt[]; //図形の頂点
protected Paint _paint = new Paint(); //ペイント
protected eType _type = eType.OUT; //タイプ(当たるとアウトな壁、ゴールの壁、等)
protected float _rotaSpeed = 0; //回転スピード
protected Bitmap bit;
//protected int images;//参照を保持するインスタンス変数(何型の変数?)
//コンストラクタ。 type=タイプ、 n=頂点の数、 conf=設定情報
public Barricade(int n, BConf conf,Bitmap img)
{
bit = img;//格納(記録);
if( conf != null ){
_rotaSpeed = conf.speed; //回転スピード
_type = conf.type; //物体のタイプ
}
switch(_type){
case OUT: //接触してアウトな物
_paint.setColor(Color.RED);
break;
case GOAL: //接触してゴールな物
_paint.setColor(Color.GREEN);
break;
}
_pt = new PointF[n]; //頂点配列を作る
for( int i=0; i<n; i++ ){
_pt[i] = new PointF(); //頂点を作る
}
_paint.setAntiAlias(true);
}
public Barricade(int n , BConf conf)
{
this(n , conf , null);
}
//更新する
public boolean onUpdate(){
if( _rotaSpeed != 0 ){ //回転するなら
DiagramCalcr.RotateDiagram( _pt, _center, _rotaSpeed ); //頂点リスト(_pt)を_centerを中心に回転する
}
return true;
}
//接触しているかを問う。円cirが線分vecと接触していれば接触した物体のタイプを返す。接触していなければNOを返す
public Def.eHitCode isHit( final Circle cir, Vec vec ){
if( DiagramCalcr.isHit( _pt, cir, vec ) == true ){
switch(_type){
case OUT:
return Def.eHitCode.OUT;
case GOAL:
return Def.eHitCode.GOAL;
}
}
return Def.eHitCode.NO;
}
//描画する
public void onDraw(Canvas c)
{
//頂点が1未満の図形なんてないので
if( _pt.length < 1 )
{
return;//返す
}
if( bit == null )
{
Path path = new Path();//パス
path.moveTo(_pt[0].x, _pt[0].y); //パスの初期位置をセット
for( int i=0; i<_pt.length; i++ )
{
path.lineTo(_pt[i].x, _pt[i].y); //頂点の位置へラインを引いていく(軌跡を描いていく)
}
c.drawPath(path, _paint); //引いたラインを描画する
}
else
{
//画像は全体を使うと仮定
c.drawBitmap(bit, null, new RectF(_pt[0].x-10 , _pt[0].y-10 , _pt[2].x+10 , _pt[2].y+10 ), null);
}
}
最後にGameMgr.java
package net.dixq.irairabar;
import java.util.ArrayList;
import java.util.LinkedList;
import net.dixq.irairabar.Barricade.eType;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.annotation.SuppressLint;
import android.content.res.Resources;
import android.content.Context;
public class GameMgr {
private enum eStatus{
NORMAL,
GAMEOVER,
GAMECLEAR
};
private static final float PI = (float) Math.PI;
private ArrayList<Barricade> _barrList = new ArrayList<Barricade>();//障害物リスト
private LinkedList<Task> _taskList = new LinkedList<Task>();// タスクリスト
private eStatus _status = eStatus.NORMAL;
private Player _player;
private int xx = 50 , yy = 70;
GameMgr(Context con)
{
Resources res = con.getResources();
Bitmap bits = BitmapFactory.decodeResource(res, R.drawable.ic_launcher);
// _barrList.add(new BarricadeSquare( 20, 30, 700,800, null));
_barrList.add(new BarricadeSquare( xx , yy,100, 100, null , bits));// 画面4隅に四角形を配置
/*
_barrList.add(new BarricadeSquare(460, 0, 20,800, null));
_barrList.add(new BarricadeSquare( 0,780,480, 20, null));
_barrList.add(new BarricadeTriangle( 0, 0, 200, new BConf(+PI / 150),));// 左上回転する三角形
_barrList.add(new BarricadeTriangle(480, 0, 180, new BConf(+PI / 150)));// 右上回転する三角形
_barrList.add(new BarricadeStar(240, 240, 50, 200, new BConf(-PI / 360)));// 中央に回転する星
_barrList.add(new BarricadeStar(240, 240, 20, 80, new BConf(+PI / 360)));// 中央に回転する星
_barrList.add(new BarricadeSquare(300, 440, 200, 20, null));//右下の固定通路
_barrList.add(new BarricadeSquare(250, 520, 130, 20, null));//
_barrList.add(new BarricadeSquare(330, 620, 130, 20, null));//
_barrList.add(new BarricadeSquare(230, 390, 20, 350, null));//中央区切り線
_barrList.add(new BarricadeSquare(0, 480, 240, 20, new BConf(+PI / 360)));// 左下回転するバー
_barrList.add(new BarricadeSquare( 20, 600, 110, 20, new BConf(+PI / 360)));// 左下回転するバー
_barrList.add(new BarricadeSquare(130, 600, 110, 20, new BConf(+PI / 360)));// 左下回転するバー
_barrList.add(new BarricadeSquare(185, 600, 55, 20, new BConf(+PI / 360)));// 左下回転するバー
*/
// _barrList.add(new BarricadeSquare(20, 680, 80, 20, null));// ゴールに接触したバー
// _barrList.add(new BarricadeSquare(20, 700, 80, 80, new BConf(eType.GOAL)));// ゴール
for (Barricade bar : _barrList) {
_taskList.add(bar); //タスクリストに障害物を追加
}
_player = new Player();
_taskList.add(_player);
_taskList.add(new FpsController());
}
private boolean Collision(){
Vec vec = new Vec();
final Circle cir = _player.getPt();
for(Barricade barr : _barrList){
Def.eHitCode code = barr.isHit(cir, vec);
switch(code){
case OUT:
_status = eStatus.GAMEOVER;
return true;
case GOAL:
_status = eStatus.GAMECLEAR;
return true;
}
}
return false;
}
public boolean onUpdate()
{
if( _status != eStatus.NORMAL ){
return true;
}
if( Collision() ){
return true;
}
for (int i = 0; i < _taskList.size(); i++) {
if (_taskList.get(i).onUpdate() == false) { // 更新失敗なら
_taskList.remove(i); // そのタスクを消す
i--;
}
}
return true;
}
private void drawStatus(Canvas c){
switch( _status ){
case GAMEOVER:
{
Paint paint = new Paint();
paint.setTextSize(80);
paint.setColor(Color.BLACK);
c.drawText("GameOver", 40, 100, paint);
}
break;
case GAMECLEAR:
{
Paint paint = new Paint();
paint.setTextSize(80);
paint.setColor(Color.BLACK);
c.drawText("GameClear", 40, 100, paint);
}
break;
}
}
@SuppressLint("WrongCall")
public void onDraw(Canvas c)
{
//白く塗りつぶす
c.drawColor(Color.WHITE);
for (Task task : _taskList)
{
//描画
task.onDraw(c);
}
drawStatus(c);
}
}
(8行目のさいごに「BMove move」とでも追加します)
package net.dixq.irairabar;
import android.graphics.Bitmap;
public class BarricadeSquare extends Barricade {
public BarricadeSquare( float x, float y, float w, float h, BConf conf, Bitmap img ){
super(4,conf, img);
_pt[0].x = x; _pt[0].y = y;
_pt[1].x = x+w; _pt[1].y = y;
_pt[2].x = x+w; _pt[2].y = y+h;
_pt[3].x = x; _pt[3].y = y+h;
_center.x = x+w/2;
_center.y = y+h/2;
}
public BarricadeSquare( float x, float y, float w, float h, BConf conf)
{
this(x, y ,w, h, conf, null);
}
}
よろしくお願いします。