テトリスの左右移動を無効にするコード

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
メモリーモリメ

テトリスの左右移動を無効にするコード

#1

投稿記事 by メモリーモリメ » 12年前

DXライブラリ使ってテトリスを作ってます。
テトリスではブロックが床に落ちてからも左右移動ができますよね?
あれって一定期間だけじゃないですか?どうやって無効化するんですか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: テトリスの左右移動を無効にするコード

#2

投稿記事 by softya(ソフト屋) » 12年前

あれは、落下待ち→これ以上下に落ちれないので固着です。
つまり、移動できる間は通常の落下の待ち処理と同じって事です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

メモリーモリメ

Re: テトリスの左右移動を無効にするコード

#3

投稿記事 by メモリーモリメ » 12年前

このコード、これはテトリスではないですがブロックゲームです。
どこをいじれば、固定までの時間を長くできますか?
関数単位で教えて下さい。



#include "DxLib.h"

#define BLOCKTYPE_NUM 5 // ブロックの種類の数

#define BLOCK_SIZE 24 // ブロックのドットサイズ
#define WORLD_WIDTH 8 // ステージの幅
#define WORLD_HEIGHT 16 // ステージの高さ

#define STAGE_X 210 // ステージの左上頂点のX座標
#define STAGE_Y 50 // ステージの左上頂点のY座標

#define WAIT 500 // 黙っててブロックが落ちるまでの時間

// ステージデータ
char Block[ WORLD_WIDTH ][ WORLD_HEIGHT ] ; // 実際のデータ
char BufferBlock[ WORLD_WIDTH ][ WORLD_HEIGHT ] ; // 一時状態保存用ブロックデータ

// アクティブブロックデータ
int ActiveX , ActiveY ; // アクティブブロックの一番下のブロックの位置
char ActiveBlock[ 3 ] ; // アクティブなブロックのデータ

// カウンター
int WaitCounter ; // 下に勝手に落とすまでの時間計測用
int NowTime ; // 現在のフレームで経過した時間
int OldTime ; // 前のフレームのときにGetNowCount関数で得たタイム

// ブロックの種類ごとの色データ
int BlockColor[ 5 ][ 3 ] =
{
{ 128 , 128 , 128 } , { 255 , 100 , 100 } ,{ 255 , 255 , 0 } ,
{ 255 , 0 , 255 } , { 0 , 255 , 255 }
} ;


void InitGame( void ) ; // ゲームの初期化
void CreateNewActiveBlock( void ) ; // 新しいブロックの生成
int KeyInput( void ) ; // キー入力処理
int TimeFunc( void ) ; // 時間関係処理
int MoveActiveBlock( int MoveX , int MoveY ) ; // アクティブブロックの移動
int CheckHitActiveBlock( int x , int y ) ; // アクティブブロックが画面上のブロックに当たっていないか調べる
int LockActiveBlock( int x , int y ) ; // アクティブブロックを固定する及び次のブロックを出すもし次のブロックを出すスペースがなかったらゲームオーバー
void GameOver( void ) ; // ゲームオーバー処理
int CheckEliminatBlock( void ) ; // 消えるブロックがあるか調べてあったら消す処理をする
void InitBufferBlock( void ) ; // 一時使用用ブロックデータの初期化
int CheckEliminatBlockToOne( int x , int y ) ; // 特定ブロックが消えるか探索
int ScreenDraw( void ) ; // 画面描画処理関数

// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
SetGraphMode( 640 , 480 , 16 ) ;
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1; // エラーが起きたら直ちに終了
}

// ゲームを初期化
InitGame() ;

// 描画先画面を裏画面にセット
SetDrawScreen( DX_SCREEN_BACK ) ;

// メインループ
while( ProcessMessage() == 0 )
{
// キー入力処理
KeyInput() ;

// 時間経過処理
TimeFunc() ;

// 画面描画
ScreenDraw() ;


}

// DXライブラリの終了
DxLib_End() ;

// 終了
return 0 ;
}

// ゲームの初期化
void InitGame( void )
{
int i , j ;

// 前回時間をセット
OldTime = GetNowCount() ;

// アクティブブロックの位置をセット
ActiveX = WORLD_WIDTH / 2 ;
ActiveY = 2 ;

// アクティブブロックを生成
CreateNewActiveBlock() ;

// マップブロックの初期化
for( i = 0 ; i < WORLD_HEIGHT ; i ++ )
for( j = 0 ; j < WORLD_WIDTH ; j ++ )
Block[ j ][ i ] = 0 ;
}

// 新しいブロックの生成
void CreateNewActiveBlock( void )
{
int i ;

// ランダムに3つブロックをセット
for( i = 0 ; i < 3 ; i ++ )
ActiveBlock[ i ] = GetRand( BLOCKTYPE_NUM - 1 ) + 1 ;
}

// キー入力処理
int KeyInput( void )
{
int Key ; // 入力されたキー
static int OldKey ; // 前フレームで取得したキー情報

// キー入力を得る
Key = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;

// キー入力に応じて処理をする
if( Key & PAD_INPUT_DOWN ) MoveActiveBlock( 0 , 1 ) ;
if( ( Key & ~OldKey ) & PAD_INPUT_LEFT && ActiveX > 0 ) MoveActiveBlock( -1 , 0 ) ;
if( ( Key & ~OldKey ) & PAD_INPUT_RIGHT && ActiveX < WORLD_WIDTH - 1 ) MoveActiveBlock( 1 , 0 ) ;

if( ( Key & ~OldKey ) & PAD_INPUT_A )
{
int TempBlock ;

// アクティブブロックの配置を変更する
TempBlock = ActiveBlock[ 2 ] ; ActiveBlock[ 2 ] = ActiveBlock[ 0 ] ; ActiveBlock[ 0 ] = TempBlock ;
TempBlock = ActiveBlock[ 0 ] ; ActiveBlock[ 0 ] = ActiveBlock[ 1 ] ; ActiveBlock[ 1 ] = TempBlock ;
}
OldKey = Key ;

// 終了
return 0 ;
}

// 時間関係処理
int TimeFunc( void )
{
int Time ;

// 現在の時間を得る
Time = GetNowCount() ;

// 今フレームで経過した時間を得る
NowTime = Time - OldTime ;

// 現在の時間を保存
OldTime = Time ;

// ウエイトカウンタに経過時間を加算する
WaitCounter += NowTime ;

// 一定時間が経過していたら勝手に下にブロックを落す
if( WaitCounter > WAIT )
{
MoveActiveBlock( 0 , 1 ) ;

// カウンターを0に戻す
WaitCounter = 0 ;
}

// 終了
return 0 ;
}

// アクティブブロックの移動
int MoveActiveBlock( int MoveX , int MoveY )
{
int NewX , NewY ;

// 移動後の座標をセットする
NewX = MoveX + ActiveX ;
NewY = MoveY + ActiveY ;

// 左右移動の処理
if( MoveX != 0 && NewX >= 0 && NewX < WORLD_WIDTH )
{
// 各3つのブロックが画面上のブロックに当たっていないか調べる
if( CheckHitActiveBlock( NewX , NewY ) == - 1 )
{
// あたっていたら左右移動を無効にする
MoveX = 0 ;
}
}

// 上下移動の処理
if( MoveY != 0 )
{
// 画面の一番下のブロック位置まで来ていたらブロックを固定させる
if( NewY >= WORLD_HEIGHT )
{
LockActiveBlock( ActiveX , ActiveY ) ;

// 移動を無効にする
MoveY = 0 ;
}
else
// 各3つのブロックが画面上のブロックに当たっていないか調べる
if( CheckHitActiveBlock( NewX , NewY ) == - 1 )
{
// あたっていたらブロックを固定する
LockActiveBlock( ActiveX , ActiveY ) ;

// 移動を無効にする
MoveY = 0 ;
}
}

// 座標を移動する
ActiveX += MoveX ;
ActiveY += MoveY ;

// 終了
return 0 ;
}

// アクティブブロックが画面上のブロックに当たっていないか調べる
int CheckHitActiveBlock( int x , int y )
{
int i ;

// 3つあるブロックがそれぞれ画面上のブロックに当たっていないか調べる
for( i = 0 ; y - i >= 0 && i < 3 ; i ++ )
{
// 当たっていたらここで終了
if( Block[ x ][ y - i ] != 0 ) return -1 ;
}

// 当たっていない場合だけ0を返す
return 0 ;
}

// アクティブブロックを固定する
// 及び次のブロックを出す
// もし次のブロックを出すスペースがなかったらゲームオーバー
int LockActiveBlock( int x , int y )
{
int i ;

for( i = 0 ; i < 3 ; i ++ )
{
// 画面上から外れている場合はセットしない
if( y - i < 0 ) continue ;

// ブロックの固定
Block[ x ][ y - i ] = ActiveBlock[ i ] ;
}

// 消せるブロックがある場合は消す
CheckEliminatBlock() ;

// 新しいブロックをセット
{
// アクティブブロックの位置をセット
ActiveX = WORLD_WIDTH / 2 ;
ActiveY = 2 ;

// 新しいアクティブブロックを生成
CreateNewActiveBlock() ;

// 次に出そうとしているスペースがなかったらゲームオーバー処理
for( i = 0 ; i < 3 ; i ++ )
{
if( Block[ ActiveX ][ ActiveY - i ] != 0 ) GameOver() ;
}
}

// カウンタリセット
WaitCounter = 0 ;

// 時間待ち


WaitTimer( 200 ) ;

// 終了
return 0 ;
}

// ゲームオーバー処理
void GameOver( void )
{
// 画面中心にゲームオーバーを表示
ScreenDraw() ;
DrawString( 300 , 220 , "GameOver" , GetColor( 255 , 255 , 255 ) ) ;
ScreenFlip() ;

// キー入力待ち
WaitKey() ;

// DXライブラリ終了
DxLib_End() ;

// ソフト終了
exit( -1 ) ;
}

// 消えるブロックがあるか調べてあったら消す処理をする
int CheckEliminatBlock( void )
{
int i , j , k; // 汎用変数
int ClsFlag ; // 一つでも消せたブロックがあったか、のフラグ

do{
// 一時使用用ブロックデータを初期化
InitBufferBlock() ;

// 消せたブロックがあるか、フラグを倒す
ClsFlag = FALSE ;

// 各ブロックが消えるか調べる
for( i = 0 ; i < WORLD_HEIGHT ; i ++ )
{
for( j = 0 ; j < WORLD_WIDTH ; j ++ )
{
// もしブロックがない場合は次に移る
if( Block[ j ][ i ] == 0 ) continue ;

// ブロックが消えるかどうか調べて調査結果をバッファに保存する
BufferBlock[ j ][ i ] = CheckEliminatBlockToOne( j , i ) ;
}
}

// 消えると判断されたブロックを消す
for( i = 0 ; i < WORLD_HEIGHT ; i ++ )
{
for( j = 0 ; j < WORLD_WIDTH ; j ++ )
{
if( BufferBlock[ j ][ i ] == 1 )
{
ClsFlag = TRUE ;
Block[ j ][ i ] = 0 ;
}
}
}

// 空きを積める
for( i = WORLD_HEIGHT - 2 ; i > -1 ; i -- )
{
for( j = 0 ; j < WORLD_WIDTH ; j ++ )
{
if( Block[ j ][ i ] != 0 )
{
for( k = i + 1 ; k < WORLD_HEIGHT && Block[ j ][ k ] == 0 ; k ++ ){}
k -- ;

if( k != i )
{
Block[ j ][ k ] = Block[ j ][ i ] ;
Block[ j ][ i ] = 0 ;
}
}
}
}

}while( ClsFlag ) ; // 消せたブロックがあった場合再度チェック

// 終了
return 0 ;
}

// 一時使用用ブロックデータの初期化
void InitBufferBlock( void )
{
int i , j ;

for( i = 0 ; i < WORLD_HEIGHT ; i ++ )
{
for( j = 0 ; j < WORLD_WIDTH ; j ++ )
{
BufferBlock[ j ][ i ] = 0 ;
}
}
}

// 特定ブロックが消えるか探索
int CheckEliminatBlockToOne( int x , int y )
{
int CheckBlock ;
int i ;
int BlockNum ;

// チェックするブロックの種類を保存
CheckBlock = Block[ x ][ y ] ;


// 左右にどれだけつながっているか調べる
for( i = 0 ; x + i >= 0 && Block[ x + i ][ y ] == CheckBlock ; i -- ){}
i ++ ;
for( BlockNum = 0 ; x + i < WORLD_WIDTH && Block[ x + i ][ y ] == CheckBlock ; BlockNum ++ , i ++ ){}

// 3つ以上つながっていたらここで終了
if( BlockNum >= 3 ) return 1 ;


// 上下にどれだけつながっているか調べる
for( i = 0 ; y + i >= 0 && Block[ x ][ y + i ] == CheckBlock ; i -- ){}
i ++ ;
for( BlockNum = 0 ; y + i < WORLD_HEIGHT && Block[ x ][ y + i ] == CheckBlock ; BlockNum ++ , i ++ ){}

// 3つ以上つながっていたらここで終了
if( BlockNum >= 3 ) return 1 ;


// 左上から右下にかけて繋がっている数を調べる
for( i = 0 ; y + i >= 0 && x + i >= 0 && Block[ x + i ][ y + i ] == CheckBlock ; i -- ){}
i ++ ;
for( BlockNum = 0 ; x + i < WORLD_WIDTH && y + i < WORLD_HEIGHT && Block[ x + i ][ y + i ] == CheckBlock ; BlockNum ++ , i ++ ){}

// 3つ以上つながっていたらここで終了
if( BlockNum >= 3 ) return 1 ;


// 右上から左下にかけて繋がっている数を調べる
for( i = 0 ; y + i >= 0 && x - i < WORLD_WIDTH && Block[ x - i ][ y + i ] == CheckBlock ; i -- ){}
i ++ ;
for( BlockNum = 0 ; x - i >= 0 && y + i < WORLD_HEIGHT && Block[ x - i ][ y + i ] == CheckBlock ; BlockNum ++ , i ++ ){}

// 3つ以上つながっていたらここで終了
if( BlockNum >= 3 ) return 1 ;


// ここまで来ていたら消えない
return 0 ;
}

// 画面描画処理関数
int ScreenDraw( void )
{
int i , j , k ;

// 画面を初期化
ClearDrawScreen() ;

// 枠を描画
DrawBox( STAGE_X - 24 , STAGE_Y , STAGE_X ,
STAGE_Y + WORLD_HEIGHT * BLOCK_SIZE ,
GetColor( 255 , 0 , 0 ) , TRUE ) ;

DrawBox( STAGE_X + WORLD_WIDTH * BLOCK_SIZE , STAGE_Y ,
STAGE_X + 24 + WORLD_WIDTH * BLOCK_SIZE , STAGE_Y + WORLD_HEIGHT * BLOCK_SIZE ,
GetColor( 255 , 0 , 0 ) , TRUE ) ;

DrawBox( STAGE_X - 24 , STAGE_Y + WORLD_HEIGHT * BLOCK_SIZE ,
STAGE_X + 24 + WORLD_WIDTH * BLOCK_SIZE , STAGE_Y + WORLD_HEIGHT * BLOCK_SIZE + 24 ,
GetColor( 255 , 0 , 0 ) , TRUE ) ;

// ブロックを描画
for( i = 0 ; i < WORLD_HEIGHT ; i ++ )
{
for( j = 0 ; j < WORLD_WIDTH ; j ++ )
{
if( Block[ j ][ i ] != 0 )
{
k = Block[ j ][ i ] - 1 ;
DrawBox( STAGE_X +j * BLOCK_SIZE , STAGE_Y + BLOCK_SIZE * i ,
STAGE_X +j * BLOCK_SIZE + BLOCK_SIZE , STAGE_Y + i * BLOCK_SIZE + BLOCK_SIZE ,
GetColor( BlockColor[ k ][ 0 ] ,BlockColor[ k ][ 1 ] ,BlockColor[ k ][ 2 ] ) , TRUE ) ;
}
}
}

// アクティブブロックを描画
for( i = 0 ; i + ActiveY >= 0 && i < 3 ; i ++ )
{
k = ActiveBlock[ i ] - 1 ;

DrawBox( STAGE_X + ActiveX * BLOCK_SIZE , STAGE_Y + ( ActiveY - i ) * BLOCK_SIZE ,
STAGE_X + ActiveX * BLOCK_SIZE + BLOCK_SIZE , STAGE_Y + ( ActiveY - i ) * BLOCK_SIZE + BLOCK_SIZE ,
GetColor( BlockColor[ k ][ 0 ] ,BlockColor[ k ][ 1 ] ,BlockColor[ k ][ 2 ] ) , TRUE ) ;
}


// 裏画面の内容を表画面に反映させる
ScreenFlip() ;
// 終了
return 0 ;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: テトリスの左右移動を無効にするコード

#4

投稿記事 by softya(ソフト屋) » 12年前

フォーラムルールを、ちゃんとお読みいただいたほうが良いと思います。
http://dixq.net/board/board.html
ソースコードを見やすくするcodeタグの使い方も書かれています。

>このコード、これはテトリスではないですがブロックゲームです。
>どこをいじれば、固定までの時間を長くできますか?
>関数単位で教えて下さい。

プログラムを組むという知識を得るためには自分で考えることが重要です。
丸投げはご自身のためにはなりません。

【補足】
どこかで見たと思ったらDXライブラリのサンプルコードのコラムスですね。
引用した場合は、礼儀のためにも引用元を明記するようにしてくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。


メリモ

Re: テトリスの左右移動を無効にするコード

#6

投稿記事 by メリモ » 12年前

別のスレで解決しますた。
スライドの話題で同じスレ確か3つ建てたと思います。
この横着ぶりに関しては反省します。

アバター
asd
記事: 319
登録日時: 14年前

Re: テトリスの左右移動を無効にするコード

#7

投稿記事 by asd » 12年前

メリモ さんが書きました:別のスレで解決しますた。
スライドの話題で同じスレ確か3つ建てたと思います。
この横着ぶりに関しては反省します。
横着ぶりをわびる文面で横着をしてどうするんですか。
解決したスレッドへのリンクを貼るなり、解決方法を引用するのがけじめではないですか?
また反省の弁を述べる文面にて「解決しまた」などのような書き方をされると
反省の効力は半減してしまいますよ。
Advanced Supporting Developer
無理やりこじつけ(ぉ

メリモ

Re: テトリスの左右移動を無効にするコード

#8

投稿記事 by メリモ » 12年前

乱立申し訳ありません。

このtopicにて、この話題を継続しています。
http://dixq.net/forum/viewtopic.php?f=3&t=13611

閉鎖

“C言語何でも質問掲示板” へ戻る