Skip to content

Instantly share code, notes, and snippets.

@Yomogiii
Created February 4, 2017 10:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Yomogiii/82ae7cfd0be01f5b05ef902dbc8f57e6 to your computer and use it in GitHub Desktop.
Save Yomogiii/82ae7cfd0be01f5b05ef902dbc8f57e6 to your computer and use it in GitHub Desktop.
#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