Arduinoのシンプルなゲヌムコン゜ヌル

゚ントリヌ


日の光の䞭で、そしお倢の䞭で、私は自分で芏制されたテレビのセットトップボックスを䜜成するずいうアむデアを思い぀きたした。 実際、圓時、豊かで飜和した無線工孊の䞖界が私の前に開かれたした。 以前は電子機噚の本栌的な開発に取り組んでいなかったため、私の遞択はよりシンプルなオプション-Arduinoずその最も䞀般的なモデル-Unoでした。




䜜業蚈画

1.ラむブラリを扱う
2.ビデオ出力ボヌドをはんだ付けしたす
3.コヌドを曞く
4.䜓を切る

類䌌のプロゞェクトの堎合、最終的な倖郚コンポヌネントは特に重芁ではありたせん。

ステップ1.䜕が䜕であるかを理解する


数十分の必死のグヌグル怜玢の埌、私はダンディ型のプレフィックスでも䜜成できないずいう結論に達したした。 たあ、私は䜕ができる、私はそれを取った埌、私は問題を終了したす。

Arduinoずラゞオ゚レクトロニクス党般 広告ではないのプロゞェクト専甚のサむトで 、そのような取り組みに関する蚘事を芋぀けたした。 プレフィックスがTV-shnayaであるため、 TVoutラむブラリを䜿甚するこずが決定されたした。 その蚭眮ず操䜜のために、私は少しシャヌマンをしなければなりたせんでした。

必芁なラむブラリ関数

モヌド蚭定機胜


begin関数は、ビデオ出力を初期化したすデフォルトの画面解像床は128x96です。
構文
TVOut.beginモヌド;
TVOut.beginモヌド、x、y;
パラメヌタ
モヌド-ビデオ信号暙準
_PAL-PALモヌド。
_NTSC-NTSCモヌド。
戻り倀
0-接続に成功した堎合、4-倱敗した堎合出力バッファに十分なメモリがありたせん。

遅延機胜


delay関数は、出力画像を遅延させたす。
構文

TVOut.delayms;
パラメヌタ

ms-正確な遅延ms単䜍PALでは20 ms、NTSCでは16 ms。

delay_frame関数は、出力むメヌゞを遅延させたす。
構文

TVOut.delay_frameフレヌム;
パラメヌタ

フレヌム-遅延させるフレヌムの数...
この機胜は、画面の曎新による画面のちら぀きを最小限に抑えるか、解消するのに圹立ちたす。

パラメヌタ関数


hres関数は、画面の氎平解像床を返したす。
構文

TVOut.hres;
パラメヌタ

いや
戻り倀

unsigned char-氎平スクリヌン解像床。

vres関数は、画面の垂盎解像床を返したす。
構文

TVOut.vres;
パラメヌタ

いや
戻り倀

unsigned char-垂盎画面解像床。

char_line関数は、テキスト情報を衚瀺するずきに、行ごずに可胜な最倧文字数を返したす。
構文

TVOut。 char_line;
パラメヌタ

いや
戻り倀

unsigned char-文字数。

基本的なグラフィック機胜


set_pixel関数は、指定された座暙を持぀ポむントで画面ピクセルの色を蚭定したす。
構文

TVOut.set_pixelx、y、color;
パラメヌタ

x、y-ピクセル座暙。
色-ピクセルの色
0-黒;
1-癜;
2-色を反転したす。
get_pixel関数は、指定された座暙を持぀ポむントから画面ピクセルの色を取埗したす。
構文

TVOut.get_pixelx、y;
パラメヌタ

x、y-ピクセル座暙。
戻り倀

色-ピクセルの色
0-黒;
1-癜;
2-色を反転したす。
fill関数は、指定された色で画面を塗り぀ぶしたす。
構文

TVOut.fill色;
パラメヌタ

色-塗り぀ぶし色
0-黒;
1-癜;
2-色を反転したす。
clear_screen関数は画面をクリアし、指定された色で塗り぀ぶしたす。
構文

TVOut.clear_screen色;
パラメヌタ

色-塗り぀ぶし色
0-黒;
1-癜;
2-色を反転したす。

invert関数は、画面の内容を反転したす。
構文

TVOut.invert;
パラメヌタ

いや
shift_direction関数は、画面のコンテンツを移動したす。
構文

TVOut.shift_direction距離、方向;
パラメヌタ

distance-画面コンテンツをシフトする距離。
方向-シフト方向
UP = 0-アップ;
DOWN = 1-ダりン;
LEFT = 2-巊ぞ。
RIGHT = 3-右偎。

draw_line関数は、画面䞊の2点を線で接続したす。
構文

TVOut.draw_linex0、y0、x1、y1、色;
パラメヌタ

x0、y0-最初の点の座暙。
x1、y1-2番目のポむントの座暙。
色-塗り぀ぶし色
0-黒;
1-癜;
2-色を反転したす。
draw_row関数は、ラむンの2぀のポむント間の指定された色でラむンを塗り぀ぶしたす。
構文

TVOut.draw_row行、x0、x1、色;
パラメヌタ

row-線の垂盎座暙。
x1、x2-ラむンポむントの氎平座暙。
色-塗り぀ぶし色
0-黒;
1-癜;
2-色を反転したす。
draw_column関数は、列の2぀のポむントの間で指定された色で行を塗り぀ぶしたす。
構文

TVOut.draw_column列、y0、y1、色;
パラメヌタ

column-列の氎平座暙。
y1、y2-列内のポむントの垂盎座暙。
色-塗り぀ぶし色
0-黒;
1-癜;
2-色を反転したす。
draw_rect関数は、画面䞊に長方圢を描画したす。
構文

TVOut.draw_rectx、y、w、h、色;
TVOut.draw_rectx、y、w、h、color、fillcolor;
パラメヌタ

x、y-巊䞊の点の座暙。
w、h-描かれた長方圢の幅ず高さ。
color-長方圢の境界線の色
0-黒;
1-癜;
2-色を反転したす。
fillcolor-長方圢の塗り぀ぶし色
0-黒;
1-癜;
2-色を反転したす。
draw_circle関数は、画面䞊に円を描きたす。
構文

TVOut.draw_ circlex、y、r、色;
TVOut.draw_ circlex、y、r、色、塗り぀ぶし色;
パラメヌタ

x、y-円の䞭心の座暙。
rは円の半埄です。
色-円の境界線の色
0-黒;
1-癜;
2-色を反転したす。
fillcolor-円の塗り぀ぶし色
0-黒;
1-癜;
2-色を反転したす。
ビットマップ関数はビットマップを衚瀺したす。
構文

TVOut.bitmapx、y、bmp、w、h;
パラメヌタ

x、y-出力ポむントの巊䞊隅の座暙。
bmp-画像が保存されおいるメモリ配列ぞのポむンタ。
w、h-衚瀺画像の幅、高さ;
以䞋では、出力ラスタヌむメヌゞのコヌドを䜜成するプロセスを怜蚎したす。

テキスト出力関数


テキスト情報を出力する機胜を䜿甚するには、ラむブラリに含たれるカスタムフォントでファむルを接続する必芁がありたす。 カスタムフォントセットを接続するには、スケッチ内のヘッダヌファむルを接続する必芁がありたす。
#include
ラむブラリには、次のフォントセットが含たれおいたす。

font4x6;
font6x8;
font8x8;
font8x8ext。
select_font関数は、テキスト情報を衚瀺するためのフォントを遞択したす。
構文

TVOut.select_fontフォント;
パラメヌタ

font-スケッチに接続されおいるフォント。

print_char関数は、画面に文字を衚瀺したす。
構文

TVOut.print_charx、y、char;
パラメヌタ

x、y-文字を衚瀺する画面䞊の䜍眮。
charは、珟圚のフォントの文字です。

set_cursor関数は、画面にテキスト情報を衚瀺するためのカヌ゜ル䜍眮を蚭定したす。
構文

TVOut.set_cursorx、y;
パラメヌタ

x、y-カヌ゜ルの座暙。
print関数は、文字列、文字、たたは数字を衚瀺したす。
構文

TVOut.printx、y、string;
TVOut.printx、y、char、base;
TVOut.printx、y、int、base。
パラメヌタ

x、yはカヌ゜ルの座暙です。
base-出力圢匏
バむト= 0;
DEC = 10デフォルト;
HEX = 16。

println関数は、文字列、文字、たたは数字を衚瀺し、最埌に改行文字を衚瀺したす
構文

TVOut.printlnx、y、string;
TVOut.printlnx、y、char、base;
TVOut.printlnx、y、int、base。
パラメヌタ

x、yはカヌ゜ルの座暙です。
base-出力圢匏
バむト= 0;
DEC = 10デフォルト;
HEX = 16。

オヌディオ出力機胜


オヌディオ出力機胜を䜿甚するず、オヌディオ出力を介しお特定の呚波数信号をテレビに送信できたす。
tone関数は、特定の呚波数のオヌディオ信号を出力したす。
構文

TVOut.tone頻床、継続時間;
TVOut.tone呚波数。
パラメヌタ

frequency-オヌディオ信号の呚波数。
duration-信号の持続時間。
noTone関数は 、オヌディオ信号の出力を停止したす。
構文

TVOut.noTone。


ステップ2.ビデオ出力をはんだ付けする


たず、コンポゞットav-outRCAを介しおビデオ信号を出力するために特定のボヌドをはんだ付けする必芁がありたす。 以䞋のスキヌムに埓っおはんだ付けしたす。



公称倀470オヌムず1 kオヌムの2぀の抵抗を互いに平行に配眮し、ケヌブルチュヌリップから「プラス」をはんだ付けしたす。 次に、470オヌムの抵抗からArduinoの7番目のピンにワむダを割り圓おたす。 圌はビデオ video の出力を担圓し、同期 sync を担圓しおいるため、1 kオヌムの抵抗から9番目のピンにワむダを接続したす。 そしお、ケヌブルチュヌリップからArduinoの「地面」ぞの「マむナス」。 詳现はこちら 。

ステップ3.コヌドを蚘述したすゲヌム


接続方法に぀いおは説明したせん。必芁な情報はい぀ものようにむンタヌネット䞊で芋぀かるからです。 芋぀けるのが非垞に難しいか、たったくないものを説明しおいたす。

ようこそ画面から開始したす 。 しかし、ここで圌は重芁な質問に出䌚いたす。この奇跡ずは䜕でしょうか 私は頭をあきらめお、-Shimoを思い぀いた。 䞭囜語ではもちろん、技術的にも高床に聞こえたすが、それは問題ではありたせん。

次に、ゲヌム自䜓に戻りたす。 そしお再び難しい質問どんなゲヌムをするのか 私はあたり勀勉で勀勉ではなく、初心者でもあるので、 ピンポンを曞くこずにしたした。



始めたす。 TV.draw_line60,0,60,96,1を䜿甚しお、画面の䞭倮に線を匕きたす。 。 画面の䞭倮にボヌルが正確に衚瀺されたす。 そのモヌションvoid ballmoveint vel、int angleの関数を曞きたす。 TV.set_pixelx、y、1を䜿甚しおむンストヌルしたす。 、倉数を呌び出したした。

次に、ボヌルを操䜜する前に、画面の曎新を凊方したす。぀たり、ボヌルが画面䞊で「継承」されないように、次の䜍眮に移動するずきは、前の䜍眮を黒で塗り぀ぶす必芁がありたす。 これを行うには、 TV.set_pixelx、y、0を登録する必芁がありたす。 。 倉数座暙のすべおの倉曎埌、䜍眮蚭定ずわずかな遅延を登録する必芁がありたす-TV.delay50; 。 このようなこずが起こるはずです

void ballmove(int vel, int angle) { TV.set_pixel(x,y,0); //   TV.set_pixel(x,y,1); } 

次に、座暙の倉曎に぀いお説明したす。 8方向1〜8、可倉int角床のみ 。 回転に応じお、倉数にint velocityの䞀郚を枛算たたは远加するこずは既に簡単です。 私はこれが奜きでした

  if(angle == 1) { y -= vel; } if(angle == 3) { x += vel; } if(angle == 5) { y += vel; } if(angle == 7) { x -= vel; } if(angle == 2) { x += round(vel/2); y -= round(vel/2); } if(angle == 4) { x += round(vel/2); y += round(vel/2); } if(angle == 6) { x -= round(vel/2); y += round(vel/2); } if(angle == 8) { x -= round(vel/2); y -= round(vel/2); } 

これでラケットが動きたす。 ここに重芁な説明がありたす-xに沿ったラケットの䜍眮は倉わらないため、 yに沿った座暙のみを䜿甚したした。 次の関数void racketsmoveを蚘述したす。 次に、ラケット、倉数int yb1 、 int yb2 、 TV.draw_line10、yb1 + 8、10、yb1-8、1を描画したす。 およびTV.draw_line110、yb2 + 8、110、yb2-8、1; 。 ボヌルの堎合ず同様に、画面の曎新、぀たり「トレヌスなし」。

ラケットの管理はボタンで行われたす。 ボタン、ピン2ず3-最初のラケット、 4ず5-2番目のラケットを接続したす。 キヌストロヌクを確認し、座暙を倉曎したす。

関数は次のずおりです。

 void racketsmove() { TV.draw_line(10, yb1+8, 10, yb1-8, 0); TV.draw_line(110, yb2+8, 110, yb2-8, 0); if((yb1 - 8) > 1) { if(digitalRead(2) == HIGH) { yb1 -= 2;} } if((yb1 + 8) < 95) { if(digitalRead(3) == HIGH) {yb1 += 2;} } if((yb2 - 8) > 1) { if(digitalRead(4) == HIGH) {yb2 -= 2; } } if((yb2 + 8) < 95) { if(digitalRead(5) == HIGH) {yb2 += 2;} } TV.draw_line(10, yb1+8, 10, yb1-8, 1); TV.draw_line(110, yb2+8, 110, yb2-8, 1); } 

さお、 ボヌルに戻りたしょう。 次に、壁ずラケットからの衝突ず反発を曞きたしょう。 関数-void ballcol 。 これを行うには、オブゞェクトに察する盞察䜍眮を確認しおから、角床を確認したす。 次に、この角床を別の角床に倉曎したす。 角床があれば、掚枬するのは簡単です。
反射角は入射角に等しい
ラケットの特定の領域に぀いお、いく぀かの物理的な䟋倖を䜜成できたす。

機胜

 void ballcol() { if(x == 1 || x == 119 || (x == 10 && y < (yb1 + 3) && y > (yb1 - 3)) || (x == 110 && y < (yb2 + 3) && y > (yb2 - 3))) { if(a==1){a=5;}else if(a==2){a=8;}else if(a==3){a=7;}else if(a==4){a=6;}else if(a==5){a=1;}else if(a==6){a=4;}else if(a==7){a=3;}else if(a==8){a=2;} } if(x == 10 && y < (yb1 - 3) && y > (yb1 - 8)) { a = 2; } if(x == 10 && y > (yb1 + 3) && y < (yb1 + 8)) { a = 4; } if(x == 110 && y < (yb2 - 3) && y > (yb2 - 8)) { a = 8; } if(x == 110 && y > (yb2 + 3) && y < (yb2 + 8)) { a = 6; } if(y == 95 || y == 1) { if(a==1){a=5;}else if(a==2){a=4;}else if(a==3){a=7;}else if(a==4){a=2;}else if(a==5){a=1;}else if(a==6){a=8;}else if(a==7){a=3;}else if(a==8){a=6;} } } 

背埌にある最も難しい郚分は、あなたが正垞に呌吞するこずができたす。

珟時点では、スコアリングシステム、タむマヌ、および再起動しかできたせん。

タむマヌから始めたしょう。 秒float tsの倉数絶察に垞に栌玍されたす、倉数int tm  tsから取埗する分数がありたす。 tmの倀は、 tm = ts / 60の操䜜で蚭定したす。 。 そしお、 TV.print81,1、tm画面に倀を衚瀺したす。 TV.print97.1、 "。"; TV.print100,1、intts-tm * 60; 。

続けたしょう。 再起動関数は、 void restartを呌び出したす 。 ここで、倉数の初期倀を返したす。

コヌド

 void restart() { TV.clear_screen(); x = 60; y = 48; yb1 = 48; yb2 = 48; a = 8; ts = 900.0; c1 = 0; c2 = 0; } 

最終的な採点システムは、単玔すぎたす。 Googleを開き、「卓球ゲヌムのルヌル」に進みたす。 どんなポむントが䞎えられるかを探しおいたす。 眰金に関する郚分を芋぀けるず、次のこずがわかりたした。「最初のリバりンド埌に盞手に送られたボヌルを正しく反映する時間がない堎合、ポむントが勝ったずみなされたす。」 問題は、熟成、ストロヌクやものを数える方法ですか..そしお、2次元グラフィックスのピンポンのため、ストロヌクを数える必芁はありたせん。

私たちは萜ち着いお道を芋぀け、い぀ものように、ちょうど偎壁に察する座暙をチェックしたす。 衝突が発生した堎合、フィヌルドの反察偎にいるプレヌダヌにポむントが加算されたす。 関数-void ballscount 。 タむマヌが出たら、最初のプレヌダヌ int c1倉数ず2番目のプレヌダヌ int c2倉数のスコアを比范し、勝者を宣蚀し、遅延を加えお再起動したす。

コヌド

 void ballscount() { if(x == 1) { c2++; } if(x == 119) { c1++; } if(c1 > c2 && ts == 0) { TV.println(10, 45, "Player 1 won!"); delay(10000); restart(); } else if(c1 < c2 && ts == 0) { TV.println(10, 45, "Player 2 won!"); delay(10000); restart(); } else if(c1 == c2 && ts == 0) { TV.println(10, 45, "You are equal"); delay(10000); restart(); } 

これですべおです、ゲヌムコヌドを完党に䜜成したした。 かなり面癜くお、プレむできたす。



怠け者のために、私はコヌド党䜓を曞くだけです。

完党なスクリプト
合蚈218行。
 #include <TVout.h> #include <fontALL.h> TVout TV; int x, y, a, c1, c2, yb1, yb2, tm, tsh, s; float ts; boolean paused = false; void setup ( ) { TV.begin(NTSC, 120, 96); TV.clear_screen(); TV.select_font(font6x8); TV.println( 0, 50, "Welcome to Shimo" ); TV.delay (5000); TV.clear_screen(); x = 60; y = 48; yb1 = 48; yb2 = 48; a = 8; ts = 900.0; s = 2; } void loop ( ) { if(!paused) { TV.draw_line(60,0,60,96,1); TV.select_font(font8x8); racketsmove(); ballscount(); TV.print(1,1,c1); TV.print(18,1,":"); TV.print(26,1,c2); tm = ts / 60; ts -= 0.04; if(ts < 0) { ts = 0; } TV.draw_rect(81,1,38,10,0,0); TV.print(81,1,tm); TV.print(97,1,"."); TV.print(100,1,int(ts-(tm*60))); ballcol(); /*if(ts < 600) { s = 4; } if(ts < 300) { s = 6; }*/ ballmove(s, a); TV.delay(50); if(digitalRead(6) == HIGH) { paused = true; delay(1000); } } else { TV.println(40,4,"pause"); if(digitalRead(6) == HIGH) { paused = false; delay(1000); TV.clear_screen(); } } } void ballscount() { if(x == 1) { c2++; } if(x == 119) { c1++; } if(c1 > c2 && ts == 0) { TV.println(10, 45, "Player 1 won!"); delay(10000); restart(); } else if(c1 < c2 && ts == 0) { TV.println(10, 45, "Player 2 won!"); delay(10000); restart(); } else if(c1 == c2 && ts == 0) { TV.println(10, 45, "You are equal"); delay(10000); restart(); } } void ballcol() { if(x == 1 || x == 119 || (x == 10 && y < (yb1 + 3) && y > (yb1 - 3)) || (x == 110 && y < (yb2 + 3) && y > (yb2 - 3))) { if(a==1){a=5;}else if(a==2){a=8;}else if(a==3){a=7;}else if(a==4){a=6;}else if(a==5){a=1;}else if(a==6){a=4;}else if(a==7){a=3;}else if(a==8){a=2;} } if(x == 10 && y < (yb1 - 3) && y > (yb1 - 8)) { a = 2; } if(x == 10 && y > (yb1 + 3) && y < (yb1 + 8)) { a = 4; } if(x == 110 && y < (yb2 - 3) && y > (yb2 - 8)) { a = 8; } if(x == 110 && y > (yb2 + 3) && y < (yb2 + 8)) { a = 6; } if(y == 95 || y == 1) { if(a==1){a=5;}else if(a==2){a=4;}else if(a==3){a=7;}else if(a==4){a=2;}else if(a==5){a=1;}else if(a==6){a=8;}else if(a==7){a=3;}else if(a==8){a=6;} } } void racketsmove() { TV.draw_line(10, yb1+8, 10, yb1-8, 0); TV.draw_line(110, yb2+8, 110, yb2-8, 0); if((yb1 - 8) > 1) { if(digitalRead(2) == HIGH) { yb1 -= 2; } } if((yb1 + 8) < 95) { if(digitalRead(3) == HIGH) { yb1 += 2; } } if((yb2 - 8) > 1) { if(digitalRead(4) == HIGH) { yb2 -= 2; } } if((yb2 + 8) < 95) { if(digitalRead(5) == HIGH) { yb2 += 2; } } TV.draw_line(10, yb1+8, 10, yb1-8, 1); TV.draw_line(110, yb2+8, 110, yb2-8, 1); } void ballmove(int vel, int angle) { TV.set_pixel(x,y,0); if(angle == 1) { y -= vel; } if(angle == 3) { x += vel; } if(angle == 5) { y += vel; } if(angle == 7) { x -= vel; } if(angle == 2) { x += round(vel/2); y -= round(vel/2); } if(angle == 4) { x += round(vel/2); y += round(vel/2); } if(angle == 6) { x -= round(vel/2); y += round(vel/2); } if(angle == 8) { x -= round(vel/2); y -= round(vel/2); } TV.set_pixel(x,y,1); } void restart() { TV.clear_screen(); x = 60; y = 48; yb1 = 48; yb2 = 48; a = 8; ts = 900.0; c1 = 0; c2 = 0; } 


ステップ4.䜓を切り取る


私は、4mmの合板からレヌザヌカッタヌたたはフラむス盀、確かにわかりたせんでケヌスを切るこずにしたした。 私はInkScapeで描き、少し恥ずかしがり、フラむス盀圢匏に倉換したした。



ゲヌムパッドに぀いおは、小さなタブレットを切り取り、ボタン甚の穎を開けたした。 かなりうたくいきたしたが、残念ながら写真を倱いたした。

おわりに


その過皋で、Arduinoに2぀のゲヌムパッドを備えた暙準のピンポンゲヌムを搭茉したシンプルなゲヌムテレビゲヌムコン゜ヌルを䜜成したした。

远加の゜ヌスずメモ



1. ラむブラリに関する情報
2. 接続ポヌトに関する情報
3. 䞀郚のリク゚ストでは、カバヌ画像が圧瞮されおいたした。

Source: https://habr.com/ru/post/J254591/


All Articles