728x90
1.Vite 프로젝트 생성하기
우선 Vite 프로젝트를 생성해준다.
PS C:\Users\asa\Desktop\code\JavaScript\fruit_game> npm create vite@latest
> create-vite
√ Project name: ... fruit-game
√ Select a framework: » Vanilla
√ Select a variant: » JavaScript
Scaffolding project in C:\Users\asa\Desktop\code\JavaScript\fruit_game\fruit-game...
Done. Now run:
cd fruit-game
npm install
npm run dev
PS C:\Users\asa\Desktop\code\JavaScript\fruit_game> cd .\fruit-game\
PS C:\Users\asa\Desktop\code\JavaScript\fruit_game\fruit-game> npm install
added 10 packages, and audited 11 packages in 5s
3 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
PS C:\Users\asa\Desktop\code\JavaScript\fruit_game\fruit-game> npm run dev
> fruit-game@0.0.0 dev
> vite
VITE v5.3.3 ready in 137 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
2.Matter.js 다운
Matter.js란 자바스크립트 라이브러리로, 웹에서 2D 물리 효과를 재현하기 위해 사용한다.
PS C:\Users\asa\Desktop\code\JavaScript\fruit_game\fruit-game> npm install matter-js
added 1 package, and audited 12 packages in 2s
3 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
3.기본틀 만들기
Matter.js의 Engine,Render,Runner를 통해 게임판을 만든다.
Matter.js를 사용하여 물리 시뮬레이션을 구현하기 위해 필요한 기본적인 설정을 정한다(배경,너비,높이)
import { Engine,Render,Runner } from "matter-js";
const engine = Engine.create();
const render = Render.create({
engine,
element: document.body,
options: {
wireframes:false,
background:"#5765e6",
width:620,
height:850,
}
});
Render.run(render);
Runner.run(engine);
4.벽생성
import에 World 를 추가해주고
rectangle을 이용한 직사각형 모양의 물리 객체를 생성
(x: 객체의 중심의 x 좌표. y: 객체의 중심의 y 좌표. width: 객체의 너비. height: 객체의 높이.)
옵션으로 객체가 정적인(움직이지 않는) 객체임을 나타내고, 색을 칠하여 벽생성
//벽
const walloption={
isStatic: true,
render:{fillStyle: "#0a0a0a"}
}
const leftWall= Bodies.rectangle(15,395,30,790, walloption);
const rightWall= Bodies.rectangle(605,395,30,790, walloption);
const groundWall= Bodies.rectangle(310,820,620,60, walloption);
const topLine=Bodies.rectangle(310,150,620,2,walloption)
World.add(world, [leftWall,rightWall,groundWall,topLine]);
5.과일생성
과일 정보가 담긴 js파일을 제작
export const FRUITS=[
{name:"00",radius: 30/2},
{name:"01",radius: 40/2},
{name:"02",radius: 60/2},
{name:"03",radius: 80/2},
{name:"04",radius: 100/2},
{name:"05",radius: 120/2},
{name:"06",radius: 120/2},
{name:"07",radius: 120/2},
{name:"08",radius: 120/2},
{name:"09",radius: 120/2},
{name:"10",radius: 120/2},
]
1~5번째 과일이 무작위로 생성되서 isSleeping으로 멈춰있게 만든다
Render.run(render);
// Runner 객체 생성 및 실행
const runner = Runner.create();
Runner.run(runner, engine);
let currentBody =null;
let currentFruit =null;
//과일추가
function addFruit(){
const index=Math.floor(Math.random()*5);
const fruit = FRUITS[index];
const body = Bodies.circle(300, 50, fruit.radius, {
index:index,
render: {
fillStyle: '#ff6347', // 채우기 색상 설정
strokeStyle: '#000000', // 테두리 색상 설정
lineWidth: 5, // 테두리 두께 설정
},
restitution:1, //탄성
isSleeping:true //멈춰있게
});
currentBody=body;
currentFruit=fruit;
World.add(world, body); // 원을 월드에 추가
}
6.과일 움직임
과일의 위치를 a,d 키로 움직이고 S를 누르면 과일이 떨어진다.
과일이 떨어지면 1초동안 키를 누를수없게된다.
let currentBody =null;
let currentFruit =null;
let disableAction = false;
function addFruit(){
const index=Math.floor(Math.random()*5);
const fruit = FRUITS[index];
const body = Bodies.circle(300, 50, fruit.radius, {
render: {
fillStyle: '#ff6347', // 채우기 색상 설정
strokeStyle: '#000000', // 테두리 색상 설정
lineWidth: 5, // 테두리 두께 설정
},
restitution:1, //탄성
isSleeping:true //멈춰있게
});
currentBody=body;
currentFruit=fruit;
World.add(world, body); // 원을 월드에 추가
}
//움직임
window.onkeydown = (event) =>{
if(disableAction){return;}
switch (event.code){
case "KeyA":
if(currentBody.position.x - currentFruit.radius>30)
Body.setPosition(currentBody,{x:currentBody.position.x-10, y:currentBody.position.y})
break;
case "KeyD":
if(currentBody.position.x - currentFruit.radius<500)
Body.setPosition(currentBody,{x:currentBody.position.x+10, y:currentBody.position.y})
break;
//떨어트리기
case "KeyS":
currentBody.isSleeping=false;
disableAction=true;
setTimeout(()=>{
addFruit();
disableAction=false;
},1000);
break;
}
}
7.충돌
과일은 충돌후 합쳐진다.
Events.on(engine,"collisionStart",(event) =>{
event.pairs.forEach((collision)=> {
if(collision.bodyA.index == collision.bodyB.index){
const index=collision.bodyA.index;
if(index== FRUITS.length-1){return;}
World.remove(world, [collision.bodyA,collision.bodyB]);
const newFruit= FRUITS[index+1];
const newBody = Bodies.circle(
collision.collision.supports[0].x,
collision.collision.supports[0].y,
newFruit.radius,
{
render: {
fillStyle: '#ff6347', // 채우기 색상 설정
strokeStyle: '#000000', // 테두리 색상 설정
lineWidth: 5, // 테두리 두께 설정
},
index:index+1,
}
);
World.add(world, newBody);
}
});
});
8.게임오버
disableAction이 켜져있을때 윗라인에 닿으면 게임오버가 된다.
Events.on(engine,"collisionStart",(event) =>{
event.pairs.forEach((collision)=> {
if(collision.bodyA.index === collision.bodyB.index){
const index=collision.bodyA.index;
if(index=== FRUITS.length-1){return;}
World.remove(world, [collision.bodyA,collision.bodyB]);
const newFruit= FRUITS[index+1];
const newBody = Bodies.circle(
collision.collision.supports[0].x,
collision.collision.supports[0].y,
newFruit.radius,
{
render: {
fillStyle: '#ff6347', // 채우기 색상 설정
strokeStyle: '#000000', // 테두리 색상 설정
lineWidth: 5, // 테두리 두께 설정
},
index:index+1,
}
);
World.add(world, newBody);
}
if(!disableAction && (collision.bodyA.name=== "topline"||collision.bodyB.name=== "topline")){
alert("Game over");
}
});
});
🎈참고자료
https://www.youtube.com/watch?v=LZvEDigv0Ww&list=LL
728x90
'FrontEnd > Node.js' 카테고리의 다른 글
[Node.js] Node.js,Vite 프로젝트 Githubpages 배포하기 (0) | 2024.07.04 |
---|---|
[Node.js] Vite 란? (0) | 2024.07.01 |
[Node.js] npm(Node Package Manager)란? (0) | 2024.07.01 |