반응형

https://youtu.be/qkTtmgCjHhM

코딩애플님의 간단한 javaScript 게임개발 예제를 따라 작성해보았다.

게임개발 2까지 진도를 나가서, 이중점프 안되게 뭐 다 코드를 작성했다.

드래그도 안되게 했고, 스페이스바를 눌렀을 때 홈페이지 내부에서 동작하지 않도록 처리도 했다.

 

let $canvas = document.getElementById('canvas');
let $h1 = document.querySelector('h1');
let ctx = $canvas.getContext('2d');
let $pScore = document.getElementById('score');
let $pHScore = document.getElementById('Hscore');

// 드래그 방지
document.onselectstart= () => {return false};
// // space바로 page down 방지 (keyborad 입력 금지)
// document.onkeydown= () => {return false};

$canvas.width = window.innerWidth - 100;
$canvas.height = window.innerHeight - 100;
$h1.style.display = 'none';
$h1.style.position = 'absolute';
// $pHScore.style.float = "right";
// $pScore.style.float = "right";

let line = {
    draw(){
        ctx.moveTo(-20,450);
        ctx.lineTo(2000,450);
        ctx.lineWidth = 4;
        ctx.stroke();
    }
}

let me = {
    x : 40,
    y : 400,
    width : 50,
    height : 50,
    
    draw(){
        ctx.fillStyle = 'rgb(0,200,0)';
        ctx.fillRect(this.x, this.y, this.width, this.height);
    }
}

let jumpNow = false;
let jumping = false;
let standing = false;
let jumpTimer = 0;
let jumpSpeed = 3;
// 나의 점프

//
let jumpKey = ['Space', 'ArrowUp', 'KeyW'];
let standKey = ['ArrowDown', 'KeyS']
document.addEventListener("keydown", (e) => {
    if(jumpKey.includes(e.code)){
        if(jumpNow === false){
            jumping = true;
            standing = false;
        } 

        if(game == false){
            game = true;
            location.reload();
        }
    }
    
    else if(standKey.includes(e.code)){
        standing = true;
     
    }
}) 

class Enemy {
    constructor(){
        this.x = 1600;
        this.y = 400;
        this.width = 50;
        this.height = 50;
    }
    draw(){
        ctx.fillStyle = 'rgb(200,0,0)';
        ctx.fillRect(this.x, this.y, this.width, this.height);
    }
}

let $input = document.querySelector('input');

let score = 0;
if(localStorage.getItem('highScore') === null){
    localStorage.setItem('highScore', 0);
}
let highScore = localStorage.getItem('highScore');

let game = true;
let timer = 0;
let enemies = [];

// 빈도 수
const hard = 140;
const normal = 240;
const difficulty = [hard, normal];
const choice = 0;

// 속도

// 충돌 여부
function isCrush(me, enemy){
    let xDif;
    let yDif = enemy.y - (me.y + me.height);
    
    if(enemy.x > 40){
        xDif = enemy.x - (me.x + me.width);
    }
    
    else{
        xDif = me.x - (enemy.x + enemy.width);
    }
    
    
    if(xDif < 0 && yDif <0){
        cancelAnimationFrame(animation);
        ctx.clearRect(0,0, $canvas.width, $canvas.height);

        game = false;
        // $h1.style.position = 'position:relative';
        // $h1.style.display = 'block';
        
        //최고기록 갱신
        if(score > highScore){
            highScore = score;
            localStorage.setItem('highScore', highScore);
        }  
    }
}

function excuteEveryFrame(){
    animation = requestAnimationFrame(excuteEveryFrame);
    timer++;
    score++;
    
    ctx.clearRect(0,0, $canvas.width, $canvas.height);

    // 적 생성
    if(timer % difficulty[1] == 0){
        let enemy = new Enemy();
        enemies.push(enemy);
    }

    // 적 소환 및 제거
    enemies.forEach((e, i, o) =>{
        if(e.x < -40) {
            o.splice(i, 1);
        }

        isCrush(me, e);

        e.draw();
        e.x -= 3;
    })

    if(jumping === true && jumpNow === false){
        me.y-= (jumpSpeed);
        jumpTimer++;
        
    }

    if(jumpTimer > 40 || standing == true){
        jumping = false;
        jumpTimer = 0;
        jumpNow = true;
    }

    if(jumping === false){
        if(me.y <= 400){
            me.y+= (jumpSpeed+0.3);

            if(standing === true){
                me.y += (jumpSpeed + 1);
            }
            // 오차 방지 및 중복 점프 방지
            if(me.y > 398){ 
                me.y = 400;
                jumpNow = false;
            }
        }
    
    }

    // 선, 자신 생성
    me.draw();
    line.draw();
    $pScore.innerHTML = 'score : ' + score;
    $pHScore.innerHTML = 'highscore : ' + highScore;

    // 최고기록 실시간 갱신
    if(score > highScore){
        $pHScore.innerHTML = 'highscore : ' + score;
    }

}

excuteEveryFrame();

 

코드해석은 추후 수정하도록 하겠다!

궁금한 부분은 질문 바란다.

반응형
반응형

함수 중복 제거하기

document.querySelector('#num-0').addEventListener('click', onClickNumber('0'));
document.querySelector('#num-1').addEventListener('click', onClickNumber('1'));
document.querySelector('#num-2').addEventListener('click', onClickNumber('2'));
document.querySelector('#num-3').addEventListener('click', onClickNumber('3'));
document.querySelector('#num-4').addEventListener('click', onClickNumber('4'));
document.querySelector('#num-5').addEventListener('click', onClickNumber('5'));
document.querySelector('#num-6').addEventListener('click', onClickNumber('6'));
document.querySelector('#num-7').addEventListener('click', onClickNumber('7'));
document.querySelector('#num-8').addEventListener('click', onClickNumber('8'));
document.querySelector('#num-9').addEventListener('click', onClickNumber('9'));

위와 같은 수식이 있다고 했을 때, 같은 로직이 반복되니 onClickNumber()이라는 함수로 묶어 중복을 제거했다.

const onCLickNumber = (number) => {
	if(operater) {
		numTwo += number;
	} else {
		numOne += number;
	}
	$result.value += number;
	}

위와 같은 수식이라면 에러가 나게된다. 왜? addEventListener에서 사용되는 콜백함수이므로 return이 무엇인지 살펴보아야 하는데, onCLickNumber()의 return값은 undefined이므로 결국 아래와 같아진다.

addEventListener('click', undefined);

그렇다는 건 이때 return에 함수를 주기위해서 고차함수를 사용해야하는데 다음과 같이 고쳐주면 되겠다.

const onCLickNumber = (number) => () => {
	if(operater) {
		numTwo += number;
	} else {
		numOne += number;
	}
	$result.value += number;
	}
// 당연히 인자가 앞에 와야겠지? 생각 잘하자.

간단하다.

+) 코드 정리 방법 - if문

return을 해버리면, 함수 자체가 끝나게 되므로, if else문을 사용하지 않고도 else의 효과를 낼 수 있다.

 

배열 - forEach, map, fill 알아보기

Array(9) // 배열의 길이가 9인 배열 생성 이건 javascript에서만 가능해용 이거 함수네..
Array(9).fill(0) // (9) [0, 0, 0, 0, 0, 0, 0, 0, 0]

fill은 보면 알겠지만 채워준다.

const answer = [5, 6, 3, 2];
const value = '4652'
let strike = 0;
let ball = 0;

answer.forEach((element, index) => {
	const answerIndex = value.indexOf(element);	
	if(answerIndex === index) strike++;
}} 
console.log(strike+"개 맞췄습니다")
//return 2개 맞췄습니다.

forEach는 for문 도는 거 처럼 행동 닉값 함 ㅇㅇ, element와 index를 순서로 매개변수를 받을 수 있다. 배열의 처음부터 끝까지 순회하며, 콜백함수 형식으로 사용해야 한다.

const array = [5, 6, 3, 2];
const result = array.map((element, index) => {
	return element * 2;
})
//return undefined, result (4) [10, 12, 6, 4]

map함수도 마찬가지로 element와 index를 순서로 매개변수를 받고, 배열의 처음부터 끝까지 순회하며 콜백함수 형식으로 사용해야하는 것은 같지만, return을 주어 그 값을 배열에 mapping 할 수 있다.

const array = Array(9).fill(1).map((el,idx) => idx +1)
array.splice(2,3) // index가 2인곳 부터 3개 빼온다.
//return (3) [3, 4, 5], array (6) [1, 2, 6, 7, 8, 9]
let a = array.slice(4)
//return (2) 8, 9
let b = array.slice(4,5)
//return 8, slice(startIndex, EndIndex-1) 

이런식으로 응용할 수 있겠다.

Array 함수를 통해 길이가 9이고, 1~9까지의 값을 가지는 array를 선언했다.

splice 함수를 통해 index가 2인곳 부터 3개를 반환했고

slice 함수를 통해 a에 인덱스가 4인곳 부터 따로 배열을 저장했으며

slice 함수를 통해 b에 인덱스가 4인곳 부터 5-1인곳 까지 배열을 저장했다.

 

조그마한 정리

  1. 배열 정렬은 그냥 검색해라.
  2. setTimeout( 콜백함수, 시간(밀리초))
  3. 스코프 - 범위 : var은 함수 스코프, let은 블록 스코프

 

이벤트 관리 EventListener

태그.addEventListener('click', 고차함수())); // 마우스 버튼 클릭 시 함수 행동
태그.removeEventlistener('click',고차함수())); // 변수 사용하는 것이 더 좋다
/*
mouseover 마우스를 태그 위에 올리면 발생
mouseout 마우스가 태그 바깥으로 벗어나면 발생
mousedown 마우스버튼을 누르고 떼기 전, 태그를 드래그할 떄 사용
mouseup 드래그한 태그를 드랍할 떄 사용
focus 태그에 포커스가 갔을 때 발생
blur 태그가 포커스에서 벗어났을 떄 발생
keypress 키를 누르는 순간 시작 누르고 있는 동안 계속 발생
keydown 키를 누를 때 발생
key up 키를 뗄 때 발생
load 페이지 상 모든 요소(파일)의 다운로드가 완료되었을 때 발생
resize 브라우저 창 크기 조절 시 발생
scroll 스크롤바 드래그 혹은 키보드(up, down)를 사용하거나 휠을 사용해서 웹페이지를 스크롤 할 때 발생
페이지에 스크롤바 없으면 이벤트 발생 안함.
unload 링크 클릭하여 다른페이지 이동 혹은 브라우저 탭 닫을 떄 브라우저 창을 닫을 때 이벤트 발생
change 상태가 변경되었을 때 발생
*/

위의 식은 잘못되었다. 왜냐면 함수와 함수간 비교는 객체와 객체간 비교로 볼 수 있는데, 이 상황에서 객체간 비교는 항상 false가 나온다. 객체의 호출은 재생성과 똑같다고 생각하면 되기에 그런데, 변수는 조금 다르다. 그렇기에 함수의 값을 변수에 담아 비교해보도록 하자. 그러면 같다고 할 수 있으니께롱

니 변수에 저장~

 

반응형
반응형

대화창 (prompt, alert, confirm)

const number = parseInt(prompt("put the number"));

prompt는 팝업형태로 창을 하나 띄워주며, 문자열 데이터로 사용자의 입력에 따른 값을 리턴해준다.

위처럼 변수를 선언했을 경우 변수에 저장되므로 undefined를 리턴한다.

 

prompt창
저장되었어용 뿌잉

alert(number);

마잔가지로 이전과 동일하게 팝업형태로 창을 띄워주지만 사용자에게 경고 표시를 하는 느낌으로 그냥 뙇! 끝

 

let TorF = confirm("check");
console.log(TorF); // return 확인 누르면 true 취소 누르면 false

 

 

HTML Tag 선택하기(querySelector)

document.querySelector('tagName'); // 해당 이름의 tag 가장 첫번째 태그 선택
document.querySelector('#idName'); // 해당 이름의 tag의 아이디 가장 첫번째 태그 선택
document.querySelectorAll('tagName.className');
// 해당 이름의 tag에서 className이라는 이름을 가진 클래스의 태그들 모두 선택
document.querySelectorAll('.className');
// className이라는 이름을 가진 클래스의 태그들 모두 선택
document.querySelector('div span'); // div 밑에 가장 첫번째 span 선택
// 해당 코드는 자손을 모두 찾기에 div 밑에 p 밑에 span이 있더라도 그것을 찾아냄.
document.querySelector('div #target span'); // 이런식으로 응용 가능
document.querySelector('div>span'); // div 바로 밑에 가장 첫번째 span 선택

//tip인데 querySelector을 받는 변수는 $를 붙혀서 표현하면 나중에 알아보기 쉽다
// conset $tagName = document.querySelector('tagName');
// conset $$tagNames = document.querySelectorAll('tagName');

그래서 이 querySelector은 tag 혹은 tag안에 있는 특정 영역을 지정하여 변동을 감지하거나 그 값을 바꾸거나 등등의 행위를 하기 위해 사용한다.

 

이벤트 리스너(콜백 함수)

const onClickButton = () => {
	console.log('button click');
};

const $button = document.querySelector('button');
$button.addEventListener('click', onClickButton);
// 버튼이 클릭되었을때 button click을 출력하는 함수.

// 이벤트리스너 사용 방식
tag.addEventListener('event Name', listenerfunction);

listener function : 리스너 함수, 콜백함수라고도 불린다. 함수가 연이어서 실행되므로 콜백함수라고 한다.

꼭 콜백함수 생각할 때는 return값으로 치환해보자. 함수()는 특정한 return이 주어지지 않았다면 return undefined 라는 것을 꼭 기억하자.

 

const onInput = (e) => {
	console.log('글자 입력', e.target.value);
};

만일 상단코드에서 사용자가 입력한 값을 변수로 받아오고 싶다면 변수를 함수에 정의해서 사용하자.

e.target.value에는 사용자가 입력한 값을 저장하게된다.

const $word = document.querySelector('input');
let word;
let newWord;
word = newWord;

$word.textContent = word; //<id = 'word'> 내부의 문자를 word로 변경된다.
$input.value = ''; // <input>에 해당하는 값을 공백으로 변환한다.
// input, select, textarea에 해당하는 영역의 변환은 .value로 적는다.

$input.focus(); //빈 프롬프트에 커서를 두게 한다.

 

반응형
반응형

다시 공부하겠습니다.

열심히 공부한 나 자신.. 기초부터 다시 다지고 올 수 있도록.
콜백함수를 확인하면서 함수가 뭘 리턴하는지 몰랐기에 다시 처음부터 시작한다.
본 포스팅은 유튜브 제로초님의 강의를 수강하며 내 입맛대로 바꾼 글임을 인지하길 바란다.

 

문자열 기본

'가나다'
"가나다"
`가나다`
"\"가나다" // "가나다
"'가나다" // '가나다

"가나"+'다'// 가나다

 

비교 연산자

'1' == 1 // true
1 == true // true
'1' === 1 // false 자료형까지 같은지 비교
!!'' //false

기본적으로 사용되는 ==는 자료형까지 비교해주지 않는다. 자바스크립트에서는 ===까지 사용해야 자료형까지 비교하여 맞는지 확인한다.

추가로, false, ‘’(빈 문자열), 0, undefined, null, NaN(Not a Number, 수의 비교시 숫자가 아닌 비교 대상자가 있을 경우 리턴해주는 값)은 불값으로 형 변환 했을 때 false가 된다.

 

Undefined와 Null

컴퓨터가 동작을 수행한 뒤 반환해줄 값이 없을 때 undefined를 반환한다.

 

대표적인 예시 1

위와 같은 console.log() 함수를 사용하면, 콘솔 내부에서는 3이라는 값을 나타내지만 반환할 값은 없으므로 undefined라는 값을 반환하게 된다.

 

대표적인 예시 2

이와 다르게 null 값 또한 비어있는 값을 뜻하는데 undefined와 비교했을 경우 자료형이 다르다. 의미는 동일하다. 근데 null의 자료형을 보면 특이하게 object 즉 객체를 반환하는데 이건 자바스크립트 고질적인 버그이니 크게 상관하지 말고 알아두도록 하자.

 

undefined은 빈 값이긴 하나, null과 의미적 차이가 약간있다. define이라는 명칭 자체가 정의 이므로, undefined는 정의 하지 않음으로 생각할 수 있지만 null은 직접 정의해줘야 하므로 의도적으로 비워뒀음을 파악할 수 있다. 같은 의미이나 사용하는 방식에 따라 차이가 있음을 확인하자.

 

비었다.. 비었어...

 

변수

let 지역변수

var 전역변수 ⇒ 요새는 잘 안씀, 다시 선언할 수 있다.

const 상수

변수의 변경

let a = 'b'; // return undefined, a = 'b'
a = 'a'; // return 'a', a = 'a'

변수를 변경하면 변경된 값을 다시 리턴해준다. 잘 기억하도록.

 

조건문 (if, else, switch)

let value = 'b';

switch(value) {
	case 'a' :
		console.log('a');
	case 'b' :
		console.log('b');
	case 'c' :
		console.log('c');
}
// return b, c break문을 사용하자.

 

조건부 연산자 (삼항 연산자)

조건식 ? 참일 때 실행되는 식 : 거짓일 떄 실행되는 식

반복문 for, while, break, continue는 아니까 넘어가도록 하겠음.

 

배열 메소드

const target = ["a", "b", "c", "d", "e"]
target.pop(); // return e, delete target[target.length-1]
target.length(); // return 4, 배열의 길이
target.unshift('f'); // return 5, 배열의 길이를 반환하며 f를 맨 앞에 추가한다.
target.shift(); // return 'f', 맨 앞에 있는 값을 반환하며, 그 값을 삭제한다.
// target = ["a", "b", "c", "d", "e"]

target.splice(1,2); // return (2) ['b', 'c'], 삭제하고자 하는 인덱스부터 삭제하고자 하는 수
target.splice(1,0,'add'); // return [], 인덱스 위치에 'add'추가
target.splice(1,2,'plus'); // return (2) ['add', 'd'], 인덱스 위치에 'plus'추가
target.includes('minus'); // return false
// target = ["a", "puls", "e"]

target.indexOf('a'); // return 0, 인덱스 위치 찾기 없으면 -1 반환
target.lastIndexOf('a'); //return 0, 배열의 마지막에서 부터 위치 찾기

 

함수 기본

function 함수이름1() {} // 함수 선언문
const 함수이름2 = function() {}; // 함수 표현식
const 함수이름3 = () => {}; // 화살표 함수

함수이름1(); // 함수 호출(call)

함수의 호출은 항상 리턴 값으로 대체하라.

 

function a(x, y, z, w) {
	console.log(x, y, z, w);
	console.log(arguments); // 호출 할 때 넣었던 인자(argument)가 뭔지 배열로 나타내줌.
}

a('hello', 'parameter', 'argument')
// return hello, parameter, argument, undefined
// Arguments(3) ['hello', 'parameter', 'argument']

 

객체 리터럴

const 객체 = {
	속성이름 : '속성값',
	'속성이름2' : '속성 값', // 숫자가 같이 있으면 따옴표도 같이 붙여야 한다. 띄어쓰기도 마찬가지. 
}; // 상수이나, 객체내부의 속성은 변경 가능 껍데기는 못바꾸는 느낌인거지.

객체.속성이름; // 속성값
객체.['속성이름2']; //속성 값

객체.속성이름 = '콩콩이'; // 추가 및 수정하기
delete 객체.속성이름; // 제거하기

객체 안에 정의된 함수는 메서드라고 말한다.

 

const debug = {
	log : function(value) {
		console.log(value);
	},
};

debug.log('Hello, Method');
//메소드 호출! debug 객체의 내부 log 함수 다시말해 메소드를 호출하는데, 인자는 'Hello, Method'다
// return undefined, 출력은 Hello, Method

 

객체의 비교

{} === {} // false, 객체의 생성이 두번 일어난 것으로 간주, 서로 다르다.

const a = { name : 'hurray'};
const array = [1, 2, a];
array === [1, 2, a]; // false 새로 생성하는 느낌이라 다르다. 그러나 a는 같다 참조이기 때문에
// 객체는 항상 새로 만든다. 원시 값은 참조형식으로 가져오기 때문에 같을 수 밖에..

 

반응형
반응형

리액트는 자바스크립트를 포함한 HTML문법을 사용할 수 있다.

엄밀히 말하자면 HTML문법에 익숙해진 프론트엔드놈들을 위해 리액트가 친절히 번역하는 기능을 넣었다.

당연히 리액트는 자바스크립트의 라이브러리 격이므로, HTML문법이 마냥 절로 통하지는 않는다 따라서~ 다음 세가지 조건을 만족해야한다.

 

1. 태그에 class주는 방법

[HTML] <div class = "클래스명"> </div>
[JSX] <div className = "클래스명"> </div>

기존 HTML 문법은 그냥 class를 반환해주면 되는 것에 비해, 리액트에서 사용되는 JSX문법은 className을 반환해 줘야 한다.
이때 주의해야 할 점은 className의 n은 대문자 N이라는 것이다.
 
Do you know camel case?

번외) 그대는 카멜케이스에 대해 알고 있는가?

변수명을 정할 때 어떤 방식으로 변수명을 정했는지 모르겠지만, 대개의 변수명 정하는 방법은 카멜 케이스 방법을 채택한다.

상기 서술한 className 또한 카멜 케이스 방법을 채택하였다. 꼭 기억하도록 하자.

 

다음으로 넘어가기 전에, 변수명을 정하는 방법 세가지에 대해 간단하게 훑고가자. 재밌잖아

변수명을 정하는 방법은 모두 띄어쓰기와 연관되어있다! 각 언어에 따라 변수명을 정하는 방법을 따라야 하는 경우가 있다!

 

1) camelCase : 카멜 케이스 🐪

낙타 등 표기법이라고도 이야기 하며, 낙타 등에 생긴 혹처럼 중간에 톡 튀어 나와있다는 느낌으로 사용되어 카멜 케이스라고 한다.

띄어쓰기가 필요한 부분에 대문자를 써보도록 하자. 그럼 당신도 카멜 케이스 마스터 👍

 

2) snake_case : 스네이크 케이스 🐍

마찬가지로 띄어쓰기가 필요한 부분에 언더바(_)를 사용하여 변수를 만든다. 생긴게 뱀처럼 생겼다나 뭐라나~

 

3) PascalCase : 파스칼 케이스 🌬️

첫글자는 대문자로 띄어쓰기도 대문자로 이게 왜 파스칼 케이스라고 불리우는지 숙제 주도록 하겠다. 알아오세요.

 

2. 리액트 데이터 바인딩

const [num, setNum] = useState(0);
<div> 현재 숫자 : {num} </div>
 
상기 서술된 코드는 state를 통해 변수를 설정하였는데, 다음 장에 state와 관련된 설명을 하겠다. 지금은 단순히 const num = 0;으로 봐주면 되겠다.
HTML 태그 안에 변수를 사용하여 그 값을 나타내고 싶다면, {}에 넣어주자.
사실 변수든 함수든 그 값을 사용하고자 한다면 넣어주면 되겠다. 작동하니깐~ 결국 html에는 현재 숫자 : 0 이라는 값을 나타내게 된다.

 

3. style 속성 집어 넣기

style = {{color: 'blue', fontSize : '30px'}}

태그에 상기 서술된 코드를 작성하는데, 앞서 설명한 카멜케이스로 넣어야한다.

font-size가 헷갈릴 수 있는데 하이픈(-)은 뺄셈기호 그 이상도 그 이하도 아니야 라는 생각을 하고 있자.

 

이정도만 알고 있어도 JSX문법은 완벽하게 파악했다고 할 수 있댄다.

아직은 그 세계에 다 발들이지는 못했지만 아주 기본적인 문법을 나타내었다.

도움이 되었길 바란다.

반응형

'FrontEnd > React 입문' 카테고리의 다른 글

React 입문  (4) 2023.07.11
반응형

본 React글은 여러 유튜브 강의들을 짜깁기 한 내용으로 뒤죽박죽 섞여 있을 확률이 높다.

핵심내용만 추렸으므로 같이 입문하는 사람들에게는 오히려 더 좋을지도 모른다.

왜냐면 내가 이해하는 방식을 그대로 적어놨기 때문이지롱~

 

기초 설치와 관련해서는 진짜 알아서 찾아보기 바란다.

너무 쉽거든.

반응형

'FrontEnd > React 입문' 카테고리의 다른 글

React JSX문법  (6) 2023.07.11

+ Recent posts