void fall() {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
foot = c1.getY() + c1.getHeight(); // 캐릭터 발 위치 재스캔
// 발바닥이 발판보다 위에 있으면 작동
if (
!escKeyOn // 일시중지가 발동 안됐을 때
&&foot < nowField // 공중에 있으며
&& !c1.isJump() // 점프 중이 아니며
&& !c1.isFall()) { // 떨어지는 중이 아닐 때
c1.setFall(true); // 떨어지는 중으로 전환
System.out.println("낙하");
if (c1.getCountJump() == 2) { // 더블점프가 끝났을 경우 낙하 이미지로 변경
c1.setImage(fallIc.getImage());
}
long t1 = Util.getTime(); // 현재시간을 가져온다
long t2;
int set = 1; // 처음 낙하량 (0~10) 까지 테스트해보자
while (foot < nowField) { // 발이 발판에 닿기 전까지 반복
t2 = Util.getTime() - t1; // 지금 시간에서 t1을 뺀다
int fallY = set + (int) ((t2) / 40); // 낙하량을 늘린다.
foot = c1.getY() + c1.getHeight(); // 캐릭터 발 위치 재스캔
if (foot + fallY >= nowField) { // 발바닥+낙하량 위치가 발판보다 낮다면 낙하량을 조정한다.
fallY = nowField - foot;
}
c1.setY(c1.getY()+fallY); // Y좌표에 낙하량을 더한다
if (c1.isJump()) { // 떨어지다가 더블 점프를 하면 낙하중지
break;
}
if (escKeyOn) {
long tempT1 = Util.getTime();
long tempT2 = 0;
while (escKeyOn) {
tempT2 = Util.getTime() -tempT1;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
t1 = t1 + tempT2;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
c1.setFall(false);
if (
downKeyOn // 다운키를 누른상태고
&& !c1.isJump() // 점프 상태가 아니고
&& !c1.isFall() // 낙하 상태가 아니고
&& c1.getImage() != slideIc.getImage()) { // 쿠키 이미지가 슬라이드 이미지가 아닐 경우
c1.setImage(slideIc.getImage()); // 쿠키 이미지를 슬라이드로 변경
} else if (
!downKeyOn // 다운키를 누른상태가 아니고
&& !c1.isJump() // 점프 상태가 아니고
&& !c1.isFall() // 낙하 상태가 아니고
&& c1.getImage() != cookieIc.getImage()) { // 쿠키 이미지가 기본 이미지가 아닐 경우
c1.setImage(cookieIc.getImage());
}
if (!c1.isJump()) { // 발이 땅에 닿고 점프 중이 아닐 때 더블점프 카운트를 0으로 변경
c1.setCountJump(0);
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
설명
코드가 약간 복잡할 수 있으므로 사진을 조금씩 중복하여 올리도록 하겠다.
낙하 쓰레드 생성
낙하 중에도 맵은 움직이고 우리는 더블점프를 하여야 한다.
그렇기 때문에 쓰레드로 만들어 준다.
낙하 쓰레드는 게임 도중 내내 발동 해야 하기 때문에 while문을 이용하였다.
먼저 캐릭터 발위치를 재스캔한다.
그리고 조건을 확인하게되는데 esc메뉴가 안떠있을 경우(메뉴가떠있는데 계속 낙하하면 안되기 때문) 발판보다 발이 위에 있을 경우 점프가 아닌 경우 (상승량이 0이 되었을 경우다) 떨어지는 중이 아닌 경우 (지금 떨어지는 중인데 또 떨어질 수는 없지 않은가.)
떨어지는 중으로 전환된다. c1.setFall(true);
쿠키런에서는 더블점프 후에만 낙하 이미지로 변경된다.
Util.getTime();으로 t1에 현재시간을 저장해준다.
Util.getTime();은 1970년 1월1일부터 현재시간까지 1/1000초씩 더하여 long값을 리턴해준다.
set값은 낙하량인데 처음에 1픽셀씩 떨어지고 점점 커지게 만드려는 의도이다.
위 코드는 길기 때문에 이미지를 나누어서 설명하도록 한다.
그 후 내부 while을 돌게 되면 발이 발판에 닫기 전까지 하락하게 된다.
t2에 현재시간 - 낙하시작시간 을 저장한다. (시간이 갈수록 늘어나기 때문에 낙하량으로 변환하려는 의도)
fallY에set + (int) ((t2) / 40); 를 해주는데 t2는 1초에 1000씩 늘어나기 때문에 값을 줄이기 위해 40을 나누어주었다.
다시한번 캐릭터 발 위치을 재스캔하고
발바닥+낙하량 위치가 발판보다 낮다면 낙하량을 조절한다.
예를들어 발판이 400인데 캐릭터가 399위치에 있다.
그런데 낙하량이 10일경우 409가 되어 발판보다 아래에 있게된다.
그러한 점을 방지하기위해 발판에 닫기 직전에 낙하량을 조절한다.
그 값을 캐릭터의 Y 값에 추가하게 된다.
떨어지는 도중 점프를 하거나 더블점프를 하면 낙하를 멈춰야 하기 때문에 break문을 사용한다.
esc메뉴 관련 코드인데 , 이전의 코드들과는 약간 다른 것을 확인 했을 것이다.
대기하는 동안에도 현실시간은 계속 흐르고 있고 그렇게 되면 낙하량이 무지막지하게 늘어나게된다.
그것을 방지하기위해 임시로 지나간 시간을 저장해 두었다가 t1에 추가해주는 것이다.
마찬가지로 무한반복문에는 대기시간을 걸어둬야한다.
만약 발이 땅에 닿아 내부 반복문을 빠져나가게 된다면,
쿠키는 하락 상태를 벗어나게 된다.
위 코드는 단순히 캐릭터의 이미지를 변환하는 코드인데, 조건이 까다로워 보인다.
하지만 결과적으로는 캐릭터나 누웠는지 서있는지 판단하는 코드이다. (글쓴이도 이리저리 테스트후 조건을 늘린 것이다.)