⛸️

MATLAB+yoloで落下物回避ゲーム2

MATLAB

5 人以外のラベルを認識し、特定の物体と図形が当たっていれば音を鳴らして図形の位置を画像の端に戻し、点数を加算しよう。
6 オリジナル要素を追加し、より面白いゲームを作ろう。ただしYoloを使い、キーボードかマウス入力も使うこと
2つの課題を満たしているプログラムファイルを提出します。

game56.m

load train.mat detector = yolov3ObjectDetector('tiny-yolov3-coco'); cap = webcam; hf = figure; %落下物を無限に作れるようにした Objects = [ randi([0, 100], 1), randi([0, 100], 1), randi([0, 50], 1), randi([0, 50], 1); randi([0, 100], 1), randi([0, 100], 1), randi([0, 50], 1), randi([0, 50], 1); randi([0, 100], 1), randi([0, 100], 1), randi([0, 50], 1), randi([0, 50], 1); randi([0, 100], 1), randi([0, 100], 1), randi([0, 50], 1), randi([0, 50], 1); randi([0, 100], 1), randi([0, 100], 1), randi([0, 50], 1), randi([0, 50], 1); randi([0, 100], 1), randi([0, 100], 1), randi([0, 50], 1), randi([0, 50], 1); ]; sound_flag_prev = false; %連続で音が鳴らないようにした sound_flag_prev2 = false; %連続で音が鳴らないようにした hitPoint = 500; while strcmp(get(hf, 'currentcharacter'), 'q') ~= true && hitPoint > 0 % qを打つかHitPointが0になるとGAMEOVER image = cap.snapshot(); image = preprocess(detector, image); image = im2single(image); [bboxes, scores, labels] = detect(detector, image, 'DetectionPreprocessing', 'none'); detectedImg = insertObjectAnnotation(image, 'Rectangle', bboxes, labels); detectedImg = insertShape(detectedImg, 'Rectangle', Objects, 'LineWidth', 5); detectedImg = insertText(detectedImg, [0, 0], int2str(hitPoint)); imshow(detectedImg); for i = 1:size(labels) if (labels(i) == 'person') %personラベルがあるときは物体との接触判定をする PersonX_min = bboxes(i, 1); PersonY_min = bboxes(i, 2); PersonX_max = bboxes(i, 1) + bboxes(i, 3); PersonY_max = bboxes(i, 2) + bboxes(i, 4); p = [PersonX_min, PersonY_min, PersonX_max, PersonY_max]; for j = 1:numel(Objects) / 4 ObjX_min = Objects(j, 1); ObjY_min = Objects(j, 2); ObjX_max = ObjX_min + Objects(j, 3); ObjY_max = ObjY_min + Objects(j, 4); b = [ObjX_min, ObjY_min, ObjX_max, ObjY_max]; if (checkHit(p, b)) %自作の衝突確認関数 if (sound_flag_prev == false) %連続で音が鳴らないようにした sound(y, 20000, 8) hitPoint = hitPoint - 10; %ポイント end sound_flag_prev = true; %連続で音が鳴らないようにした fprintf("Hit!! \n"); else fprintf("noting \n"); sound_flag_prev = false; %連続で音が鳴らないようにした end end end if (labels(i) == 'cell phone') %cell phoneラベルがあるときは物体との接触判定をする(携帯電話) PhoneX_min = bboxes(i, 1); PhoneY_min = bboxes(i, 2); PhoneX_max = bboxes(i, 1) + bboxes(i, 3); PhoneY_max = bboxes(i, 2) + bboxes(i, 4); p = [PhoneX_min, PhoneY_min, PhoneX_max, PhoneY_max]; for j = 1:numel(Objects) / 4 ObjX_min = Objects(j, 1); ObjY_min = Objects(j, 2); ObjX_max = ObjX_min + Objects(j, 3); ObjY_max = ObjY_min + Objects(j, 4); b = [ObjX_min, ObjY_min, ObjX_max, ObjY_max]; if (checkHit(p, b)) %自作の衝突確認関数 Objects(j, 1) = 0; Objects(j, 2) = 0; %人以外に当たると落下物が上に上がるやつ if (sound_flag_prev2 == false) %連続で音が鳴らないようにした sound(y, 20000, 8) hitPoint = hitPoint + 100; %ポイント追加!ボーナス! %スマホをかざすと最強になれます! end sound_flag_prev2 = true; %連続で音が鳴らないようにした fprintf("Hit!! \n"); else fprintf("noting \n"); sound_flag_prev2 = false; %連続で音が鳴らないようにした end end end end for i = 1:numel(Objects) / 4 %複数の落下物に対応 if (strcmp(get(hf, 'currentcharacter'), 's')) Objects(i, 2) = Objects(i, 2) + 10%sをおすとめっちゃ早く落ちてくる else Objects(i, 2) = Objects(i, 2) + 3 * i; %iを使ってそれぞれの落下速度が違うようにした end end for i = 1:numel(Objects) / 4 % 複数の落下物に対応 if (Objects(i, 2) > 400) Objects(i, 1) = randi([0, 360], 1); Objects(i, 2) = 0; Objects(i, 3) = randi([0, 50], 1); Objects(i, 4) = randi([0, 50], 1); end end end close(hf); fprintf("GAME OVER!!\n");

checkHit.m

function hit = checkHit(p, b) ObjX_min = b(1); ObjY_min = b(2); ObjX_max = b(3); ObjY_max = b(4); PersonX_min = p(1); PersonY_min = p(2); PersonX_max = p(3); PersonY_max = p(4); stateA_X = (ObjX_min <= PersonX_min && PersonX_min <= ObjX_max); stateB_X = (ObjX_min <= PersonX_max && PersonX_max <= ObjX_max); stateC_X = (PersonX_min <= ObjX_min && ObjX_min <= PersonX_max && PersonX_min <= ObjX_max && ObjX_max <= PersonX_max); stateA_Y = (ObjY_min <= PersonY_min && PersonY_min <= ObjY_max); stateB_Y = (ObjY_min <= PersonY_max && PersonY_max <= ObjY_max); stateC_Y = (PersonY_min <= ObjY_min && ObjY_min <= PersonY_max && PersonY_min <= ObjY_max && ObjY_max <= PersonY_max); if (stateA_X || stateB_X || stateC_X) %fprintf("X IN \t"); x_in = true; else %fprintf("X OUT \t"); x_in = false; end if (stateA_Y || stateB_Y || stateC_Y) %fprintf("Y IN \t"); y_in = true; else %fprintf("Y OUT \t"); y_in = false; end if (x_in && y_in) hit = true; else hit = false; end end

工夫したところ

  • 落下物の数を増やしたかったので、落下物接触判定の関数を作った。
  • 落下物の速度がバラバラになるようにした
  • スマートフォンを認識させて物体にぶつけるとHPが100回復する
  • 行列を使って落下ぶつを追加しやすくした(Objects)
  • forを使って複数の物体に対するアクションを効率化してみた
  • ベクトルを引数で渡した(checkHit.m)
notion image
 
notion image