|
프로세싱. 아두이노연동 핑퐁 게임만들기 [수원코딩학원 이지로봇]
안녕하세요 수원코딩전문학원 이지로봇 입니다.
이번시간에는 아두이노 와 프로세싱을 연동하여 고전게임 핑퐁을 구현해 보았습니다
먼저 아두이노 나노보드와 조이스틱을 이용하여 조이스틱의 값을 판독한뒤 플레이어 2인용 데이터를 시리얼로 전송합니다
프로세싱에서는 디버그모드는 마우스로 패달이동을 하도록 하였고 디버그모드 false일때 아두이노로 부터 받은 값으로
패달을 이동하도록 구현 하였습니다
사운드와 배경음악을 미구현되어 있으며 카페의 벽돌깨기 게임만들기를 이용하시면 추가 가능하므로 생략하였습니다
사진과 동영상을 먼저 보시고 아래 소스코드를 살펴보시죠!
자세한 사항이나 추가사항은 네이버 수원이지로봇학원 카페의 다른게임 만들기를 참조하시기 바랍니다. 소스코드 첨부파일은 학원카페에 있습니다
코딩전문학원 http://easyrobot.co.kr
http://cage.naver.com/easyrobot
상담 : 031-293-6355
아두이노측 소스코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | /********************************************** 제목 : 아두이노와 프로세싱을 연동한 핑퐁프로젝트 작성 : 수원이지로봇학원 수원코딩학원 일자 : 2017.01.29 **********************************************/ int analog_Pin[4] = {A0,A1,A3,A4}; int digital_Pin[2] = {A2,A5}; int sensorValue[4] = {0,0,0,0}; int outputValue[4] = {0,0,0,0}; int posi_data[4] = {0,0,0,0}; int sw_status[2] = {0,0}; int i; /*********************************************/ void setup() { /*********************************************/ Serial.begin(9600); for(i=0;i<2;i++){ pinMode(digital_Pin[i],INPUT_PULLUP); } } /*********************************************/ void loop() { /*********************************************/ for(i=0;i<4;i++){ sensorValue[i] = analogRead(analog_Pin[i]); outputValue[i] = map(sensorValue[i], 0, 1023, 0, 100); if(outputValue[i]<10) {posi_data[i]--;} if(outputValue[i]>90) {posi_data[i]++;} if(posi_data[i]<=0) posi_data[i]=0; if(posi_data[i]>=40) posi_data[i]=40; } for(i=0;i<2;i++){ sw_status[i]= digitalRead(digital_Pin[i]); } sendData(); delay(10); } /********************************************/ void sendData(void) { /********************************************/ Serial.print("T"); Serial.print(posi_data[0]); //player1_Y Serial.print(","); Serial.print(posi_data[1]); //player1_X Serial.print(","); Serial.print(posi_data[2]); //player2_Y Serial.print(","); Serial.print(posi_data[3]); //player2_X Serial.print(","); Serial.print(sw_status[0]); //player1_SW Serial.print(","); Serial.print(sw_status[1]); //player2_SW Serial.println(","); } |
<프로세싱측 소스코드>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | /******************************************************* 작성일 : 2017. 1.29 작성자 : 수원이지로봇학원, 수원코딩학원 제 목 : 프로세싱과 아두이노를 이용한 핑퐁게임 만들기 *******************************************************/ import java.util.List; import processing.serial.*; PFont pfont1,pfont2; //boolean Debug = false; boolean Debug = true; Serial myPort; // Create object from Serial class // Ball과 Player 클래스 객체가 생성될때 자동으로 Draw(), Update()를 실행할 수 있게 배열에 저장. // 각 클래스에서는 생성될때 자기 자신을 배열에넣는 구문이 추가되어 있음. List<Ball> Ball_List = new ArrayList<Ball>(); //Ball 배열과 객체 동시선언 List<Player> Player_List = new ArrayList<Player>();//Ball 배열과 객체 동시선언 Player Player1 = new Player(25,LEFT); //객체선언, 생성및 초기화 Player Player2 = new Player(775,RIGHT); //Player Player1; 객체선언 //Player1 = new Player(25,LEFT); //객체 생성및 초기화 int L_score=0,R_score=0; /*******************************************************/ void setup(){ /*******************************************************/ size(800,600); frameRate(60); //String[] fontList = PFont.list(); //printArray(fontList); String portName = ""; if (!Debug){ portName = Serial.list()[0]; myPort = new Serial(this, portName, 9600); } pfont1 = createFont("맑은 고딕", 32); pfont2 = createFont("DS-Digital Bold Italic",120); surface.setTitle("이지로봇학원의 아두이노 연동 핑퐁 게임만들기"); restart(true); } /****************** 화면 그리기 관련 ********************/ void draw(){ /********************************************************/ BackGround_Draw(); for(Ball Data:Ball_List){ Data.Update(); Data.Draw(); //String numFormat1 = nf(abs(Data.speed_x), 1, 1); //String numFormat2 = nf(abs(Data.speed_y), 1, 1); textFont(pfont1); textSize(16); text("SPD_X : "+nf(Data.speed_x, 1, 1), 40, 520); text("SPD_Y : "+nf(Data.speed_y, 1, 1), 40, 560); textFont(pfont2); text( nf(L_score, 2), 250, 130); text( nf(R_score, 2), 415, 130); } for(Player Data:Player_List){ Data.Update(); Data.Draw(); } fill(0,30,127); textFont(pfont1); textSize(16); text("코딩전문 이지로봇학원. http://easyrobot.co.kr", 325, 560); //text("now x=" + (int)p.getX() + ", y=" + (int)p.getY(), 10, 32); fill(#CFFAC0); //text("now x=" + mouseX + ", y=" +mouseY, 340, 560); if(mousePressed == true) restart(true); } /*********************************************************/ void BackGround_Draw(){ /*********************************************************/ fill(#57AF3A); rect(0, 0, width, height); fill(0,255); fill(#57AF3A); strokeWeight(3); //블럭경계선 두께 stroke(#CFFAC0); //블럭경계선 색상 rect(25,25,750,550); line(400,25,400,575); fill(#57AF3A); ellipse(400,300,100,100); } /****************** 아두이노와 시리얼 통신 ********************/ boolean Start = false; String temp = ""; /**************************************************************/ void serialEvent(Serial myPort) { /**************************************************************/ boolean End = false; while(myPort.available() > 0){ char Read_Data = (char)myPort.read(); if (Read_Data == 'T') { Start = true;} //T 가 올때부터 모든 데이터를 읽기 시작함. else if (Read_Data == '\n' && Start) { End = true; break; } // 줄바꿈 표시가 오면 End 스위치를 켜고 아래에서 데이터를 처리함. else if (Start) { temp+=Read_Data; } } if (End == true){ println(temp); String[] ReturnList = temp.split(","); Player1.Y_Update(Integer.valueOf(ReturnList[0]) * 15); Player2.Y_Update(Integer.valueOf(ReturnList[2]) * 15); //Player1.Y_Update((int)Ball_List.get(0).y); //Player2.Y_Update((int)Ball_List.get(0).y); if (ReturnList[4].equals("0") && ReturnList[5].equals("0")) restart(true); temp = ""; End = false; } } /****************************************************************/ void restart(boolean score_restart){ /****************************************************************/ Ball_List = new ArrayList<Ball>(); Player_List = new ArrayList<Player>(); Player1 = new Player(25,LEFT); Player2 = new Player(775,RIGHT); new Ball().Move(80,300); if (score_restart){ L_score=0; R_score=0; } } /****************************************************************/ |
<ball 클래스>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | /**************************************************************/ class Ball{ /**************************************************************/ //필드 float x = 0; float y = 0; float speed_x = 2.0; float speed_y = 1.0; int speed = 3; /*******************************/ Ball(){ //생성자 /*******************************/ Ball_List.add(this); } //메서드(함수)부분 /*******************************/ void Update(){ /*******************************/ if (x<-15 ){ R_score++;restart(false);return; } else if (x>815 ){ L_score++;restart(false);return; } x += speed_x * speed; y += speed_y * speed; if (y <= 38) speed_y *= -1; if (y >= 563) speed_y *= -1; y = max(min(y,563),38); // 혹시 다른 물체와 충돌했는가? for(Player Player_Data:Player_List){ if (Player_Data.x-23 <= x && Player_Data.x+23 >= x && Player_Data.y-83 <= y && Player_Data.y+83 >= y ){ if (Player_Data.Team == LEFT) speed_x = abs(speed_x)+0.1000000000; if (Player_Data.Team == RIGHT) speed_x = -abs(speed_x)-0.1000000000; speed_x = max(min(speed_x,11),-11); //if(speed_y>=0) speed_y =speed_y + 0.1; //if(speed_y<=0) speed_y =speed_y - 0.1; // 혹시 충돌한 물체가 움직이던(힘을 가하던) 중이었는가? float Plus_Force = max(min(Player_Data.Get_Force(),100),-100) / 50.0; speed_y += Plus_Force; speed_y = max(min(speed_y,5),-5); break; } } } /*******************************/ void Move(int x, int y){ // 강제 위치 설정 /*******************************/ this.x = x; this.y = y; } /*******************************/ void Draw(){ /*******************************/ strokeWeight(0); //블럭경계선 두께 fill(#ECFFE5); // 볼의 컬러 stroke(color(255,255,255)); // 테두리 색상은 연한 갈색 ellipse((int)x,(int)y,25,25); // 볼 원그리 이동되는좌표의 크기는 15*15 } } /**************************************************************/ |
<플레이어 클래스>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /******************************************************/ class Player{ // Player 객체 /******************************************************/ //객체선언 변수 = 필드 float x = 0; float y = 300; int Force_Size = 5; int[] Force = new int[Force_Size]; //배열선언 int next_y = 0; int Team; //생성자(필드에 값을 할당하는 특수메서드) /*******************************/ Player(int x, int Team){ /*******************************/ this.x = x; next_y = 300; this.Team = Team; Player_List.add(this); } //메서드(함수)부분 /*******************************/ void Y_Update(int next){ /*******************************/ next_y = next; } /*******************************/ void Update(){ /*******************************/ if (Debug) Y_Update(mouseY); for(int i=0;i<Force_Size - 1;i++) { Force[i]= Force[i + 1]; } Force[Force_Size - 1] = (int)(next_y-y); y = next_y; } /*******************************/ int Get_Force(){ /*******************************/ int all_f = 0; // Force 는 int[] 배열, 이 배열에서 각 요소를 int temp로 가져와서 //배열의 사이즈만큼 반복됨. Force.length for(int temp:Force) { all_f += temp; } return all_f; } /*******************************/ void Draw(){ /*******************************/ strokeWeight(0); // 블럭경계선 두께 fill(#ECFFE5); // 볼의 컬러 stroke(color(255,0,0,0)); // 테두리 색상은 연한 갈색 rect(x - 10,y - 70,20,140); // 라켓사각형그리기 //println(Force.length); } } |
로봇공학은 단순조립이 아닌 전자와 기계 , 그리고 알고리즘 프로그래밍 제어까지 합쳐진 융합과학 학문입니다. 이지로봇창의과학학원 에서 최고의 로봇과학 교육 교습을 경험하세요. "즐거움과 깨달음. 감동이 있는 교육" 수원로봇교육학원 031-293-6355. 카페바로가기 http://cafe.naver.com/easyrobot 주소 : 수원시 권선구 구운동 897-2 수원아두이노학원,수원스크래치학원,수원코딩학원,수원프로그래밍학원,수원로봇학원,수원과학상자학원 |