//ブロック崩しゲーム //2006.04.03 久原  //2006.04.03 伊藤注釈 //PB,PC 16本のLEDアレイをドライブ(縦) //PA4_PA1 をデコードして、16本のLEDアレイをドライブ(横) //PA0 可変抵抗スライダのAD変換用入力 //3V電池駆動 //PA4はプルアップが必要 //余りのピンはPA5のみ //使用メモリ ROM 54% RAM=51% - 84% //課題 //残りのブロック数は調べていない //したがってクリアしても終了しない //音がしない //ポイントが出ない //縦と横のLEDアレイのドライブ方向を逆にする //ボタンがあるとインベーダ型ゲームができる #include <16f876.h> #fuses HS, NOWDT, NOPROTECT, PUT, NOBROWNOUT, NOLVP, NODEBUG, NOWRT #device ADC=10 #use delay( CLOCK = 20000000 ) #use fast_io(A) #use fast_io(B) #use fast_io(C) #include #define BLOCK_WIDTH 20 // 変数群 int matrix[64]; // ドットマトリクス int pad_pos; // パッドの位置 float x, y, vx, vy, v; // 弾の位置と速さ // 関数群 void Loop( void );//主ループ void Init( void );//初期画面 void Pad( void );//パッド位置の変更 int GetSlidePos( void );//スライダのAD変換 void Move( float *x, float *y, float vx, float vy );//ボールの移動 void Collision( void );//以下の要因別衝突判断 int IsBlock( int x, int y ); int IsWall( int x, int y ); int IsPad( int x, int y ); int IsBall( int bx, int by ); int IsDead( int x, int y ); void EraseBlock( int x, int y );//ブロックを消す void CreateBlock( int x, int y );//ブロックを作る void CreateWall( int x, int y ); void CreateRound( void ); void LoseGame( void );//ゲーム終了 void Show( void );//画面表示 void ShowWait( int wait ); // メイン関数 void main( void ) { // とりあえず待つ delay_ms( 100 ); // 入出力ポートの設定 setup_adc_ports( RA0_ANALOG ); setup_adc( ADC_CLOCK_DIV_32 ); set_tris_a( 0b00000001 ); // in:RA0 out:RA1-4 set_tris_b( 0b00000000 ); // out:RB0-7 set_tris_c( 0b00000000 ); // out:RC0-7 // 初期化処理 Init(); // 無限ループ while( 1 ) { Loop(); } } // 無限ループ void Loop( void ) { // パッド移動 Pad(); // 衝突判定と向き調整 Collision(); // ボール移動 Move( &x, &y, vx, vy ); // 表示 //Showには時間遅延なし、したがってshow1回程度の時間余裕 //ただし、縦方向のバイト合成をしたためで、縦横のドライブ方向を変えれば、 //時間余裕が出る Show(); Show(); } // 初期化 void Init( void ) { pad_pos = 8; x = 4.0f; y = 8.0f; v = 0.2f; vx = 0.075f; vy = (float)(sqrt( (v*v - vx*vx) )); // 面作り CreateRound(); // 3を描く CreateBlock( 11, 9 ); CreateBlock( 12, 9 ); CreateBlock( 13, 9 ); CreateBlock( 13, 10 ); CreateBlock( 11, 11 ); CreateBlock( 12, 11 ); CreateBlock( 13, 11 ); CreateBlock( 13, 12 ); CreateBlock( 11, 13 ); CreateBlock( 12, 13 ); CreateBlock( 13, 13 ); // 静止画 ShowWait( 5000 ); // 3を消す EraseBlock( 11, 9 ); EraseBlock( 12, 9 ); EraseBlock( 13, 9 ); EraseBlock( 13, 10 ); EraseBlock( 11, 11 ); EraseBlock( 12, 11 ); EraseBlock( 13, 11 ); EraseBlock( 13, 12 ); EraseBlock( 11, 13 ); EraseBlock( 12, 13 ); EraseBlock( 13, 13 ); // 2を描く CreateBlock( 11, 9 ); CreateBlock( 12, 9 ); CreateBlock( 13, 9 ); CreateBlock( 13, 10 ); CreateBlock( 13, 11 ); CreateBlock( 12, 11 ); CreateBlock( 11, 11 ); CreateBlock( 11, 12 ); CreateBlock( 11, 13 ); CreateBlock( 12, 13 ); CreateBlock( 13, 13 ); // 静止画 ShowWait( 5000 ); // 2を消す EraseBlock( 11, 9 ); EraseBlock( 12, 9 ); EraseBlock( 13, 9 ); EraseBlock( 13, 10 ); EraseBlock( 13, 11 ); EraseBlock( 12, 11 ); EraseBlock( 11, 11 ); EraseBlock( 11, 12 ); EraseBlock( 11, 13 ); EraseBlock( 12, 13 ); EraseBlock( 13, 13 ); // 1を描く CreateBlock( 13, 9 ); CreateBlock( 13, 10 ); CreateBlock( 13, 11 ); CreateBlock( 13, 12 ); CreateBlock( 13, 13 ); // 静止画 ShowWait( 5000 ); // 1を消す EraseBlock( 13, 9 ); EraseBlock( 13, 10 ); EraseBlock( 13, 11 ); EraseBlock( 13, 12 ); EraseBlock( 13, 13 ); // 0を描く CreateBlock( 11, 9 ); CreateBlock( 11, 10 ); CreateBlock( 11, 11 ); CreateBlock( 11, 12 ); CreateBlock( 11, 13 ); CreateBlock( 12, 9 ); CreateBlock( 12, 13 ); CreateBlock( 13, 9 ); CreateBlock( 13, 10 ); CreateBlock( 13, 11 ); CreateBlock( 13, 12 ); CreateBlock( 13, 13 ); // 静止画 ShowWait( 5000 ); // 0を消す EraseBlock( 11, 9 ); EraseBlock( 11, 10 ); EraseBlock( 11, 11 ); EraseBlock( 11, 12 ); EraseBlock( 11, 13 ); EraseBlock( 12, 9 ); EraseBlock( 12, 13 ); EraseBlock( 13, 9 ); EraseBlock( 13, 10 ); EraseBlock( 13, 11 ); EraseBlock( 13, 12 ); EraseBlock( 13, 13 ); } // パッド位置調整 void Pad( void ) { // スライダの値を取得 pad_pos = GetSlidePos(); } // スライダの位置を取得 int GetSlidePos( void ) { //スライダが直線的でない long analog; set_adc_channel( 0 ); delay_us( 50 ); analog = read_adc(); if( analog<30 ) return 3; if( analog<60 ) return 4; if( analog<90 ) return 5; if( analog<120 ) return 6; if( analog<160 ) return 7; if( analog<230 ) return 8; if( analog<330 ) return 9; if( analog<480 ) return 10; if( analog<750 ) return 11; return 12; } // ボールの移動 void Move( float *x, float *y, float vx, float vy ) { *x += vx; *y += vy; } // 衝突判定 void Collision( void ) { float test_x, test_y; int flag_x, flag_y, flag_pad; int tx, ty; int xx, yy; test_x = x; test_y = y; flag_x = 0; flag_y = 0; flag_pad = 0; Move( &test_x, &test_y, vx, vy );//仮に移動 tx = (int)( test_x+0.5 ); ty = (int)( test_y+0.5 ); xx = (int)( x+0.5 ); yy = (int)( y+0.5 ); // 死亡フラグ if( IsDead( xx, ty ) )//ボールが下に落ちた { LoseGame(); Init(); return; } // ブロック(ブロックを消す処理も追加) if( IsBlock( tx, yy ) ) { flag_x = 1; EraseBlock( tx, yy ); } if( IsBlock( xx, ty ) ) { flag_y = 1; EraseBlock( xx, ty ); } // 壁(普通に反転) if( IsWall( tx, yy ) ) { flag_x = 1; } if( IsWall( xx, ty ) ) { flag_y = 1; } // パッド(当たった位置によって角度を変化させる) //ランダム性はなし //音を入れたいね if( flag_pad = IsPad( xx, ty ) ) { v += 0.01; vx = (float)( vx + vx * ( (float)flag_pad-3.0f )*0.02 ); vy = -(float)sqrt( v*v - vx*vx ); y -= 0.5; flag_y = 0; } if( flag_pad = IsPad( tx, yy ) ) { v += 0.01; vx = (float)( vx + vx * ( (float)flag_pad-3.0f )*0.02 ); vy = -(float)sqrt( v*v - vx*vx ); y -= 0.5; return; // flag_x = 0; } if( flag_x == 1 ) { vx = -vx; } if( flag_y == 1 ) { vy = -vy; } } // その位置にブロックがあるか int IsBlock( int x, int y ) { int pos, bit, mask; pos = y*4+x/4; bit = x%4; mask = 0x02 << ( 6-bit*2 ); return matrix[pos] & mask; } // その位置に壁があるか int IsWall( int x, int y ) { int pos, bit, mask; pos = y*4+x/4; bit = x%4; mask = 0x01 << ( 6-bit*2 ); return matrix[pos] & mask; } // その位置にパッドがあるか //パッドのサイズは固定 int IsPad( int x, int y ) { if( y>=15 && ( pad_pos-2 <= x && x <= pad_pos+2 ) ) { return x - pad_pos + 3; } return 0; } // その位置にパッドがあるか int IsBall( int bx, int by ) { return ( bx == (int)( x+0.5 ) && by == (int)( y+0.5 ) ); } // ボールが落ちた int IsDead( int x, int y ) { return y>15; } // ブロック消す void EraseBlock( int x, int y ) { int pos, bit, mask; pos = y*4+x/4; bit = x%4; mask = 0x03 << ( 6-bit*2 ); matrix[pos] = matrix[pos] & (~mask); } // ブロック生作る void CreateBlock( int x, int y ) { int pos, bit, mask; pos = y*4+x/4; bit = x%4; mask = 0x02 << ( 6-bit*2 ); matrix[pos] = matrix[pos] | mask; } // 壁作る void CreateWall( int x, int y ) { int pos, bit, mask; pos = y*4+x/4; bit = x%4; mask = 0x01 << ( 6-bit*2 ); matrix[pos] = matrix[pos] | mask; } // 画面作り void CreateRound( void ) { int i, j; for( i=0; i<64; i++ ) { matrix[i] = 0; } for( j=1; j<5; j++ ) { for( i=1; i<15; i++ ) { CreateBlock( i, j ); } } for( i=0; i<16; i++ ) { CreateWall( i, 0 ); } for( j=0; j<16; j++ ) { CreateWall( 0, j ); } for( j=0; j<16; j++ ) { CreateWall( 15, j ); } } // 敗戦処理 void LoseGame( void ) { // ×を描く CreateBlock( 9, 9 ); CreateBlock( 10, 10 ); CreateBlock( 11, 11 ); CreateBlock( 12, 12 ); CreateBlock( 13, 13 ); CreateBlock( 13, 9 ); CreateBlock( 12, 10 ); CreateBlock( 10, 12 ); CreateBlock( 9, 13 ); // 静止画 ShowWait( 1000 ); } // 出力 void Show( void ) { int b, c; int rb, rc; int scan; for( scan = 0; scan < 16; scan++ ) { rb = 0; rc = 0; // rbの作成 //縦方向にビットを合成する for( b = 0; b < 8; b++ ) { if( IsBlock( scan, b ) || IsWall( scan, b ) || IsPad( scan, b ) || IsBall( scan, b ) ) { rb |= 0b1 << ( b ); } } // rcの作成 //縦方向にビットを合成する for( c = 8; c < 16; c++ ) { if( IsBlock( scan, c ) || IsWall( scan, c ) || IsPad( scan, c ) || IsBall( scan, c ) ) { rc |= 0b1 << ( c - 8 ); } } output_B( rb ); output_C( rc ); output_A( scan << 1 );//縦方向に1本表示 } } // 出力(指定回数表示し続ける) //loop>Collision>Losegame>SHowWait //スタックは最大8レベル、なぜShowを呼ばない? void ShowWait( int wait ) { int b, c; int rb, rc; int scan; int i; for( i=0; i