28
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MATLAB プログラムを書いて、見事なコンボを決めよう。

Posted at

金曜日の午後はやる気が出ない。

 前もこんな出だしで書いたな。。。

 みんな在宅勤務だし、オフィスに誰もいないし、緊張感がないからであろうか。。ということで、プログラムを書くモチベーションを上げるための環境を作ってみよう。

e-sports みたいなプログラミング環境を目指そう!

 e-sports って、プレイヤーと操作画面が絶妙に配置されてて、操作してる人と内容が一気に見えるのがいい感じですよね。
というのを「プログラムを書く」という行為にも採用してみましょう!

ストリーム映像に文字を書こう。

 ライブ映像にプログラムがスムーズに書ければ第一歩かな。Image Acquisition Toolbox と Computer Vision Toolbox と Image Processing Toolbox があれば簡単ですね。

function TextOnVideo

a = imaqfind;
if ~isempty(a)
    delete(a)
end

vid = videoinput('winvideo', 1, 'RGB24_1280x720');
vid.TriggerRepeat = Inf;

nBands = get(vid, 'NumberOfBands');
res = get(vid, 'Videoresolution');
start(vid);

F = figure(31415926);
F.CloseRequestFcn = @ReleaseFun;

prepstream = imshow(zeros([res(2) res(1) nBands] ));
hold on

stream = getdata(vid,1);
mask = false(size(stream));

str = 'function o = tameshi(de,su)';
while (ishandle(F) && islogging(vid))
    stream = getdata(vid,1);
    stream = insertText(stream,[550,100],str,'FontSize',30,'Font','Meiryo');
    
    stream(mask) = 0;
    set(prepstream, 'Cdata', stream);
    flushdata(vid);
    drawnow;
end

    function ReleaseFun(~,~)
        delete(vid)
        delete(F)
    end
end

パソコンに内蔵の内向きカメラを使ってこんな感じ。

Combo1.jpg

プログラムを書く人とプログラムが表示されればいいね。
(後ろは誰もいないオフィス。)

Qiita は動画を載せるのが大変なので、頭の中でサクサク動いてると思ってくださいね。

キーボード経由でプログラムを書けるようにしよう。

 上のままだと決められた内容を表示するだけなので、キータッチでプログラムを書けるようにしましょう。KeyPressFcn を使おう。

function TextOnVideo

a = imaqfind;
if ~isempty(a)
    delete(a)
end

vid = videoinput('winvideo', 1, 'RGB24_1280x720');
vid.TriggerRepeat = Inf;

nBands = get(vid, 'NumberOfBands');
res = get(vid, 'Videoresolution');
start(vid);

F = figure(31415926);
F.CloseRequestFcn = @ReleaseFun;
F.KeyPressFcn = @KeyFun;

prepstream = imshow(zeros([res(2) res(1) nBands] ));
hold on

stream = getdata(vid,1);
mask = false(size(stream));

str = 'function o = tameshi(de,su)';
while (ishandle(F) && islogging(vid))
    stream = getdata(vid,1);
    stream = insertText(stream,[550,100],str,'FontSize',30,'Font','Meiryo');
    
    stream(mask) = 0;
    set(prepstream, 'Cdata', stream);
    flushdata(vid);
    drawnow;
end

    function KeyFun(~,ev)
        if strcmp(ev.Key,'backspace')
            if ~isempty(str)
                str(end) = [];
            end
        elseif strcmp(ev.Key,'return')
            str = [str,newline];
        else
            str = [str,ev.Character];
        end
    end

    function ReleaseFun(~,~)
        delete(vid)
        delete(F)
    end
end

こんな感じ。

Combo2.jpg

書いたり消したりできております!
(心のなかでスイスイ動いていると思って見ましょう。)

コンボを決めて爽快感を出してみよう!

 プログラムが一気に書けると爽快!ということで、連続でキーを叩いたらコンボ表示が出るようにしたらいいかな。コンボ用に適当な絵があるといいので、あのオレンジの丘みたいな絵をたくさん用意しておこう。

 あのオレンジの丘↓↓

logo01.png

(これは動いておりません。)

コンボの前準備で画像を用意する。

 とりあえず12枚を自動生成して、現在のフォルダに logo01.png, logo02.png みたいな名前で保存するスクリプトです。

for nn = 1:12
L = 20*membrane(nn,25);

logoFig = figure('Color',[0 0 0]);
logoFig.Position = [100 100 200 120];
logoax = axes('CameraPosition', [-193.4013 -265.1546  220.4819],...
    'CameraTarget',[26 26 10], ...
    'CameraUpVector',[0 0 1], ...
    'CameraViewAngle',9.5, ...
    'DataAspectRatio', [1 1 .9],...
    'Position',[0 0 1 1], ...
    'Visible','off', ...
    'XLim',[1 51], ...
    'YLim',[1 51], ...
    'ZLim',[-13 40], ...
    'parent',logoFig);
s = surface(L, ...
    'EdgeColor','none', ...
    'FaceColor',[0.9 0.2 0.2], ...
    'FaceLighting','phong', ...
    'AmbientStrength',0.3, ...
    'DiffuseStrength',0.6, ... 
    'Clipping','off',...
    'BackFaceLighting','lit', ...
    'SpecularStrength',1, ...
    'SpecularColorReflectance',1, ...
    'SpecularExponent',7, ...
    'Tag','TheMathWorksLogo', ...
    'parent',logoax);
l1 = light('Position',[40 100 20], ...
    'Style','local', ...
    'Color',[0 0.8 0.8], ...
    'parent',logoax);
l2 = light('Position',[.5 -1 .4], ...
    'Color',[0.8 0.8 0], ...
    'parent',logoax);

z = zoom(logoFig);
z.setAxes3DPanAndZoomStyle(logoax,'camera');
print('-dpng',['logo',num2str(nn,'%02d'),'.png'])
end
close all

現在のフォルダにこんなファイルが12個できてますね。

logo04.png

コンボ数に応じて画像を表示する。

 Computer Vision Toolbox の AlphaBlender を使おう。

function ComboSystem

a = imaqfind;
if ~isempty(a)
    delete(a)
end

vid = videoinput('winvideo', 1, 'RGB24_1280x720');
vid.TriggerRepeat = Inf;
AB = vision.AlphaBlender;
AB.Operation = 'Binary mask';
AB.MaskSource = 'Input port';

nBands = get(vid, 'NumberOfBands');
res = get(vid, 'Videoresolution');
start(vid);

F = figure(31415926);
F.CloseRequestFcn = @ReleaseFun;
F.KeyPressFcn = @KeyFun;

prepstream = imshow(zeros([res(2) res(1) nBands] ));
hold on

[X,BW] = logomaker(12);
stream = getdata(vid,1);
mask = false(size(stream));

str = '';
Combo = 0;
while (ishandle(F) && islogging(vid))
    stream = getdata(vid,1);
    if Combo > 0
        n = mod(Combo,12) + 1;
        stream = AB(stream,X{n},BW{n});
        stream = insertText(stream,[75,200],[num2str(Combo),' Combo!'],'FontSize',30);
    end
    stream = insertText(stream,[550,100],str,'FontSize',30,'Font','Meiryo');
    
    stream(mask) = 0;
    set(prepstream, 'Cdata', stream);
    flushdata(vid);
    drawnow;
end

    function [X,BW] = logomaker(n)
        for m = 1:n
            X{m} = imread(['logo',num2str(m,'%02d'),'.png']);
            G = rgb2gray(X{m});
            BW{m} = G < 220;
        end
    end

    function KeyFun(~,ev)
        if strcmp(ev.Key,'backspace')
            if ~isempty(str)
                str(end) = [];
            end
        elseif strcmp(ev.Key,'return')
            str = [str,newline];
        else
            str = [str,ev.Character];
            Combo = Combo + 1;
        end
    end

    function ReleaseFun(~,~)
        delete(vid)
        delete(F)
    end
end

 タイピングするたびに、左上にコンボ数が出るようになってればいいね。

Combo3.jpg

 いい感じになりました!

間違うとダメージを受ける。

 コンボだけだと適当にキーボードを連打して3000コンボとかなっちゃうので、体力メーターでも置いておいてバックスペースでダメージを受けるようにして、間違いすぎると死ぬ(=書いたプログラムが全部消える)ようにしよう。

 とりあえず体力は 640 からスタート(ピクセル数)で、20 ピクセルずつ減ります。

function MatKen

a = imaqfind;
if ~isempty(a)
    delete(a)
end

vid = videoinput('winvideo', 1, 'RGB24_1280x720');
vid.TriggerRepeat = Inf;
AB = vision.AlphaBlender;
AB.Operation = 'Binary mask';
AB.MaskSource = 'Input port';

nBands = get(vid, 'NumberOfBands');
res = get(vid, 'Videoresolution');
start(vid);

F = figure(20200527);
F.CloseRequestFcn = @ReleaseFun;
F.KeyPressFcn = @KeyFun;

prepstream = imshow(zeros([res(2) res(1) nBands] ));
hold on

[X,BW] = logomaker(12);
stream = getdata(vid,1);
mask = false(size(stream));

str = '';
Combo = 0;
HP = 640;
while (ishandle(F) && islogging(vid))
    stream = getdata(vid,1);
    if Combo > 0
        n = mod(Combo,12) + 1;
        stream = AB(stream,X{n},BW{n});
        stream = insertText(stream,[75,200],[num2str(Combo),' Combo!'],'FontSize',30);
    end
    stream = insertText(stream,[550,100],str,'FontSize',30,'Font','Meiryo');
    stream = insertShape(stream,'rectangle',[300 20 650 40],'LineWidth',8,'Color','w');
    stream = insertShape(stream,'FilledRectangle',[305 25 HP 30],'LineWidth',8,'Color','g');
    
    
    stream(mask) = 0;
    set(prepstream, 'Cdata', stream);
    flushdata(vid);
    drawnow;
    
    if HP < 0
        stream = insertText(stream,[160,200],'GAME OVER','FontSize',144,'Font','Meiryo','BoxOpacity',0,'TextColor','w');
        set(prepstream, 'Cdata', stream);
        flushdata(vid);
        drawnow;
        break
    end
end

    function [X,BW] = logomaker(n)
        for m = 1:n
            X{m} = imread(['logo',num2str(m,'%02d'),'.png']);
            G = rgb2gray(X{m});
            BW{m} = G < 220;
        end
    end

    function KeyFun(~,ev)
        if strcmp(ev.Key,'backspace')
            if ~isempty(str)
                str(end) = [];
                Combo = 0;
                HP = HP - 20;
                if ~mask(1,1,2)
                    mask(:,:,2) = true;
                    mask(:,:,3) = true;
                end
                
            end
        elseif strcmp(ev.Key,'return')
            str = [str,newline];
        else
            str = [str,ev.Character];
            if ~strcmp(ev.Key,'space')
                Combo = Combo + 1;
            end
            
            if mask(1,1,2)
                mask(:,:,2) = false;
                mask(:,:,3) = false;
            end
        end
    end

    function ReleaseFun(~,~)
        delete(vid)
        delete(F)
    end
end

 間違ったときに危険な色になる。上にある四角は体力メーター。

Combo4.jpg

 体力が 0 未満になったら今まで書いたプログラムは全部消えます。緊張感!

Combo5.jpg

楽しいので、プログラミングコンテストに使おうかな。

 とりあえず GIF にしてみました。見えるかな。

ComboMov.gif

 (色数を落としすぎて顔色が悪い・・・)

 もうちょっと改良すればコンテンストなんかでも使えますね!
 こういうコンテスト環境とかに興味があれば、「いいね!」 **「LGTM」**しておいてね!

28
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?