top drop menu

Recent Post

레이블이 파이썬인 게시물을 표시합니다. 모든 게시물 표시
레이블이 파이썬인 게시물을 표시합니다. 모든 게시물 표시

월요일, 11월 26

파이썬 : 윈도우에서 pygame을 이용하여 게임 개발하기(2)–기본동작

이제 게임에 캐릭터를 등장 시켜서 몇가지 상황을 만들고 기본적인 동작을 하도록 수정해 주자. 게임패트 왼쪽 스틱으로 화면 아래쪽의 사각형을 x방향으로 만 왔다 갔다 움직이도록 하였다. 캐릭터가 아래로 빠져서 게임오버가 되지 않도록 위치를 잡아서 위로 튕켜 줘야 한다. 캐릭터는 자동으로 앞으로 점프를 하면서 이동하게 되어있다. 무기의 사용은 게임패드 우측의 A 버튼에 부여 하였다.
이미지 133
enemy들은 우측에서 무작위로 나오게 되어 있다. 이것들을 피하거나 제거해야 하는데 기능을 따로 주지 않았기 때문에 피할수는 없고 무기를 쐬서 제거를 해줘야 한다.  캐릭터도 스틱으로 움직히게 하면 되지만 예제는 예제니깐 간단히 하자.

-----------game.py--------------
import pygame
import random
import os
WIDTH = 800
HEIGHT = 480
FPS = 30
# Define colors
player1Color = (0, 180, 255)
player2Color = (180, 0, 180)
BGCOLOR = (255, 200, 0) #background color
WHITE = (255,255,255)
enemyColor = (0, 5, 255)
# set up assets folders
game_folder = os.path.dirname(__file__)
img_folder = os.path.join(game_folder, "img")
# Player Class
class Player(pygame.sprite.Sprite):
     def __init__(self):
         pygame.sprite.Sprite.__init__(self)
         self.image = pygame.image.load(os.path.join(img_folder, "player1_1.png")).convert() # 이미지를 사용하는 경우
         self.image.set_colorkey(WHITE)
         self.rect = self.image.get_rect()
         self.rect.center = (WIDTH/2 - 100, HEIGHT - 50)
         self.y_speed = 3
    def update(self):
         self.rect.x += 3
         self.rect.y += self.y_speed
         if self.rect.bottom > HEIGHT:
             self.rect.y = 0
         if self.rect.top < 50:
             self.y_speed = 3
         if self.rect.left > WIDTH:
             self.rect.right = 0
        
         # 외곽를 지나면 처리
         if self.rect.left > WIDTH:
             self.rect.right = 0
         if self.rect.right < 0:
             self.rect.left = WIDTH
    def shoot(self):
         bullet = Bullet(player1.rect.x+25, player1.rect.y+25)
         bullet_sprites.add(bullet)
         all_sprites.add(bullet)

# Class
class Box(pygame.sprite.Sprite):
     def __init__(self):
         pygame.sprite.Sprite.__init__(self)
         self.image = pygame.Surface((60, 20)) # 도형을 사용하는 경우
         self.image.fill(player2Color)
         self.rect = self.image.get_rect()
         self.rect.center = (WIDTH/2, HEIGHT - 45)
         self.x_speed = 0
    def update(self):
         self.rect.x  += self.x_speed
         # 스틱을 움직이면
         if event.type == pygame.JOYAXISMOTION:
             self.x_speed  += gamepads[-1].get_axis(0) *1
             if self.x_speed > 10:
                 self.x_speed = 10
             # self.rect.y += gamepads[-1].get_axis(1) *4
         if self.rect.left > WIDTH:
             self.rect.right = 0
         if self.rect.right < 0:
             self.rect.left = WIDTH
# Enemy Class
class Enemy(pygame.sprite.Sprite):
     def __init__(self):
         pygame.sprite.Sprite.__init__(self)
         self.image = pygame.Surface((30, 30)) # 도형을 사용하는 경우
         self.image.fill(enemyColor)
         self.rect = self.image.get_rect()
         self.rect.center = (random.randrange(WIDTH, WIDTH *2), random.randrange(50, HEIGHT - 50))
         self.x_speed = random.randrange(-5, -1)
    def update(self):
         self.rect.x += self.x_speed
         if (self.rect.right < 0):
             self.rect.left = WIDTH
             self.rect.top = random.randrange(100, 300)
# bullets
class Bullet(pygame.sprite.Sprite):
     def __init__(self, x, y):
         pygame.sprite.Sprite.__init__(self)
         self.image = pygame.Surface((10, 3)) # 도형을 사용하는 경우
         self.image.fill(player2Color)
         self.rect = self.image.get_rect()
         self.rect.center = (x,y)
         self.x_speed = 20
    def update(self):
         self.rect.x += self.x_speed
         if self.rect.left > WIDTH:
             self.kill() # 오호 이거 편하네 .

# initialize
pygame.init()
pygame.mixer.init() #for sound
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Jumper')
clock = pygame.time.Clock()
width, height = pygame.display.get_surface().get_size()
lead_x = width/2 -100
lead_y = height - 100
lead2_x = width/2 + 100
lead2_y = height - 100
#연결된 모든 디바이스 배열에 추가
gamepads = []
for i in range(0, pygame.joystick.get_count()):
     gamepads.append(pygame.joystick.Joystick(i))
     gamepads[-1].init()
# set up sprites
all_sprites = pygame.sprite.Group()
player_sprites = pygame.sprite.Group()
bullet_sprites = pygame.sprite.Group()
enemy_sprites = pygame.sprite.Group()
player1 = Player()
player_sprites.add(player1)
box_sprites = pygame.sprite.Group()
box = Box()
box_sprites.add(box)
# for문
for i in range(10):
     enemy = Enemy()
     enemy_sprites.add(enemy)
     all_sprites.add(enemy)
all_sprites.add(player1)
all_sprites.add(box)
# print(all_sprites)

#Game Loop
running = True
while running:
     clock.tick(FPS)
     # process input(events)
     for event  in pygame.event.get():
         if event.type == pygame.QUIT:
             running = False
     # 버튼을 누르면
     if event.type == pygame.JOYBUTTONDOWN :
         if event.button == 0:
             player1.shoot()
    # update
     all_sprites.update()
    hits = pygame.sprite.groupcollide(enemy_sprites, bullet_sprites, True, True)
     if hits:
         # 새로운 enemy를 추가해 줌
         enemy = Enemy()
         enemy_sprites.add(enemy)
         all_sprites.add(enemy)
    # 충돌감지
     hit = pygame.sprite.spritecollide(player1, box_sprites, False)
     if hit:
         player1.y_speed *= -1
    # draw / render
     screen.fill(BGCOLOR)
     all_sprites.draw(screen)
     pygame.display.update() # or flip()
pygame.quit()
quit()
-----------------
각각의 요소들은 클래스를 이용해서 생성하고 sprite 그룹에 등록해서 관리를 편하게 해준다. 충돌 감지등을 할때 편리하다.  각각의 스프라이트 클래스에 원하는대로 동작이나 모양을 지정해 주면 된다.


파이썬 : 윈도우에서 pygame을 이용하여 게임 개발하기(1)

윈도우에서 파이썬으로 간단한 게임을 개발해 보기로 하자. 이전에 해 본것 같은데 복습이 될듯 하다. pygame을 사용하기 위해서 먼저 설치를 해줘야 한다.
python -m pip install -U pygame –user
먼저 게임패드를 파이썬에서 어떻게 읽어 들릴까? 자바스크립트에서 끙끙대며 겨우 알아 냈었는데 파이썬도 마찬가지로 겨우 알아 냈다. 필요한 버튼만 찾아 내자. 나머지 버튼은 동일한 방식으로 활용하면 된다. 먼저 간단히 게임패드로 화면의 박스를 움직이는 예제를 만들어 보자.  좌, 우 스틱을 이용해서 박스를 움직이도록 했다. 전면의 L1과 R1에는 슈팅기능이나 기타 기능을 연결해 주면 될듯 하다. 예제에서는 색상이 변하도록 했다.  양손으로 오브젝트를 따로 따로 움직이는게 쉬운게 아니구나..ㅋ
이미지 131
유아틱한 색상 좋아. 파이썬 코드를 살펴 보자.
------------- game.py----------
import pygame
pygame.init()
playerColor1 = (0, 180, 255)
playerColor2 = (180, 0, 180)
bgColor = (255, 200, 0) #background color
gameDisplay = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Control')
pygame.display.update()
gameExit = False
lead_x = 200
lead_y = 300
lead2_x = 400
lead2_y = 300
gamepads = []
clock = pygame.time.Clock()

width, height = pygame.display.get_surface().get_size()
font = pygame.font.SysFont("comicsansms", 42)
basicfont = pygame.font.SysFont(None, 22)
text = font.render("Hello Pygame", True, (0, 128, 0))
stick1 = font.render("L", True, (0, 0, 0))
stick2 = font.render("R", True, (0, 0, 0))
basicText = basicfont.render('<info>', True, (0, 0, 0))

for i in range(0, pygame.joystick.get_count()):
     gamepads.append(pygame.joystick.Joystick(i))#연결된 모든 디바이스 배열에 추가
     gamepads[-1].init()
     gamepadInfo = basicfont.render("Detected joystics: " + gamepads[-1].get_name(), True, (0,0,0))
     gamepadInfo2 = basicfont.render("Button: " + str(gamepads[-1].get_numbuttons()), True, (0,0,0))
     gamepadInfo3 = basicfont.render("Stick: " + str(gamepads[-1].get_numaxes()), True, (0,0,0))

while not gameExit:
     clock.tick(60)
    
     for event in pygame.event.get():
         if event.type == pygame.QUIT:
             gameExit = True
    # 버튼을 누르면
     if event.type == pygame.JOYBUTTONDOWN :
         if event.button == 4:
             playerColor1 = (255, 0, 0)
         if event.button == 5:
             playerColor2 = (255, 0, 0)
     else:
         playerColor1 = (0, 180, 255)
         playerColor2 = (180, 0, 180)

    # 스틱을 움직이면
     if event.type == pygame.JOYAXISMOTION:
         lead_x += gamepads[-1].get_axis(0) *4
         lead_y += gamepads[-1].get_axis(1) *4
         lead2_x += gamepads[-1].get_axis(4) *4 #뭐지 이 얼척없는 번호의 순서는?
         lead2_y += gamepads[-1].get_axis(3) *4
        #
        # 외곽을 벗어 나면
         if(lead_x > width):
             lead_x = 0
         elif(lead_x < 0):
             lead_x = width
         elif(lead_y > height):
             lead_y = 0
         elif(lead_y < 0):
             lead_y = height
        if(lead2_x > width):
             lead2_x = 0
         elif(lead2_x < 0):
             lead2_x = width
         elif(lead2_y > height):
             lead2_y = 0
         elif(lead2_y < 0):
             lead2_y = height
    # 화면에 그리기
     gameDisplay.fill(bgColor)
     pygame.draw.rect(gameDisplay, playerColor1, [lead_x, lead_y, 40, 40])
     pygame.draw.rect(gameDisplay, playerColor2, [lead2_x, lead2_y, 40, 40])
     gameDisplay.blit(stick1, (lead_x+10, lead_y-20))
     gameDisplay.blit(stick2, (lead2_x+10, lead2_y-20))
     gameDisplay.blit(text, (320 - text.get_width() // 2, 80 - text.get_height() // 2))
     gameDisplay.blit(basicText, (10, 20))
     gameDisplay.blit(gamepadInfo, (10, 40))
     gameDisplay.blit(gamepadInfo2, (10, 60))
     gameDisplay.blit(gamepadInfo3, (10, 80))
     pygame.display.update()
pygame.quit()
quit()
-------------
파이썬3으로 실행하면 된다. 이젠 기본이 파이썬3이다. 파이썬2? 그런게 있는지 난 모른다. 신경 안쓴다. ^^;
파이썬에서 게임패드 사용에 대한 자세한 내용은 아래 링크를 참조 하자.
https://www.pygame.org/docs/ref/joystick.html


목요일, 11월 8

윈도우에서 아나콘다(파이썬 배포판) 삭제하기

파이썬에 알 수 없는 혼선이 생겨서 아나콘다를 싹 지워 보기로 했다. 그런데 윈도우의 프로그램추가/삭제에서 제거가 안되기 때문에 아나콘다가 설치된 폴더를 찾아서 언인스톨러를 실행해서 지워줘야 한다고 한다.

보통 C:\Users\username\Anaconda3에 설치 되어 있다. 다른곳에 설치 했으면 그곳을 찾아야 한다. Uninstall-Anaconda3.exe 를 실행하자.

이미지 071

미련 없이 지우자. 나중에 다시 설치 하면 되니깐.

이미지 072

아나콘다를 재설치 하는 경우라면 시스템을 재부팅 한번 해주고 하는 것이 문제의 소지를 없도록 하는 방법이라고 한다.

월요일, 11월 5

NodeMCU(혹 아두이노)를 이용하여 웹소켓 통신하기


이것저것 두서 없이 다루다 보니 웹소켓은 해 본것인지 아닌지 헷갈린다. 중복되면 뭐 어때 자꾸 해봐야 알 수 있는 것인데.
이번에는 NodeMCU에 웹소켓 서버를 설치하고 통신을 시도해 보기로 하자.

20181106_091915

LED 두개를 연결해 두었다. 목표는 웹소켓을 이용 두개의 LED를 제어 해 보는 것이다.
먼저 아두이노 코드를 작성해 보자.
웹소켓에 대한 추가 정보는 아래 사이트에서 확인해 보자.
http://www.websocket.org/aboutwebsocket.html
http://www.zdnet.co.kr/news/news_view.asp?artice_id=20111028085010&lo=zv41


먼저 와이파이 연결을 하도록 설정하자.

#include "ESP8266WiFi.h"
//Wifi 연결하기
const char* ssid = "SSID";
const char* password = "PASSSWORD";
void setup() {
   Serial.begin(115200);
   connectWifi();
  
}
void loop() {
}
//wifi
void connectWifi(){
   Serial.print("Connecting to ");
   Serial.print(ssid);
  WiFi.disconnect(true);
   delay(1000);
   WiFi.begin(ssid, password);
   while(WiFi.status() != WL_CONNECTED){
     delay(500);
     Serial.print(".");
   }
  
   Serial.println("");
   Serial.println("WiFi connected");
   Serial.print("IP Address: ");
   Serial.print(WiFi.localIP());
   Serial.println("");
}

이미지 036

웹소켓 라이브러리를 설치해 주자. 라이브러리 매니저으로 들어 가자.
websockets를 검색해서 설치 해준다. 웹소켓 서버 코드를 작성하자.

#include "ESP8266WiFi.h"
#include "WebSocketsServer.h"
//Wifi 연결하기
const char* ssid = "SSID";
const char* password = "PASSWORD";

//WebSocket
WebSocketsServer webSocket = WebSocketsServer(80);
//Callback function(웹소켓 메세지를 수신하면 실행)
void onWebSocketEvent(uint8_t num,
                     WStype_t type,
                     uint8_t * payload,
                     size_t length) {
   //웹소켓이벤트의 타입
   switch(type) {
     //클라이언트 연결 해제시
     case WStype_DISCONNECTED:
       Serial.printf("[%u] Disconnected!\n", num);
       break;
       //클라이언트 연결시
     case WStype_CONNECTED:
       {
         IPAddress ip = webSocket.remoteIP(num);
         Serial.printf("[%u] Connected!\n", num);
         Serial.println(ip.toString());
       }
       break;
      
     //클라이언트에게 응답을 보낸다.
     case WStype_TEXT:
       Serial.printf("[%u] Text: %s\n", num, payload);
       webSocket.sendTXT(num, payload);
       break;
      
     //기타 필요에 따라
     case WStype_BIN:
     case WStype_ERROR:
     case WStype_FRAGMENT_TEXT_START:
     case WStype_FRAGMENT_BIN_START:
     case WStype_FRAGMENT:
     case WStype_FRAGMENT_FIN:
     default:
       break;
   }
}
void setup() {
   Serial.begin(115200);
   connectWifi();
  //Start websocket server
   webSocket.begin();
   webSocket.onEvent(onWebSocketEvent);//콜백실행
}
void loop() {
   //웹소켓 데이터를 기다림
   webSocket.loop();
}

//wifi
void connectWifi(){
   Serial.print("Connecting to ");
   Serial.print(ssid);
  WiFi.disconnect(true);
   delay(1000);
   WiFi.begin(ssid, password);
   while(WiFi.status() != WL_CONNECTED){
     delay(500);
     Serial.print(".");
   }
  
   Serial.println("");
   Serial.println("WiFi connected");
   Serial.print("IP Address: ");
   Serial.print(WiFi.localIP());
   Serial.println("");
}
<웹소켓 서버 코드>

소켓 데이터 수신을 기다렸다. 접속한 클라이언트 ip를 알려 주고 받은 값을 그대로 클라이언트에게 되돌려 주는 코드이다.
이제 라즈베리파이에서 클라이언트 프로그램을 코딩하자.

이미지 037

라즈베리파이에 파이썬 클라이언트를 만들자. 먼저 websocket-client를 설치해야 한다.
파이썬 2와 파이썬3에서 설치및 사용용어에 차이가 있다. 지금 작업중인 파이썬이 몇 버전인지 먼저 체크하고 파이썬3으로 시작하자.

pip3 install websocket-client

클라이언트 코드는 간단하다.

import websocket
#Connect to websocket server
ws = websocket.WebSocket()
ws.connect("ws://websocket server ip")
print("Connected to WebSocket Server")
#Ask the user for some input
inputStr = input("Say something: ")
ws.send(inputStr)
#Wait for server to respond
result = ws.recv()
print("Received: " + result)
#Socket close
ws.close()


이제 실행해 보자. 파이썬3으로 실행해야 한다.

이미지 038
<NodeMCU 결과>

이미지 039
<라즈베리파이 파이썬 결과>

정상적으로 동작하는 것을 확인 할 수 있다. 이렇게 해서 웹소켓을 통해 소켓통신이 가능해 졌다. 이제 이것으로 좀 더 응용을 해 보기로 하자.

다음편에 계속 …

수요일, 7월 6

파이썬(2) - 라즈베리파이와 PC 소켓 통신하기

파이썬을 이용해서 라즈베리파이와 PC 사이에 소켓통신을 해 보는 간단한 실습... 그런데 완벽하지 않다. 파이썬 버전에 따라 str 변환에 곤란을 겪었다. 완전히 이해를 못한 상태이다.

라즈베리파이 - 파이썬 서버


#python3 import socket import sys HOST = '' #all available interfaces PORT = 8888 #1. open Socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print ('Socket created') #2. bind to a address and port try: s.bind((HOST, PORT)) except socket.error as msg: print ('Bind Failed. Error code: ' + str(msg[0]) + ' Message: ' + msg[1]) sys.exit() print ('Socket bind complete') #3. Listen for incoming connections s.listen(10) print ('Socket now listening') #keep talking with the client while 1: #4. Accept connection conn, addr = s.accept() print ('Connected with ' + addr[0] + ':' + str(addr[1])) #5. Read/Send data = conn.recv(1024) if not data: break conn.sendall(data) print(data.decode()) conn.close() s.close()





PC 파이썬 클라이언트 코드 


#python3 import socket HOST = 'server-ip' PORT = 8888 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) msg=input() s.send(msg.encode(encoding='utf_8', errors='strict')) data = s.recv(1024) print ('result: ' + data.decode()) s.close()

간단한 데이터를 주고 받을 수 있게 되었다.그런데 중요한 안드로이드와의 소켓통신은 어떻게 하나...
Blogger Widget