🥊결투 게임

1) 파일

2) main.js

let ghost = App.loadSpritesheet("ghost.png", 32, 48, {
	left: [2],
	right: [1],
	up: [3],
	down: [0],
});

let redBoxing = App.loadSpritesheet("redBoxing.png");

const STATE_INTRO = 3001;
const STATE_INIT = 3002;
const STATE_RULE = 3003;
const STATE_PLAYING = 3004;
const STATE_JUDGE = 3005;
const STATE_END = 3006;

let lastSurvivor = null;
let _start = false;
let _players = App.players;

let _state = STATE_INIT;
let _stateTimer = 0;

let _alive = 0;

let _widget = null;

function init() {
	for (let i in _players) {
		let p = _players[i];
		setHPgage(p, p.tag.hp);
		p.sendUpdated();
	}
	_alive = checkSuvivors();
}

function startState(state) {
	_state = state;
	_stateTimer = 0;
	switch (_state) {
		case STATE_INTRO:
			for (let i in _players) {
				let p = _players[i];
				if (p.tag.widget) {
					p.tag.widget.destroy();
					p.tag.widget = null;
				}
			}
			// 게임시작
			_start = true;
			_widget = App.showWidget("intro.html", "middle", 350, 340);
			App.playSound("intro.wav");
			break;
		case STATE_INIT:
			init();
			break;
		case STATE_RULE:
			_widget = App.showWidget("rule.html", "middle", 400, 200);

			for (let i in _players) {
				let p = _players[i];
				p.moveSpeed = 0;
				p.sendUpdated();
			}
			break;
		case STATE_PLAYING:
			if (_widget) {
				_widget.destroy();
				_widget = null;
			}

			_widget = App.showWidget("status.html", "top", 700, 300);

			for (let i in _players) {
				let p = _players[i];
				p.moveSpeed = 80;
				p.sendUpdated();
			}

			break;
		case STATE_JUDGE:
			break;
		case STATE_END:
			if (_widget) {
				_widget.destroy();
				_widget = null;
			}

			_start = false;

			for (let i in _players) {
				let p = _players[i];
				p.sprite = null;
				p.attackSprite = null;
				p.title = null;
				p.sprite = null;
				p.moveSpeed = 80;
				p.sendUpdated();
			}

			Map.clearAllObjects();
			break;
	}
}

// 체력바 표시 함수
function setHPgage(p, hp) {
	switch (hp) {
		case 5:
			p.title = "▮▮▮▮▮";
			break;
		case 4:
			p.title = "▮▮▮▮";
			break;
		case 3:
			p.title = "▮▮▮";
			break;
		case 2:
			p.title = "▮▮";
			break;
		case 1:
			p.title = "▮";
			break;
	}
}

// 생존자 수 체크 함수
function checkSuvivors() {
	let alive = 0;
	for (let i in _players) {
		let p = _players[i];
		if (p.tag.alive) {
			lastSurvivor = p;
			++alive;
		}
	}
	return alive;
}

App.onStart.Add(function () {
	startState(STATE_INTRO);
});

App.onJoinPlayer.Add(function (p) {
	p.tag = {
		widget: null,
		alive: true,
		hp: 5,
		shield: false,
		time: 1, // 피격 후 1초간 무적 상태를 설정하기 위한 속성
	};

	p.attackSprite = redBoxing;

	// 게임 시작 후 새로운 플레이어 입장시 해당 플레이어를 죽음으로 처리
	if (_start) {
		p.moveSpeed = 5;
		p.sprite = ghost;
		p.tag.alive = false;
		p.sendUpdated();
	}

	_players = App.players;
});

App.onLeavePlayer.Add(function (p) {
	p.attackSprite = null;
	p.title = null;
	p.sprite = null;
	p.moveSpeed = 80;
	p.sendUpdated();

	_players = App.players;
});

// 다른 플레이어를 공격할 때 
App.onUnitAttacked.Add(function (sender, x, y, target) {
	if (_state != STATE_PLAYING) return;

	// 공격자가 죽은 상태이면 return
	if (!sender.tag.alive) return;

	// 타겟이 살아 있는 상태이면서 shield가 false인 경우
	if (target.tag.alive && !target.tag.shield) {
		target.tag.hp--; // 타겟의 체력이 1 만큼 감소

		// 타겟의 체력이 0이된 경우
		if (target.tag.hp == 0) {
			target.title = null; // 타이틀 삭제
			target.tag.alive = false; // alive 속성 false
			target.sprite = ghost; // 캐릭터 이미지를 ghost로 변경
			target.moveSpeed = 5; // moveSpeed 80 -> 5
			target.sendUpdated(); // 타겟 속성 업데이트

			_alive = checkSuvivors();
			// 생존자가 1명이면
			if (_alive == 1) {
				if (_widget) {
					_widget.destroy();
					_widget = null;
				}
				// 접속중인 모든 플레이어에게 result.html 위젯을 보여줌
				_widget = App.showWidget("result.html", "top", 1055, 500);
				// 위젯에 표시할 마지막 생존자의 닉네임을 전달
				_widget.sendMessage({
					alive: _alive,
					name: lastSurvivor.name,
				});

				App.playSound("result.wav");

				_stateTimer = 0;
				startState(STATE_JUDGE);
			}
		} else {
			// 타겟을 공격하면 타겟이 1초간 무적 상태가 됨. (shield = true)
			target.tag.shield = true;
			setHPgage(target, target.tag.hp);
			target.sendUpdated();
		}
	}
});

App.onUpdate.Add(function (dt) {
	if (!_start) return;

	_stateTimer += dt;
	switch (_state) {
		case STATE_INTRO:
			// intro.html 위젯을 5초 동안 표시하고 STATE_INIT 시작
			if (_stateTimer >= 5) {
				if (_widget) {
					_widget.destroy();
					_widget = null;
				}
				App.stopSound();

				startState(STATE_INIT);
			}
			break;
		case STATE_INIT:
			startState(STATE_RULE);
			break;

		// rule.html 위젯을 3초 동안 표시하고 STATE_PLAYING 시작
		case STATE_RULE:
			if (_stateTimer >= 3) {
				if (_widget) {
					_widget.destroy();
					_widget = null;
				}
				startState(STATE_PLAYING);
			}
			break;

		case STATE_PLAYING:
			// status.html 위젯의 생존자 수 업데이트
			if (_widget) {
				_widget.sendMessage({
					suvivors: _alive,
				});
			}

			for (let i in _players) {
				let p = _players[i];

				// 플레이어가 죽은 상태라면 건너뜀
				if (!p.tag.alive) continue;

				// 피격 후 1초가 지나면 shield 속성을 false로 변경
				if (p.tag.shield) {
					p.tag.time -= dt;
					if (p.tag.time <= 0) {
						p.tag.shield = false;
						p.tag.time = 1; // shield 지속시간 1초로 초기화
					}
				}
			}

			_alive = checkSuvivors();

			// 생존자가 1명 또는 0명일 경우 result.html 위젯 표시
			if (_alive == 1) {
				if (_widget) {
					_widget.destroy();
					_widget = null;
				}

				_widget = App.showWidget("result.html", "top", 1055, 500);
				_widget.sendMessage({
					alive: _alive,
					name: lastSurvivor.name,
				});

				App.playSound("result.wav");
				startState(STATE_JUDGE);
			} else if (_alive == 0) {
				if (_widget) {
					_widget.destroy();
					_widget = null;
				}

				_widget = App.showWidget("result.html", "top", 1055, 500);
				_widget.sendMessage({
					alive: _alive,
				});

				App.playSound("result.wav");
				startState(STATE_JUDGE);
			}

			break;
		//result.html 위젯을 5초 동안 표시하고 STATE_END 시작
		case STATE_JUDGE:
			if (_stateTimer >= 5) {
				startState(STATE_END);
			}
			break;
		case STATE_END:
			break;
	}
});

// App이 종료되거나 Game Block이 파괴 될 때 실행되는 함수
App.onDestroy.Add(function () {
	// 앱으로 설치된 모든 오브젝트 삭제
	Map.clearAllObjects();
});

Last updated