Created
February 3, 2017 02:21
-
-
Save Yomogiii/8720110f5dcbc72c23cced04e98f588b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <wiringPi.h> | |
#include <lcd.h> | |
#include <signal.h> | |
#include <sys/time.h> | |
#include <time.h> | |
#include <stdbool.h> | |
//使用するGPIO.PIN(wiringPiのPIN) | |
#define SHOOT_PIN 28 | |
#define RELOAD_PIN 25 | |
#define IR_READ_PIN 7 | |
#define IR_SEND_PIN 29 | |
//LCD用縦横 | |
#define LCD_ROW 2 | |
#define LCD_COL 16 | |
//音声用コマンド | |
char *voice_se = "./voice_create.sh %s"; | |
//効果音用コマンド | |
char *error_se = "aplay /home/pi/IR_SOUND/error.wav"; | |
char *reload_se = "aplay /home/pi/IR_SOUND/reload.wav"; | |
char *shot_se = "aplay /home/pi/IR_SOUND/gun.wav"; | |
char *start_se = "aplay /home/pi/IR_SOUND/GameStart.wav"; | |
char *end_se = "aplay /home/pi/IR_SOUND/TimeOver.wav"; | |
char *over_se = "aplay /home/pi/IR_SOUND/GameOver.wav"; | |
char *hp10_se = "aplay /home/pi/IR_SOUND/HP10.wav"; | |
char *hp50_se = "aplay /home/pi/IR_SOUND/HP50.wav"; | |
char *start_count = "aplay /home/pi/IR_SOUND/Start_count.wav"; | |
//ゲーム用変数 | |
char bullet_blamk[2]= {0xff,0x00}; | |
int max_hp = 100; | |
int hp; | |
int max_bullet = 7; | |
int bullet; | |
int Damage = 10; | |
//赤外線送信回数用カウンタ | |
int led_count; | |
//ゲーム設定用変数 | |
int start_time_h; | |
int start_time_m; | |
int game_time; | |
int end_time_h; | |
int end_time_m; | |
char team_id[100]; | |
int team_num; | |
//player_id | |
int interval_time; | |
bool frendly_fire_use; | |
int player_status = 0;//0生存中 1死亡 2リスポーン待ち | |
int reborn_time_h; | |
int reborn_time_m; | |
//LCD用変数 | |
int fd = 0; | |
char lcd_hp[3]; | |
int hp_pointer=0; | |
int bullet_pointer=0; | |
int col = LCD_COL - 1; | |
//ゲーム時間外はfalse ゲーム時間中はtrue | |
bool game_flg = false; | |
//赤外線受信用変数 | |
int readable = 1; // 非同期でイベントが発生した場合、コールバックにより0に設定される | |
int interval = 10; // 継続時間判定の間隔(us) | |
int max_wait = 5000;// 最大継続時間(us) | |
//タイマー用変数 | |
time_t timer; | |
struct tm *date;//現在時刻用 | |
struct game_time{ | |
int hour; | |
int min; | |
}; | |
struct game_time Game_Time[2];//ゲームの開始・終了を保存 | |
//赤外線受信データ挿入用配列 | |
char signal_data[7]; | |
//まれに受信してしまう赤外線の空用配列 | |
char signal_kara[] = {"0000000"}; | |
char signal_a[] = {"1110011"}; | |
char signal_b[] = {"1110000"}; | |
char signal_c[] = {"0011000"}; | |
char signal_d[] = {"1101010"}; | |
char signal_mine[] = {"0000000"}; | |
char str[256]; | |
//怖い使い方なきがする | |
char buf[256]; | |
//ゲームの初回起動時用フラグ | |
bool start_flg = true; | |
//プロトタイプ宣言 | |
void reload(); | |
void scant(); | |
void shoot(); | |
void lcd_bullet_set(); | |
void lcd_anime(); | |
void lcd_hp_set(); | |
//赤外線LED消灯 | |
void outl(){ | |
digitalWrite(IR_SEND_PIN, 0); | |
delayMicroseconds(598); | |
} | |
//赤外線LED点滅 38kHzに変調 | |
void outh(){ | |
for (led_count = 0; led_count < 23; led_count++) { | |
digitalWrite(IR_SEND_PIN, 1); | |
delayMicroseconds(13); | |
digitalWrite(IR_SEND_PIN, 0); | |
delayMicroseconds(13); | |
} | |
} | |
//赤外線送信 | |
void startbit(){ | |
outh(); | |
outl(); | |
} | |
/*ーーーーー送信データを四種類 メソッドとして宣言ーーーーー*/ | |
void send_team_a(){ | |
//1110011 | |
outh();outh();outh();outl();outl();outh();outh(); | |
} | |
void send_team_b(){ | |
//1110000 | |
outh();outh();outh();outl();outl();outl();outl(); | |
} | |
void send_team_c(){ | |
//0011000 | |
outl();outl();outh();outh();outl();outl();outl(); | |
} | |
void send_team_d(){ | |
//1101010 | |
outh();outh();outl();outh();outl();outh();outl(); | |
} | |
void send_ir(){ | |
// 1110011(テスト用) | |
outh();outh();outh();outl();outl();outh();outh(); | |
} | |
/*ーーーーーーーーーーーーーーーーーーーーーーーーーーーーー*/ | |
//割り込みをすかすようメソッド | |
void empty(){ | |
return; | |
} | |
//タイマハンドラ(1秒周期) | |
void timer_handler(int signum){ | |
timer = time(NULL); /* 現在時間を取得 */ | |
date = localtime(&timer); /* 現在時間を時間を表す構造体 date に変換 */ | |
if(start_flg == true){ | |
printf("待機中・・・\n"); | |
} | |
//ゲーム開始時刻になったとき | |
if(date->tm_hour == Game_Time[0].hour && date->tm_min == Game_Time[0].min && date->tm_sec < 10 && start_flg == true){ | |
printf("game_start!!\n"); | |
game_flg = true; | |
printf("check\n"); | |
} | |
//ゲーム終了時刻になったとき | |
if(date->tm_hour == Game_Time[1].hour && date->tm_min == Game_Time[1].min && date->tm_sec == 0){ | |
printf("game_end\n"); | |
//system(end_se); | |
exit(0); | |
} | |
//死亡時の最初の割り込みでリスポーンタイムの設定 | |
if(player_status == 1){ | |
player_status = 2;//リスポーン待機に変更 | |
reborn_time_m = date->tm_min + interval_time; | |
if(reborn_time_m >= 60){ | |
reborn_time_h = date->tm_hour + 1; | |
reborn_time_m -= 60; | |
}else{ | |
reborn_time_h = date->tm_hour; | |
} | |
printf("リボーンタイムは%d時%d分に設定されました\n",reborn_time_h,reborn_time_m); | |
} | |
//リボーン待機中かつリボーン予定時刻になったときに復活処理 | |
if(date->tm_hour == reborn_time_h && date->tm_min == reborn_time_m && player_status == 2){ | |
player_status = 0;//リボーン | |
hp = max_hp; | |
printf("リボーン完了です。戦場に帰還してください\n"); | |
} | |
} | |
void game_interval(){ | |
printf("HPが0になりました\n自陣に一時帰還してください\n"); | |
printf("インターバルタイム:%d分です\n",interval_time); | |
player_status = 1;//死亡状態に変更 | |
} | |
void damage_hp() { | |
hp -= Damage; | |
//hpの残量を通知 | |
if(hp == max_hp/2){ | |
//system(hp50_se); | |
}else if(hp == max_hp/10){ | |
//system(hp10_se); | |
} | |
//HPが0になったとき | |
if(hp == 0 && player_status == 0){ | |
//HP0になった時に自陣に戻ることを想定 | |
game_interval(); | |
} | |
} | |
//赤外線受信時のイベント | |
void signalCallBackHandler(int sig){ | |
readable = 0; | |
} | |
void scant(){ | |
//イベントをすかすようメソッドに変更 | |
wiringPiISR(RELOAD_PIN,INT_EDGE_BOTH,&empty); | |
wiringPiISR(SHOOT_PIN,INT_EDGE_BOTH,&empty); | |
//受信まで待機させる | |
//while( readable && digitalRead(IR_READ_PIN) ){} | |
int i; | |
//最初のスタートビット分待機してすかす | |
delayMicroseconds(598*3); | |
//598usごとに赤外線受信用ピンの値を取得して配列に順次格納する(7ビット分) | |
for (i = 0; i < 7; i++ ) { | |
if ( digitalRead(IR_READ_PIN) == 0 ){ | |
signal_data[i] = '1'; | |
delayMicroseconds(598); | |
} else { | |
signal_data[i] = '0'; | |
delayMicroseconds(598); | |
} | |
} | |
//時折混ざる赤外線はスルーさせる | |
if(strcmp(signal_data,signal_kara) == 0){ | |
return; | |
} | |
//受信したデータの表示 | |
printf("%s\n",signal_data ); | |
// //フレンドリファイアが有効であれば、受信内容を確認せずにダメージ処理に移行 | |
// if(frendly_fire_use){ | |
// damage_hp(); | |
// }else{ | |
// //受信したデータが自分のチームを表すものだったら | |
// if(strcmp(signal_data,signal_mine) == 0){ | |
// printf("味方に撃たれました\n"); | |
// }else{ | |
// damage_hp(); | |
// } | |
// } | |
//イベント設定見直し | |
wiringPiISR(RELOAD_PIN,INT_EDGE_RISING,&reload); | |
wiringPiISR(SHOOT_PIN,INT_EDGE_RISING,&shoot); | |
return; | |
} | |
void shoot(void){ | |
//HP0の場合return | |
if(hp == 0){return;} | |
//イベントをすかすようイベント変更 | |
wiringPiISR(RELOAD_PIN,INT_EDGE_BOTH,&empty); | |
wiringPiISR(IR_READ_PIN,INT_EDGE_BOTH,&empty); | |
//残弾アリ | |
if(bullet > 0){ | |
printf("Fire!!!\t残弾数%d\n",--bullet); | |
bullet_pointer = bullet+8; | |
lcdPosition(fd,bullet_pointer,1); | |
lcdPuts(fd," "); | |
//赤外線送信 | |
startbit(); | |
if(strcmp(team_id,"チームA") == 0){ | |
send_team_a(); | |
}else if(strcmp(team_id,"チームB") == 0){ | |
send_team_b(); | |
}else if(strcmp(team_id,"チームC") == 0){ | |
send_team_c(); | |
}else if(strcmp(team_id,"チームD") == 0){ | |
send_team_d(); | |
} | |
send_ir(); | |
//system(shot_se); | |
usleep(30000); | |
//残弾ナシ | |
}else{ | |
printf("NeedReload!!\n"); | |
//system(error_se); | |
usleep(30000); | |
} | |
//チャタリング対策 | |
usleep(30000); | |
//イベントの設定しなおし | |
wiringPiISR(RELOAD_PIN,INT_EDGE_BOTH,&reload); | |
wiringPiISR(IR_READ_PIN,INT_EDGE_FALLING,&scant); | |
} | |
void reload(void){ | |
//イベントをすかすようイベント変更 | |
wiringPiISR(IR_READ_PIN,INT_EDGE_BOTH,&empty); | |
wiringPiISR(SHOOT_PIN,INT_EDGE_BOTH,&empty); | |
//HP0の場合return | |
if(hp == 0){return;} | |
//残弾数によって処理変更 | |
if(bullet < 7){ | |
printf("Reload Start\n"); | |
bullet = 0; | |
lcd_bullet_set(); | |
lcd_anime(); | |
bullet = 7; | |
printf("Reload Finish\n"); | |
//system(reload_se); | |
//残弾数MAXの場合リロードなし | |
}else{ | |
printf("No Reload Require\n"); | |
} | |
usleep(30000); | |
//イベント設定しなおし | |
wiringPiISR(IR_READ_PIN,INT_EDGE_FALLING,&scant); | |
wiringPiISR(SHOOT_PIN,INT_EDGE_BOTH,&shoot); | |
} | |
//LCD周り処理 | |
void lcd_hp_set(){ | |
lcdPosition(fd,0,0); | |
lcdPuts(fd,"HP "); | |
lcdPosition(fd,3,0); | |
sprintf(lcd_hp,"%d",max_hp); | |
lcdPuts(fd,lcd_hp); | |
lcdPosition(fd,6,0); | |
lcdPuts(fd,"/"); | |
lcdPosition(fd,7,0); | |
lcdPuts(fd,lcd_hp); | |
} | |
void lcd_bullet_set(){ | |
lcdPosition(fd,0,1); | |
lcdPuts(fd,"BULLET [ ]"); | |
} | |
void lcd_anime(){ | |
int col = LCD_COL; | |
int i=0; | |
col -= 1; | |
for(i = 8;i < col ; i++){ | |
lcdPosition(fd,i,1); | |
lcdPuts(fd,bullet_blamk); | |
} | |
} | |
//ゲーム設定用ファイルの読み込み処理 | |
int csv_set(){ | |
FILE *game_fp; | |
char *game_fname = "game_setting.csv"; | |
game_fp = fopen( game_fname, "r" ); | |
if( game_fp == NULL ){ | |
printf( "%sファイルが開けません¥n", game_fname ); | |
return -1; | |
} | |
fscanf( game_fp, "%d,%d,%[^,],%d", &start_time_h, &start_time_m, team_id, &game_time ); | |
//汚い時間の加算 tm構造体複数を使えればと模索中・・・ | |
end_time_m = start_time_m + game_time; | |
if(end_time_m >= 60){ | |
end_time_h = start_time_h + 1; | |
if(end_time_h == 24){ | |
end_time_h = 0; | |
} | |
end_time_m -= 60; | |
}else{ | |
end_time_h = start_time_h; | |
} | |
//死亡時のインターバルタイム(分)の設定 | |
interval_time = 3; | |
//フレンドリファイアの有効(true:味方に被弾あり false:味方に被弾なし) | |
frendly_fire_use = true; | |
//現在時刻の取得 | |
timer = time(NULL); | |
//構造体tmのdateポインタへ挿入 | |
date = localtime(&timer); | |
// //Game_Time[0] ゲーム開始時刻の設定 | |
// Game_Time[0].hour = start_time_h; | |
// Game_Time[0].min = start_time_m; | |
// //Game_Time[1] ゲーム修了時刻の設定 | |
// Game_Time[1].hour = end_time_h; | |
// Game_Time[1].min = end_time_m; | |
// テスト環境として使用 | |
Game_Time[0].hour = date->tm_hour; | |
Game_Time[0].min = date->tm_min + 1; | |
Game_Time[1].hour = date->tm_hour; | |
Game_Time[1].min = date->tm_min + 3; | |
sprintf(buf,"./voice_create.sh ゲーム開始時刻は%d時%d分です",Game_Time[0].hour,Game_Time[0].min); | |
//system(buf); | |
sleep(1); | |
sprintf(buf,"./voice_create.sh ゲーム終了時刻は%d時%d分です",Game_Time[1].hour,Game_Time[1].min); | |
//system(buf); | |
sleep(1); | |
/*テスト用に表示*/ | |
printf("ゲーム開始時刻は%d時%d分です\n",Game_Time[0].hour,Game_Time[0].min); | |
printf("インターバルタイム:%d分\n",interval_time); | |
printf("所属チーム:%s\n",team_id ); | |
return 0; | |
} | |
int main(void){ | |
hp = max_hp; | |
bullet = max_bullet; | |
int setup = 0; | |
// wiringpiのセットアップ | |
if(wiringPiSetup() == -1){ | |
printf("wiringPiのセットアップができませんでした\n"); | |
exit(1); | |
} | |
//ゲーム用制限時間などの読み込み | |
if(csv_set() == -1){ | |
printf("game_setting.csvが読み込めませんでした\n"); | |
exit(1); | |
} | |
//lcd周りの初期設定 | |
fd = lcdInit(2,16,4,4,5,0,1,2,3,0,0,0,0); | |
lcdClear(fd); | |
lcd_hp_set(); | |
lcd_bullet_set(); | |
lcd_anime(); | |
if(setup != -1){ | |
//タイマー設定 | |
int i; | |
struct sigaction act, oldact; | |
timer_t tid; | |
struct itimerspec itval; | |
memset(&act, 0, sizeof(struct sigaction)); | |
memset(&oldact, 0, sizeof(struct sigaction)); | |
// シグナルハンドラの登録 | |
act.sa_handler = timer_handler; | |
act.sa_flags = SA_RESTART; | |
if(sigaction(SIGALRM, &act, &oldact) < 0) { | |
perror("sigaction()"); | |
return -1; | |
} | |
// タイマ割り込みを発生させる | |
itval.it_value.tv_sec = 1; // 最初の1回目は1秒後 | |
itval.it_value.tv_nsec = 0; | |
itval.it_interval.tv_sec = 2; // 2回目以降は1秒間隔 | |
itval.it_interval.tv_nsec = 0; | |
// タイマの作成 | |
if(timer_create(CLOCK_REALTIME, NULL, &tid) < 0) { | |
perror("timer_create"); | |
return -1; | |
} | |
// タイマのセット | |
if(timer_settime(tid, 0, &itval, NULL) < 0) { | |
perror("timer_settime"); | |
return -1; | |
} | |
printf("ゲーム開始待機\n"); | |
//ゲーム開始までここで無限ループ | |
while(!game_flg){} | |
start_flg = false; | |
//各種イベントの設定 | |
wiringPiISR(SHOOT_PIN,INT_EDGE_RISING,&shoot); //ショットボタン | |
wiringPiISR(RELOAD_PIN,INT_EDGE_RISING,&reload); //リロードボタン | |
wiringPiISR(IR_READ_PIN,INT_EDGE_FALLING,&scant); //赤外線受信イベント | |
pinMode(IR_READ_PIN, INPUT); //赤外線受信ピンの設定 | |
pinMode(IR_SEND_PIN, OUTPUT); //赤外線送信ピンの設定 | |
printf("PINイベント設定完了\n"); | |
//system(start_se); | |
//ゲーム終了までここで無限ループ | |
while(game_flg){} | |
return 0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment