いくつものためになるアドバイスありがとうございます。
今回は当たり判定の移動を分割して行う方法でやってみようと思っています。
実際アドバイス頂いた通りGameUpData関数内に
コード:
for(int i = 0;i<10; i++){
BarUpData(&bar); //バーの移動
BallUpData(&ball,bar); //ボールの移動
HitBallandBar(&ball,bar); //ボールとバーの当たり判定
HitBlockandBall(block,&ball,&blocknumber); //ブロックとボールの当たり判定
}
という文を加えました。(当たり判定をそのまま書くと長くなってしまうため、それそれ関数にしました。)
それでもやはり無敵ブロックに当たった場合ボールがはまってしまいました。
一応それぞれの関数は
BarUpData
コード:
void BarUpData(BAR *bar){
int i,sayu_flag=0,joge_flag=0;
double x,y,mx,my,naname=1;
double move_x[4] ={-bar->speed,bar->speed,0,0},move_y[4]={0,0,bar->speed,-bar->speed};//{左,右,下,上}のスピード
int inputpad[4];
inputpad[0]=CheckStatePad(configpad.left); inputpad[1]=CheckStatePad(configpad.right);
inputpad[2]=CheckStatePad(configpad.down); inputpad[3]=CheckStatePad(configpad.up);
//キャラクター選択
if(func_state == SELECTCHAR){
if(CheckStatePad(configpad.right)%30==1){ // 右キーが押された瞬間だけ処理
if(bar->state == 2){
bar->state = 0;
}else{
bar->state =bar->state + 1;
}
}
if(CheckStatePad(configpad.left)%30==1){ // 左キーが押された瞬間だけ処理
if(bar->state == 0){
bar->state = 2;
}else{
bar->state -=1;
}
}
}
if(func_state == GAMEPLAY){
if(bar->life > 0){
//バーの移動制御
for(i=0;i<2;i++)//左右分
if(inputpad[i]>0)//左右どちらかの入力があれば
sayu_flag=1;//左右入力フラグを立てる
for(i=2;i<4;i++)//上下分
if(inputpad[i]>0)//上下どちらかの入力があれば
joge_flag=1;//上下入力フラグを立てる
if(sayu_flag==1 && joge_flag==1)//左右、上下両方の入力があれば斜めだと言う事
naname=sqrt(2.0);//移動スピードを1/ルート2に
for(int i=0;i<4;i++){//4方向分ループ
if(inputpad[i]>0){//i方向のキーボード、パッドどちらかの入力があれば
x=bar->x , y=bar->y;//今の座標をとりあえずx,yに格納
mx=move_x[i]/10; my=move_y[i]/10;//移動分をmx,myに代入
x+=mx/naname , y+=my/naname;//今の座標と移動分を足す
if(!(x< field.x|| x>fieldmax.x - 9.5*bar->longth || y<field.y || y>fieldmax.y)){//計算結果移動可能範囲内なら
bar->x=x , bar->y=y;//実際に移動させる
}
}
}
}
//ダメージ時の無敵解除条件
if(bar->damegeflag == TRUE){
bar->cnt++;
if(bar->cnt>180){
if(bar->life <=0)
bar->life = lifemax;
bar->damegeflag = FALSE;
bar->cnt = 0;
}
}
}
if(bar->state == 1){
//キャラクターB
bar->hit.lt.x = bar->x - 45; bar->hit.lt.y = bar->y - 15;
bar->hit.rb.x = bar->x + 9 * bar->longth; bar->hit.rb.y = bar->y + 3;
bar->hit.height= bar->hit.rb.y - bar->hit.lt.y;
bar->hit.width = bar->hit.rb.x - bar->hit.lt.x;
}else{
bar->hit.lt.x = bar->x - 46; bar->hit.lt.y = bar->y - 15;
bar->hit.rb.x = bar->x + 9.75 * bar->longth; bar->hit.rb.y = bar->y + 3;
bar->hit.height= bar->hit.rb.y - bar->hit.lt.y;
bar->hit.width = bar->hit.rb.x - bar->hit.lt.x;
}
}
BallUpData
コード:
void BallUpData(BALL *ball,BAR bar){
if(func_state == OPTION){
if(CheckStatePad(configpad.left)%30 == 1 && ball->life >1)
ball->life--;
if(CheckStatePad(configpad.right)%30 == 1 && ball->life <5)
ball->life++;
}
if(func_state == GAMEPLAY){
//ボール発射
if(CheckStatePad(5) == 1){
ball->flag = TRUE;
if( startshootflag == FALSE){
ball->dx = 2;
ball->dy = -5;
}
startshootflag = TRUE;
shootflag = TRUE;
}
//ボールの大きさ
if(ball->type == Normal){
ball->hit.hankei = 9;
}else if(ball->type == Small){
ball->hit.hankei = 5;
}else{
ball->hit.hankei = 7;
}
if(ball->flag == FALSE){
if(startshootflag == FALSE){
ball->x = bar.x - 23 + 5*bar.longth;
ball->y = bar.y - 22;
ball->hit.pos.x = bar.x - 23 + 5*bar.longth;
ball->hit.pos.y = bar.y - 22;
}
if(startshootflag == TRUE){
ball->x = bar.x + bardifball.x;
ball->y = bar.y + bardifball.y;
ball->hit.pos.x = bar.x + bardifball.x;
ball->hit.pos.y = bar.y + bardifball.y;
}
}
//ボールの移動
if(ball->flag == TRUE){
//移動量を加算
ball->x+= ball->dx/10;
ball->y+= ball->dy/10;
ball->hit.pos.x += ball->dx/10;
ball->hit.pos.y += ball->dy/10;
//左の壁にヒット
if(ball->hit.pos.x < leftwall){
//PlaySoundMem(seall[5],DX_PLAYTYPE_BACK);
//ball.hit.pos.x = leftwall;
ball->dx*=-1;
}
//右の壁にヒット
if(ball->hit.pos.x > rightwall){
//ball.hit.pos.x = rightwall;
ball->dx*= -1;
//PlaySoundMem(seall[5],DX_PLAYTYPE_BACK);
}
//上の壁にヒット
if(ball->hit.pos.y < upwall){
//ball.hit.pos.y = 20;
ball->dy*=-1;
//PlaySoundMem(seall[5],DX_PLAYTYPE_BACK);
}
//ボールが下に落ちたとき
if(ball->hit.pos.y > autoline){
ball->life--;
ball->type = nball;
ball->hit.pos.x = bar.x;
ball->hit.pos.y = bar.y -20;
ball->flag = FALSE;
startshootflag = FALSE;
//ゲームオーバー
if(ball->life == 0)
ChangeGameState(Gameover);
}
}
}
}
HitBallandBar
コード:
void HitBallandBar(BALL *ball,BAR bar){
//バーの各4辺(上、左、右、下)
Line2D pt[4] ={{{bar.hit.lt.x,bar.hit.lt.y},{bar.hit.lt.x + bar.hit.width,bar.hit.lt.y}},
{{bar.hit.lt.x,bar.hit.lt.y},{bar.hit.lt.x,bar.hit.lt.y + bar.hit.height}},
{{bar.hit.lt.x + bar.hit.width,bar.hit.lt.y},{bar.hit.rb.x,bar.hit.rb.y}},
{{bar.hit.lt.x,bar.hit.lt.y + bar.hit.height},{bar.hit.rb.x,bar.hit.rb.y}}};
//バーにあたったときのボールの移動
if((HitLineAndCircle(pt[0],ball->hit) == TRUE && HitLineAndCircle(pt[1],ball->hit) == TRUE)||
(HitLineAndCircle(pt[0],ball->hit) == TRUE && HitLineAndCircle(pt[2],ball->hit) == TRUE))
{
if(ball->hit.pos.x < bar.x){
ball->dx = -4;
ball->dy = -2;
}else{
ball->dx = 4;
ball->dy = -2;
}
}else if((HitLineAndCircle(pt[3],ball->hit) == TRUE && HitLineAndCircle(pt[1],ball->hit) == TRUE)||
(HitLineAndCircle(pt[3],ball->hit) == TRUE && HitLineAndCircle(pt[2],ball->hit) == TRUE))
{
if(ball->hit.pos.x < bar.x){
ball->dx = -4;
ball->dy = 2;
}else{
ball->dx = 4;
ball->dy = 2;
}
}else{
if(HitLineAndCircle(pt[0],ball->hit) == TRUE ){
if(ball->hit.pos.x < bar.hit.lt.x + bar.hit.width/14){
ball->dx = -4;
ball->dy = -2;
}
if(ball->hit.pos.x > bar.hit.rb.x - bar.hit.width/14){
ball->dx = 4;
ball->dy = -2;
}
if(ball->hit.pos.x >= bar.hit.lt.x + bar.hit.width/14 && ball->hit.pos.x < bar.hit.lt.x + 5*bar.hit.width/14){
ball->dx = -2;
ball->dy = -5;
}
if(ball->hit.pos.x <= bar.hit.rb.x - bar.hit.width/14 && ball->hit.pos.x > bar.hit.rb.x - 5*bar.hit.width/14){
ball->dx = 2;
ball->dy = -5;
}
if(ball->hit.pos.x >= bar.hit.lt.x + 5*bar.hit.width/14 && ball->hit.pos.x < bar.hit.lt.x + 7*bar.hit.width/14){
ball->dx = -1;
ball->dy = -6;
}
if(ball->hit.pos.x <= bar.hit.rb.x - 5*bar.hit.width/14 && ball->hit.pos.x >= bar.hit.rb.x - 7*bar.hit.width/14){
ball->dx = 1;
ball->dy = -6;
}
}
if(HitLineAndCircle(pt[3],ball->hit) == TRUE){
//ball->hit.pos.y = bar.hit.rb.y + 7;
ball->dy*= -1;
}
if(HitLineAndCircle(pt[1],ball->hit) == TRUE){
ball->dx = -6;
ball->dy = -2;
}
if(HitLineAndCircle(pt[2],ball->hit) == TRUE){
ball->dx = 6;
ball->dy = -2;
}
}
if(HitLineAndCircle(pt[0],ball->hit) == TRUE ||
HitLineAndCircle(pt[1],ball->hit) == TRUE ||
HitLineAndCircle(pt[2],ball->hit) == TRUE ||
HitLineAndCircle(pt[3],ball->hit) == TRUE){
//barhitflag = TRUE;
if(ball->type == Sucker){
if(shootflag == TRUE){
bardifball.x = ball->hit.pos.x - bar.x;
bardifball.y = ball->hit.pos.y - bar.y;
}
shootflag = FALSE;
ball->flag = FALSE;
}
}
}
HitBlockandBall
コード:
void HitBlockandBall(BLOCK block[3][13][9],BALL *ball,int *blocknumber){
//ボールとブロックのあたり判定
for(int k=0;k<3;k++){
for(int i = 0; i < 13 ; i++){
for(int j = 0; j < 9; j++){
//バーの各4辺(上、左、右、下)
Line2D pt[4] ={{{block[k][i][j].hit.lt.x,block[k][i][j].hit.lt.y},{block[k][i][j].hit.lt.x + block[k][i][j].hit.width,block[k][i][j].hit.lt.y}},
{{block[k][i][j].hit.lt.x,block[k][i][j].hit.lt.y},{block[k][i][j].hit.lt.x,block[k][i][j].hit.lt.y + block[k][i][j].hit.height}},
{{block[k][i][j].hit.lt.x +block[k][i][j].hit.width,block[k][i][j].hit.lt.y},{block[k][i][j].hit.rb.x,block[k][i][j].hit.rb.y}},
{{block[k][i][j].hit.lt.x,block[k][i][j].hit.lt.y + block[k][i][j].hit.height},{block[k][i][j].hit.rb.x,block[k][i][j].hit.rb.y}}};
//ブロックがまだ消えていないときのブロックとボールの当たり判定
if(block[k][i][j].flag == 0){
//ボールの反射
if((HitLineAndCircle(pt[0],ball->hit) == TRUE && HitLineAndCircle(pt[1],ball->hit) == TRUE)||
(HitLineAndCircle(pt[0],ball->hit) == TRUE && HitLineAndCircle(pt[2],ball->hit) == TRUE))
{
//上と左or右と同時に当たった時
if(block[k][i][j].life <= 1 && ball->type == 5){
ball->dy*= -1;
}
}else if((HitLineAndCircle(pt[3],ball->hit) == TRUE && HitLineAndCircle(pt[1],ball->hit) == TRUE)||
(HitLineAndCircle(pt[3],ball->hit) == TRUE && HitLineAndCircle(pt[2],ball->hit) == TRUE))
{
//下と左or右と同時に当たった時
if(block[k][i][j].life != 1 || ball->type != 5)
ball->dx*= -1;
}else{
//上、下、左、右に当たった時
if(HitLineAndCircle(pt[0],ball->hit) == TRUE){
if(block[k][i][j].life != 1 || ball->type != 5)
ball->dx*= -1;
}
if(HitLineAndCircle(pt[3],ball->hit) == TRUE){
if(block[k][i][j].life != 1 || ball->type != 5)
ball->dy*= -1;
}
if(HitLineAndCircle(pt[1],ball->hit) == TRUE){
if(block[k][i][j].life != 1 || ball->type != 5)
ball->dx*= -1;
}
if(HitLineAndCircle(pt[2],ball->hit) == TRUE){
if(block[k][i][j].life != 1 || ball->type != 5)
ball->dx*= -1;
}
}
//ブロックにダメージ
if(HitLineAndCircle(pt[0],ball->hit) == TRUE ||
HitLineAndCircle(pt[1],ball->hit) == TRUE ||
HitLineAndCircle(pt[2],ball->hit) == TRUE ||
HitLineAndCircle(pt[3],ball->hit) == TRUE){
if(block[k][i][j].life >= 1){
if(ball->type == Needle){
if(block[k][i][j].life == 1){
block[k][i][j].life--;
}else{
block[k][i][j].life -= 2;
}
}else{
block[k][i][j].life--;
}
}
if(block[k][i][j].life == 0){
block[k][i][j].flag = 1;
*blocknumber +=1;
}
}
}
}
}
}
}
というようになります。
一応、データをアップしておきます。上がソースと実際ボールがどのような挙動をするのかという動画、下が動画のみとなります。パスワードは「YT2013」です。
http://www1.axfc.net/uploader/so/2874245
http://www1.axfc.net/uploader/so/2874249
ちなみに動画は無印が上(または下)と左右の辺が当たった時ボールの移動方向をball.dy*=-1とした場合、
2がball.dx*=-1とした場合になります。