Created
February 4, 2017 10:33
-
-
Save Yomogiii/82ae7cfd0be01f5b05ef902dbc8f57e6 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 21 | |
#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; | |
//タイマー用変数 | |
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; | |
//割り込み処理管理用フラグ | |
bool interval_flg = false; | |
bool damage_flg = false; | |
bool ir_scan_flg = false; | |
bool shoot_flg = false; | |
bool reload_flg = false; | |
//プロトタイプ宣言 | |
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(); | |
} | |
/*ーーーーーーーーーーーーーーーーーーーーーーーーーーーーー*/ | |
//タイマハンドラ(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 && start_flg == true){ | |
start_flg = false; | |
game_flg = true; | |
return; | |
} | |
//ゲーム終了時刻になったとき | |
if(date->tm_hour == Game_Time[1].hour && date->tm_min == Game_Time[1].min && game_flg == true){ | |
game_flg = false; | |
return; | |
} | |
//リボーン待機中かつリボーン予定時刻になったときに復活処理 | |
if(date->tm_hour == reborn_time_h && date->tm_min == reborn_time_m && player_status == 2){ | |
interval_flg = false; | |
return; | |
} | |
} | |
void scant(void){ | |
ir_scan_flg = true; | |
} | |
void shoot(void){ | |
shoot_flg = true; | |
} | |
void reload(void){ | |
reload_flg = true; | |
} | |
//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; | |
end_time_m -=60; | |
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; | |
/*テスト用に表示*/ | |
printf("ゲーム開始時刻は%d時%d分です\n",Game_Time[0].hour,Game_Time[0].min); | |
sprintf(buf,"./voice_create.sh ゲーム開始時刻は%d時%d分です",Game_Time[0].hour,Game_Time[0].min); | |
system(buf); | |
sleep(1); | |
printf("インターバルタイム:%d分\n",interval_time); | |
printf("所属チーム:%s\n",team_id ); | |
printf("ゲーム終了時刻は%d時%d分です\n",Game_Time[1].hour,Game_Time[1].min); | |
sprintf(buf,"./voice_create.sh ゲーム終了時刻は%d時%d分です",Game_Time[1].hour,Game_Time[1].min); | |
system(buf); | |
sleep(1); | |
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 = 1; // 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("game_standby\n"); | |
//ゲーム開始までここで無限ループ | |
while(!game_flg){} | |
printf("game_start!!\n"); | |
//各種イベントの設定 | |
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){ | |
if(shoot_flg == true && hp != 0){ | |
//残弾アリ | |
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); | |
shoot_flg = false; | |
} | |
if(reload_flg == true && hp != 0){ | |
//残弾数によって処理変更 | |
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(60000); | |
reload_flg = false; | |
} | |
if(ir_scan_flg == true){ | |
int scan_count; | |
//最初のスタートビット分待機してすかす | |
delayMicroseconds(598*3); | |
//598usごとに赤外線受信用ピンの値を取得して配列に順次格納する(7ビット分) | |
for (scan_count = 0; scan_count < 7; scan_count++ ) { | |
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(); | |
// } | |
// } | |
ir_scan_flg = false; | |
} | |
if(damage_flg == true){ | |
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){ | |
interval_flg = true; | |
} | |
damage_flg = false; | |
} | |
if(interval_flg == true){ | |
printf("HPが0になりました\n自陣に一時帰還してください\n"); | |
printf("インターバルタイム:%d分です\n",interval_time); | |
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); | |
while(interval_flg){ | |
} | |
player_status = 0;//リボーン | |
hp = max_hp; | |
printf("リボーン完了です。戦場に帰還してください\n"); | |
} | |
} | |
//system(end_se); | |
printf("ゲーム終了\n"); | |
// タイマの解除 | |
timer_delete(tid); | |
// シグナルハンドラの解除 | |
sigaction(SIGALRM, &oldact, NULL); | |
//ゲーム終了後のループ | |
while(!game_flg){} | |
return 0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment