IdoCleanCode
article thumbnail
반응형

웹 게임 개발

[웹 게임 개발] 스틱 히어로 - 게임 인트로 만들기(1)

 

[웹 게임 개발] 스틱 히어로 - 게임 인트로 만들기(1)

웹 게임 개발 폴더 구성 기본적은 게임을 구성하는 파일과 폴더를 생성합니다. HTML 파일 생성 index.html 이렇게 구성된 HTML파일은 캔버스를 생성하고, 외부 스타일시트 및 스크립트를 연결합니다.

idocleancode.tistory.com

히어로 몸통 만들기

game.js 파일에 전역 변수로 히어로 크기 변수 지정합니다.

// 히어로 크기
let heroWidth = 80;
let heroHeight = 90;

 

game.js 파일에 createHero함수를 만들어 아래 코드를 작성합니다

function createHero(ctx, x, y, width, height, cornerRadius) {
    ctx.beginPath();
    ctx.moveTo(x + cornerRadius, y);
    ctx.lineTo(x + width - cornerRadius, y);
    ctx.arcTo(x + width, y, x + width, y + cornerRadius, cornerRadius);
    ctx.lineTo(x + width, y + height - cornerRadius);
    ctx.arcTo(x + width, y + height, x + width - cornerRadius, y + height, cornerRadius);
    ctx.lineTo(x + cornerRadius, y + height);
    ctx.arcTo(x, y + height, x, y + height - cornerRadius, cornerRadius);
    ctx.lineTo(x, y + cornerRadius);
    ctx.arcTo(x, y, x + cornerRadius, y, cornerRadius);
    
    ctx.closePath();
    ctx.fillStyle = "black";
    ctx.fill();
}

둥근 모서리 가진 사각형을 그리는 역할을 합니다.

  • ctx : 캔버스에 그리기 위한 2D컨텍스트입니다
  • x: 사각형의 시작점 x 좌표
  • y: 사각형의 시작하는 y 좌표
  • width : 사각형의 너비 입니다.
  • height : 사각형의 높이 입니다.
  • cornerRadius : 사각형의 모서리의 둥근 반지름 입니다.

다음은 함수 내부 동작 원리 입니다.

  • beginPath() : 새로운 경로를 시작합니다.
  • moveTo(x + cornerRadius, y) : 사각형의 왼쪽 상단 모서리에서 cornerRadius만큼 오른쪽으로 이동하여 그리기 시작점을 설정합니다. 
  • lineTo(x + width - cornerRadius, y) : 사각형의 상단 가장다리를 따라 오른쪽으로 그립니다. 모서리 반경을 뺀 거리입니다.
  • arcTo(x + width, y, x + width, y + cornerRadius, cornerRadius) : 곡선의 시작점과 끝점을 지점 하여 라운딩 처리을 합니다.

이런 작업을 반복해 closePath로 경로 닫아주고 색상과 사각형을 채우면 됩니다.

 

 

gameIntro함수에 creatreHero함수를 호출 합니다.

function gameIntro(){
	//게임 제목 생성
    //시작버튼
    //히어로생성
createHero(ctx, gameWidth / 2 - heroWidth / 2, gameHeight / 2 - heroHeight / 2 + 80, heroWidth, heroHeight, 15)
}

인자를 15값을 넣어 라운된 사각형을 호출합니다.

히어로 몸통 만들기
히어로 몸통 만들기

 

히어로 다리 만들기

createHero 함수에 매개변수 legRadius 추가하고, 다리부분 코딩을 합니다

function createHero(ctx, x, y, width, height, cornerRadius,legRadius) {
// 히어로 몸통만들기
// 히어로 다리 만들기
    // 왼쪽 다리
    ctx.beginPath();
    ctx.arc(x + width * 0.25, y + height, legRadius, 0, Math.PI * 2);
    ctx.fill();

    // 오른쪽 다리
    ctx.beginPath();
    ctx.arc(x + width * 0.75, y + height, legRadius, 0, Math.PI * 2);
    ctx.fill();
}

다리만들는 역활중

  • 왼쪽 다리 첫번째 인자(x + width *0.25)는 원의 중심 x 좌표입니다. 이는 케릭터 전체 너비 25% 위치에 해당합니다
  • 오른쪽 다리 첫번째 인자 (x + width * 0.75) 75% 위치입니다.

이 수치를 조절하여 다리 위치를 선택합니다

 

gameIntro함수에  legRadius 10을 추가합니다.

function gameIntro(){
	//게임 제목 생성
    //시작버튼
    //히어로생성
createHero(ctx, gameWidth / 2 - heroWidth / 2, gameHeight / 2 - heroHeight / 2 + 80,
	heroWidth, heroHeight,15, 10) )
}

히어로 다리 생성
히어로 다리 생성

 

히어로 눈 만들기

createHero에 eteRadius 매개변수 추가하고, 눈 만드는 코딩을 합니다.

function createHero(ctx, x, y, width, height, cornerRadius, legRadius, eyeRadius) {
// 히어로 몸통만들기
// 히어로 다리 만들기
// 히어로 눈 만들기
    ctx.fillStyle = "white"; 
    ctx.beginPath();
    // 캐릭터의 오른쪽 상단 부분에 눈 그리기
    // x 좌표는 캐릭터의 너비에 일정 비율(예: 70%)을 더한 값
    // y 좌표는 캐릭터의 높이에 일정 비율(예: 30%)을 더한 값
    ctx.arc(x + width * 0.7, y + height * 0.3, eyeRadius, 0, Math.PI * 2);
    ctx.fill();
}

 

게임 인트로 함수에 인자 8를 추가하여 생성합니다.

function gameIntro(){
	//게임 제목 생성
    //시작버튼
    //히어로생성
createHero(ctx, gameWidth / 2 - heroWidth / 2, gameHeight / 2 - heroHeight / 2 + 80,
	heroWidth, heroHeight,15, 10, 8) )
}

히어로 눈 만들기

 

히어로 두건 만들기

매개변수 bandanaHeight 추가하고 두건 코딩을합니다.

function createHero(ctx, x, y, width, height, cornerRadius,legRadius,eyeRadius,bandanaHeight) {
	    // 두건 그리기
    ctx.fillStyle = "red"; // 두건의 색깔을 빨간색으로 설정
    ctx.beginPath();
    ctx.moveTo(x-2, y + height * 0.15); // 두건의 시작점
    ctx.lineTo(x + width+2, y + height * 0.15); // 두건의 윗부분
    ctx.lineTo(x + width+2, y + height * 0.2 + bandanaHeight); // 두건의 오른쪽 아래
    ctx.lineTo(x-2, y + height * 0.2 + bandanaHeight); // 두건의 왼쪽 아래
    ctx.closePath();
    ctx.fill();
}

 

호출에 매개변수 10 추가하여 호출합니다.

function gameIntro(){
	//게임 제목 생성
    //시작버튼
    //히어로생성
createHero(ctx, gameWidth / 2 - heroWidth / 2, gameHeight / 2 - heroHeight / 2 + 80,
	heroWidth, heroHeight,15, 10, 8, 10) )
}

히어로 두건 만들기
히어로 두건 만들기

 

game.js

더보기
// 캔버스 요소와 그래픽 컨텍스트를 가져옵니다.
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

// 캔버스 크기 설정
let gameWidth = canvas.width = 400;
let gameHeight = canvas.height = 550;

// 히어로 크기
let heroWidth = 80;
let heroHeight = 90;

// 게임 인트로
function gameIntro(){
    //게임 제목 생성
    const text = "Stick Hero"
    ctx.fillStyle = 'black'
    ctx.textAlign = 'center'; // 가로 중앙 정렬
    ctx.font = "bold 34px Arial "
    ctx.fillText(text, gameWidth / 2, 70)

    //게임 시작 버튼과 글생성
    const btnPositionX = gameWidth / 2
    const btnPositionY = gameHeight / 2 - 100
    const radius = 50
    ctx.fillStyle = "red"
    ctx.beginPath();
    ctx.arc(btnPositionX,btnPositionY, radius,  0, 2 * Math.PI, false);
    ctx.fill();

    const btnText = "Start"
    ctx.font = "bold 30px Arial"
    ctx.textBaseline ="middle"
    ctx.fillStyle = "white"
    ctx.fillText(btnText, btnPositionX, btnPositionY)


//    배경음악 설정
//     const backgroundMusic = new Audio('assets/sounds/intro.mp3')
//     backgroundMusic.loop = true;
//     try{
//         backgroundMusic.play()
//     }catch (error){
//         console.log("음악을 재생할 수 없습니다.", error)
//     }

    //히어로 생성
    createHero(ctx, gameWidth / 2 - heroWidth / 2, gameHeight / 2 - heroHeight / 2 + 80, heroWidth, heroHeight, 15, 10, 8, 10);

}

function createHero(ctx, x, y, width, height, cornerRadius,legRadius,eyeRadius,bandanaHeight) {
    //몸통
    ctx.beginPath();
    ctx.moveTo(x + cornerRadius, y);
    ctx.lineTo(x + width - cornerRadius, y);
    ctx.arcTo(x + width , y, x + width, y + cornerRadius, cornerRadius);
    ctx.lineTo(x + width, y + height - cornerRadius);
    ctx.arcTo(x + width, y + height, x + width - cornerRadius, y + height, cornerRadius);
    ctx.lineTo(x + cornerRadius, y + height);
    ctx.arcTo(x, y + height, x, y + height - cornerRadius, cornerRadius);
    ctx.lineTo(x, y + cornerRadius);
    ctx.arcTo(x, y, x + cornerRadius, y, cornerRadius);
    ctx.closePath();
    ctx.fillStyle = "black";
    ctx.fill();

    // 왼쪽 다리
    ctx.beginPath();
    ctx.arc(x + width * 0.25, y + height, legRadius, 0, Math.PI * 2);
    ctx.fill();

    // 오른쪽 다리
    ctx.beginPath();
    ctx.arc(x + width * 0.75, y + height, legRadius, 0, Math.PI * 2);
    ctx.fill();

    // 오른쪽 눈 그리기
    ctx.fillStyle = "white"; // 눈의 색깔을 흰색으로 설정
    ctx.beginPath();
    // 캐릭터의 오른쪽 상단 부분에 눈 그리기
    // x 좌표는 캐릭터의 너비에 일정 비율(예: 70%)을 더한 값
    // y 좌표는 캐릭터의 높이에 일정 비율(예: 30%)을 더한 값
    ctx.arc(x + width * 0.7, y + height * 0.3, eyeRadius, 0, Math.PI * 2);
    ctx.fill();


    // 두건 그리기
    ctx.fillStyle = "red"; // 두건의 색깔을 빨간색으로 설정
    ctx.beginPath();
    ctx.moveTo(x-2, y + height * 0.15); // 두건의 시작점
    ctx.lineTo(x + width+2, y + height * 0.15); // 두건의 윗부분
    ctx.lineTo(x + width+2, y + height * 0.2 + bandanaHeight); // 두건의 오른쪽 아래
    ctx.lineTo(x-2, y + height * 0.2 + bandanaHeight); // 두건의 왼쪽 아래
    ctx.closePath();
    ctx.fill();
}



window.onload = gameIntro

 

반응형
profile

IdoCleanCode

@IdoCleanCode

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!