반응형
- E02_애니메이션
- 01단계_타이틀
- 보통 인터넷 강의에서는 한페이지에 다 때려 박는다 ㅋ 알아볼 수도 없게.
- 한페이지에 다 넣으면 구조를 기능을 간소하게 할 수 밖에 없다.
- 애니메이션만 파악해도 머리가 개운해진다.
- 다른 페이지에서 함수를 실행하고 싶으면 해야한다.
- let ctx = ManagerGame.getInstance().getCtx();
- export class ManagerImage
- 페이지 않에서. 다른 페이지 함수를 실행하고 싶으니까.
- export를 해놓으면 다른 곳에서 import를 가능하다.
- import는 다른 클래스를 사용하기 위해서.
- export안에 클래스 안에 변수는 this.를 붙여서 사용한다.
- 이제는 let을 안쓰고 this.를 쓴다.
- let은 한번쓰고 버린다.
- let은 중괄호에서 사라지니까.
- this는 사라지지 않는다.
- class가 this 자신이다.
- this는 클래스 안에서만 사용가능하다.
- 한 페이지에서만 사용할 수 있는 변수다.
- static instance = new ManagerGame();
static getInstance() { return ManagerGame.instance; }
//스태틱 처리
//getInstance => 스태틱 함수를 만든것
//원래 함수앞에는
//구조화 => 다른 페이지에서 가져오는거
// 가져올때. 함수를 만들때는 꼭 스태틱 new를 붙여야 하는데. 그게 힘드니까.
//구조화를 하기 위해서는 꼭 함수앞에는 스태틱을 붙여야 하는데. new를 하지 않기 위해서 getInstance()함수를 만든것
- 배열 넣는 방법
-
let arr = [];arr.push(10);document.writeln(arr[0]);
let arr2 = {};arr2["a"] = 10;document.writeln(arr2["a"]);
- _index.html
-
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>_index.html</title><script src="_main.js" type="module"></script></head><body><canvas id="myCanvas" width="1280" height="720"></canvas></body></html>
- _main.js
- 여기서 중요한것은 function draw() 이 함수를 계속 실행시키는 것 => setInterval(draw,20) 때문에
- ManagerGame.getInstance().update();
ManagerGame.getInstance().draw();- ManagerGame => 이 페이지 안에서
- getInstance => new 하기 싫고. 스태틱 붙이기 싫으니까. stactic
- update() 함수를 실행시켜라
- ManagerGame.getInstance().update();
- _index.html => 여기서 캔버스 태그를 만들었으니까.
- 캔버스에서 그림 그리게 하는것
- ManagerGame.getInstance().start($canvas, ctx);
- $canvas, ctx 이것을 쓸수 있게 넘겨준것
-
import { ManagerGame } from "./managerGame.js";//메니저 게임을 임포트//페이지에 대한 임포트
function draw() {ctx.clearRect(0, 0, $canvas.width, $canvas.height);//지우기
ManagerGame.getInstance().update();//업데이트 //움직이고ManagerGame.getInstance().draw();//그리고}//윈도우도 위의 draw처럼 반복한다.//메인은 function draw() 이것만 계속 반복하는것
//--------------------------------------------------------let $canvas = document.querySelector("#myCanvas");$canvas.style.border = "1px solid black"; //외각선let ctx = $canvas.getContext("2d");
ManagerGame.getInstance().start($canvas, ctx);//ManagerGame => 여기에다가 $canvas, ctx를 넘겨준것//ManagerGame => 이 페이지에 대한 start함수를 실행하라.
setInterval(draw, 20);
- managerGame.js
- static instance = new ManagerGame();
- ManagerGame 클래스의 유일한 인스턴스를 정적으로(static) 하나만 만들어 둔 거예요.
- 즉, 프로그램 전체에서 이 ManagerGame 객체 하나만 사용하도록 강제하려는 목적이에요
- static getInstance() { return ManagerGame.instance; }
- 이건 클래스 외부에서 new ManagerGame()으로 새로 만들지 못하게 하고,
- 대신 이미 만들어져 있는 그 하나의 객체만 접근할 수 있도록 getInstance() 함수를 만든 거예요.
- 🧠 왜 이렇게 쓰는가?
- 💡 싱글턴 패턴의 목적
- 어떤 클래스의 인스턴스를 하나만 유지하고 공유하려고 할 때 사용합니다.
- 예: 게임 매니저, 설정값 관리자, 데이터베이스 연결 등
- ManagerGame.getInstance().start(canvas, ctx);
이런 식으로 외부에서 ManagerGame을 쓸 수 있어요.
new를 직접 하지 않아도, 내부적으로 만들어둔 instance를 가져오니까요. -
import { ManagerImage } from "./managerImage.js";import { ManagerScene } from "./managerScene.js";
export class ManagerGame {static instance = new ManagerGame();static getInstance() { return ManagerGame.instance; }//스태틱 처리//getInstance => 스태틱 함수를 만든것//원래 함수앞에는//구조화 => 다른 페이지에서 가져오는거// 가져올때. 함수를 만들때는 꼭 스태틱 new를 붙여야 하는데. 그게 힘드니까.//구조화를 하기 위해서는 꼭 함수앞에는 스태틱을 붙여야 하는데. new를 하지 않기 위해서 getInstance()함수를 만든것
start(canavs, ctx) { //canavs, ctx => 넘어옴// 메인에서 넘겨줌 => ManagerGame.getInstance().start($canvas, ctx);this.canavs = canavs;this.ctx = ctx;//위의 2개를 저장함ManagerImage.getInstance().start();// ManagerImage.instance.start();//ManagerImage => 매니저 이미지를 스타트를 했다.//ManagerImage => 이미지만 로딩하는 것//미리 이미지 로딩을 다 한것//그냥 처음에 모든 이미지를 모두 로딩ManagerScene.getInstance().start();//ManagerScene => 매니저 씬을 스타트 했다.//다 분리시켰다.//씬을 로딩
ManagerScene.getInstance().changeScene("title");//타이틀 씬을 틀어줘
// ManagerScene.getInstance().changeScene("lobby"); //로비// ManagerScene.getInstance().changeScene("select"); // 셀렉트
//여기서 위의 3개가 화면전환을 하는것이다.}
update() {ManagerScene.getInstance().update();}
draw() {ManagerScene.getInstance().draw();}
getCtx() {return this.ctx;}
}
- managerImage.js
import { NodeImage } from "./nodeImage.js";
export class ManagerImage { //이미지만 로딩함static instance = new ManagerImage();static getInstance() { return ManagerImage.instance; }//직접적으로 꺼내면 안되서. 꺼내는 함수를 만든것start() {this.imageList = {};this.setImageList();}
setImageList() { //이미지만 다 가지고 있음this.setImage("타이틀_배경화면", 1280, 720, "../img/타이틀/타이틀_배경화면.png");this.setImage("타이틀_제목", 530, 240, "../img/타이틀/타이틀_제목.png");
this.setImage("로비_배경화면", 1280, 720 , "../img/로비/로비_배경화면.jpg");
this.setImage("셀렉트_배경화면", 1280, 720, "../img/셀렉트/셀렉트_배경화면.png");}
setImage(imageName, width, height, imagePath) {//이미지를 만들어서 배열에 저장함 => this.imageList = {};this.imageList[imageName] = new NodeImage(width, height, imagePath);}
getImage(imageName) { //이미지 꺼낼때.//직접적으로 꺼내는것을 하면 안되서. 함수로 만든것return this.imageList[imageName];}
}
- managerScene.js
-
import { SceneLobby } from "./sceneLobby.js";import { SceneSelect } from "./sceneSelect.js";import { SceneTitle } from "./sceneTitle.js";
export class ManagerScene {static instance = new ManagerScene();static getInstance() { return ManagerScene.instance; }
start() {this.sceneList = {}; //객체 가지고 있음this.curScene = null; //현제씬this.curSceneName = ""; //현제씬 이름
this.setSceneList(); //씬 3개 함수 실행//3개를 로딩}
setSceneList() { //씬 3개를 로딩 // 위의 임포트 해야됨this.sceneList["title"] = new SceneTitle();this.sceneList["lobby"] = new SceneLobby();this.sceneList["select"] = new SceneSelect();}
changeScene(sceneName) {//타이틀을 틀라고 했다. / 지금 현재는 null이다. 즉 this.curScene = null; //현제씬// 위의 start()에서 null로 해놨다.if(this.curSceneName == sceneName) {return;}//현재 씬이 겹치면//이미 현재씬이랑 바꾸는 씬이랑 이름이 같으면 취소.
this.curScene = this.sceneList[sceneName];//위의 if가 아니면 바뀌었다는거다.//sceneName => 이름을 꺼내가지고 curScene => 현재씬을 꺼내는것
if(this.curScene != null) {//sceneName => 이름이 잘못될수도 있다. 그래서 curScene=> 이름이 있으면this.curSceneName = sceneName;//sceneName => 씬 이름 바꿔주고this.sceneList[sceneName].start();//그씬을 실행해라. / 현재씬을 틀어라}}update() {if(this.curScene != null) {this.curScene.update();}}
draw() {if(this.curScene != null) {this.curScene.draw();}}
}
- nodeImage.js
-
import { ManagerGame } from "./managerGame.js";
export class NodeImage {constructor(width, height, imagePath) {this.image = new Image();this.image.width = width;this.image.height = height;this.image.src = imagePath;}
nodeImageDraw(x, y) {let ctx = ManagerGame.getInstance().getCtx();//ManagerGame 페이지 않에 있는 .getCtx() 함수를 실행하고 싶으니까.//getInstance()를 쓴것//new랑 스태틱 하기 싫으니가. 앞에 getInstance()쓴것ctx.drawImage(this.image, x, y, this.image.width, this.image.height);}
}
- sceneLobby.js
-
import { ManagerImage } from "./managerImage.js";
export class SceneLobby {start() {this.imageBackground = ManagerImage.getInstance().getImage("로비_배경화면");
}update() {}
draw() {this.imageBackground.nodeImageDraw(0, 0);}
}
- sceneSelect.js
-
import { ManagerImage } from "./managerImage.js";
export class SceneSelect {start() {this.imageBackground = ManagerImage.getInstance().getImage("셀렉트_배경화면");}update() {
}
draw() {this.imageBackground.nodeImageDraw(0, 0);}
}
- sceneTitle.js
-
import { ManagerGame } from "./managerGame.js";import { ManagerImage } from "./managerImage.js";
export class SceneTitle {start() {this.imageBackground = ManagerImage.getInstance().getImage("타이틀_배경화면");this.imageTitle = ManagerImage.getInstance().getImage("타이틀_제목");}
update() {}
draw() {this.imageBackground.nodeImageDraw(0, 0);this.imageTitle.nodeImageDraw(400, 30);}
}
반응형
'코딩 > 1-JavaScript' 카테고리의 다른 글
E02_애니메이션 => 03단계_로비완성 (0) | 2025.06.13 |
---|---|
E02_애니메이션 => 02단계_페이지이동 (0) | 2025.06.13 |
05_게임_오목 (0) | 2025.06.12 |
04_캔버스충돌처리 (1) | 2025.06.12 |
03_캔버스키보드 (2) | 2025.06.12 |