728x90
반응형

 미니 프로젝트로 만드는 웹 페이지에 이것저것 추가하다가 날씨 정보를 불러오고 싶었다. 다양한 방법을 찾아보다 날씨 정보를 무료 API로 받아 올 수 있는 Open Weather 사이트를 이용해 보았다.

https://openweathermap.org/

 

Сurrent weather and forecast - OpenWeatherMap

Access current weather data for any location on Earth including over 200,000 cities! The data is frequently updated based on the global and local weather models, satellites, radars and a vast network of weather stations. how to obtain APIs (subscriptions w

openweathermap.org

 

날씨 API를 받아오는 방법

1.Key 발급

해당 사이트 로그인 후 나의 계정 My API Keys에 들어가면 발급 된 Key가 보일 것이다. (Key는 따로 메모해둔다)

 

2. Current Weather Data

상단 카테고리 중 API 로 들어간다. 아래로 내려가면 Current Weather Data가 보일 것이다. 아래 API doc을 클릭한다.

 

3. Json 호출

API doc에 들어가서 아래로 내려가다 보면 아래와 같은 링크가 있다.

https://api.openweathermap.org/data/2.5/weather?q={city name}&appid={API key}

 

{city name}에 날씨를 알고 싶은 도시(ex. seoul, london 등) 를 넣고 {API key]에는 자신의 key(1번 내용)를 넣어서 주소를 입력하면 Json형식으로 현재의 날씨정보을 알려준다.

 

날씨 API 활용

 받아온 날씨 API를 이용해 날씨를 검색해 볼 수 있는 웹을 구현해 보았다. 도시명을 입력하면 기본값인 Gwangju 옆으로 검색한 도시의 날씨가 보여진다.

728x90
반응형
728x90
반응형

개요

 

컴퓨터의 구성

1. 중앙처리장치(CPU: Central Processing Unit) - 산술/논리 연산, 흐름제어

2. 주기억장치(Memory)-임시저장소

3. 보조기억장치(Secondary storage)

4. 다양한 입/출력 장치(input/output(I/O) device) -HDD, SSD 등 데이터소스, 영구 저장소

컴퓨터에서 가장 중요한 부품인 CPU가 담당하는 기능
→계산기 능력과 순서를 제어하는 중앙 처리 장치
1개의 CPU(Core)안에
레지스터(임시저장) + ALU(산술/연산 유닛) + CU(흐름제어 유닛)

 

▶ALU는 계산기. 계산만을 위해 존재. 컴퓨터 내부에서 수행되는 대부분의 계산은 ALU가 수행

▶ 레지스터는 CPU 내부의 임시 저장 장치. 프로그램을 실행하는 데 필요한 값들을 임시로 저장. CPU 안에는 여러 개의 레지스터가 존재하고 각기 다른 이름과 역할을 함.

▶ 제어장치는 제어 신호라는 전기 신호(컴퓨터 부품들을 관리하고 작동시키기 위한 일종의 전기 신호)를 내보내고 명령어를 해석하는 장치.


컴퓨터 언어

Code

어셈블리어(문자코드, 의사코드): 어셈블리어는 기계어에 비해 사람이 이해하기 쉬운 저수준 프로그래밍 언어. 어셈블리어는 특정 컴퓨터 아키텍처에 대한 기계어 명령어를 기호화하여 표현한다.

기계어(숫자코드, 실행코드): 기계어는 컴퓨터가 직접 이해하고 실행하는 프로그래밍 언어. 이진 코드로 표현되며, 각각의 명령어와 데이터를 특정 비트와 바이트의 패턴으로 나타낸다.

 

*전달하고 해석할 때 동일한 코드를 사용하는 것이 무엇보다 중요하다.

 

알파벳을 위한 약속: 아스키 코드

ABC를 0과 1로 표현하는 방법 

ex) cmd에서 Alt+65를 치면 A가 입력됨

 

                                 인코딩(Encoding) →

사람의 언어                 번역: 컴파일러                   컴퓨터 언어

                                 ←디코딩(Decoding)

 

모든 언어를 위한 코드: 유니코드

16bit 사용

아스키코드 + 전 세계 언어에 대한 코드

 

프로그래밍 언어

사람이 알아볼 수 있는 언어로 작성하면 이것을 기계어로 번역해서 컴퓨터에게 알려주는 도구

기계어 < 어셈블리어 < 하이레벨 언어 < C언어 자바 파이썬 등

 

기계마다 다른 기계어

각각의 제작사에서 만드는 중앙처리장치는 저마다 특성이 다르기 때문에, 서로의 기계어가 다르다. 그래서 기계어에 관해서 이야기할 때는 반드시 적용되는 기준 기계를 함께 표시해 준다.

같은 프로그래밍 언어라도 기계가 다르면 (예를 들어, 윈도우 pc와 맥 pc) 컴파일러가 서로 달라야 하기 때문이다.

 

컴퓨터 언어 번역기: 컴파일러

사람이 알아볼 수 있는 단어로 작성된 언어를 컴퓨터가 이해하는 언어로 변환하는 작업을 컴파일 Complie이라고 한다.

컴파일 언어로 만든 프로그램을 실행하는 방법

complie install run excute

 

스크립트 언어 (vs 컴파일 언어)

자바스크립트와 파이썬의 코드는 1줄

이 두 언어는 스크립트 언어이기 때문

 

스크립트 언어: 스크립트 언어는 인터프리터를 사용하여 소스 코드를 런타임 중에 해석하고 실행한다. 이것은 소스 코드를 기계어로 변환하는 별도의 컴파일 단계가 없음을 의미한다. (ex. Python, JavaScript, Ruby, PHP 등)

컴파일 언어: 컴파일 언어는 소스 코드를 컴파일러를 사용하여 기계 코드로 먼저 변환한 다음 실행한다. 이것은 실행 전에 미리 컴파일 단계가 필요다. (ex. C, C++, Java, C# 등)

 

 


파이썬 소개

 

컴퓨터 시스템의 발전

1. 컴퓨터와 4차 산업혁명

-컴퓨터의 발전

-1946년 애니악

     #컴퓨터의 다양한 활용분야

     -범용기계

     -튜링 머신의 개념(1937년 알란 튜링)

     -인간 두뇌와 컴퓨터(마이크로 프로세서 칩)의 비교

2. 정보 통신과 네트워크

-컴푸터 네트워크의 중요성

-다양한 컴퓨터 네트워크

3.인터넷과 초연결사회

-인터넷의 개념과 발전

-인터넷 서비스의 발전 역사

     >>초기 정보검색 수단

     >>'인터넷 경제' 시대의 도래

 4. 웹의 출현

-1989년 스위스 CREN 연구소의 팀 버너스리

5.초연결사회로 변화

-초연결사회

     >>인터넷, 사물인터넷, 센서의 발달

 

소프트웨어의 중요성

-무어의 법칙: 마이크로프로세서 칩의 성능은 18개월 마다 두 배씩 증가한다.

-소프트웨어의 생산성

-하드웨어의 비용이 급격히 감소, 소프트웨어의 비용은 매우 빠르게 증가

>>인공지능, 빅데이터 분석, 사물인터넷, 자율주행 자동차, 모바일 컴퓨팅의 핵심 기술은 소프트 웨어(즉, 알고리즘)

 

프로그래밍 언어의 발전

 -프로그래밍 언어의 역사

     >> 4가지 패러다임: 절차적 언어, 객체지향 언어, 선언적 언어, 함수형 언어

-절차적 언어와 객체지향 프로그래밍 언어

 

컴파일러와 인터프리터

-기계어와 고수준 언어

     >>기계어: 하드웨어에서 자료 표현의 기본 단위인 비트값 0과 1로 표현

-컴파일러: 고수준 언어로 작성된 프로그램을 특정 CPU의 기계어로 번역

-인터프리터: 미리 번역해두는 것이 아니고 프로그램이 실행 될때 한문장 씩 기계어로 해석

 

파이썬의 철학과 특징

-파이썬의 철학

1991년 네덜란드의 귀도 반 로썸

쓰기 쉽고 이해하기 쉬운 프로그래밍 언어로 개발

 

Python

장점: 단순성, 오픈소스 언어, high-level 언어, interpreted, 객체지향적, 가독성, 간결한 언어

제약점: C, C++, Java에 비해여 실행 속도가 늦다

 

인공지능, 빅데이터 분석, 딥러닝, 컴퓨터 비전 영역의 다양한 외부 라이브러리 모듈의 지원으로 파이썬이 많이 이용되고 있다.

사이킷-런, 텐서플로우, 아파치 스파크, 파이토치 등 성능도 뛰어나며 많이 사용되는 머신러닝, 딥러닝 프레임워크들이 파이썬으로 접근이 가능하다.

 

파이썬은 어디에 작성하는가?

텍스트 에디터와 대화형 인터프리

VS Code, PyCharm, Jupyter Notebook, Colaboratory 등

 

문제 해결 방법론

-폴야의 문제 해결과정

1. 주어진 문제의 이해

2. 문제를 풀기위한 구체적 방법 > 알고리즘

3. 찾은 방법에 따라 실현 > 프로그램

4. 신뢰성 검증

 

알고리즘의 중요성

컴퓨터과학은 알고리즘에 관한 공부

 알고리즘은 컴퓨터과학에서 가장 중요한 개념이며 핵심 주제

 

소프트웨어와 알고리즘

알고리즘의 실현

-'잘 정의된 기본 절차(Well-defined Primitives)'들을 이용

-잘 정의된 기본 절차는 어떤 시스템을 만드는 '빌딩 블록'

-기본절차: 소프트웨어 개발에서 기본 절차는 프로그래밍 언어


 

추천 사이트

 

1. 타이핑 연습

https://www.speedcoder.net/

 

Typing Practice for Programmers | SpeedCoder

 

www.speedcoder.net

2. 프로그래밍에 대한 Q&A

https://stackoverflow.com/ 

 

Stack Overflow - Where Developers Learn, Share, & Build Careers

Stack Overflow | The World’s Largest Online Community for Developers

stackoverflow.com

3. 번역  

https://www.deepl.com/

 

DEEP

engineering wonder Making Humans Aquatic DEEP exists to radically advance how humankind can access, explore and inhabit underwater environments. Through flexible, modular subsea habitats, work-class submarines, and advanced human performance research, DEEP

www.deep.com

 


Python 설치 

 

1. Data Spell

https://www.jetbrains.com/  

 

JetBrains: Essential tools for software developers and teams

JetBrains is a cutting-edge software vendor specializing in the creation of intelligent development tools, including IntelliJ IDEA – the leading Java IDE, and the Kotlin programming language.

www.jetbrains.com

DataSpell에서 편의성 향상을 위해 설치할 옵션

Indent Rainbow (들여쓰기)

Key Promotor X (단축키 알려주는 옵션)

Material Theme Ul

Rainbow brackets

https://github.com/naver/d2codingfont 에서 글꼴 다운 받고 Dataspell 시스템 설정 내에서 적용

 

2. 파이썬 인터프리터 (필요한 라이브러리 제공)

설치 시 PC에 Microsoft Visual C++ Redistributable 설치 여부 확인

https://www.anaconda.com/  

 

Anaconda | The World’s Most Popular Data Science Platform

Anaconda is the birthplace of Python data science. We are a movement of data scientists, data-driven enterprises, and open source communities.

www.anaconda.com

 

아나콘다 설치 후 시스템 환경 변수 확인

 

※ 아나콘다 설치 시 아래 내용에 체크 해야 path에 아나콘다가 환경 변수로 들어온다.

  설치가 완료되면 Git Bash를 통해 설치된 경로와 버전을 확인 할 수 있다.

728x90
반응형
728x90
반응형

 미니 게임 만들기

 

목차

1. 게임에 대한 간단한 설명

2. 게임 실행 영상

3. 주요 코드

4. 어려웠던 점

 

1. 게임에 대한 간단한 설명

프로젝트의 일부분으로 미디어 카테고리에 전기차를 주제로 게임을 만들어보았다.

 해당 페이지에 들어오면 본 게임 시작 전에 미니 게임이 진행된다. 키보드를 이용해 지도 위에 있는 전기차를 이동시켜 주유소에 도달하면 본 게임으로 들어가게 된다. 

 본 게임은 스페이스바를 눌러 다가오는 장애물을 점프로 피해 목적지에 도달하는 게임이다. 목적지인 주유소는 Score가 150점에 도달하면 화면상에 나타나게 해 놓았고 주유소에 도달하면 게임 성공에 관련 된 모달이 뜬다. 성공 모달에서 찌리릿 코인을 받을 수 있으며 이 코인을 10개 모으면 쿠폰으로 교환할 수 있도록 다른 카테고리에 구현해 놓았다. 

 게임은 여러번 할 수 있지만 코인은 하루에 1개만 수집할 수 있도록 설정해 두었으며 게임을 진행하다 목적지에 도달하기 전에 장애물에 부딪히면 게임 실패에 관련 된 모달이 뜨고 실패 모달에서 다시하기 버튼을 눌러 게임을 다시 실행할 수 있다. 

 

2. 게임 실행 영상

3. 주요 코드

3 - 1. 게임 화면을 구성한 Html

    <!-- 게임 화면 -->
    <div class="game-wrap">
        <div class="bakcground">
            <div class="ground"></div>
            <a th:href="@{/home}">
                <div class="sun" th:style="'background-image:url(' + @{/eco-house.png} + ')'"></div>
            </a>
        </div>
        <div class="score">
            <p>SCORE</p>
            <span></span>
        </div>
        <canvas id="canvas" height="200"></canvas>
    </div>
    <!-- 안내 -->
    <h3 class="info">SPACE BAR로 JUMP 하세요! <br> 주유소에 도달하면 코인이 지급됩니다.</h3>
    <!-- 성공/실패 모달 -->
    <div class="game-over">
        <div class="pop-up">
            <img class="game-over-img" th:src="@{/link.png}" alt="게임오버" />
            <h2>충전소를 찾지 못했다!</h2>
            <p><span class="total-score"></span> 점</p>
            <button class="replay">다시하기</button>
            <button class="home">홈으로</button>
            <button class="get-coins" style="display: none;">찌리릿 코인 받기</button>
        </div>
    </div>

3 - 2. 관련 CSS 

본 게임 배경에 나오는 폭죽은 아래 링크에서 사용한 방법을 프로젝트 html에 적용 하였다.

https://mzero.tistory.com/13

 

Tistory에 마우스 애니메이션 효과 적용하는 방법

현재 나의 Tistory에 들어오면 마우스 움직임에 따라 애니메이션 효과가 따라 오는 걸 볼 수 있다. Tistory 외에도 자신이 만든 웹 사이트에서 마우스 커서에 효과를 넣을 수 있다. 1. 관련 사이트 먼

mzero.tistory.com

<style>
	.game-wrap {
        background-color: #000;
        position: relative;
        width: 100%;
        height: 100%;
    }

    .sun {
        position: absolute;
        top: 10px;
        right: 20px;
        width: 5rem;
        height: 5rem;
        background-image: url("/src/main/resources/static/der.png");
        background-size: cover;
        animation: rotate 5s linear infinite;
    }

    @keyframes rotate {
        to {
            rotate: 1turn;
        }
    }

    .ground {
        position: absolute;
        bottom: 0.8rem;
        left: 0;
        width: 100%;
        height: 0.2rem;
        background: #fff;
        z-index: 0;
    }

    .score {
        color: #fff;
        display: flex;
        gap: 6px;
        position: absolute;
        top: 8px;
        left: 0;
        font-size: 1.5rem;
    }

    .info {
        color: #fff;
        width: fit-content;
        margin: 0 auto;
        padding: 10px;
        border: 4px solid;
        border-radius: 8px;
        text-align: center;
        cursor: default;
    }

    #canvas {
        margin-top: 12rem;
        position: relative;
        z-index: 1;
    }

    .game-over {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.4);
        z-index: 10;
    }

    .game-over .pop-up {
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: 8px;
        align-items: center;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        max-width: 400px;
        width: 100%;
        height: fit-content;
        padding: 40px 0 32px;
        background-color: #fff;
    }

    .game-over .pop-up .replay {
        padding: 4px 8px;
        margin-top: 8px;
        border: 3px solid #191919;
        border-radius: 4px;
        background-color: #fff;
        font-size: 1.5rem;
        font-weight: bold;
        cursor: pointer;
    }

    .game-over .pop-up .home {
        padding: 4px 8px;
        margin-top: 8px;
        border: 3px solid #191919;
        border-radius: 4px;
        background-color: #fff;
        font-size: 1.5rem;
        font-weight: bold;
        cursor: pointer;
    }

    .game-over .pop-up .get-coins {
        padding: 4px 8px;
        margin-top: 8px;
        border: 3px solid #191919;
        border-radius: 4px;
        background-color: #fff;
        font-size: 1.5rem;
        font-weight: bold;
        cursor: pointer;
    }

    @media (max-width: 420px) {
        .game-over .pop-up {
            max-width: 300px;
        }
    }

    .game-over-img {
        width: 20rem;
        height: 20rem;
    }
</style>

3 - 3. 화면 구성과 관련된 Java Script

  • 본 게임 화면 우측 상단에 회전하는 집을 클릭하면 "/home" 경로로 이동하도록 이벤트 리스너를 설정하였다 .
  • let canvaslet ctx 부분은 게임 화면을 렌더링하는데 사용할 Canvas 요소와 2D Context를 가져온다.
  • electricCar 객체는 전기 자동차의 속성과 동작을 정의하고 있다. x, y는 자동차의 위치, widthheight는 자동차 이미지의 크기를 나타낸다. draw, jump, fall 메서드를 통해 자동차를 그리고, 점프와 낙하 동작을 처리하였다.
  • Box 클래스는 장애물을 나타낸다. draw 메서드를 통해 장애물을 생성하는데, 장애물의 위치는 화면 오른쪽 끝에서 시작하며 이미지는 장애물 이미지는 2개를 넣어 랜덤으로 번갈아 나오게 설정하였다.
	<script>
		const homeButton = document.querySelector(".home");
        homeButton.addEventListener("click", function () {
            window.location.href = "/home";
        });

        let canvas = document.getElementById("canvas");
        let ctx = canvas.getContext("2d");
        let currentCar = 0;
        canvas.width = window.innerWidth;

        var carImages = new Image();
        carImages.src = "/cargame.png";

		//전기차
        let electricCar = {
            x: 20,
            y: 50,
            width: 80,
            height: 80,
            draw() {
                ctx.drawImage(
                    carImages,
                    this.x,
                    this.y,
                    this.width,
                    this.height
                );
            },
            jump() {
                if (this.y > 40) {
                    this.y -= 60;
                }
            },
            fall() {
                if (this.y < 120) {
                    this.y += 10;
                }
            },
        };

        // 장애물
        var boxImages = [new Image(), new Image()];
        boxImages[0].src = "/pong.png";
        boxImages[1].src = "/pong2.png";

        class Box {
            constructor() {
                this.width = 40;
                this.height = 40;
                this.x = canvas.width - this.width;
                this.y = 155;

                // 장애물 이미지 선택
                const randomImageIndex = Math.floor(Math.random() * boxImages.length);
                this.image = boxImages[randomImageIndex];
            }
            draw() {
                ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
            }
        }
        
         // spaceBar
        var jumpSwitch = false;
        let lastSpacePressTime = 0;

        document.addEventListener("keydown", function (e) {
            if (e.code === "Space") {
                const currentTime = Date.now();
                const timeSinceLastPress = currentTime - lastSpacePressTime;

                if (timeSinceLastPress > 500) {
                    jumpSwitch = true;
                    lastSpacePressTime = currentTime;
                }
            }
        });
	</script>

3 - 4. 장애물, 도착지 생성 및 Score 관련 Java Script

  • Destination 클래스에서는 도착지의 속성과 초기 위치를 설정하고, 도착지가 다른 장애물들과 충돌하지 않도록 확인하도록 하였다. 만약 충돌이 발생하면 새로운 도착지를 생성한다.
  • createBox 함수는 장애물을 생성하고, 생성된 장애물이 다른 장애물이나 도착지와 충돌하지 않게 하였다. 만약 충돌이 있으면 다시 호출되어 장애물을 다시 생성하게 된다
  • updateScore 함수는 Score를 1씩 증가시키고, 게임화면 좌측 상단에 있는 Score를 업데이트한다.
	<script>
        // 도착지 이미지 로드
        let destinationImage = new Image();
        destinationImage.src = "/link.png";

        class Destination {
            constructor() {
                this.width = 100;
                this.height = 100;
                this.x = canvas.width - this.width; // 장애물과 동일한 위치에서 시작
                this.y = 95;

                // 새로 생성한 도착지와 다른 장애물들과의 충돌 확인
                let isCollision = manyBoxes.some(existingBox => {
                    return (
                        this.x < existingBox.x + existingBox.width &&
                        this.x + this.width > existingBox.x
                    );
                });

                // 충돌이 있으면 다시 생성 시도
                if (isCollision) {
                    return new Destination();
                }
            }

            draw() {
                ctx.drawImage(destinationImage, this.x, this.y, this.width, this.height);
            }
        }

        let manyBoxes = [];
        let destination;

        // 장애물 생성 함수
        function createBox() {
            let box = new Box();

            // 새로 생성한 장애물과 다른 장애물들 및 도착지와의 충돌 확인
            let isCollisionWithOtherBoxes = manyBoxes.some(existingBox => {
                return (
                    box.x < existingBox.x + existingBox.width &&
                    box.x + box.width > existingBox.x
                );
            });

            let isCollisionWithDestination =
                destination &&
                box.x < destination.x + destination.width &&
                box.x + box.width > destination.x;

            // 충돌이 없으면 배열에 추가, 있으면 다시 생성 시도.
            if (!isCollisionWithOtherBoxes && !isCollisionWithDestination) {
                manyBoxes.push(box);
            } else {
                createBox();  // 다시 생성 시도.
            }
        }
        
        // score
        let score = 0;
        let scoreInterval;

        function updateScore() {
            score += 1;
            document.querySelector(".score span").textContent = score;
        }
	</script>

3 - 5. 게임 진행시 반복적으로 실행되는 게임 Frame 관련 Java Script

    • requestAnimationFrame(frameRun)은 브라우저에게 다음 프레임에서 frameRun 함수를 호출하도록 요청하는 함수로 이를 통해 게임 루프가 지속적으로 실행한다.
    • if (timer % 10 === 0) 은 매 10프레임마다 스코어를 업데이트한다.
    • if (Math.random() < 0.005) 부분은 게임에서 무작위로 장애물을 생성하기 위한 확률적인 조건을 나타낸다. Math.random() 함수는 0 이상 1 미만의 값을 반환한다. 즉, 매 프레임에서 Math.random() 함수를 호출하여 0 이상 1 미만의 난수를 생성하고, 이 값이 0.005 미만일 때에만 실행된다. 이렇게 함으로써 매 프레임마다 장애물을 생성할 확률을 매우 낮게 만들고, 게임이 무작위로 장애물을 생성할 수 있다.
    • if (score == 150 && !isDestinationVisible) 은 도착지 생성 조건을 나타내고 있다. score가 150점 일 때 도착지를 생성하여 화면상에 나타나도록 설정하였다.
    • if (isDestinationVisible) 은 도착지가 화면에 표시되는 경우 실행되어 도착지의 위치를 업데이트하고, 플레이어가 도착지에 도달하면 게임이 성공으로 처리됩니다.
	<script>
    	let isDestinationVisible = false;
    	let timer = 0;
        let jumpTimer = 0;
        let animation;

        // 프레임마다 실행하기
        function frameRun() {
            animation = requestAnimationFrame(frameRun);
            timer++;
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // score 처리
            if (timer % 10 === 0) {
                updateScore();
            }
            
            // 무작위로 장애물 소환
            if (Math.random() < 0.005) {
                createBox();
            }

            // 도착지 생성 조건
            if (score == 150 && !isDestinationVisible) {
                isDestinationVisible = true;
                destination = new Destination();
            }

            if (isDestinationVisible) {
                destination.x -= 2;
                destination.draw();

                // 도착지에 도달하면 성공 처리
                if (electricCar.x + electricCar.width >= destination.x && electricCar.y + electricCar.height >= destination.y &&
                    electricCar.x <= destination.x + destination.width && electricCar.y <= destination.y + destination.height) {
                    showGameSuccess();
                    cancelAnimationFrame(animation);
                    clearInterval(scoreInterval);
                    return;
                }
            }

            // x좌표가 0미만이면 제거
            manyBoxes.forEach((a, i, o) => {
                if (a.x < 5) {
                    o.splice(i, 1);
                }
                a.x -= 2;
                // 충돌 체크
                crash(electricCar, a);
                a.draw();
            });

            // 점프!
            if (jumpSwitch == true) {
                electricCar.jump();
                jumpTimer++;
            }
            if (jumpSwitch == false) {
                if (electricCar.y < 120) {
                    electricCar.y++;
                }
            }
            if (jumpTimer > 40) {
                jumpSwitch = false;
                jumpTimer = 0;
            }
            electricCar.draw();
        }
	</script>

3 - 6. 충돌확인과 게임리셋 Java Script

	<script>
	// 충돌확인
        function crash(electricCar, box) {
            let xCalculate = box.x - (electricCar.x + electricCar.width);
            let yCalculate = box.y - (electricCar.y + electricCar.height);
            if (xCalculate < 0 && yCalculate < 0) {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                cancelAnimationFrame(animation);
                clearInterval(scoreInterval);
                const totalScore = document.querySelector(".total-score");
                totalScore.textContent = `${score}`;
                const sun = document.querySelector(".sun");
                const gameOver = document.querySelector(".game-over");
                sun.style.animationPlayState = "paused";
                gameOver.style.display = "block";
            }
        }
        
        // 리셋 버튼
        const replayBtn = document.querySelector(".replay");
        replayBtn.addEventListener("click", () => {
            resetGame();
        });

        // 게임리셋
        function resetGame() {
            cancelAnimationFrame(animation);
            clearInterval(scoreInterval);
            score = 0;
            document.querySelector(".score span").textContent = score;
            manyBoxes = [];
            currentCar = 0;
            jumpSwitch = false;
            lastSpacePressTime = 0;

            isDestinationVisible = false;
            destination = null;

            frameRun();

            const sun = document.querySelector(".sun");
            const gameOver = document.querySelector(".game-over");
            sun.style.animationPlayState = "running";
            gameOver.style.display = "none";

            // 스코어 인터벌 제거
            if (scoreInterval) {
                clearInterval(scoreInterval);
            }
            
            // 스코어 인터벌 다시시작
            scoreInterval = setInterval(updateScore, 2000);
        }
</script>

3 - 7. 게임 성공 시 뜨는 모달 Java Script

	<script>
    	// 도착지에 도달하면 게임 성공 팝업 표시
        function showGameSuccess() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            cancelAnimationFrame(animation);
            clearInterval(scoreInterval);

            const totalScore = document.querySelector(".total-score");
            totalScore.textContent = `${score}`;

            const sun = document.querySelector(".sun");
            const gameSuccess = document.querySelector(".game-over");

            sun.style.animationPlayState = "paused";
            gameSuccess.style.display = "block";

            let gameOverMsgElement = document.querySelector('.game-over .pop-up h2');
            gameOverMsgElement.textContent = '충전소에 도착했습니다!';

            const getCoinsButton = document.querySelector(".get-coins");
            getCoinsButton.style.display = "block"; // 버튼 표시

            getCoinsButton.addEventListener("click", async function () {
                const response = await fetch("/getCoins", {
                    method: "GET",
                });

                if (response.ok) {
                    const message = await response.text();
                    alert(message);
                    // 필요하다면 이후에 페이지를 새로고침하거나 다른 동작을 수행하세요.
                } else {
                    console.error("찌리릿 코인을 받는 중 오류가 발생했습니다: " + response.status);
                }
            });

            // "다시하기" 버튼을 숨깁니다.
            const replayButton = document.querySelector(".replay");
            replayButton.style.display = "none";
        }

	</script>

 

4. 어려웠던 점

 구현하는데 가장 시간이 오래 걸렸던 기능은 장애물이 생성되는 시간과 간격을 조절 하는 것이었다. 0.001초 단위로 장애물 생성의 변화가 크게 달라지다보니 적당한 시간을 찾기가 어려웠다.

 또한 게임을 하다보면 목적지와 장애물이 겹쳐나오거나 목적지를 지나치는 변수가 발생했다. 그래서 처음에 도착지를 지나치면 그 다음 설정한 점수에 도달했을 때도 목적지가 다시 생성되게 구현하고 싶었는데 아무리 코드를 작성해도 목적지가 한번 나오면 그 다음에 나오지 않았다. 결국 다른 방법으로 문제를 해결했는데 목적지인 주유소의 크기를 크게 만들어 목적지 근처에만 도달해도 성공할 수 있도록 수정하였다.

 

 

728x90
반응형
728x90
반응형

올해 5월에 다녀온 유럽여행 기록을
11월이 되서야 올리는 사람?


런던일기
1 - 2 일차

 
1일차
5월 18일
런던 도착

호텔 근처 Russell Square 역에서 나와 처음 마주한 런던
무거운 캐리어 들고 계단 올라올때까지만 해도 한국 돌아가고싶었는데
보자마자 싹 잊어버렸다
이때로 돌아가고싶다

체크인 하고 짐 대충 정리하고 근처 마트 가려고 나왔는데
문이 안잠기면 어떡하라는거야
마침 관리인이 지나가서 말씀드렸더니 기다리라고 하셔서
친구랑 가만히 서있는데 계속 안되는지 사람들이 하나 둘 늘어났다
나중에 한 5명 와있었나
방 안에서 계속 기다리다 결국 안되서 방 바꿔줬는데 바꾼 방이 너무 별로였다
쮀엣

대충 마무리 하고 마트가서 사온 것들
파예 요거트 먹고싶었는데 왜인지 런던에는 없었다
원래 안파나?
저 프로틴 빵은... 파리 넘어갈때 까지 남아있었다


2일차
5월 19일
본격적인 런던 투어

짜 런던이구나 느꼈던 빨간 2층 버스!
눈 돌릴 때 마다 너무 행복했다
건물 하나하나가 너무 예쁘고
그냥 여기 평생 살고 싶어
나 여기 다시 갈 수 있을까

지하철 타고 와서 걷다보니
저 멀리 보이는 런던에 온 이유
Tottenham Hotspur Stadium
웅장 삐까뻔쩍
그자체

투어 시작하기 전에
일단 굿즈샵 투어
시즌 종료 전이라 그런지 홈 유니폼이 없었다
나 저 간고등어 싫은뒈...
경기날 몇개 풀지 않을까 싶어서 일단 유니폼은 안사고 머플러만 샀다
근데 머플러 사진을 안찍었네

투어시작 !
나의 행복
나의 사랑
그리고
Son, H-M

나 홈구장 잔디도 밟아봤다
여기서 찍은 사진들 보면 
그렇게 행복해 보일 수 가 없음 

아프지말고
행축하자

역 앞에 있던 플리마켓
목요일에만 열리는 것 같았다.
여기서 피스타치오 티라미수 사 먹었는데
여긴 진짜 피스타치오에 진심이다
맛을 고를 수 있다?
무조건 피스타치오 레츠고 

짐 내려두려고 호텔 가다가 들린
호텔 바로 옆에 있던
Tavistock Square Garden
날씨가 너무 좋았다.
그래서 공원에서 만난 청설모 인생샷도 찍어줌✌️

 호텔에서 잠깐 쉬고
나와서
SOHO 갔는데
런던 사람들 여기 다 모였나?
사람이 너무 많아서
가방 꽉 붙잡고 걸은 기억 밖에 안나

유럽 여행 다녀와서 해리포터 정주행 했는데
여행 가기 전에 봤다?
런던에서 캐리어 하나 더 샀다
슬리데린 머플러 왜 안샀어왜
그리고 계속 돌아다니다 갑자기 든 생각
우리 밥 왜 안먹지?

이게 뭐냐구요?
바로 J의 여행 계획표 입니다
전날 침대에 누워서 내일 뭐하지 하면서 계획표 보는데 
이렇게 댕강 써져있는게 너무 웃겨서 찍어놓음
그래서 먹으러 갔다

근데 지금 생각하면 왜 런던까지 와서 쌀국수 먹었는지 모르겠는데
한국 사람들이 많이 먹길래...
그래서 그랬지...
근데 지금 생각나는 건
그냥 너무 비쌌다
🫠
근데 단 하나 좋았던 점?
바로 옆에 왕 맛있는 스콘집이 있었다는

밥은 밥이고 빵은 빵이지 
여기가 그 유명한
Masion Bertaux
가게 후기 보면 다들 매장에서 차랑 같이 드시던데
매장에 자리도 없고 배도 불러서
일단 포장했다

근데 밥 먹고 커피랑 스콘?
어떻게 참아
날씨도 좋고 호텔 들어가기 싫어서
바로 빵크닉 해버렸다
스콘 딱 처음 먹었을 땐 잉? 했는데
근데 크림이랑 먹으니까
계속 생각나는 맛이다
그래서 파리 가기 전에 또 사먹었다😙 

빵크닉하고 호텔 들어가서 몇분 안쉬고 바로 또 나왔다
구경한다고 버스도 안타고 돌아다녔는데
나중에 걸음 수 보니까
4만보정도 걸었나 

여기저기 구경하다가 도착한 트라팔가 광장
외국인 아저씨랑 내 친구랑 만담 펼치는데 옆에서 동영상 찍고 있었다
그리고 이때까진 몰랐다
내가 런던에 또 오고 싶은 이유이자
런던하면 바로 생각나는 그게
바로 앞에 있을 줄은
!! 

보이세요?
저기 보이세요?
정말 생각지도 못하고
신호등 대기하고 있는데
저 멀리 보이는 빅벤에
신호등 건너지도 않고 사진을 찍었고
내가 제일 좋아하는
사진이 되었다. 

빅벤에 점점 가까워지는 중입니다.
빅벤으로 걸어가다가 런던아이도 살짝 
 
 
지금부터 빅벤 사진만 나옵니다
제가 찍은 빅벤 자랑하고 싶어요

 40분 정도 앉아서 빅벤 구경하다
9시 정각에 종소리도 듣고
그냥 앉아서 보는 것 만으로도
너무 행복했다 

빅벤 구경 실컷하고
어두워질때쯤 런던아이 보러갔는데
여기 한국사람들 정모 중 맞죠
한국분들 사진 찍어드린 기억밖에 안난다

어쨌든 런던아이 국룰 인증 사진 건졌으니 만족하고
너무 추우니까 호텔로 돌아가겠습니다.

근데 이 사람들 또 걸어감
들어가서 한식 챙겨온거 먹고 바로 기절 했슴미다
 2일차 런던여행 마무리 !
 
그 다음 런던일기는 언제 돌아오려나...

728x90
반응형
728x90
반응형

Front-End 와 Back-End 수업이 끝나고 진행 한 프로젝트

주제: 전기차 충전소 시스템 프로젝트

 

프로젝트 인원 : 6명

프로젝트 기간 : 2023-10-23 ~ 2023-10-30

 

구성

1. Main Page

2. Account Page

3. Categori Page

4. Admin Page

 

1. Main Page

1-1. Intro

프로젝트 페이지 주소로 들어가면 1초간 화면 인트로가 보여진다.

1-2. 멤버십 팝업

 첫 화면에 들어오면 멤버십 가입 관련 팝업이 뜬다. '혜택 자세히 알아보기'를 누르면 멤버십 가입 페이지로 이동하고 '오늘 하루 이 창을 열지 않습니다'에 체크한 뒤 닫기를 누르면 쿠키에 정보가 저장이 되어 오늘 하루 팝업 창이 뜨지 않는다.

1-3. 홈 화면

 상단에 웹 이름, 로고, 카테고리를 두었고 오른쪽에 사이드바(현재 닫힘), 중간에 피카충전소의 슬로건과 관련 이미지를 배치하였다. 뒷 배경에 번개가 치는 애니메이션 효과를 넣어 전기라는 이미지가 떠올리게 하였다.

1-4. 사이드 바

 오른쪽에 번개모양의 이모티콘을 누르면 사이드 바가 열리고 닫힌다. 로그인 전, 후에 생성되는 항목이 다르며 하위 요소가 있는 목록들은 해당 목록에 마우스를 올리면 사이드바가 하나 더 열려 하위 항목들이 나타난다.

1-5. 카테고리 바

 5개의 카테고리로 구성되어 있고, 하위 항목이 있는 카테고리일 경우 해당 카테고리에 마우스를 올리면 하위 항목들이 아래로 내려온다.

 

2. Account Page

2-1. 회원가입

 회원가입 시 이용약관 필수사항 동의, 아이디 중복확인, 이메일 본인인증을 완료해야 회원가입 버튼이 활성화 되도록 구현하였다. 자신의 차를 등록하고자 할 때 차량 회사 선택을 하면 회사에 포함 된 차종이 항목으로 뜬다.

 아래 관리자로 체크를 하고 가입을 하면 관리자 계정으로 구분되어 일반 User보다 다룰 수 있는 사항이 많아진다.

2-2. 로그인

 간단한 로그인 창으로 DB에 저장되어있는 정보로 로그인을 할 수 있다. 로그인을 할 때 정확한 이메일을 입력하지 않으면 형식이 올바르지 않다고 알림창이 뜨고 비밀번호나 아이디를 틀리면 '이메일 또는 비밀번호가 일치하지 않습니다' 라는 알림창이 뜨게 된다. 비밀번호 입력창에 자신의 비밀번호를 입력한 뒤 오른쪽에 눈 모양의 버튼을 누르면 Password처리 되어 보이지 않았던 비밀번호가 현재 자신이 무엇을 입력해 놓았는지 볼 수 있다.

2-3. 비밀번호 찾기

 로그인 창 아래의 '비밀번호가 기억나지 않는다면?'을 클릭하면 본인 인증 후 비밀번호를 새롭게 설정할 수 있. 본인인증에 실패하면 '입력하신 정보와 일치하는 사용자를 찾을 수 없습니다.' 라는 알림창이 뜨기 때문에 DB에 있는 계정만이 본인인증에 성공해서 비밀번호를 변경할 수 있다.

2-4. Mypage

 로그인 후 마이페이지 탭에 들어가면 회원탈퇴가 가능하다. (회원수정을 오류로 수정 중)

3. Categori Page

3-1. 충전소 찾기

 충전소 찾기로 들어오면 왼쪽 사이드바를 이용하여 지정한 반경 이내의 전기차 충전소 위치를 확인 할 수 있고, 카테고리별로 항목을 선택하여 전기차 위치를 볼 수 있다.

3-2. 게시판

 게시판은 공지사항, Q&A로 나뉘어져있으며 글쓰기와, 글의 수정 삭제가 가능하다. Q&A는 일반 글쓰기와, 충전소 추가요청, Car정보 추가요청이 따로 나뉘어져 있어서 각각 추가요청을 하고 글을 쓰면 추가 요청 리스트가 보이게 된다. 

3-3. 정보마당

 정보마당에는 통계정보와 서비스 안내가 있다. 통계정보에는 전기차 현황과 충전기 현황을 볼 수 있도록 나누어 놓았으며, 서비스 안내에는 충전요금, 전기차 충전방식을 볼 수 있도록 나누어 놓았다.

3-4. 미디어

 미디어는 전기차 뉴스, 전기차 영상, 전기차 주행거리, 전기차 게임으로 구성 된 하위 항목을 가지고 있다.

 

3-4-1. 전기차 뉴스

뉴스 API를 이용해 전기차 관련 뉴스를 불러와 보여주고 있으며 네이버 뉴스 링크로 이동이 가능하다.

3-4-2. 전기차 영상

 유튜브API를 이용해 전기차 관련 영상을 보여주고 있다. 카테고리를 전기차와 친환경으로 나누어 항목에 따라 다른 영상을 볼 수 있게 하였다. 

3-4-3. 전기차 주행거리

 유일하게 리액트로 구현한 페이지로 해당 페이지에 들어가면 전기차에 따른 주행거리를 알 수 있으며, 자신이 궁금한 차량을 검색해서 볼 수도 있다.

3-4-5. 전기차 게임

  전기차 게임 페이지 들어가면 왼쪽에 게임 관련 설명이 나와있고 오른쪽 미니 게임에서 키보드로 자동차를 움직여 충전소로 가면 본 게임이 시작된다. 만약 자동차가 지도의 가장자리에 닿으면 다음 지도로 전환되게 구현하였다.

 본 게임은 장애물을 피해 목적지인 주유소에 도착하면 되는 게임으로 성공시 찌리릿 코인을 지급한다. 찌리릿 코인은 하루에 1번만 받을 수 있으며 게임을 해서 한번 더 받으려고 한다면 오늘은 이미 받았다는 알림창이 뜨게 된다.

3-5. 멤버십

 멤버십은 코인교환, 쿠폰함, 구독하기로 구성되어있으며 만약 멤버십에 가입한다면 마이멤버십이라는 하위 항목이 하나 더 보이게 된다.

 

3-5-1. 코인 교환

 게임에서 얻은 코인을 쿠폰으로 교환할 수 있는 페이지이다. 코인 10개당 1개의 무료 충전 쿠폰으로 교환 되며 교환 성공 시 교환 성공 모달이 코인이 없어 교환이 실패 되면 코인이 부족하다는 모달 창이 뜨게 된다.

3-5-2. 쿠폰함

 피카충전소 웹에서 얻게 되는 쿠폰을 한번에 볼 수 있는 페이지이다. 사용기간이 나와 있으며 사용하고자 할 때는 사용하기 버튼을 눌러 사용할 수 있다. 사용하기 버튼을 누르면 쿠폰 사용하기 모달이 뜨는데 해당 모달에서 직원확인 버튼을 누르며 해당 쿠폰은 사라지게 된다.

3-5-3. 가입하기

 피카 PASS라는 멤버십에 가입 할 수 있도록 멤버십 혜택 보기와 가입하기를 구현해 놓았다. 멤버십에 가입을 한다면 로그인 했을 시 멤버십 카테고리에 마이멤버십이라는 항목이 생기는데 이곳에선 멤버십 종료 날짜를 알 수 있다. 또한 멤버십 가입 혜택인 충전소 근처 편의점, 카페, 음식점의 위치 정보와 해당 매장의 쿠폰을 발급 받을 수 있도록 하였다.

가입하기 페이지
가입하기 버튼을 누르면 뜨는 모달 창
마이멤버십 페이지

4. Admin

 회원가입 시 관리자는 관리자 계정으로 회원가입을 할 수 있다. 관리자로 로그인하게 되면 사이드바에 Admin이라는 항목이 나타나게 되는데 해당 페이지에서 user 수, 구독자 수, 고객문의 수 등을 알 수 있다. 또한 user들의  Charging Q&A, Car Q&A, 발급 된 Coupon 을 한 페이지에서 볼 수 있어 관리하기 쉽게 구현해 놓았다.

 

728x90
반응형
728x90
반응형

현재 나의 Tistory에 들어오면 마우스 움직임에 따라 애니메이션 효과가 따라 오는 걸 볼 수 있다.

Tistory 외에도 자신이 만든 웹 사이트에서 마우스 커서에 효과를 넣을 수 있다. 

 

1. 관련 사이트

먼저 아래의 관련 사이트로 들어가서 상단에 MOUSE EFFECTS 카테고리를 보면 여러가지 효과들이 있다.

https://www.mf2fm.com/rv/ 

(해당 사이트에는 MOUSE EFFECTS 외에도 TEXT EFFECTS, GRAPHIC EFFECTS가 있는데 다음에 한번 적용시켜 봐야겠다)

 

RV's free DHTML and JavaScript text and graphic effects for your web-site

Copyright notice: All scripts are © copyright mf2fm.com. You can use them wherever and whenever you wish, however the copyright notice at the start of the script should remain intact and a link back to this page would be appreciated. The address for this

www.mf2fm.com

 

나의 Tistory에는 TINKERBELL MOUSE EFFECT가 적용 되어있다.

(다른 선택지에 들어가서 보면 어떤 효과가 나타나는지 해당 페이지에서 볼 수 있다)

 

 

2. 코드 복사

자신이 원하는 효과로 들어가서 아래에 나와있는 코드를 전부 복사한다.

( 아래의 CLICK HERE를 누르면 코드 전체가 선택 된다) 

Tistory에 효과를 적용하고자 한다면 블로그 관리에서 왼쪽 카테고리에 꾸미기>스킨편집에 들어 간다.

들어가면 오른쪽 상단 스킨 편집에 html 편집이 있는데 이곳에서 나의 Tistory html 코드를 작성 할 수 있는 곳이 있다.

 

 

3. 코드 넣기

코드를 살펴보면 <head>태그가 있는데 <head> </head>사이에 복사한 코드를 그대로 붙여 넣으면 된다.

 

 

코드를 넣고 적용을 누르면 자신의 Tistory에서 애니메이션 효과가 적용되는 걸 볼 수 있다.

Tistory가 아니여도 자신이 작성한 html코드 <head>부분에 마우스 효과 코드를 넣으면 구현한 페이지에서 마우스 효과가 나타난다. 

 

728x90
반응형

+ Recent posts