일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- intellij
- spring-boot
- 모두의 파이썬
- intllij 내 Bean을 찾지 못해서 발생하는 오류
- react오류
- You are importing createRoot from "react-dom" which is not supported. You should instead import it from "react-dom/client"
- 웹 게임을 만들며 배우는 리액트
- googleColaboratory
- vs code 내 node
- DB Browser
- 계산맞추기 게임
- node.js로 로그인하기
- react
- 인프런
- Concurrently
- ReactDOM.render is no longer supported in React 18. Use createRoot instead
- 거북이 대포 게임
- JS 개념
- 리액트
- Python
- 따라하며 배우는 노드 리액트 기본 강의
- props
- 모던자바스크립트
- 노드에 리액트 추가하기
- Spring-Framework
- Colaboratory 글자 깨짐
- 자바스크립트
- 타자 게임 만들기
- node.js 설치
- Do it 자바스크립트 + 제이쿼리 입문
- Today
- Total
프로그래밍 삽질 중
Let's Get IT 자바스크립트 프로그래밍 - 텍스트 RPG 본문
* 출처 : https://thebook.io/080270/part02/ch10/
* 얕은 복사 & 깊은 복사 (참고 : https://bbangson.tistory.com/78)
- 얕은 복사 : 객체의 참조값(주소 값)을 복사, 중첩된 객체가 있을 때 가장 바깥 객체만 복사, 내부 객체는 참조 관계 유지
- 깊은 복사 : 객체의 실제값 복사
- JSON.parse(문자열을 객체로) 과 JSON.stringify(객체를 문자열로)를 조합 시 대상 객체를 깊은 복사가 가능
(단 Math, Date 같은 객체는 복사 불가능)
- 참조값 : 여러 자료형으로 구성되는 메모리에 저장된 객체 ex) object, symbol 등
-> 변수에 객체를 저장하면 독립적인 메모리 공간에 값을 저장, 변수에 저장된 메모리 공간의 참조(위치 값)을 저장
-> 할당된 변수를 조작하는 것은 객체 자체를 조작하는 것이 아닌, 객체의 참조 조작
- 참조 : 메모리에서의 객체의 위치를 가리킴, 변수는 실제로 값을 가지는 것이 아님
- 얕은 참조는 깊은 복사와 참조의 중간에 위치한 복사 방법
- 얕은 복사는 ...연산자 이용, 배열은 [...배열], 객체는 {...객체}
const array = [{ j: 'k' }, { l: 'm' }];
const shallowCopy = [...array]; // 얕은 복사
console.log(array === shallowCopy); // false
console.log(array[0] === shallowCopy[0]); // true
const reference = array; // 참조
const deepCopy = JSON.parse(JSON.stringify(array)); // 깊은 복사
console.log(array === reference); // true
console.log(array[0] === reference[0]); // true
console.log(array === deepCopy); // false
console.log(array[0] === deepCopy[0]); // false`
//5개의 값을 각각 복사
const a = 'b';
const c = ['d', true, 1];
const e = { g: 'h' };
const i = [{ j: 'k' }, { l: 'm' }];
const n = { o: { p: 'q' }};
const a2 = a;
const c2 = s.slice(); //내부 객체를 복사 대신 참조로 연결
const e2 = {...e};
const i2 = JSON.parse(JSON.stringify(i));
const n2 = JSON.parse(JSON.stringify(n));
* 객체의 메서드에서는 function 예약어 생략 가능(1번 방법과 2번 방법 둘 다 동일)
- this : 여기서는 hero (function 한정, 화살표 함수는 아님), 보통은 window 객체
-> 객체에서 this 사용 시 해당 객체를 가리키는 말
//1번 방법
attack(monster) {
monster.hp -= this.att;
this.hp -= monster.att;
},
heal(monster) {
this.hp += 20;
this.hp -= monster.att;
},
//2번 방법
attack: function(monster) {
monster.hp -= this.att;
this.hp -= monster.att;
},
heal: function(monster) {
this.hp += 20;
this.hp -= monster.att;
},
//예시
const person = {
name: '톰 크루즈',
sayName() {
console.log(this === person);
}
};
person.sayName(); // true
* 클래스
- 객체를 생성하기 위한 템플릿(객체의 메서드를 같이 묶을 수 있음)
-> 생성자 함수와 메서드가 묶여 있어 보기도 편하고 메서드 함수를 매번 재생성하는 문제 발생하지 않음
- 함수 호출 시 함수 이름 앞에 new 붙임 = 생성자 함수(new를 붙이지 않고 호출한 this는 window로 인식)
- 클래스 문법 : class 예약어로 클래스 선언, constructor 메서드 안에 기존 코드를 넣음
-> 클래스에 new를 붙여 호출 시 constructor 함수가 실행되고 객체가 반환됨, this는 생성된 객체 자신
function Topgun(name, hp, att, xp) {
this.name = name;
this.hp = hp;
this.att = att;
this.xp = xp;
}
const monster1 = new Monster('매버릭', 25, 10, 11);
const monster2 = new Monster('루스터', 26, 10, 10);
const monster3 = new Monster('피닉스', 25, 11, 10);
* 클래스 위주로 프로그래밍 = 객체 지향 프로그래밍
* 함수를 조합하며 프로그래밍 = 함수형 프로그래밍
* 순서도 절차대로 프로그래밍 = 절차형 프로그래밍
* 상속
- 반복되는 부분을 따로 분리해서 extends를 이용한 예약어로 상속 가능
- super함수 : 부모 클래스 : Unit 의미
- 부모 클래스에서는 game, name, maxHp, hp, xp, att 속성을 this에 입력
//반복되는 부분 - 공통 클래스
class Unit {
constructor(game, name, hp, att, xp) {
this.game = game;
this.name = name;
this.maxHp = hp;
this.hp = hp;
this.xp = xp;
this.att = att;
}
attack(target) {
target.hp -= this.att;
}
}
//상속받는 클래스
class Hero extends Unit {
constructor(game, name) {
super(game, name, 100, 10, 0);
this.lev = 1; //그외 속성
}
attack(target) {
super.attack(target);
}
...
}
class Monster extends Unit {
constructor(gam,e name, hp, att, xp) {
super(game, name, hp, att, xp);
}
}
* 텍스트 RPG
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Text RPG CLASS</title>
</head>
<body>
<form id="start-screen">
<input id="name-input" placeholder="주인공 이름을 입력하세요!" />
<button id="start">시작</button>
</form>
<div id="screen">
<div id="hero-stat">
<span id="hero-name"></span>
<span id="hero-level"></span>
<span id="hero-hp"></span>
<span id="hero-xp"></span>
<span id="hero-att"></span>
</div>
<form id="game-menu" style="display: none;">
<div id="menu-1">1.모험</div>
<div id="menu-2">2.휴식</div>
<div id="menu-3">3.종료</div>
<input id="menu-input" />
<button id="menu-button">입력</button>
</form>
<form id="battle-menu" style="display: none;">
<div id="battle-1">1.공격</div>
<div id="battle-2">2.회복</div>
<div id="battle-3">3.도망</div>
<input id="battle-input" />
<button id="battle-button">입력</button>
</form>
<div id="message"></div>
<div id="monster-stat">
<span id="monster-name"></span>
<span id="monster-hp"></span>
<span id="monster-att"></span>
</div>
</div>
<script>
const $startScreen = document.querySelector('#start-screen');
const $gameMenu = document.querySelector('#game-menu');
const $battleMenu = document.querySelector('#battle-menu');
const $heroName = document.querySelector('#hero-name');
const $heroLevel = document.querySelector('#hero-level');
const $heroHp = document.querySelector('#hero-hp');
const $heroXp = document.querySelector('#hero-xp');
const $heroAtt = document.querySelector('#hero-att');
const $monsterName = document.querySelector('#monster-name');
const $monsterHp = document.querySelector('#monster-hp');
const $monsterAtt = document.querySelector('#monster-att');
const $message = document.querySelector('#message');
class Game {
constructor(name) {
this.monster = null;
this.hero = new Hero(this, name);
this.monsterList = [
{ name: '슬라임', hp: 25, att: 10, xp: 10 },
{ name: '스켈레톤', hp: 50, att: 15, xp: 20 },
{ name: '마왕', hp: 150, att: 35, xp: 50 },
];
this.start(name); //name을 start 메서드 -> Hero 클래스
}
start(name) {
$gameMenu.addEventListener('submit', this.onGameMenuInput);
$battleMenu.addEventListener('submit', this.onBattleMenuInput);
this.changeScreen('game');
this.hero = new Hero(this, name);
this.updateHeroStat();
}
changeScreen(screen) {
if (screen === 'start') {
$startScreen.style.display = 'block';
$gameMenu.style.display = 'none';
$battleMenu.style.display = 'none';
} else if (screen === 'game') {
$startScreen.style.display = 'none';
$gameMenu.style.display = 'block';
$battleMenu.style.display = 'none';
} else if (screen === 'battle') {
$startScreen.style.display = 'none';
$gameMenu.style.display = 'none';
$battleMenu.style.display = 'block';
}
}
onGameMenuInput = (event) => {
event.preventDefault();
const input = event.target['menu-input'].value;
if (input === '1') { // 모험
this.changeScreen('battle');
const randomIndex = Math.floor(Math.random() * this.monsterList.length);
const randomMonster = this.monsterList[randomIndex];
this.monster = new Monster(
this,
randomMonster.name,
randomMonster.hp,
randomMonster.att,
randomMonster.xp,
);
this.updateMonsterStat();
this.showMessage(`몬스터와 마주쳤다. ${this.monster.name}인 것 같다!`);
} else if (input === '2') { // 휴식
this.hero.hp = this.hero.maxHp;
this.showMessage('충분한 휴식을 취했다');
} else if (input === '3') { // 종료
this.showMessage('');
this.quit();
}
}
onBattleMenuInput = (event) => {
event.preventDefault();
const input = event.target['battle-input'].value;
if (input === '1') { // 공격
const { hero, monster } = this;
hero.attack(monster);
monster.attack(hero);
if (hero.hp <= 0) {
this.showMessage(`${hero.lev} 레벨에서 전사. 새 주인공을 생성하세요.`);
this.quit();
} else if (monster.hp <= 0) {
this.showMessage(`몬스터를 잡아 ${monster.xp} 경험치를 얻었다.`);
hero.getXp(monster.xp);
this.monster = null;
this.changeScreen('game');
} else {
this.showMessage(`${hero.att}의 데미지를 주고, ${monster.att}의 데미지를 받았다.`);
}
this.updateHeroStat();
this.updateMonsterStat();
} else if (input === '2') { // 회복
hero.hp = Math.min(hero.maxHp, hero.hp + 20);
monster.attack(hero);
this.showMessage(`체력을 조금 회복했다!`);
this.updateHeroStat();
} else if (input === '3') { // 도망
this.changeScreen('game');
this.showMessage('부리나케 도망쳤다!');
this.monster = null;
this.updateMonsterStat();
}
}
updateHeroStat() {
const { hero } = this;
if (hero === null) {
$heroName.textContent = '';
$heroLevel.textContent = '';
$heroHp.textContent = '';
$heroXp.textContent = '';
$heroAtt.textContent = '';
return;
}
$heroName.textContent = hero.name;
$heroLevel.textContent = `${hero.lev}Lev`;
$heroHp.textContent = `HP: ${hero.hp}/${hero.maxHp}`;
$heroXp.textContent = `XP: ${hero.xp}/${15 * hero.lev}`;
$heroAtt.textContent = `ATT: ${hero.att}`;
}
updateMonsterStat() {
const { monster } = this;
if (monster === null) {
$monsterName.textContent = '';
$monsterHp.textContent = '';
$monsterAtt.textContent = '';
return;
}
$monsterName.textContent = monster.name;
$monsterHp.textContent = `HP: ${monster.hp}/${monster.maxHp}`;
$monsterAtt.textContent = `ATT: ${monster.att}`;
}
showMessage(text) {
$message.textContent = text;
}
quit() {
this.hero = null;
this.monster = null;
this.updateHeroStat();
this.updateMonsterStat();
$gameMenu.removeEventListener('submit', this.onGameMenuInput);
$battleMenu.removeEventListener('submit', this.onBattleMenuInput);
this.changeScreen('start');
game = null;
}
}
class Unit {
constructor(game, name, hp, att, xp) {
this.game = game;
this.name = name;
this.maxHp = hp;
this.hp = hp;
this.xp = xp;
this.att = att;
}
attack(target) {
target.hp -= this.att;
}
}
class Hero extends Unit {
constructor(game, name) {
super(game, name, 100, 10, 0);
this.lev = 1;
}
attack(target) {
super.attack(target);
//target.hp -= this.att
}
heal(monster) {
this.hp += 20;
this.hp -= monster.att;
}
getXp(xp) {
this.xp += xp;
if (this.xp >= this.lev * 15) { // 경험치를 다 채우면
this.xp -= this.lev * 15;
this.lev += 1;
this.maxHp += 5;
this.att += 5;
this.hp = this.maxHp;
this.game.showMessage(`레벨업! 레벨 ${this.lev}`);
}
}
}
class Monster extends Unit {
constructor(game, name, hp, att, xp) {
// this.game = game;
// this.name = name;
// this.maxHp = hp;
// this.hp = hp;
// this.xp = xp;
// this.att = att;
super(game, name, hp, att, xp);
}
// attack(target) {
// target.hp -= this.att
// }
}
let game = null;
$startScreen.addEventListener('submit', (event) => {
event.preventDefault();
const name = event.target['name-input'].value;
game = new Game(name); //클래스 호출
});
</script>
</body>
</html>
'과거 프로그래밍 자료들 > Javascript&typescript' 카테고리의 다른 글
Let's Get IT 자바스크립트 프로그래밍 - 카드 짝 맞추기 (0) | 2022.07.20 |
---|---|
slice, concat, forEach + 원본을 바꾸는 매서드, 바꾸지 않는 매서드 (0) | 2022.07.20 |
Let's Get IT 자바스크립트 프로그래밍 - 틱택토게임, 컴퓨터랑 하기 (0) | 2022.07.15 |
Let's Get IT 자바스크립트 프로그래밍 - 반응속도 테스트, 상위 5개만 보여주기 (0) | 2022.07.14 |
Let's Get IT 자바스크립트 프로그래밍 - 계산기 만들기, 연속 계산 추가 (0) | 2022.07.07 |