도드넷
JAVASCRIPT#76 - 횡스크롤 101 본문
I can only hope, i can only prey that someday in some point of my life, i finally meet you and we fall in love.
JAVASCRIPT#76 - 횡스크롤 101 모든 함수정리
1. 스프라이트 추가하기
1. 스프라이트 프래그먼트 선언.
gf.spriteFragment = $("<div class='gf_sprite' style='position: absolute; overflow: hidden;'></div>");
2. 스프라이트 DOM 객체 생성함수.
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. options를 데이터로 가지는 스프라이트 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. 만든 DOM 객체를 실제로 스크린에 추가.
parent.append(sprite);
2-4. DOM 객체를 반환.
return sprite;
}
2. 애니메이션 셋팅 시스템
1. 프레임 설정 함수.
gf.setFrame = function(div, animation) {
div.css("backgroundPosition", "-" + (animation.currentFrame * animation.width + animation.offset) + "px 0px");
}
2. 애니메이션 객체 정의.
gf.animation = function(options)
{
2-1. 전달된 옵션값을 바탕으로 애니메이션 객체의 프로퍼티를 설정.
var defaultValues = {
url : false,
width : 64,
numberOfFrames : 1,
currentFrame : 0,
rate : 1,
offset: 0
}
$.extend(this, defaultValues, options);
2-2. 애니메이션의 레이트값을 기본 반복문 레이트값에 의해 설정.
if(options.rate){
// normalize the animation rate
this.rate = Math.round(this.rate / gf.baseRate);
}
2-3. 프리로드에 애니메이션에 사용될 이미지 주소 저장.
if(this.url){
gf.addImage(this.url);
}
}
3. 애니메이션 집합 설정.
gf.animations = [];
4. 애니메이션 설정 함수 정의.
gf.setAnimation = function(div, animation, loop)
{
4-1. 해당 div를 위한 복사_제 2차 애니메이션 객체 선언.
var animate = {
animation: $.extend({}, animation), // extend로 전달하게 될경우 복사해서 따로 만드는게 됨
div: div,
loop: loop,
counter: 0
}
4-2. 해당 DOM의 배경 이미지를 전달된 애니메이션 객체의 url로 설정.
if(animation.url){
div.css("backgroundImage","url('"+animation.url+"')");
}
4-3. 재생되고 있는 애니메이션이 있나없나 검사.
var divFound = false;
4-4. 만약 입력받은 div의 div를 가진 애니메이션이 있다면 해당 애니메이션을 입력받은 애니메이션으로 변경.
for (var i = 0; i < gf.animations.length; i++)
{
if(gf.animations[i].div.is(div)) // 참고로 여기서 is 는 == 하고 같음.
{
divFound = true;
gf.animations[i] = animate;
}
}
4-5. 찾을수없다면 해당 애니메이션을 div의 애니메이션으로 새로등록
if(!divFound) {
gf.animations.push(animate);
}
5. 주 반복문
gf.refreshGame = function (){
5-1. 끝난 애니메이션 배열 정의
var finishedAnimations = [];
5-2. 애니메이션 재생 반복문 (1반복 당 한 프레임씩 진행시킴)
for (var i=0; i < gf.animations.length; i++) {
var animate = gf.animations[i];
animate.counter++;
if (animate.counter == animate.animation.rate) {
animate.counter = 0;
animate.animation.currentFrame++;
if(!animate.loop && animate.animation.currentFrame > animate.animation.numberOfFrames){
finishedAnimations.push(i);
} else {
animate.animation.currentFrame %= animate.animation.numberOfFrames;
gf.setFrame(animate.div, animate.animation);
}
}
}
5-3. 끝난 애니메이션은 배열에서 제외함으로 애니메이션 종료.
for(var i=0; i < finishedAnimations.length; i++){
gf.animations.splice(finishedAnimations[i], 1);
}
?. 종합 반복문 (time 관련해서 지워도 상관없음)
// execute the callbacks
for (var i=0; i < gf.callbacks.length; i++) {
var call = gf.callbacks[i];
call.counter++;
if (call.counter == call.rate) {
var currentTime = (new Date()).getTime();
call.counter = 0;
call.callback(currentTime - gf.time);
}
}
gf.time = (new Date()).getTime();
}
/// DEMO :
var playerAnim = {
stand: new gf.animation({
url: "Images/player.png",
offset: 75
}),
walk: new gf.animation({
url: "Images/player.png",
offset: 150,
width: 75,
numberOfFrames: 10,
rate: 90
}),
jump: new gf.animation({
url: "Images/player.png",
offset: 900
})
};
gf.setAnimation(this.div, playerAnim.walk, true);
3. DOM 포지셔닝 시스템
gf.x = function(div,position) {
if(position) {
div.css("left", position);
div.data("gf").x = position;
} else {
return div.data("gf").x;
}
}
gf.y = function(div,position) {
if(position) {
div.css("top", position);
div.data("gf").y = position;
} else {
return div.data("gf").y;
}
}
gf.x(this.div, newX);
gf.y(this.div, newY);
4. 타일 시스템
1. 타일 애니메이션 배열 정의
var tiles =
[
new gf.animation({
url: "Images/tiles.png"
}),
new gf.animation({
url: "Images/tiles.png",
offset: 70
}),
new gf.animation({
url: "Images/tiles.png",
offset: 140
}),
new gf.animation({
url: "Images/tiles.png",
offset: 210
}),
new gf.animation({
url: "Images/tiles.png",
offset: 280
}),
new gf.animation({
url: "Images/tiles.png",
offset: 350
}),
new gf.animation({
url: "Images/tiles.png",
offset: 420
}),
];
2. 레벨 구성용 2차 배열 정의
var level = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7],
[5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 6, 6, 6, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 6, 6, 6, 5, 5, 5, 6, 6, 5, 5]];
3. 타일맵 DOM 프래그맨트 생성
gf.tilemapFragment = $("<div class='gf_tilemap' style='position: absolute'></div>");
4. 타일맵과 타일 객체 생성함수
gf.addTilemap = function(parent, divId, options)
{
4-1. 타일맵 객체의 옵션 설정
var options = $.extend({
x: 0,
y: 0,
tileWidth: 64,
tileHeight: 64,
width: 0,
height: 0,
map: [],
animations: []
}, options);
4-2. 타일을 담을 타일맵 객체 생성
var tilemap = gf.tilemapFragment.clone().attr("id",divId).data("gf",options);
4-3. 타일 생성
for (var i=0; i < options.height; i++){
for(var j=0; j < options.width; j++) {
4-3-1. 타일 인덱스 값 구하기
var animationIndex = options.map[i][j];
4-3-2. 타일 인덱스 값이 0 보다 크면 타일 생성
if(animationIndex > 0){
4-3-2-1. 타일 옵션 설정
var tileOptions = {
x: options.x + j*options.tileWidth,
y: options.y + i*options.tileHeight,
width: options.tileWidth,
height: options.tileHeight
}
4-3-2-2. i행 j열에 해당하는 타일 생성
var tile = gf.spriteFragment.clone().css({
left: tileOptions.x,
top: tileOptions.y,
width: tileOptions.width,
height: tileOptions.height}
).addClass("gf_line_"+i).addClass("gf_column_"+j).data("gf", tileOptions);
4-3-2-3. 해당 타일의 애니메이션 설정
gf.setAnimation(tile, options.animations[animationIndex-1]);
4-3-2-4. 해당 타일을 타일맵에 추가
tilemap.append(tile);
}
}
}
4-4. 타일맵을 부모 DOM에 추가
parent.append(tilemap);
4-5. 타일맵 반환
return tilemap;
}
5. 타일 - 물체 충돌 시스템
1. 두 선분의 충돌 위치를 반환하는 함수
gf.intersect = function(a1,a2,b1,b2){
var i1 = Math.min(Math.max(a1, b1), a2);
var i2 = Math.max(Math.min(a2, b2), a1);
return [i1, i2];
}
2. 타일맵과 물체의 충돌 위치를 인덱스로 전환해서 반환하는 인덱스 반환 함수
gf.tilemapBox = function(tilemapOptions, boxOptions){
2-1. 타일맵의 가로, 세로
var tmX = tilemapOptions.x;
var tmXW = tilemapOptions.x + tilemapOptions.width * tilemapOptions.tileWidth;
var tmY = tilemapOptions.y;
var tmYH = tilemapOptions.y + tilemapOptions.height * tilemapOptions.tileHeight;
2-2. 물체의 가로, 세로
var bX = boxOptions.x;
var bXW = boxOptions.x + boxOptions.width;
var bY = boxOptions.y;
var bYH = boxOptions.y + boxOptions.height;
2-3. 타일맵과 물체의 충돌 위치를 구함.
var x = gf.intersect(tmX,tmXW, bX, bXW);
var y = gf.intersect(tmY, tmYH, bY, bYH);
2-4. 충돌위치를 인덱스로 전환
return {
x1: Math.floor((x[0] - 0) / tilemapOptions.tileWidth),
y1: Math.floor((y[0] - 0) / tilemapOptions.tileHeight),
x2: Math.ceil((x[1] - 0) / tilemapOptions.tileWidth),
y2: Math.ceil((y[1] - 0) / tilemapOptions.tileHeight)
}
}
3. 타일 충돌 감지 :: 반환된 인덱스를 바탕으로 어떤 타일이 충돌했는지 알아내서 배열로 반환함.
gf.tilemapCollide = function(tilemap, box)
{
3-1. 타일맵 데이터 가져오기
var options = tilemap.data("gf");
3-2. 타일맵과 물체의 충돌위치 인덱스 구하기
var collisionBox = gf.tilemapBox(options, box);
3-3. 겹친 타일의 div를 저장할 배열 선언
var divs = [];
3-4. 충돌위치 인덱스 바탕으로 해당 타일과 타일의 인덱스 구하기
for (var i = collisionBox.y1; i < collisionBox.y2; i++){
for (var j = collisionBox.x1; j < collisionBox.x2; j++){
var index = options.map[i][j];
if( index > 0 && index < 6 ){
divs.push(tilemap.find(".gf_line_"+i+".gf_column_"+j)); // 타일맵이라는 객체중 ".gf_line_"+i+".gf_column_"+j"에 해당하는 클래스를 가진 객체를 찾아서 divs에 저장함.
}
else
{
player.onTheGround = 0;
}
}
}
3-5. 충돌한 타일 객체를 모은 divs 반환
return divs;
}
4. 플레이어 객체 선언
var player = new (function()
{
var acceleration = 9;
var speed = 20;
var status = "stand";
var horizontalMove = 0;
var onTheGround = 0;
4-1. 플레이어 위치 갱신 함수 (반복됨)
this.update = function ()
{
var delta = 30;
speed = Math.min(100,Math.max(-100, speed + acceleration * delta / 100.0));
4-1-1. 새 위치 설정용 변수들 설정.
var newY = gf.y(this.div) + speed * delta / 100.0;
var newX = gf.x(this.div) + horizontalMove;
var newW = gf.width(this.div);
var newH = gf.height(this.div);
4-1-2. 충돌한 타일을 구하기위해 함수호출해서 배열로써 저장.
var collisions = gf.tilemapCollide(tilemap, {x: newX, y: newY, width: newW, height: newH});
4-1-3. 충돌 반응/처리용 특수 반복문
var i = 0;
while (i < collisions.length > 0)
{
4-1-3-1. 충돌한 타일객체를 저장
var collision = collisions[i];
i++;
4-1-3-2. 충돌한 타일객체를 상자형 4포인트 객체로 만듬
var collisionBox = {
x1: gf.x(collision),
y1: gf.y(collision),
x2: gf.x(collision) + gf.width(collision),
y2: gf.y(collision) + gf.height(collision)
};
4-1-3-3. 방금만든 타일 상자와 플레이어 캐릭터간에 충돌 지점을 구함
var x = gf.intersect(newX, newX + newW, collisionBox.x1,collisionBox.x2);
var y = gf.intersect(newY, newY + newH, collisionBox.y1,collisionBox.y2);
4-1-3-4. 진입 방향에 따라 차잇값을 따로 구하게함.
var diffx = (x[0] == newX)? x[0]-x[1] : x[1]-x[0];
var diffy = (y[0] == newY)? y[0]-y[1] : y[1]-y[0];
4-1-3-5. Y충돌 인지 X충돌 인지 가려서 각기다른 차잇값을 빼줌으로 겹치지않게 해줌.
if (Math.abs(diffx) > Math.abs(diffy)){
// displace along the y axis
if(y[0] == newY)
{
}
else
{
}
this.onTheGround = 1;
newY -= diffy;
speed = 0;
if(status=="jump" && diffy > 0)
{
status="stand";
gf.setAnimation(this.div, playerAnim.stand);
}
}
else
{
if(x[0] == newX)
{
}
else
{
}
newX -= diffx;
}
}
5. 플레이어 위치설정
gf.x(this.div, newX);
gf.y(this.div, newY);
6. 1 업데이트당 좌우로 움직이는 양 제한. 무한 이속 스택킹 방지.
horizontalMove = 0;
};
this.left = function ()
{
switch (status)
{
case "stand":
gf.setAnimation(this.div, playerAnim.walk, true);
status = "walk";
horizontalMove -= 7;
break;
case "jump":
horizontalMove -= 5;
break;
case "walk":
horizontalMove -= 7;
break;
}
gf.transform(this.div, {flipH: true});
};
this.right = function ()
{
switch (status)
{
case "stand":
gf.setAnimation(this.div, playerAnim.walk, true);
status = "walk";
horizontalMove += 7;
break;
case "jump":
horizontalMove += 5;
break;
case "walk":
horizontalMove += 7;
break;
}
gf.transform(this.div, {flipH: false});
};
this.jump = function ()
{
switch (status)
{
case "stand":
case "walk":
status = "jump";
speed = -60;
gf.setAnimation(this.div, playerAnim.jump);
this.onTheGround = 0;
break;
}
};
this.idle = function (){
switch (status)
{
case "walk":
status = "stand";
gf.setAnimation(this.div, playerAnim.stand);
break;
}
};
});
6. 중력 구현
var player = new (function()
{
1. 플레이어 객체의 프로퍼티들
var acceleration = 9;
var speed = 20;
var status = "stand";
var horizontalMove = 0;
var onTheGround = 0;
2. 플레이어 위치 갱신함수
this.update = function ()
{
2-1. 조절값 정의
var delta = 30;
2-2. 상하 움직임용 속도를 -100~100 범위에서 일정히 지속적으로 증가시킴 (중력)
speed = Math.min(100,Math.max(-100, speed + acceleration * delta / 100.0));
2-3. 새 위치 설정
var newY = gf.y(this.div) + speed * delta / 100.0;
var newX = gf.x(this.div) + horizontalMove;
var newW = gf.width(this.div);
var newH = gf.height(this.div);
// COLLISION PART2
var collisions = gf.tilemapCollide(tilemap, {x: newX, y: newY, width: newW, height: newH});
var i = 0;
while (i < collisions.length > 0)
{
var collision = collisions[i];
i++;
var collisionBox = {
x1: gf.x(collision),
y1: gf.y(collision),
x2: gf.x(collision) + gf.width(collision),
y2: gf.y(collision) + gf.height(collision)
};
var x = gf.intersect(newX, newX + newW, collisionBox.x1,collisionBox.x2);
var y = gf.intersect(newY, newY + newH, collisionBox.y1,collisionBox.y2);
var diffx = (x[0] == newX)? x[0]-x[1] : x[1]-x[0];
var diffy = (y[0] == newY)? y[0]-y[1] : y[1]-y[0];
if (Math.abs(diffx) > Math.abs(diffy)){
// displace along the y axis
if(y[0] == newY)
{
}
else
{
}
this.onTheGround = 1;
newY -= diffy;
speed = 0;
if(status=="jump" && diffy > 0)
{
status="stand";
gf.setAnimation(this.div, playerAnim.stand);
}
}
else
{
if(x[0] == newX)
{
}
else
{
}
newX -= diffx;
}
//collisions = gf.tilemapCollide(tilemap, {x: newX, y: newY, width: newW, height: newH});
}
2-4. 플레이어 객체 위치설정.
gf.x(this.div, newX);
gf.y(this.div, newY);
2-5. 좌우 속도 제한, 스택킹 방지.
horizontalMove = 0;
};
this.left = function ()
{
switch (status)
{
case "stand":
gf.setAnimation(this.div, playerAnim.walk, true);
status = "walk";
horizontalMove -= 7;
break;
case "jump":
horizontalMove -= 5;
break;
case "walk":
horizontalMove -= 7;
break;
}
gf.transform(this.div, {flipH: true});
};
this.right = function ()
{
switch (status)
{
case "stand":
gf.setAnimation(this.div, playerAnim.walk, true);
status = "walk";
horizontalMove += 7;
break;
case "jump":
horizontalMove += 5;
break;
case "walk":
horizontalMove += 7;
break;
}
gf.transform(this.div, {flipH: false});
};
this.jump = function ()
{
switch (status)
{
case "stand":
case "walk":
status = "jump";
speed = -60;
gf.setAnimation(this.div, playerAnim.jump);
this.onTheGround = 0;
break;
}
};
this.idle = function (){
switch (status)
{
case "walk":
status = "stand";
gf.setAnimation(this.div, playerAnim.stand);
break;
}
};
});
7. 플레이어 컨트롤
1. 키값 저장할 배열 선언
gf.keyboard = [];
2. 키 이벤트를 통해서 키값 설정
$(document).keydown(function(event){
gf.keyboard[event.keyCode] = true;
});
$(document).keyup(function(event){
gf.keyboard[event.keyCode] = false;
});
3. 플레이어 객체 전용 이동함수 정의
var player = new (function()
{
var acceleration = 9;
var speed = 20;
var status = "stand";
var horizontalMove = 0;
var onTheGround = 0;
this.update = function ()
{
var delta = 30;
speed = Math.min(100,Math.max(-100, speed + acceleration * delta / 100.0));
var newY = gf.y(this.div) + speed * delta / 100.0;
var newX = gf.x(this.div) + horizontalMove;
var newW = gf.width(this.div);
var newH = gf.height(this.div);
// COLLISION PART2
var collisions = gf.tilemapCollide(tilemap, {x: newX, y: newY, width: newW, height: newH});
var i = 0;
while (i < collisions.length > 0)
{
var collision = collisions[i];
i++;
var collisionBox = {
x1: gf.x(collision),
y1: gf.y(collision),
x2: gf.x(collision) + gf.width(collision),
y2: gf.y(collision) + gf.height(collision)
};
var x = gf.intersect(newX, newX + newW, collisionBox.x1,collisionBox.x2);
var y = gf.intersect(newY, newY + newH, collisionBox.y1,collisionBox.y2);
var diffx = (x[0] == newX)? x[0]-x[1] : x[1]-x[0];
var diffy = (y[0] == newY)? y[0]-y[1] : y[1]-y[0];
if (Math.abs(diffx) > Math.abs(diffy)){
// displace along the y axis
if(y[0] == newY)
{
}
else
{
}
this.onTheGround = 1;
newY -= diffy;
speed = 0;
if(status=="jump" && diffy > 0)
{
status="stand";
gf.setAnimation(this.div, playerAnim.stand);
}
}
else
{
if(x[0] == newX)
{
}
else
{
}
newX -= diffx;
}
//collisions = gf.tilemapCollide(tilemap, {x: newX, y: newY, width: newW, height: newH});
}
gf.x(this.div, newX);
gf.y(this.div, newY);
horizontalMove = 0;
};
3-1. 좌이동 함수
this.left = function ()
{
switch (status)
{
case "stand":
gf.setAnimation(this.div, playerAnim.walk, true);
status = "walk";
horizontalMove -= 7;
break;
case "jump":
horizontalMove -= 5;
break;
case "walk":
horizontalMove -= 7;
break;
}
gf.transform(this.div, {flipH: true});
};
3-2. 우이동 함수
this.right = function ()
{
switch (status)
{
case "stand":
gf.setAnimation(this.div, playerAnim.walk, true);
status = "walk";
horizontalMove += 7;
break;
case "jump":
horizontalMove += 5;
break;
case "walk":
horizontalMove += 7;
break;
}
gf.transform(this.div, {flipH: false});
};
3-3. 점프 함수
this.jump = function ()
{
switch (status)
{
case "stand":
case "walk":
status = "jump";
speed = -60;
gf.setAnimation(this.div, playerAnim.jump);
this.onTheGround = 0;
break;
}
};
3-4. 아이들 함수
this.idle = function (){
switch (status)
{
case "walk":
status = "stand";
gf.setAnimation(this.div, playerAnim.stand);
break;
}
};
});
4. 주 반복문
var gameLoop = function()
{
4-1. 키가 눌리지않은 상황에서 기본적으로 플레이어는 아이들(idle) 상태여야함.
var idle = true;
4-2. 키 바인딩
if(gf.keyboard[37]){
player.left();
idle = false;
}
if(gf.keyboard[38] && player.onTheGround == 1){
player.jump();
idle = false;
}
if(gf.keyboard[39]){
player.right();
idle = false;
}
4-3. 키가 눌리지않아 아이들이 유지될경우 idle 함수 실행
if(idle){
player.idle();
}
4-4. 플레이어 위치 갱신 함수 실행
player.update();
for (var i = 0; i < enemies.length; i++){
enemies[i].update();
if (gf.spriteCollide(player.div, enemies[i].div)){
enemies[i].kill();
}
}
var playerPos = gf.x(player.div);
if(playerPos > 200) {
gf.x(group, 200 - playerPos);
$("#backgroundFront").css("background-position",""+(200 * 0.66 - playerPos * 0.66)+"px 0px");
$("#backgroundBack").css("background-position",""+(200 * 0.33 - playerPos * 0.33)+"px 0px");
}
};
8. 적 생성
1. 적 모음집 정의
var enemies = [];
2. 슬라임 객체 생성함수
var Slime = function()
{
2-1. 슬라임 객체의 여러가지 프로퍼티를 설정하는 함수정의
this.init = function(div, x1, x2, anim) {
this.div = div;
this.x1 = x1;
this.x2 = x2;
this.anim = anim;
this.direction = 1;
this.speed = 5;
this.dead = false;
gf.transform(div, {flipH: true});
gf.setAnimation(div, anim.walk);
};
2-2. 슬라임 객체 위치갱신 함수
this.update = function(){
if(this.dead){
this.dies();
} else {
var position = gf.x(this.div);
if (position < this.x1){
this.direction = 1;
gf.transform(this.div, {flipH: true});
}
if (position > this.x2){
this.direction = -1;
gf.transform(this.div, {flipH: false});
}
gf.x(this.div, gf.x(this.div) + this.direction * this.speed);
}
}
2-3. 슬라임 킬(죽이는) 함수 정의
this.kill = function(){
this.dead = true;
gf.setAnimation(this.div, this.anim.dead);
}
2-4. 죽음이면 발동하는 함수 정의
this.dies = function(){}
};
3. 플라이 생성함수 정의
var Fly = function() {}
3-1. 슬라임 함수를 복사해서 플라이함수 재정의
Fly.prototype = new Slime();
3-2. 플라이용 사망 함수 재정의
Fly.prototype.dies = function(){
gf.y(this.div, gf.y(this.div) + 5);
}
4. 주 반복문
var gameLoop = function() {
var idle = true;
if(gf.keyboard[37]){ //left arrow
player.left();
idle = false;
}
if(gf.keyboard[38] && player.onTheGround == 1){ //up arrow
player.jump();
idle = false;
}
if(gf.keyboard[39]){ //right arrow
player.right();
idle = false;
}
if(idle){
player.idle();
}
player.update();
4-1. 적 그룹으로 반복문 실행
for (var i = 0; i < enemies.length; i++){
4-1-1. 적 객체 위치갱신
enemies[i].update();
4-1-2. 적과 플레이어가 충돌시 해당 적 객체 킬함수 작동.
if (gf.spriteCollide(player.div, enemies[i].div)){
enemies[i].kill();
}
}
var playerPos = gf.x(player.div);
if(playerPos > 200) {
gf.x(group, 200 - playerPos);
$("#backgroundFront").css("background-position",""+(200 * 0.66 - playerPos * 0.66)+"px 0px");
$("#backgroundBack").css("background-position",""+(200 * 0.33 - playerPos * 0.33)+"px 0px");
}
};
gf.addCallback(gameLoop, 30);
9. 화면, 맵 이동 구현
var gameLoop = function() {
var idle = true;
if(gf.keyboard[37]){ //left arrow
player.left();
idle = false;
}
if(gf.keyboard[38] && player.onTheGround == 1){ //up arrow
player.jump();
idle = false;
}
if(gf.keyboard[39]){ //right arrow
player.right();
idle = false;
}
if(idle){
player.idle();
}
player.update();
for (var i = 0; i < enemies.length; i++){
enemies[i].update();
if (gf.spriteCollide(player.div, enemies[i].div)){
enemies[i].kill();
}
}
1. 플레이어 객체 위치 저장
var playerPos = gf.x(player.div);
2. 플레이어 객체 위치가 200 초과할시 뒷배경과 그룹에 속하는 모든 DOM 요소를 반대방향으로 이동
if(playerPos > 200) {
gf.x(group, 200 - playerPos);
$("#backgroundFront").css("background-position",""+(200 * 0.66 - playerPos * 0.66)+"px 0px");
$("#backgroundBack").css("background-position",""+(200 * 0.33 - playerPos * 0.33)+"px 0px");
}
};
gf.addCallback(gameLoop, 30);
10. 이미지 프리로드와 초기화 함수
0. 프리로드용 배열과 이미지 추가 함수정의
gf.imagesToPreload = [];
gf.addImage = function(url)
{
if ($.inArray(url, gf.imagesToPreload) < 0)
{
gf.imagesToPreload.push();
}
gf.imagesToPreload.push(url);
}
1. 게임시작 함수
gf.startGame = function(endCallback, progressCallback)
{
1-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];
}
1-2. 이미지 프리로드 검사용 반복문 설정
var preloadingPoller = setInterval(function() {
var counter = 0;
var total = gf.imagesToPreload.length;
for (var i = 0; i < total; i++) {
if (images[i].complete) {
counter++;
}
}
1-2-1. 이미지 로드가 끝나면 반복문을 마치고 주 반복문을 실행시킴
if (counter == total) {
clearInterval(preloadingPoller);
endCallback()
setInterval(gf.refreshGame, gf.baseRate);
gf.time = (new Date()).getTime();
} else {
if (progressCallback) {
count++;
progressCallback((count / total) * 100);
}
}
}, 100);
};
2. 초기화 함수
var initialize = function()
{
2-1. 스프라이트 객체, 그룹, 타일, 플레이어, 슬라임, 플라이 생성하고 애니메이션 설정하고 씬에 추가
$("#mygame").append("<div id='container' style='display: none; width: 640px; height: 480px;'>");
container = $("#container");
backgroundBack = gf.addSprite(container,"backgroundBack",{width: 640, height: 480});
backgroundFront = gf.addSprite(container,"backgroundFront",{width: 640, height: 480});
group = gf.addGroup(container,"group");
tilemap = gf.addTilemap(group, "level", {tileWidth: 70, tileHeight: 70, width: 42, height: 7, map: level, animations: tiles});
player.div = gf.addSprite(group,"player",{width: 74, height: 93});
var fly1 = new Fly();
fly1.init(
gf.addSprite(group,"fly1",{width: 69, height: 31, x: 280, y: 220}),
280, 490,
flyAnim
);
enemies.push(fly1);
var slime1 = new Slime();
slime1.init(
gf.addSprite(group,"slime1",{width: 43, height: 28, x: 980, y: 392}),
980, 1140,
slimeAnim
);
enemies.push(slime1);
var slime2 = new Slime();
slime2.init(
gf.addSprite(group,"slime2",{width: 43, height: 28, x: 1960, y: 392}),
1960, 2200,
slimeAnim
);
enemies.push(slime2);
gf.setAnimation(player.div, playerAnim.stand);
gf.setAnimation(backgroundBack, backgroundBackAnim);
gf.setAnimation(backgroundFront, backgroundFrontAnim);
container.css("display", "block");
}
gf.startGame(initialize);
11. 주 반복문
1. 콜백(추가 반복문) 배열 정의
gf.callbacks = [];
2. 콜백(추가 반복문)으로 추가하는 함수정의
gf.addCallback = function(callback, rate){
2-1. 콜백 배열에 해당 함수와 레이트, 카운터로 구성된 반복문 객체 넣기.
gf.callbacks.push({
callback: callback,
rate: Math.round(rate / gf.baseRate),
counter: 0
});
}
3. 주 반복문 정의
gf.refreshGame = function (){
var finishedAnimations = [];
for (var i=0; i < gf.animations.length; i++) {
var animate = gf.animations[i];
animate.counter++;
if (animate.counter == animate.animation.rate) {
animate.counter = 0;
animate.animation.currentFrame++;
if(!animate.loop && animate.animation.currentFrame > animate.animation.numberOfFrames){
finishedAnimations.push(i);
} else {
animate.animation.currentFrame %= animate.animation.numberOfFrames;
gf.setFrame(animate.div, animate.animation);
}
}
}
for(var i=0; i < finishedAnimations.length; i++){
gf.animations.splice(finishedAnimations[i], 1);
}
3-1. 콜백(추가 반복문) 제어함수
for (var i=0; i < gf.callbacks.length; i++) {
3-1-1. 현재 인덱스에 해당하는 콜백을 콜에 넣어서 설정
var call = gf.callbacks[i];
3-1-2. 현재 콜백의 카운터 값 증가
call.counter++;
3-1-3. 만약 현재 콜백의 카운터값이 레이트와 동일할경우 콜백 실행
if (call.counter == call.rate) {
call.counter = 0;
call.callback();
}
}
}
4. 제 1 반복문 gameLoop 정의
var gameLoop = function() {
var idle = true;
if(gf.keyboard[37]){ //left arrow
player.left();
idle = false;
}
if(gf.keyboard[38] && player.onTheGround == 1){ //up arrow
player.jump();
idle = false;
}
if(gf.keyboard[39]){ //right arrow
player.right();
idle = false;
}
if(idle){
player.idle();
}
player.update();
for (var i = 0; i < enemies.length; i++){
enemies[i].update();
if (gf.spriteCollide(player.div, enemies[i].div)){
enemies[i].kill();
}
}
var playerPos = gf.x(player.div);
if(playerPos > 200) {
gf.x(group, 200 - playerPos);
$("#backgroundFront").css("background-position",""+(200 * 0.66 - playerPos * 0.66)+"px 0px");
$("#backgroundBack").css("background-position",""+(200 * 0.33 - playerPos * 0.33)+"px 0px");
}
};
5. 제 1 반복문을 주 반복문에 추가
gf.addCallback(gameLoop, 30);
'창고 > JS KING 포니 [중단]' 카테고리의 다른 글
JAVASCRIPT#78 - offset 오프셋에 관하여 (0) | 2016.08.06 |
---|---|
JAVASCRIPT#77 - 탑다운 1부 (0) | 2016.08.02 |
JAVASCRIPT#75 - data 메소드 data("gf")의 존재에 대하여 (0) | 2016.07.29 |
JAVASCRIPT#74 - 자바스크립트 중력 연출하기 (0) | 2016.07.26 |
JAVASCRIPT#73 - 자바스크립트 타일내 충돌 검출! (0) | 2016.07.25 |