제조공정
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 6 | |||
![]() |
| × | 1 | |||
![]() |
| × | 3 | |||
![]() |
| × | 1 |
![]() |
| |||
![]() |
|
Arduboy는 신용 카드 크기의 미니어처 게임 시스템입니다. 클래식 8비트 게임과 함께 설치되며 온라인에서 사용할 수 있는 오픈 소스 게임 라이브러리에서 다시 프로그래밍할 수 있습니다. Arduboy는 오픈 소스이므로 코딩을 배우고 자신만의 게임을 만들 수 있습니다. 원래 버전은 ATmega32U4 마이크로컨트롤러 및 128x64 픽셀 직렬 OLED 디스플레이를 기반으로 합니다.
아래와 같이 구성한 콘솔은 아두이노 나노와 I2C 버전의 OLED 디스플레이로 구성되어 있어 훨씬 저렴한 가격에 쉽게 찾을 수 있습니다. 다음에서 필요한 라이브러리와 코드를 다운로드할 수 있습니다.
https://github.com/harbaum/Arduboy2
3D 프린터를 소유하고 있다면 콘솔이 설치된 가능한 박스 옵션의 .STL 파일을 다운로드할 수도 있습니다. 자세한 설치 가이드는 같은 사이트에서 사용할 수 있습니다. 3.7v의 리튬 이온 배터리 1개가 있는 Arduino Nano로 구동되며 꽤 잘 작동합니다.
이 콘솔에서 많은 게임을 테스트했는데 모두 훌륭하게 작동합니다.
- 아두브레이크아웃
- 핀볼
- 섀도우 러너
- 뱀
- 바이러스-LQP-79
- 나인틴43
그리고 더 많은...
개략도는 아래와 같습니다.
예를 들어 ArduBreakout 게임에 코드를 제공하고 있지만 이 버전의 콘솔과 호환되는 Arduboy 사이트에서 다른 게임을 다운로드할 수 있습니다.
섹션> <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">/* Breakout Copyright (C) 2011 Sebastian Goscik All rights reserved. Scott Allen 2016의 수정 사항(???에 의한 이전 변경 이후) 이 라이브러리는 자유 소프트웨어입니다. 자유 소프트웨어 재단(Free Software Foundation)에서 발행한 GNU 약소 일반 공중 라이선스(GNU Lesser General Public License) 조건에 따라 이를 재배포 및/또는 수정할 수 있습니다. 라이선스 버전 2.1 또는 (귀하의 선택에 따라) 이후 버전. */#include섹션>// 높은 점수를 저장하기 위해 EEPROM에서 차단#define EE_FILE 2Arduboy2 arduboy;BeepPin1 beep;const unsigned int FRAME_RATE =40; // 프레임 속도(초당 프레임 수)const unsigned int COLUMNS =13; //bricksconst의 열 unsigned int ROWS =4; // bricksint dx =-1의 행; //ballint의 초기 이동 dy =-1; //ballint의 초기 이동 xb; //볼 시작 위치int yb; // 시작 위치 불린 공이 해제됨; //플레이어가 공을 놓으면 paused =false; //게임이 일시 중지된 경우byte xPaddle; // paddleboolean의 X 위치 isHit[ROWS][COLUMNS]; //벽돌이 맞았는지 또는 notboolean bounded=false인 경우의 배열; //이중 바운스를 수정하는 데 사용 glitchbyte lives =3; //livebyte의 양 =1; //현재 레벨unsigned int score=0; // 게임에 대한 점수 unsigned int brickCount; // 벽돌의 양 hitboolean pad, pad2, pad3; //버튼 누름 버퍼 반복 일시 중지 반복 부울 oldpad, oldpad2, oldpad3;char text_buffer[16]; //일반 문자열 버퍼부울 start=false; //메뉴 또는 게임에 있는 경우 initialDraw=false;//초기 추첨이 발생한 경우char initials[3]; //높은 점수에 사용된 이니셜 //충돌 감지에 사용된 볼 경계byte leftBall;byte rightBall;byte topBall;byte bottomBall;//충돌 감지에 사용되는 벽돌 경계byte leftBrick;byte rightBrick;byte topBrick;byte bottomBrick;byte tick;void 설정 (){ arduboy.begin(); beep.begin(); 아두보이.setFrameRate(FRAME_RATE); arduboy.initRandomSeed();}void loop(){ // 다음 프레임 시간이 될 때까지 렌더링을 일시 중지합니다. if (!(arduboy.nextFrame())) return; // 톤의 타이밍 및 중지 처리 beep.timer(); //타이틀 스크린 루프는 타이틀 스크린에서 //FIRE를 누를 때까지 높은 점수를 얻습니다. while (!start) { start =titleScreen(); if (!start) { 시작 =displayHighScores(EE_FILE); } } //초기 레벨 그리기 if (!initialDraw) { //화면 지우기 arduboy.clear(); //글꼴 선택 //새 레벨을 그립니다. =1; 새로운 레벨(); 점수 =0; 초기 그리기=참; } if (live>0) { drawPaddle(); // FIRE 눌렀을 때 게임 일시 중지 패드 =arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON); if(패드 ==true &&oldpad ==false &&해제됨) { oldpad2 =false; //패드 루프 2가 한 번 실행되도록 강제합니다. pause(); } 오래된 패드 =패드; 드로볼(); if(brickCount ==행 * 열) { 레벨++; 새로운 레벨(); } } else { drawGameOver(); if (점수> 0) { enterHighScore(EE_FILE); } arduboy.clear(); initialDraw=거짓; 시작=거짓; 생명=3; 새로운 레벨(); } arduboy.display();}void movePaddle(){ //오른쪽으로 이동 if(xPaddle 0) { if (arduboy.pressed(LEFT_BUTTON)) { xPaddle-=2; } }} moveBall(){ 틱++; if(released) { //공 이동 if (abs(dx)==2) { xb +=dx/2; // 2배속은 실제로 1.5배속 if (tick%2==0) xb +=dx/2; } 그렇지 않으면 { xb +=dx; } yb=yb + dy; // 경계 설정 leftBall =xb; 오른쪽 볼 =xb + 2; 탑볼 =yb; 바텀볼 =yb + 2; // 상단 가장자리에서 바운스 if (yb <=0) { yb =2; 디 =-디; 플레이톤(523, 250); } //하단 가장자리가 히트하면 생명을 잃습니다. if (yb>=64) { arduboy.drawRect(xPaddle, 63, 11, 1, 0); x패들 =54; 연=60; 해제 =거짓; 삶--; playToneTimed(175, 500); if (무작위(0, 2) ==0) { dx =1; } 그렇지 않으면 { dx =-1; } } //왼쪽에서 바운스 if (xb <=0) { xb =2; dx =-dx; 플레이톤(523, 250); } //오른쪽으로 바운스 if (xb>=WIDTH - 2) { xb =WIDTH - 4; dx =-dx; 플레이톤(523, 250); } // 패들에서 바운스 if (xb+1>=xPaddle &&xb<=xPaddle+12 &&yb+2>=63 &&yb<=64) { dy =-dy; dx =((xb-(x패들+6))/3); //볼에 스핀을 적용합니다 // 직선 바운스를 방지 if (dx ==0) { dx =(random(0,2) ==1) ? 1:-1; } 플레이톤(200, 250); } //Bounce off Brick for (byte row =0; row =topBrick &&leftBall <=rightBrick &&rightBall>=leftBrick) { Score(); 벽돌 개수++; isHit[행][열] =true; arduboy.drawRect(10*열, 2+6*행, 8, 4, 0); //수직 충돌 if (bottomBall> bottomBrick || topBall rightBrick) { //각 공이 한 번만 벽돌로 이동 if(!bounced) { dx =- dx; xb +=dx; 바운스 =사실; 플레이톤(261, 250); } } } } } } //바운스 재설정 =false; } else { //공은 패들을 따라갑니다 xb=xPaddle + 5; //FIRE가 눌려지면 공을 놓는다 pad3 =arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON); if (pad3 ==true &&oldpad3 ==false) { 릴리스 =true; // 놓을 때 공에 임의의 방향을 적용합니다. if (random(0, 2) ==0) { dx =1; } 그렇지 않으면 { dx =-1; } //공이 위쪽으로 향하는지 확인 dy =-1; } 오래된 패드3 =패드3; }}무효 drawBall(){ // arduboy.setCursor(0,0); // arduboy.print(arduboy.cpuLoad()); // arduboy.print(" "); arduboy.drawPixel(xb, yb, 0); arduboy.drawPixel(xb+1, yb, 0); arduboy.drawPixel(xb, yb+1, 0); arduboy.drawPixel(xb+1, yb+1, 0); 무브볼(); arduboy.drawPixel(xb, yb, 1); arduboy.drawPixel(xb+1, yb, 1); arduboy.drawPixel(xb, yb+1, 1); arduboy.drawPixel(xb+1, yb+1, 1);}무효 drawPaddle(){ arduboy.drawRect(xPaddle, 63, 11, 1, 0); 이동 패들(); arduboy.drawRect(xPaddle, 63, 11, 1, 1);}무효 drawGameOver(){ arduboy.drawPixel(xb, yb, 0); arduboy.drawPixel(xb+1, yb, 0); arduboy.drawPixel(xb, yb+1, 0); arduboy.drawPixel(xb+1, yb+1, 0); arduboy.setCursor(37, 42); arduboy.print("게임 오버"); arduboy.setCursor(31, 56); arduboy.print("점수:"); arduboy.print(점수); 아두보이.디스플레이(); arduboy.delayShort(4000);}void pause(){ 일시 중지 =true; //화면에 일시정지 그리기 arduboy.setCursor(52, 45); arduboy.print("일시 중지"); 아두보이.디스플레이(); 동안 (일시 중지) { arduboy.delayShort(150); //FIRE를 누르면 일시 중지 해제 pad2 =arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON); if (pad2 ==true &&oldpad2 ==false &&해제됨) { arduboy.fillRect(52, 45, 30, 11, 0); 일시 중지됨=거짓; } 오래된 패드2 =패드2; }}void Score(){ score +=(level*10);}void newLevel(){ // 패들 그리기 arduboy.drawRect(xPaddle, 63, 11, 1, 0); //공 풀기 arduboy.drawPixel(xb, yb, 0); arduboy.drawPixel(xb+1, yb, 0); arduboy.drawPixel(xb, yb+1, 0); arduboy.drawPixel(xb+1, yb+1, 0); //게임을 재설정하기 위해 다양한 변수를 변경합니다. xPaddle =54; yb =60; 벽돌 개수 =0; 해제 =거짓; //새 벽돌을 그리고 값을 재설정합니다. for (byte row =0; row <4; row++) { for (byte column =0; column <13; column++) { isHit[row][column] =false; arduboy.drawRect(10*열, 2+6*행, 8, 4, 1); } } arduboy.display();}//버튼을 읽는 동안 이미지를 지연시키는 데 사용 inputboolean pollFireButton(int n){ for(int i =0; i 0) { sprintf(text_buffer, "%c%c%c %u", 이니셜[0], 이니셜[1], 이니셜[2], 점수); arduboy.setCursor(x + 24, y + (i*8)); arduboy.print(텍스트 버퍼); 아두보이.디스플레이(); } } if (pollFireButton(300)) { true를 반환합니다. } 반환 거짓; arduboy.display();}boolean titleScreen(){ //화면 지우기 arduboy.clear(); arduboy.setCursor(16,22); 아두보이.setTextSize(2); arduboy.print("브레이크아웃"); 아두보이.setTextSize(1); 아두보이.디스플레이(); if (pollFireButton(25)) { true를 반환합니다. } // "Press FIRE"를 5번 플래시 for(byte i =0; i <5; i++) { //"Press FIRE"를 그립니다. arduboy.setCursor(31, 53); arduboy.print("발사를 눌러주세요!"); 아두보이.디스플레이(); if (pollFireButton(50)) { true를 반환합니다. } // "Press FIRE" 제거 arduboy.setCursor(31, 53); arduboy.print(" "); 아두보이.디스플레이(); if (pollFireButton(25)) { true를 반환합니다. } } return false;}//높은 점수를 추가하기 위한 누트로픽 디자인의 기능void enterInitials(){ byte index =0; arduboy.clear(); 이니셜[0] =' '; 이니셜[1] =' '; 이니셜[2] =' '; 동안 (참) { arduboy.display(); arduboy.clear(); arduboy.setCursor(16,0); arduboy.print("높은 점수"); sprintf(text_buffer, "%u", 점수); arduboy.setCursor(88, 0); arduboy.print(텍스트 버퍼); arduboy.setCursor(56, 20); arduboy.print(이니셜[0]); arduboy.setCursor(64, 20); arduboy.print(이니셜[1]); arduboy.setCursor(72, 20); arduboy.print(이니셜[2]); for(바이트 i =0, i <3, i++) { arduboy.drawLine(56 + (i*8), 27, 56 + (i*8) + 6, 27, 1); } arduboy.drawLine(56, 28, 88, 28, 0); arduboy.drawLine(56 + (인덱스*8), 28, 56 + (인덱스*8) + 6, 28, 1); arduboy.delayShort(70); if (arduboy.pressed(LEFT_BUTTON) || arduboy.pressed(B_BUTTON)) { if (인덱스> 0) { 인덱스--; playToneTimed(1046, 80); } } if (arduboy.pressed(RIGHT_BUTTON)) { if (인덱스 <2) { 인덱스++; playToneTimed(1046, 80); } } if (arduboy.pressed(UP_BUTTON)) { 이니셜[인덱스]++; playToneTimed(523, 80); // AZ 0-9 :-? !-/ ' ' if (이니셜[인덱스] =='0') { 이니셜[인덱스] =' '; } if (이니셜[인덱스] =='!') { 이니셜[인덱스] ='A'; } if (이니셜[인덱스] =='[') { 이니셜[인덱스] ='0'; } if (이니셜[인덱스] =='@') { 이니셜[인덱스] ='!'; } } if (arduboy.pressed(DOWN_BUTTON)) { 이니셜[인덱스]--; playToneTimed(523, 80); if (이니셜[인덱스] ==' ') { 이니셜[인덱스] ='?'; } if (이니셜[인덱스] =='/') { 이니셜[인덱스] ='Z'; } if (이니셜[인덱스] ==31) { 이니셜[인덱스] ='/'; } if (이니셜[인덱스] =='@') { 이니셜[인덱스] =' '; } } if (arduboy.pressed(A_BUTTON)) { playToneTimed(1046, 80); if (인덱스 <2) { 인덱스++; } 그렇지 않으면 { 반환; } } }}void enterHighScore(byte file){ // EEPROM의 각 블록에는 7개의 최고 점수가 있고 각 최고 점수 항목은 // 길이가 5바이트입니다. 이니셜은 3바이트, 점수는 2바이트입니다. int 주소 =파일 * 7 * 5 + EEPROM_STORAGE_SPACE_START; 바이트 안녕하세요, 로; char tmpInitials[3]; 부호 없는 정수 tmpScore =0; // 고득점 처리 for(byte i =0; i <7; i++) { hi =EEPROM.read(address + (5*i)); lo =EEPROM.read(주소 + (5*i) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) { // 값이 초기화되지 않았으므로 이 항목을 // 0의 점수로 처리합니다. tmpScore =0; } else { tmpScore =(안녕 <<8) | 봐라; } if (점수> tmpScore) { enterInitials(); for(바이트 j =i; j <7; j++) { hi =EEPROM.read(주소 + (5*j)); lo =EEPROM.read(주소 + (5*j) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) { tmpScore =0; } else { tmpScore =(안녕 <<8) | 봐라; } tmpInitials[0] =(char)EEPROM.read(주소 + (5*j) + 2); tmpInitials[1] =(char)EEPROM.read(주소 + (5*j) + 3); tmpInitials[2] =(char)EEPROM.read(주소 + (5*j) + 4); // 현재 슬롯에 점수와 이니셜 쓰기 EEPROM.update(address + (5*j), ((score>> 8) &0xFF)); EEPROM.update(주소 + (5*j) + 1, (점수 &0xFF)); EEPROM.update(주소 + (5*j) + 2, 이니셜[0]); EEPROM.update(주소 + (5*j) + 3, 이니셜[1]); EEPROM.update(주소 + (5*j) + 4, 이니셜[2]); // tmpScore 및 tmpInitials는 이제 다음 슬롯에 // 쓰고 싶은 것을 보유합니다. 점수 =tmpScore; 이니셜[0] =tmpInitials[0]; 이니셜[1] =tmp이니셜[1]; 이니셜[2] =tmp이니셜[2]; } 점수 =0; 이니셜[0] =' '; 이니셜[1] =' '; 이니셜[2] =' '; 반품; } }}// 지정된 기간 동안 지정된 주파수로 톤 재생.void playTone(unsigned int frequency, unsigned int duration){ beep.tone(beep.freq(frequency), duration / (1000 / FRAME_RATE));} // 지정된 시간 동안 지정된 주파수로 톤을 재생합니다// 톤 시간 지연을 사용합니다.// beep.timer()가 호출되지 않을 때 사용됩니다.void playToneTimed(unsigned int frequency, unsigned int duration){ beep.tone(beep.freq(주파수)); arduboy.delayShort(지속 시간); beep.noTone();}
제조공정
구성품 및 소모품 Arduino Nano R3 × 1 LED 매트릭스 × 1 포토 저항기 × 1 브레드보드(일반) × 1 DS3231 × 1 앱 및 온라인 서비스 Arduino IDE 이 프로젝트 정보 몇 미터 떨어진 방의 시계 디스플레이를 읽으려면 이러한 LED 매트릭스 디스플레이가 필요합니다. 좋은 가격에 4셀 디스플레이를 구입한 후 Hackster에서 사용 가능한 프로젝트를
구성품 및 소모품 Arduino UNO × 1 Adafruit Standard LCD - 파란색 바탕에 16x2 흰색 × 1 SparkFun 푸시버튼 스위치 12mm × 4 저항 10k 옴 × 4 저항 221옴 음, 220옴... × 2 단일 회전 전위차계 - 100,000옴 × 1 부저 × 1 브레드보드(일반) × 1 점퍼 와이어(일반) × 1