Phaser 사용법 2 - Scene1.js
2022. 2. 13. 11:12ㆍTechnology[Front]
앞선 게시글에서 Phaser의 설정을 관리하는 config.js에서 scene에 사용하는 js파일로 입력해놓은 Scene1.js를 알아보겠습니다. 해당 js파일은 웹환경에서 Phaser 라이브러리를 사용하여 2D 게임맵을 구현한 js파일입니다.
(1) Scene1.js
class Scene1 extends Phaser.Scene {
constructor() {
super("Scene1");
// 처음 실행 시 시작위치 x, y 초기화
this.location_x = 1300;
this.location_y = 500;
}
init(data) {
// 추후 data를 포함하여 호출 시 해당 data의 값으로 시작위치 x, y 초기화
if(Number.isInteger(data.x) && Number.isInteger(data.y)) {
this.location_x = data.x;
this.location_y = data.y;
}
}
// 이미지 로딩
preload ()
{
//배경맵 이미지 로드
this.load.image('map1', 'assets/Sample1.png');
this.load.image('ground', 'assets/안보임0.png');
//캐릭터, npc, 포탈 등 이미지 로드
this.load.spritesheet('potal', 'assets/potal.png',{ frameWidth: 89 , frameHeight: 248 });
this.load.spritesheet('dude1', 'assets/남자캐릭터 스탠드 왼쪽.png',{ frameWidth: 59, frameHeight: 69 });
this.load.spritesheet('admin1', 'assets/궁수전직.png',{ frameWidth: 78, frameHeight:80});
//음악 로드
this.load.audio("music", "")
}
//맵 만들기
create (){
//화면멈춤 설정
this.pause = false;
//캐릭터 초기 방향 설정
this.facing = 'left';
//카메라 바운드 설정
this.cameras.main.setBounds(1010, -690, 5380, 10000);
//맵 이미지 (가로위치,세로위치,url), 맵 바운드 설정
this.add.image (3700, 50, 'map1');
this.physics.world.setBounds( 1000, -5000, 5420 , 10000);
//장애물 그룹 만들기
this.platformsG = this.physics.add.staticGroup({
collideWorldBounds: true
});
this.platformsB = this.physics.add.staticGroup({
collideWorldBounds: true
});
this.platforms = this.physics.add.staticGroup({
collideWorldBounds: false
});
//장애물 설정 후 그룹에 할당
for(var j = 1000; j < 6500; j += 1250) {
this.platformsG.create(j, 590, 'ground').setScale(10).refreshBody(); // 가장 밑바닥 땅
}
this.platformsB.create(5412, 305, 'ground').setScale(1).refreshBody(); // Sample collider
//캐릭터 설정
this.player = this.physics.add.sprite(this.location_x, this.location_y, 'dude1');
this.player.depth = 100; //캐릭터 레이어를 앞으로 설정
this.player.setBounce(0); //땅에 닿았을때 다시 튀어오르는 정도
this.player.setCollideWorldBounds(true); //맵 밖으로 안나가게
this.player.body.setGravityY(1000) //캐릭터 중력설정
this.player.setScale(1,1); // 크기 설정
this.physics.add.collider(this.player, this.platformsG); //ground블럭과 충돌여부
this.colliderB = this.physics.add.collider(this.player, this.platformsB); //collider블럭과 충돌여부
//this.player.body.setCircle(30); //캐릭터 외곽 둥글게
//왼쪽으로
this.anims.create({
key: 'left', //key값 설정
frames: this.anims.generateFrameNumbers('dude3', { start: 0, end: 3 }), //재생할 프레임 선택
frameRate: 5, //프레임 재생속도
repeat: -1 //반복
});
//포탈 설정 setImmovable() -> 충돌에도 움직이지 않음
this.potal1 = this.physics.add.sprite(5034, -380,'potal').setImmovable();
this.potal1.body.setGravityY(-300) //포탈 중력설정
//포탈 움직임---------------
this.anims.create({
key: 'potal',
frames: this.anims.generateFrameNumbers('potal', { start: 0, end: 7 }), //프레임 선택
frameRate: 13, //프레임 재생속도
repeat: -1 //반복
});
this.potal1.anims.play('potal',true); //포탈 스프라이트 움직임 실행
//npc 설정 setInteractive() -> 이벤트 설정 가능메서드
this.admin1 = this.physics.add.sprite(5060, 0, 'admin1').setInteractive(); // 운영자 -setInteractive() -> 이벤트 설정 가능메서드
this.admin1.body.setGravityY(-300) //운영자 중력설정
this.physics.add.collider(this.admin1, this.platformsG); //ground블럭과 충돌여부
this.physics.add.collider(this.admin1, this.platformsB); //ground블럭과 충돌여부
this.admin1.setBounce(0); //땅에 닿았을때 다시 튀어오르는 정도
this.admin1.setCollideWorldBounds(true); //맵 밖으로 안나가게
//운영자 움직임(gif로 움직임이 있을 때)--------------
this.anims.create({
key: 'admin1',
frames: this.anims.generateFrameNumbers('admin1',{start:0,end:2}), //프레임 선택
frameRate: 5, //프레임 재생속도
repeat: -1 //반복
}
);
//운영자 움직임(jpg 등으로 움직임이 없을 때)--------------
//this.anims.create({
//key: 'admin2',
//frames: [ { key: 'admin2', frame: 0 } ], //재생할 프레임 선택
// }
//);
//운영자 클릭시 대화
this.element1 = document.getElementById('input-box4'); // index.html에 있는 html태그 select
//대화 켜기 (캐릭터 선택)
this.admin1.on('pointerdown',()=>{
this.pause = true; // 게임화면 멈춤
if(this.element1 && this.element1.style.display === 'none') {
this.element1.style.display = 'block'; // 숨겨놓은 대화창 block으로 화면출력
}
})
//끄는 버튼 (대화창 close 버튼)
document.getElementById('btn4').addEventListener('click',()=>{ // index.html에 있는 html태그 select
this.pause = false; // 게임화면 재생
this.element1.style.display = 'none' // 화면출력된 대화창 none으로 숨김
})
//대화 켜기 (팝업창 띄울 때)
//this.admin6.on('pointerdown',()=>{
//let width = 800;
//let height = 600;
//let top = (window.innerHeight - height) / 2 + screenY;
//let left = (window.innerWidth - width) / 2 + screenX;
//let spec = 'status=no, menubar=no, toolbar=no, resizable=no';
//spec += ', width=' + width + ', height=' + height;
//spec += ', top=' + top + ', left=' + left;
//window.open('book.html', 'popup', spec); // book.html을 popup형식으로 화면띄움
})
//아래점프시 충돌 설정 다시해줌
this.timedEvent = this.time.addEvent({ delay: 500, callback: this.onEvent, callbackScope: this, loop: true });
// 카메라 설정----------------------------------
this.cameras.main.startFollow(this.player, true, 1, 1);//속도
this.cameras.main.setZoom(1.7); // 줌 배율
this.cameras.main.setFollowOffset( 0, 120);
}
//반복문으로 움직임 구현 부분 ---------------------------------------------------------
update () {
// 키보드 입력 변수 선언 및 초기화 createCursorKeys() 메서드엔 up down left light space shift 만 지정되어 있음
this.cursors = this.input.keyboard.createCursorKeys();
this.space = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); // alt 키 추가
this.ctrl = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.CTRL);
this.key_x = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.X);
this.key_w = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
var player = this.player;
//player보다 아래에 있는 장애물은 통과불가(땅) & player보다 위에 있는 장애물은 통과가능(이동)
this.platforms.children.entries.forEach(element => {
if(element.y < player.y + 30) {
this.platformsB.remove(element);
this.platforms.add(element);
}
else {
this.platforms.remove(element);
this.platformsB.add(element);
}
});
this.platformsB.children.entries.forEach(element => {
if(element.y < player.y + 30) {
this.platformsB.remove(element);
this.platforms.add(element);
}
else {
this.platforms.remove(element);
this.platformsB.add(element);
}
});
//포탈에서 맵이동 구현(같은맵)-----------------
if((this.player.x>=4670 && this.player.x <=4720 && this.player.y <= 427.5 && this.player.y >= 422.5 && this.player.body.touching.down)){
if(this.cursors.up.isDown ){
this.scene.start('Scene1', {x: 5034, y: -300}); //data를 함께 넘겨서 시작위치 설정
}
}
//포탈에서 맵이동 구현(다른맵)-----------------
if(this.player.x >= (this.potal3.x-40) && this.player.x <= (this.potal3.x+40) && this.player.y >=(this.potal3.y+30) && this.player.y <=(this.potal3.y+100) && this.player.body.touching.down){
if(this.cursors.up.isDown ){
this.scene.start('market');
}
}
//키보드 & 방향키 조작
if (this.key_w.isDown) {
//W키를 눌렀을 때 월드맵 팝업
let width = 1000;
let height = 600;
let top = (window.innerHeight - height) / 2 + screenY;
let left = (window.innerWidth - width) / 2 + screenX;
let spec = 'status=no, menubar=no, toolbar=no, resizable=no';
spec += ', width=' + width + ', height=' + height;
spec += ', top=' + top + ', left=' + left;
window.open('Worldmap.html', 'popup', spec);
}
else if (this.cursors.left.isDown) //왼쪽 (왼쪽방향키 누를시 실행)
{ if(this.pause)
return;
if(this.player.body.touching.down)
this.player.anims.play('left', true);
this.player.setVelocityX(-250); //x축 속도 설정
this.facing ='left';// 캐릭터 방향
}
else{
if(this.pause)
return;
if(this.player.body.velocity.y < 0){
this.colliderB.active = false; // 점프 시 장애물 무시
}
else{
this.colliderB.active = true;
}
this.player.setVelocityX(0); //멈춤 (키보드 떼면 자동으로 실행)
if(this.facing == 'left'){
this.player.anims.play('stop',true);
}else{
this.player.anims.play('stopright',true);
}
}
}
}
onEvent =()=>
{
this.colliderB.active = true; // 혹시 장애물이 무시되어있었다면 true로 장애물 설정 복원
}
}
위의 코드는 실제 프로젝트에서 일부 발췌한 코드로 실제 사용시 상황에 맞게 수정하여 사용하시면 됩니다. Phaser 라이브러리 사용 시 구현하는 땅, npc, 메인캐릭터, 장애물 충돌, 중력, 키보드 & 방향키 조작, 대화창 출력, 팝업창 띄우기, 맵 간 이동, 애니메이션 설정, 음악 설정, 이미지파일 적용, 맵 / 카메라 바운드 설정 등 대부분의 기능은 주석으로 설명하였으므로 위의 코드를 참고하여 Phaser 라이브러리를 사용하시면 됩니다.
이상으로 저번게시글에 걸쳐서 Phaser 라이브러리 사용법에 대해 알아보았습니다.
'Technology[Front]' 카테고리의 다른 글
3D맵 구현하기 - THREE.js 구조 (1) | 2022.02.17 |
---|---|
정적 이미지파일 React - Spring 업데이트 데이터 전송 (1) | 2022.02.14 |
Phaser 사용법 1 - index.html, config.js (1) | 2022.02.12 |
HTML코드를 Javascript(JQuery)로 Paging 처리하기 <검색기능 추가> (1) | 2022.02.10 |
React 파일업로드 및 미리보기 && React - Spring ajax로 file 전송 (1) | 2022.02.08 |