23.03.20 Day35

오윤범·2023년 3월 20일
0
post-custom-banner

DinoRun 마무리(PyGame)

# DinoRun / 공룡 달리기(크롬)
import pygame
import os
import random # 구름 생성 시 필요했음

pygame.init()

ASSETS='./PyGame/Assets/' #경로 계속 적기 귀찮으니까 하나의 변수로 지정
SCREEN_WIDTH=1100 # 게임 윈도우 넓이 
SCREEN_HEIGHT=600
SCREEN=pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))

# form 상단에 나오는 이름 / 이미지 출력
pygame.display.set_caption('다이노 런')
icon = pygame.image.load('./PyGame/dinoRun.png')
pygame.display.set_icon(icon)

bg=pygame.image.load(os.path.join(f'{ASSETS}Other','Track.png'))

#공룡 이미지
#뛰는 모션 / 애니메이션
RUNNING = [pygame.image.load(f'{ASSETS}Dino/DinoRun1.png'),
           pygame.image.load(f'{ASSETS}Dino/DinoRun2.png')]

#숙이는 모션
DUCKING = [pygame.image.load(f'{ASSETS}Dino/DinoDuck1.png'),
           pygame.image.load(f'{ASSETS}Dino/DinoDuck1.png')]

#점프 모션
JUMPING = pygame.image.load(f'{ASSETS}Dino/DinoJump.png') # 점프는 사진 하나라 배열로 선언X

#시작이미지/종료 이미지
START=pygame.image.load(f'{ASSETS}Dino/DinoStart.png')
DEAD=pygame.image.load(f'{ASSETS}Dino/DinoDead.png')

#구름이미지
CLOUD = pygame.image.load(f'{ASSETS}Other/Cloud.png')

#익룡이미지
BIRD = [pygame.image.load(f'{ASSETS}Bird/Bird1.png'),
        pygame.image.load(f'{ASSETS}Bird/Bird2.png')]

#선인장 이미지 / 애니메이션이 아니고 선인장 종류가 세개임
LARGE_CACTUS = [pygame.image.load(f'{ASSETS}Cactus/LargeCactus1.png'),
                pygame.image.load(f'{ASSETS}Cactus/LargeCactus2.png'),
                pygame.image.load(f'{ASSETS}Cactus/LargeCactus3.png')]

SMALL_CACTUS = [pygame.image.load(f'{ASSETS}Cactus/SmallCactus1.png'),
                pygame.image.load(f'{ASSETS}Cactus/SmallCactus2.png'),
                pygame.image.load(f'{ASSETS}Cactus/SmallCactus3.png')]

# 공룡 클래스
class Dino: 
    X_POS=80 ; Y_POS = 310 ; Y_POS_DUCK = 340 ; JUMP_VEL = 9.0

    def __init__(self) -> None:
        self.run_img=RUNNING
        self.duck_img=DUCKING
        self.jump_img=JUMPING

        self.dino_run=True
        self.dino_duck=False
        self.dino_jump=False

        self.step_index=0
        self.jump_vel=self.JUMP_VEL # 점프 초기값 9.0
        self.image=self.run_img[0]
        self.dino_rect=self.image.get_rect() # 이미지 사각형 정보
        self.dino_rect.x=self.X_POS
        self.dino_rect.y=self.Y_POS


    def update(self,userInput) -> None:
        if self.dino_run:
            self.run()
        elif self.dino_duck:
            self.duck()
        elif self.dino_jump:
            self.jump()

        if self.step_index>=10 : self.step_index=0 # 애니메이션 스텝을 위해서 씀

        if userInput[pygame.K_UP] and not self.dino_jump : #점프
            self.dino_run=False
            self.dino_duck=False
            self.dino_jump=True
            self.dino_rect.y=self.Y_POS # 점프 할때마다 올라가는거 방지
        elif userInput[pygame.K_DOWN] and not self.dino_jump: #숙이기
            self.dino_run=False
            self.dino_duck=True
            self.dino_jump=False
        elif not (self.dino_jump or userInput[pygame.K_DOWN]): # 달리기
            self.dino_run=True
            self.dino_duck=False
            self.dino_jump=False

    # 공룡 달리는 부분
    def run(self): 
        self.image=self.run_img[self.step_index//5]  # run_img
        self.dino_rect=self.image.get_rect() # 이미지 사각형 정보
        self.dino_rect.x=self.X_POS
        self.dino_rect.y=self.Y_POS
        self.step_index+=1

    # 공룡 숙이는 부분
    def duck(self):
        self.image=self.duck_img[self.step_index//5] # duck_img
        self.dino_rect=self.image.get_rect() # 이미지 사각형 정보
        self.dino_rect.x=self.X_POS
        self.dino_rect.y=self.Y_POS_DUCK # 이미지 높이 따로 설정
        self.step_index+=1

    # 공룡 점프하는 부분
    def jump(self):
        self.image=self.jump_img
        if self.dino_jump:
            self.dino_rect.y-=self.jump_vel * 4
            self.jump_vel -= 0.8
        if self.jump_vel<-self.JUMP_VEL: # 초기에 설정해둔 9.0이 되버리면 점프 중단
            self.dino_jump=False
            self.jump_vel=self.JUMP_VEL # 9.0으로 다시 초기화


    def draw(self,SCREEN) -> None:
        SCREEN.blit(self.image,(self.dino_rect.x,self.dino_rect.y))

#구름 클래스
class Cloud: 
    def __init__(self) -> None:
        self.x = SCREEN_WIDTH + random.randint(300,500)
        self.y = random.randint(50,100)
        self.image=CLOUD
        self.width=self.image.get_width()

    def update(self) -> None:
        self.x-=game_speed
        if self.x < -self.width: #화면밖으로 벗어나면
            self.x=SCREEN_WIDTH + random.randint(1300,2000)
            self.y=random.randint(50,100)

    def draw(self,SCREEN) -> None:
        SCREEN.blit(self.image, (self.x,self.y))

#장애물 클래스(부모 클래스)
class Obstacle:
    def __init__(self,image,type) -> None:
        self.image=image
        self.type=type
        self.rect=self.image[self.type].get_rect()
        self.rect.x=SCREEN_WIDTH #1100

    def update(self)->None:
        self.rect.x-=game_speed
        if self.rect.x<=-self.rect.width: # 왼쪽 화면 밖으로 벗어나면
            obstacles.pop() # 장애물(배열) 에서 값들을 하나씩 빼옴


    def draw(self,SCREEN)->None:
        SCREEN.blit(self.image[self.type],self.rect)

#장애물 클래스 상속클래스(익룡)
class Bird(Obstacle): 
    def __init__(self, image) -> None:
        self.type=0 # 새는 0
        super().__init__(image,self.type)
        self.rect.y=250 # 새라서 하늘에 그림그려야하니까 y좌표 올림
        self.index=0 #0이미지로 시작

    def draw(self,SCREEN)->None:#draw 재정의
        if self.index >= 9:
            self.index=0
        SCREEN.blit(self.image[self.index//5],self.rect)
        self.index+=1

#장애물 (선인장)
class LargeCactus(Obstacle):
    def __init__(self, image) -> None:
        self.type=random.randint(0,2) # 큰 선인장 세가지 종류
        super().__init__(image, self.type)
        self.rect.y=300

class SmallCactus(Obstacle):
    def __init__(self, image) -> None:
        self.type=random.randint(0,2) # 작은 선인장 세가지 종류
        super().__init__(image, self.type)
        self.rect.y=325

def main():
    global game_speed, x_pos_bg , y_pos_bg, points , obstacles , font 
    x_pos_bg = 0
    y_pos_bg = 380
    points=0 # 게임 점수
    run=True
    clock=pygame.time.Clock()
    dino=Dino() # 공룡 객체 생성
    cloud = Cloud() # 구름 객체 생성
    game_speed = 14
    obstacles=[]
    death_count = 0

    font=pygame.font.Font(f'{ASSETS}NanumGothicBold.ttf',size=20)

    def background(): # 함수 내 함수 즉 main 함수에서만 사용, 땅바닥 update와 draw 동시에 해주는 함수
        global x_pos_bg, y_pos_bg 
        image_width=bg.get_width() # track 이미지 2404쯤됨
        SCREEN.blit(bg,(x_pos_bg,y_pos_bg)) # 0,300 먼저 그림
        SCREEN.blit(bg,(image_width+x_pos_bg,y_pos_bg)) # 2404+ 0,380

        if x_pos_bg<=-image_width:
            #SCREEN_WIDTH.blit(bg,(image_width+x_pos_bg,y_pos_bg))
            x_pos_bg=0

        x_pos_bg-=game_speed

    def score(): # main 함수에서만 사용가능한 함수 내 함수 / 점수 표시
        global points, game_speed
        points+=1
        if points % 100==0: #100,200,300... 
            game_speed +=1 #점수가 높아질수록 게임 속도가 빠르게

        txtScore=font.render(f'SCORE : {points}', True , (83,83,83)) #공룡과 색 맞춤(회색)
        txtRect=txtScore.get_rect()
        txtRect.center = (1000,40)
        SCREEN.blit(txtScore,txtRect)

    while run:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                run=False

        SCREEN.fill((255,255,255)) # 배경 흰색
        userInput=pygame.key.get_pressed() #키보드입력

        background()
        score()

        cloud.draw(SCREEN) # 구름이 애니메이션
        cloud.update() # 구름이 공룡보다 먼저 그려져야됨

        dino.draw(SCREEN) # 공룡 그리기
        dino.update(userInput)

        if len(obstacles)==0:
            if random.randint(0,2)==0:#작은선인장
                obstacles.append(SmallCactus(SMALL_CACTUS))
            elif random.randint(0,2)==1:#큰선인장
                obstacles.append(LargeCactus(LARGE_CACTUS))
            elif random.randint(0,2)==2:#새
                obstacles.append(Bird(BIRD))

        for obs in obstacles:
            obs.draw(SCREEN)
            obs.update()
            #Collision Detection 충돌 감지 시 게임 종료
            if dino.dino_rect.colliderect(obs.rect): # 장애물에 부딪히면 표시
                #pygame.draw.rect(SCREEN,(255,0,0),dino.dino_rect,3)
                pygame.time.delay(300) #1.5초 딜레이 생성
                death_count +=1 #죽음
                menu(death_count) #메인 메뉴화면으로 전환

        clock.tick(30)
        pygame.display.update() # 초당 30번 update 수행함

#메뉴함수
def menu(death_count): 
    global points, font
    run = True
    font=pygame.font.Font(f'{ASSETS}NanumGothicBold.ttf',size=20)

    while run:
        SCREEN.fill((255,255,255))
        #최초 상태(죽지않은)
        if death_count == 0 :
            text=font.render('시작하려면 아무 키나 누르세요',True,(83,83,83))
            SCREEN.blit(START,(SCREEN_WIDTH//2-20,SCREEN_HEIGHT//2-140))
        #죽음
        elif death_count >0:
            text=font.render('재시작하려면 아무키나 누르세요',True,(83,83,83))
            score=font.render(f'SCORE : {points}',True,(83,83,83))
            scoreRect=score.get_rect() # 변경되는 점수를 사각형 영역으로 잡아서 처리
            scoreRect.center=(SCREEN_WIDTH//2,SCREEN_HEIGHT//2+50) #점수 표시를 위해 Y좌표 50만큼 더 내림
            SCREEN.blit(score,scoreRect)
            SCREEN.blit(DEAD,(SCREEN_WIDTH//2-20,SCREEN_HEIGHT//2-140))

        textRect=text.get_rect()
        textRect.center = (SCREEN_WIDTH//2,SCREEN_HEIGHT//2)
        SCREEN.blit(text,textRect) #text를 textRect위치에 그려줌
        pygame.display.update()

        #pygame에서 event 발생시(키보드 클릭 등) 
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                run=False
                pygame.quit()
            if event.type==pygame.KEYDOWN:
                main()

if __name__=='__main__':
    menu(death_count=0)



전국 대학교를 지도에 표시(Folium)

#PyQT에 folium 지도 표시
import sys
import folium
import io 
import pandas as pd
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import QWebEngineView #pip install PyQtWebEngine

class qtApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('전국대학교 위치')
        self.width,self.height=1000,800
        self.setMinimumSize(self.width,self.height)

        layout=QVBoxLayout()
        self.setLayout(layout)

        filePath='./Python_practice/university_locations.xlsx'
        df_excel=pd.read_excel(filePath,engine='openpyxl',header=None)
        df_excel.columns=['학교명','주소','lng','lat']

        name_list=df_excel['학교명'].to_list() # 학교명을 name_list에 다 담음
        addr_list=df_excel['주소'].to_list()
        lng_list=df_excel['lng'].to_list()
        lat_list=df_excel['lat'].to_list()


        m=folium.Map(location=[37.553175,126.989326],zoom_start=10)

        for i in range(len(name_list)):
            if lng_list[i] !=0:#위/경도 값이 0이 아니면
marker=folium.Marker([lat_list[i],lng_list[i]],popup=name_list[i],
                                    icon=folium.Icon(color='blue'))
                marker.add_to(m)

        data=io.BytesIO()
        m.save(data,close_file=False)

        webView=QWebEngineView()
        webView.setHtml(data.getvalue().decode()) # 가져오는 데이터를 html로 저장
        layout.addWidget(webView)

if __name__=='__main__':
    app=QApplication(sys.argv)
    ex=qtApp()
    ex.show()
    sys.exit(app.exec_())

Calculator 앱(PyQt 활용)

import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import math

class qtApp(QWidget):
    def __init__(self):
        super().__init__()
        uic.loadUi('./PyQt_Practice/calculator.ui',self)

        #시그널 16개인데 슬롯함수 1개임
        self.btn_C.clicked.connect(self.btnClicked)
        self.btn_number0.clicked.connect(self.btnClicked)
        self.btn_number1.clicked.connect(self.btnClicked)
        self.btn_number2.clicked.connect(self.btnClicked)
        self.btn_number3.clicked.connect(self.btnClicked)
        self.btn_number4.clicked.connect(self.btnClicked)
        self.btn_number5.clicked.connect(self.btnClicked)
        self.btn_number6.clicked.connect(self.btnClicked)
        self.btn_number7.clicked.connect(self.btnClicked)
        self.btn_number8.clicked.connect(self.btnClicked)
        self.btn_number9.clicked.connect(self.btnClicked)

        self.btn_result.clicked.connect(self.btnClicked)
        self.btn_minus.clicked.connect(self.btnClicked)
        self.btn_add.clicked.connect(self.btnClicked)
        self.btn_multipy.clicked.connect(self.btnClicked)
        self.btn_divide.clicked.connect(self.btnClicked)

        self.txt_view.setEnabled(False)
        self.text_value=''

    def btnClicked(self):
        btn_val=self.sender().text()
        if btn_val=='C': # clear
            print('clear')
            self.txt_view.setText('0')
            self.text_value=''
        elif btn_val=='=': #계산결과
            print('=')
            try:
                result=eval(self.text_value.lstrip('0'))
                print(round(result,4))
                self.txt_view.setText(str(round(result,4))) # 소수점 4자리까지만
            except:
                self.txt_view.setText('ERROR')
        else:
            if btn_val=='X':
                btn_val='*'
            self.text_value += btn_val
            print(self.text_value)
            self.txt_view.setText(self.text_value)

if __name__=='__main__':
    app=QApplication(sys.argv)
    ex=qtApp()
    ex.show()
    sys.exit(app.exec_())

post-custom-banner

0개의 댓글