도드넷
JAVASCRIPT#77 - 탑다운 1부 본문
Big things have small beginnings...
JAVASCRIPT#77 - 탑다운 1부
1. 게임의 시작
$("#startButton").click(function() {
gf.startGame(initialize);
});
스타트 버튼이라는 요소를 클릭하면 gf.startGame 함수가 initialize라는 파라미터와 함께 시작된다.
2. gf.startGame 과 initialize 함수
gf.startGame = function(endCallback, progressCallback) {
// 1. 이미지 배열과 프리로드
var images = [];
var total = gf.imagesToPreload.length;
for (var i = 0; i < total; i++) {
var image = new Image();
images.push(image);
image.src = gf.imagesToPreload[i];
}
var preloadingPoller = setInterval(function() {
var counter = 0;
var total = gf.imagesToPreload.length;
for (var i = 0; i < total; i++) {
if (images[i].complete) {
counter++;
}
}
if (counter == total) {
// 2. 프리로드가 완료됬을시, 콜백(initialize)과 주 반복문(refreshGame) 실행 시작.
clearInterval(preloadingPoller);
endCallback();
setInterval(gf.refreshGame, gf.baseRate);
gf.time = (new Date()).getTime();
} else {
if (progressCallback) {
count++;
progressCallback((count / total) * 100);
}
}
}, 100);
};
var initialize = function()
{
// 1. 컨테이너 만들기
$("#mygame").append("<div id='container' style='display: none; width: 800px; height: 600px;'>");
container = $("#container");
// 2. 컨테이너에 콘솔 추가
container.append("<div id='console' style='font-family: \"Press Start 2P\", cursive; color: #fff; width: 770px; height: 20px; padding: 15px; position: absolute; bottom: 0; background: rgba(0,0,0,0.5); z-index: 3000'>");
console = $("#console");
// 3. "world"(group) 그룹 객체 정의
world = gf.addGroup(container,"group",{
x: -(510-192)/2,
y: -(360-192)/2
});
// 4. "tiles"(tiles) 그룹 만들기
tiles = gf.addGroup(world,"tiles");
// 5. json 기반 타일 불러오기
gf.importTiled("level.json",tiles, "tiles");
// 6. 제 3 타일 z 좌표 설정 (맨위에서 플레이어를 덮는 타일이 됨)
$("#tiles3").css("z-index", "2989");
// 7. "npcsGroup"(npcs) 그룹 만들기
npcsGroup = gf.addGroup(world,"npcs");
// 8. npcs배열에 NPC1 DOM 객체 div와 NPC함수에 의해 생성된 object 값 전달
npcs.push({
div: gf.addSprite(npcsGroup,"NPC1", {
x: 800,
y: 800,
width: 96,
height: 96
}),
object: new NPC("Dr. Where", ["안녕","I hope you will enjoy it.","You should head east from here...","there's someone you may want to meet."], console)
});
// 9. object의 div값을 생성하면서 지정함.
npcs[npcs.length-1].object.div = npcs[npcs.length-1].div;
// 10. 해당 npc의 애니메이션 설정
gf.setAnimation(npcs[npcs.length-1].div, new gf.animation({
url: "npc/scientist.png"
}));
// 11. 해당 npc DOM의 z 좌표 설정
$("#NPC1").css("z-index", 800 + 96);
// 12. npcs배열에 NPC2 DOM 객체 div와 NPC 함수에 의해 생성된 object 값 전달
npcs.push({
div: gf.addSprite(npcsGroup,"NPC2", {
x: 1800,
y: 600,
width: 96,
height: 96
}),
object: new NPC("Junior",["Howdy lad! If you explore this country"," be carefull! There are monsters", "roaming around!"], console)
});
// 13. 해당 npcs의 오브젝트.div 설정
npcs[npcs.length-1].object.div = npcs[npcs.length-1].div;
// 14. 해당 npc의 애니메이션 설정
gf.setAnimation(npcs[npcs.length-1].div, new gf.animation({
url: "npc/desertnpc.png"
}));
// 15. 해당 npc DOM의 z 좌표 설정
$("#NPC2").css("z-index",600 + 96);
// 16. "enemiesGroup"(enemies) 그룹 정의
enemiesGroup = gf.addGroup(world,"enemies");
// 17. enemies 배열에 enemy1 DOM 객체 div와 Enemy 함수에 의해 생성된 object 값 전달
enemies.push({
div: gf.addSprite(\
enemiesGroup,"enemy1", {
x: 100,
y: 1300,
width: 192,
height: 192
}),
object: new Enemy(10,15)
});
// 18. 해당 enemy의 애니메이션 설정
gf.setAnimation(enemies[enemies.length-1].div, skeletonAnim.stand.down, true);
// 19. 해당 enemy의 z 좌표 설정
$("#enemy1").css("z-index",1300 + 192-16);
// 20. enemies 배열에 enemy2 DOM 객체 div와 Enemy 함수에 의해 생성된 object 값 전달
enemies.push({
div: gf.addSprite(enemiesGroup,"enemy2", {
x: 1800,
y: 1200,
width: 192,
height: 192
}),
object: new Enemy(2,50)
});
// 21. 해당 enemy의 애니메이션 설정
gf.setAnimation(enemies[enemies.length-1].div, ogreAnim.stand.down, true);
// 22. 해당 enemy의 z 좌표 설정
$("#enemy2").css("z-index",1200 + 192 - 16);
// 23. player.div(player) 그룹 객체 생성
player.div = gf.addGroup(world,"player", {
x: 510,
y: 360
});
// 24. 플레이어 아바타 생성
player.avatar = gf.addSprite(player.div, "avatar", {
x: (192-128)/2,
y: (192-128)/2,
width: 128,
height: 128
});
// 25. 플레이어 웨폰 생성
player.weapon = gf.addSprite(player.div, "weapon", {
width: 192,
height: 192
});
// 26. 플레이어 히트존 생성
player.hitzone = gf.addSprite(player.div, "hitzone", {
x: 16,
y: 192-80,
width: 128 + 32,
height: 64
});
// 27. 플레이어 콜존(히트존2) 생성
player.colzone = gf.addSprite(player.div, "hitzone", {
x: 72,
y: 76,
width: 48,
height: 64
});
// 28. 플레이어 아이들 함수 실행
player.idle();
// 29. 플레이어 상태 walk로 설정
gameState = "walk";
// 30. 플레이어 버튼 요소 삭제
$("#startButton").remove();
// 31. 콘테이너 디스플레이 설정
container.css("display", "block");
}
ㄴinitialize 에서 사용된 함수들
1. gf.addGroup
// 1. 그룹 프래그맨트 정의
gf.groupFragment = $("<div class='gf_group' style='position: absolute; overflow: visible;'></div>");
// 2. 그룹 생성 함수
gf.addGroup = function(parent, divId, options)
{
// 2-1. 옵션 합치기
var options = $.extend({
x: 0,
y: 0,
flipH: false,
flipV: false,
rotate: 0,
scale: 1
}, options);
// 2-2. 그룹 DOM 객체 생성.
var group = gf.groupFragment.clone().css({
left: options.x,
top: options.y}).attr("id",divId).data("gf",options);
// 2-3. 해당 그룹 DOM 화면에 더하기
parent.append(group);
return group;
}
2. gf.ImportTiled
PASS.. 2부에서 다뤄봄!
gf.importTiled = function(url, parent, divIdPrefix){
var animations = [];
var tilemaps = [];
$.ajax({
url: url,
async: false,
dataType: 'json',
success: function(json){
var height = json.height;
var width = json.width;
var tileHeight = json.tileheight;
var tileWidth = json.tilewidth;
var layers = json.layers;
var usedTiles = [];
var animationCounter = 0;
var tilemapArrays = [];
// detection which animations we need to generate
// and converting the tiles array indexes to the new ones
for (var i=0; i < layers.length; i++){
if(layers[i].type === "tilelayer"){
var tilemapArray = new Array(height);
for (var j=0; j<height; j++){
tilemapArray[j] = new Array(width);
}
for (var j=0; j < layers[i].data.length; j++){
var tile = layers[i].data[j];
if(tile === 0){
tilemapArray[Math.floor(j / width)][j % width] = 0;
} else {
if(!usedTiles[tile]){
animationCounter++;
usedTiles[tile] = animationCounter;
animations.push(new gf.animation({
url: json.tilesets[0].image,
offsetx: ((tile-1) % Math.floor(json.tilesets[0].imagewidth / tileWidth)) * tileWidth,
offsety: Math.floor((tile-1) / Math.floor(json.tilesets[0].imagewidth / tileWidth)) * tileHeight
}));
}
tilemapArray[Math.floor(j / width)][j % width] = usedTiles[tile];
}
}
tilemapArrays.push(tilemapArray);
}
}
// adding the tilemaps
for (var i=0; i<tilemapArrays.length; i++){
tilemaps.push(gf.addTilemap(parent, divIdPrefix+i, {
x: 0,
y: 0,
tileWidth: tileWidth,
tileHeight: tileHeight,
width: width,
height: height,
map: tilemapArrays[i],
animations: animations
}));
}
}
});
return {
animations: animations,
tilemaps: tilemaps
}
}
3. gf.addSprite
// 1. 스프라이트 프래그맨트 정의.
gf.spriteFragment = $("<div class='gf_sprite' style='position: absolute; overflow: hidden;'></div>");
// 2. 스프라이트 생성 함수.
gf.addSprite = function(parent, divId, options)
{
// 2-1. 옵션 합치기.
var options = $.extend({
x: 0,
y: 0,
width: 64,
height: 64,
flipH: false,
flipV: false,
rotate: 0,
scale: 1
}, options);
// 2-2. 스프라이트 DOM 객체 생성.
var sprite = gf.spriteFragment.clone().css({
left: options.x,
top: options.y,
width: options.width,
height: options.height}).attr("id",divId).data("gf",options);
// 2-3. 해당 스프라이트 화면에 더하기.
parent.append(sprite);
// 2-4. 해당 스프라이트 반환.
return sprite;
}
4. gf.setAnimation
// 0. div 프레임 설정 함수
gf.setFrame = function(div, animation) {
div.css("backgroundPosition", "" + (-animation.currentFrame * animation.width - animation.offsetx) + "px "+(-animation.offsety)+"px");
}
// 1. 애니메이션 배열 선언
gf.animations = [];
// 2. 애니메이션 설정 함수
gf.setAnimation = function(div, animation, loop, callback){
// 2-1. 입력받은 파라미터 바탕으로 animate 객체 생성.
var animate = {
animation: $.extend({}, animation),
div: div,
loop: loop,
callback: callback,
counter: 0
}
// 2-2 . 해당 div url 프로퍼티 설정.
if(animation.url){
div.css("backgroundImage","url('"+animation.url+"')");
}
// 2-3. 해당div의 존재여부 기본값으로 거짓 설정
var divFound = false;
// 2-4. 애니메이션 배열 검사해서 해당 div가 존재하는지 검사
for (var i = 0; i < gf.animations.length; i++) {
// 2-4-1. 만약 존재할경우 애니메이션 변경
if(gf.animations[i].div.is(div)){
divFound = true;
gf.animations[i] = animate;
}
}
// 2-5. 존재하지 않을경우 애니메이션 추가
if(!divFound) {
gf.animations.push(animate);
}
// 2-6. 해당 div프레임을 애니메이션으로 설정
gf.setFrame(div, animation);
}
5. NPC 생성 함수
// 1. NPC 생성함수 [파라미터 : 이름 텍스트 콘솔]
var NPC = function(name, text, console)
{
// 1-1. 현재 텍스트의 인덱스를 정의 하는변수 current 설정.
var current = 0;
// 1-2. getText 함수 정의
this.getText = function()
{
// 1-2-1. text 배열의 길이가 카운터와 같을경우 끝냄
if(current === text.length){
current = 0;
return "[end]";
}
// 1-2-2. 이름과 현재 텍스트 반환, current 값 증가
return name + ": " + text[current++];
};
// 1-3.dialog 함수 정의
this.dialog = function(){
// 1-3-1. console 이라는 DOM객체의 내용을 getText로 가져온 내용으로 설정.
console.html(this.getText());
}
}
6. Enemy 생성 함수
// 1. Enemy 생성함수 [파라미터 : 디펜드 모디파이어, 라이프]
var Enemy = function(defendModifier, life) {
// 1-1. defend 함수 정의
this.defend = function(){
// 1-1-1. 랜덤 소수를 반환해서 6을 곱한뒤 반올림한뒤 디펜드 모디파이어와 더해서 반환
return Math.round(Math.random() * 6) + defendModifier;
}
// 1-2. kill 함수 정의
this.kill = function(value){
//1-2-1. 라이프에서 밸류값을 뺌 (데미지를 입힘)
life -= value;
//1-2-2. 만약 라이프값이 0이랑 같거나 낮아질경우 상태를 dead로 만들고 참을 반환
if (life <= 0){
state = "dead";
return true;
}
// 평소에는 거짓을 반환
return false;
}
}
미스테리1.
npcs[npcs.length-1].object.div = npcs[npcs.length-1].div;
var A_GROUP = [];
var WTF = function()
{
console.log("nigga whaaaat?");
}
A_GROUP.push({A: $("#mygame"), B: new WTF});
A_GROUP[A_GROUP.length - 1].B.nigggggaaaaa = 23;
console.log(A_GROUP[0].B.nigggggaaaaa);
결과::
결론::
1) push 할때 불러도 함수 호출이 발생하는 구나.
2) push된 객체의 B값에 저장된 WTF 객체에 사실 niggggggggga 라는 변수가 없으나 위와같이 지정할경우
자동으로 생성되면서 값할당까지 함.
'창고 > JS KING 포니 [중단]' 카테고리의 다른 글
JAVASCRIPT#78 - offset 오프셋에 관하여 (0) | 2016.08.06 |
---|---|
JAVASCRIPT#76 - 횡스크롤 101 (0) | 2016.08.01 |
JAVASCRIPT#75 - data 메소드 data("gf")의 존재에 대하여 (0) | 2016.07.29 |
JAVASCRIPT#74 - 자바스크립트 중력 연출하기 (0) | 2016.07.26 |
JAVASCRIPT#73 - 자바스크립트 타일내 충돌 검출! (0) | 2016.07.25 |