더보기

쿠키런 프로젝트 시리즈
1.준비
https://ondolroom.tistory.com/297
2.전역공간
https://ondolroom.tistory.com/298
3.JPanel생성자
https://ondolroom.tistory.com/299
4.mapMove메서드
https://ondolroom.tistory.com/300
5.hit메서드
https://ondolroom.tistory.com/301
6.fall메서드
https://ondolroom.tistory.com/302
7.jump메서드
https://ondolroom.tistory.com/303
8.paintComponent 및 결과
https://ondolroom.tistory.com/304

 

https://ondolroom.tistory.com/300

 

자바 스윙 쿠키런 만들기 mapMove() 메서드 (프로젝트 진행)

https://ondolroom.tistory.com/299 자바 스윙 쿠키런 만들기 MyPanel 생성자 수정 (프로젝트 진행) https://ondolroom.tistory.com/298 자바 스윙 쿠키런 만들기 전역 변수 선언하기 (프로젝트 진행) 들어가기 전..

ondolroom.tistory.com

이번 편에는 위 코드 중 장애물에 피격 되었을 경우 발동되는 hit메서드를 만들어 보려고 한다.

 

더보기를 눌러 전체코드 확인

더보기
void hit() {
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				
				c1.setInvincible(true); // 쿠키를 무적상태로 전환
				
				System.out.println("피격무적시작");
				
				c1.setHealth(c1.getHealth() - 100); // 쿠키의 체력을 100 깎는다
				
				c1.setImage(hitIc.getImage()); // 쿠키를 부딛힌 모션으로 변경
				
				c1.setAlpha(80); // 쿠키의 투명도를 80으로 변경
				
				try { // 0.5초 대기
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				if(c1.getImage() == hitIc.getImage()) { // 0.5초 동안 이미지가 바뀌지 않았다면 기본이미지로 변경
					
					c1.setImage(cookieIc.getImage());
					
				}
				
				
				for (int j = 0; j < 11; j++) { // 2.5초간 캐릭터가 깜빡인다. (피격후 무적 상태를 인식)
					
					if(c1.getAlpha() == 80) { // 이미지의 알파값이 80이면 160으로 
						
						c1.setAlpha(160);
						
					} else { // 아니면 80으로
						
						c1.setAlpha(80);
						
					}
					try {
						Thread.sleep(250);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
				c1.setAlpha(255); // 쿠키의 투명도를 정상으로 변경
				
				c1.setInvincible(false);
				System.out.println("피격무적종료");
			}
		}).start();
	}

 

설명

 

피격시 새 쓰레드 가동

피격 이펙트가 도는 동안에도 우리는 움직여야 하기 때문에 

따로 쓰레드를 만들어 줘야한다.

 

피격시 필요한 변수 수정

피격이되면, 캐릭터 상태가 무적(Invincible)이 되니 true로 바꿔주자
( 생성자에서 무적인 경우에는 낙사하지 않도록 미리 제작해 두었다는 점을 참고하자.)

부딛히게 되면 체력이 100 깎이고 부딛힌 모션으로 변경된다.

그리고 부딛힌 점을 확인하기 위해 캐릭터의 투명도를 80으로 내린다.
(0투명 ~ 반투명 ~ 255불투명)

그리고 0.5초간 피격모션이 끝나도록 다른 이미지로 변경이 되지 않았다면 달리는 모션으로 다시 바꿔준다.

 

캐릭터 깜빡이게 하기

캐릭터가 무적인 상태를 확실히 보여주기 위해 캐릭터를 깜빡이게 할 것이다.

for문으로 2.5초간 깜빡이게 되는데 투명도가 80일경우 160으로, 160일 경우 80으로 변경된다.

마지막으로 무적이 끝나기 전에 투명도를 255로 변경하고

무적을 종료한다.

 

다음편에 계속

 

 

더보기

쿠키런 프로젝트 시리즈
1.준비
https://ondolroom.tistory.com/297
2.전역공간
https://ondolroom.tistory.com/298
3.JPanel생성자
https://ondolroom.tistory.com/299
4.mapMove메서드
https://ondolroom.tistory.com/300
5.hit메서드
https://ondolroom.tistory.com/301
6.fall메서드
https://ondolroom.tistory.com/302
7.jump메서드
https://ondolroom.tistory.com/303
8.paintComponent 및 결과
https://ondolroom.tistory.com/304

 

https://ondolroom.tistory.com/299

 

자바 스윙 쿠키런 만들기 MyPanel 생성자 수정 (프로젝트 진행)

https://ondolroom.tistory.com/298 자바 스윙 쿠키런 만들기 전역 변수 선언하기 (프로젝트 진행) 들어가기 전에... 아래 내용을 숙지하고 시작하자 https://ondolroom.tistory.com/279 자바 WindowBuilder 설치..

ondolroom.tistory.com

 

패널 생성자에서 필요한 메서드들 중 맵 발판 젤리 장애물 이동 및 작동을  아래에서 구현하고자 한다.

 

더보기로 전체코드 확인

더보기
void mapMove() {
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				while (true) {
					
					if(runPage > 800) { // 800픽셀 이동 마다 체력이 10씩 감소한다 (추후 맵길이에 맟추어 감소량 조절)
						c1.setHealth(c1.getHealth()-10);
						runPage = 0;
					}
					
					runPage +=gameSpeed; // 화면이 이동하면 runPage에 이동한 만큼 저장된다.
					
					
					if (b11.getX() < -(b11.getWidth()-1)) { // 배경1-1 이 -(배경넓이)보다 작으면, 즉 화면밖으로 모두나가면 배경 1-2뒤에 붙음
						b11.setX(b11.getWidth());
					}
					if (b12.getX() < -(b12.getWidth()-1)) { // 배경1-2 가 -(배경넓이)보다 작으면, 즉 화면밖으로 모두나가면 배경 1-1뒤에 붙음
						b12.setX(b12.getWidth());
					}
					
					
					// 배경의 x좌표를 -1 해준다 (왼쪽으로 흐르는 효과)
					b11.setX(b11.getX()-gameSpeed/3); 
					b12.setX(b12.getX()-gameSpeed/3);
					
					
					// 발판위치를 -4 씩 해준다. (왼쪽으로 흐르는 효과)
					for (int i = 0; i < fieldList.size(); i++) {
						
						Field tempField = fieldList.get(i); // 임시 변수에 리스트 안에 있는 개별 발판을 불러오자
						
						if(tempField.getX() < -90) { // 발판의  x좌표가 -90 미만이면 해당 발판을 제거한다.(최적화)
							
							fieldList.remove(tempField);
							
						} else {
							
							tempField.setX(tempField.getX() - gameSpeed);  // 위 조건에 해당이 안되면 x좌표를 줄이자
							
						}
					}
					
					// 젤리위치를 -4 씩 해준다.
					for (int i = 0; i < jellyList.size(); i++) {
						
						Jelly tempJelly = jellyList.get(i); // 임시 변수에 리스트 안에 있는 개별 젤리를 불러오자
						
						if(tempJelly.getX() < -90) { // 젤리의 x 좌표가 -90 미만이면 해당 젤리를 제거한다.(최적화)
							
							fieldList.remove(tempJelly);
							
						} else {
							
							tempJelly.setX(tempJelly.getX() - gameSpeed); // 위 조건에 해당이 안되면 x좌표를 줄이자
							
							foot = c1.getY() + c1.getHeight(); // 캐릭터 발 위치 재스캔
							
							if( // 캐릭터의 범위 안에 젤리가 있으면 아이템을 먹는다.
								c1.getImage() != slideIc.getImage()
								&& tempJelly.getX() + tempJelly.getWidth()*20/100 >= c1.getX()
								&& tempJelly.getX() + tempJelly.getWidth()*80/100 <= face
								&& tempJelly.getY() + tempJelly.getWidth()*20/100 >= c1.getY()
								&& tempJelly.getY() + tempJelly.getWidth()*80/100 <= foot
								&& tempJelly.getImage() != jellyEffectIc.getImage()) {
								
								tempJelly.setImage(jellyEffectIc.getImage()); // 젤리의 이미지를 이펙트로 바꾼다
								resultScore = resultScore + tempJelly.getScore(); // 총점수에 젤리 점수를 더한다
								
								
							} else if( // 슬라이딩 하는 캐릭터의 범위 안에 젤리가 있으면 아이템을 먹는다.
								c1.getImage() == slideIc.getImage()
								&& tempJelly.getX() + tempJelly.getWidth()*20/100 >= c1.getX()
								&& tempJelly.getX() + tempJelly.getWidth()*80/100 <= face
								&& tempJelly.getY() + tempJelly.getWidth()*20/100 >= c1.getY() + c1.getHeight()*1/3
								&& tempJelly.getY() + tempJelly.getWidth()*80/100 <= foot
								&& tempJelly.getImage() != jellyEffectIc.getImage()) {
								
								tempJelly.setImage(jellyEffectIc.getImage()); // 젤리의 이미지를 이펙트로 바꾼다
								resultScore = resultScore + tempJelly.getScore(); // 총점수에 젤리 점수를 더한다
								
							}
						}
					}
					
					// 장애물위치를 - 4 씩 해준다.
					for (int i = 0; i < tacleList.size(); i++) {
						
						Tacle tempTacle = tacleList.get(i); // 임시 변수에 리스트 안에 있는 개별 장애물을 불러오자
						
						if(tempTacle.getX() < -90) { 
							
							fieldList.remove(tempTacle); // 장애물의 x 좌표가 -90 미만이면 해당 젤리를 제거한다.(최적화)
							
						} else {
							
							tempTacle.setX(tempTacle.getX() - gameSpeed);	// 위 조건에 해당이 안되면 x좌표를 줄이자
							
							face = c1.getX() + c1.getWidth(); // 캐릭터 정면 위치 재스캔
							foot = c1.getY() + c1.getHeight(); // 캐릭터 발 위치 재스캔
							
							if( // 무적상태가 아니고 슬라이드 중이 아니며 캐릭터의 범위 안에 장애물이 있으면 부딛힌다
									!c1.isInvincible()
									&& c1.getImage() != slideIc.getImage()
									&& tempTacle.getX() + tempTacle.getWidth()/2 >= c1.getX()
									&& tempTacle.getX() + tempTacle.getWidth()/2 <= face
									&& tempTacle.getY() + tempTacle.getHeight()/2 >= c1.getY()
									&& tempTacle.getY() + tempTacle.getHeight()/2 <= foot) {
								
								hit(); // 피격 + 무적 쓰레드 메서드
								
							} else if( // 슬라이딩 아닐시 공중장애물
									!c1.isInvincible()
									&& c1.getImage() != slideIc.getImage()
									&& tempTacle.getX() + tempTacle.getWidth()/2 >= c1.getX()
									&& tempTacle.getX() + tempTacle.getWidth()/2 <= face
									&& tempTacle.getY() <= c1.getY()
									&& tempTacle.getY() + tempTacle.getHeight()*95/100 > c1.getY()) {
								
								
								hit(); // 피격 + 무적 쓰레드 메서드
								
							}else if( // 무적상태가 아니고 슬라이드 중이며 캐릭터의 범위 안에 장애물이 있으면 부딛힌다
									!c1.isInvincible()
									&& c1.getImage() == slideIc.getImage()
									&& tempTacle.getX() + tempTacle.getWidth()/2 >= c1.getX()
									&& tempTacle.getX() + tempTacle.getWidth()/2 <= face
									&& tempTacle.getY() + tempTacle.getHeight()/2 >= c1.getY() + c1.getHeight()*2/3
									&& tempTacle.getY() + tempTacle.getHeight()/2 <= foot) {
								
								hit(); // 피격 + 무적 쓰레드 메서드
								
							} else if( // 슬라이딩시 공중장애물
									!c1.isInvincible()
									&& c1.getImage() == slideIc.getImage()
									&& tempTacle.getX() + tempTacle.getWidth()/2 >= c1.getX()
									&& tempTacle.getX() + tempTacle.getWidth()/2 <= face
									&& tempTacle.getY() < c1.getY()
									&& tempTacle.getY() + tempTacle.getHeight()*95/100 > c1.getY() + c1.getHeight()*2/3) {
								
								hit(); // 피격 + 무적 쓰레드 메서드
							}
						}
					}
					
					// 쿠키가 밟을 발판을 계산하는 코드
					int tempField; // 발판위치를 계속 스캔하는 지역변수
					int tempNowField; // 캐릭터와 발판의 높이에 따라 저장되는 지역변수, 결과를 nowField에 저장한다
					
					
					// 쿠키가 무적상태라면 낙사 하지 않기 때문에 400으로 세팅 / 무적이 아니라면 2000(낙사지점);
					if (c1.isInvincible()) {
						tempNowField = 400;
					} else {
						tempNowField = 2000;
					}

					for (int i = 0; i < fieldList.size(); i++) { // 발판의 개수만큼 반복

						int tempX = fieldList.get(i).getX(); // 발판의 x값

						if (tempX > c1.getX()-60 && tempX <= face) { // 발판이 캐릭 범위 안이라면 

							tempField = fieldList.get(i).getY(); // 발판의 y값을 tempField에 저장한다

							
							foot = c1.getY() + c1.getHeight(); // 캐릭터 발 위치 재스캔
							
							// 발판위치가 tempNowField보다 높고, 발바닥 보다 아래 있다면
							// 즉, 캐릭터 발 아래에  제일 높이 있는 발판이라면 tempNowField에 저장한다.
							if (tempField < tempNowField && tempField >= foot) {

								tempNowField = tempField;

							}
						}
					}

					nowField = tempNowField; // 결과를 nowField에 업데이트 한다.
					
					
					
					if(escKeyOn) { // esc키를 누르면 게임이 멈춘다
						while (escKeyOn) {
							try {
								Thread.sleep(10);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
					
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
				}
			}
		}).start();
	}

 

설명

 

맵이동 메서드

맵이동 메서드는 쓰레드를 하나 새로 생성한다.

 

캐릭터 체력 자연감소

맵을 일정거리 이상 이동하면 캐릭터의 체력이 깎이도록 하였다.

 

배경 이동

같은 배경을 무한 반복하는 내용이다.

1번째 배경이 -(배경넓이)가 되면 2번째 배경이 X좌표 0으로 오게될테니 2번째 배경 뒤쪽으로 옮기는 식이다.

배경은 느리게 흐르기 때문에 게임속도의 1/3만 해주었다.

 

발판 이동

발판과 젤리, 장애물은 같은량을 움직인다. 참고하자.

발판리스트에서 발판을 하나씩 가져와서 화면 밖으로 나간 발판은 최적화를 위해 제거해주고

그렇지 않은 발판은 게임속도에 맟춰서 왼쪽으로 이동시킨다.

 

젤리 이동 및 동작

젤리는 장판과 비슷하지만, 캐릭터가 젤리를 먹는 이벤트가 있다.

젤리를 먹는 조건은 위와 같다.

캐릭터의 발위치를 확인한 뒤

젤리 획득범위를 넓게하고 싶다면

20/100을 1/100 가까이로 줄이면되고, 80/100을 100/100 가까이로 늘이면된다.

슬라이딩을 하는경우 높이가 낮아지기 때문에 Y값에다가 캐릭터의 높이의 1/3을 더해주었다.

 

 

장애물 이동 및 동작

장애물은 코드가 너무 길어 접은글로 올렸다

더보기
					// 장애물위치를 - 4 씩 해준다.
					for (int i = 0; i < tacleList.size(); i++) {
						
						Tacle tempTacle = tacleList.get(i); // 임시 변수에 리스트 안에 있는 개별 장애물을 불러오자
						
						if(tempTacle.getX() < -90) { 
							
							fieldList.remove(tempTacle); // 장애물의 x 좌표가 -90 미만이면 해당 젤리를 제거한다.(최적화)
							
						} else {
							
							tempTacle.setX(tempTacle.getX() - gameSpeed);	// 위 조건에 해당이 안되면 x좌표를 줄이자
							
							face = c1.getX() + c1.getWidth(); // 캐릭터 정면 위치 재스캔
							foot = c1.getY() + c1.getHeight(); // 캐릭터 발 위치 재스캔
							
							if( // 무적상태가 아니고 슬라이드 중이 아니며 캐릭터의 범위 안에 장애물이 있으면 부딛힌다
									!c1.isInvincible()
									&& c1.getImage() != slideIc.getImage()
									&& tempTacle.getX() + tempTacle.getWidth()/2 >= c1.getX()
									&& tempTacle.getX() + tempTacle.getWidth()/2 <= face
									&& tempTacle.getY() + tempTacle.getHeight()/2 >= c1.getY()
									&& tempTacle.getY() + tempTacle.getHeight()/2 <= foot) {
								
								hit(); // 피격 + 무적 쓰레드 메서드
								
							} else if( // 슬라이딩 아닐시 공중장애물
									!c1.isInvincible()
									&& c1.getImage() != slideIc.getImage()
									&& tempTacle.getX() + tempTacle.getWidth()/2 >= c1.getX()
									&& tempTacle.getX() + tempTacle.getWidth()/2 <= face
									&& tempTacle.getY() <= c1.getY()
									&& tempTacle.getY() + tempTacle.getHeight()*95/100 > c1.getY()) {
								
								
								hit(); // 피격 + 무적 쓰레드 메서드
								
							}else if( // 무적상태가 아니고 슬라이드 중이며 캐릭터의 범위 안에 장애물이 있으면 부딛힌다
									!c1.isInvincible()
									&& c1.getImage() == slideIc.getImage()
									&& tempTacle.getX() + tempTacle.getWidth()/2 >= c1.getX()
									&& tempTacle.getX() + tempTacle.getWidth()/2 <= face
									&& tempTacle.getY() + tempTacle.getHeight()/2 >= c1.getY() + c1.getHeight()*2/3
									&& tempTacle.getY() + tempTacle.getHeight()/2 <= foot) {
								
								hit(); // 피격 + 무적 쓰레드 메서드
								
							} else if( // 슬라이딩시 공중장애물
									!c1.isInvincible()
									&& c1.getImage() == slideIc.getImage()
									&& tempTacle.getX() + tempTacle.getWidth()/2 >= c1.getX()
									&& tempTacle.getX() + tempTacle.getWidth()/2 <= face
									&& tempTacle.getY() < c1.getY()
									&& tempTacle.getY() + tempTacle.getHeight()*95/100 > c1.getY() + c1.getHeight()*2/3) {
								
								hit(); // 피격 + 무적 쓰레드 메서드
							}
						}
					}

 

장애물은 경우의 수는 아래와 같다.

1. 달리는 중 아래에 있는 장애물
2. 달리는 중 머리 위에 있는 장애물
3. 슬라이드 중 아래에 있는 장애물
4. 슬라이드 중 머리 위에 있는 장애물

캐릭터는 장애물에 부딛히면 캐릭터가 데미지를 입고 깜빡이며 3초간 무적상태가 된다.(추후 hit() 메서드 추가)

그러므로 무적상태가 아닐때 충돌이 발생해야한다.(!c1.isInvincible())
또한 이미지가 슬라이드 중인지 달리는 중인지 구분하고
(downKeyOn으로 구분하게 되면 공중에서 다운키를 눌러서 범위를 줄일 수 있게된다.)

장애물은 커보이지만 피격범위가 좁기때문에 (이용자 배려인듯)

x값은 장애물 넓이의 정중앙으로

y값도 높이의 정중앙으로 범위를 정했다.

공중장애물은 캐릭터 머리와 만나기 때문에 높이의 95퍼센트 까지로 지정하였다.

데미지를 입지 않는다면 96~99퍼센트 까지 조정해보자.

 

발판 계산

쿠키가 밟을 발판을 계산하는 코드이다.

예를들어 발판이 없고 무적이라면 최저바닥이 400으로서 낙사하지 않는다.

발판이 없고 무적이 아니라면 바닥은 2000으로 화면 밖으로 나가 낙사하게 된다.

그 경우가 아니라면 발판들을 모두 스캔해서 캐릭터가 달리고 있는 위치의 발판만 추려 낸뒤

제일 높은 곳에 있는 발판의 위치를 업데이트한다.

예를들어 Y값을 기준으로 400위치에만 발판이 하나 있고 캐릭터가  300위치에 있다면 nowField는  400

400위치 200위치 두 곳에 발판이 있는데

캐릭터가 100에 있다면 200이 발판이 되며 캐릭터가 300에 있다면 400이 발판이 된다
(머리위에 있는 발판으로 떨어질 수는 없지 않은가.)

 

esc관련 코드

esc를 누르면 위의 모든 코드들이 중지되고 esc를 다시누를 때까지 대기한다.

 

while문이기 때문에 0.01초정도 간격을 준다 (주지 않으면 리소스 사용량이 폭증한다.)

 

다음편에 계속

더보기

쿠키런 프로젝트 시리즈
1.준비
https://ondolroom.tistory.com/297
2.전역공간
https://ondolroom.tistory.com/298
3.JPanel생성자
https://ondolroom.tistory.com/299
4.mapMove메서드
https://ondolroom.tistory.com/300
5.hit메서드
https://ondolroom.tistory.com/301
6.fall메서드
https://ondolroom.tistory.com/302
7.jump메서드
https://ondolroom.tistory.com/303
8.paintComponent 및 결과
https://ondolroom.tistory.com/304

 

https://ondolroom.tistory.com/298

 

자바 스윙 쿠키런 만들기 전역 변수 선언하기 (프로젝트 진행)

들어가기 전에... 아래 내용을 숙지하고 시작하자 https://ondolroom.tistory.com/279 자바 WindowBuilder 설치 들어가기 전에... 필자는 STS툴(이클립스)를 사용하고 있으며, WindowBuilder로 스윙을 간단히 구현..

ondolroom.tistory.com

 

 

더보기를 눌러 전체코드확인

더보기

 

package Test4;

import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicTreeUI.TreeCancelEditingAction;

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;

public class CookieRun2 {

	private JFrame frame;

	private JPanel panel; // 패널

	private Button escButton; // esc 버튼 (테스트 중)

	// 배경 이미지
	private ImageIcon backIc = new ImageIcon("testimg/backTest.png"); // 제일 뒷 배경
	private ImageIcon secondBackIc = new ImageIcon("배경이미지2"); // 2번째 배경

	// 쿠키 이미지 아이콘들
	private ImageIcon cookieIc = new ImageIcon("testimg/cookieTest.png"); // 기본모션
	private ImageIcon jumpIc = new ImageIcon("testimg/jumpTest.png"); // 점프모션
	private ImageIcon doubleJumpIc = new ImageIcon("testimg/doubleJumpTest.png"); // 더블점프모션
	private ImageIcon fallIc = new ImageIcon("testimg/fallTest.png"); // 낙하모션(더블 점프 후)
	private ImageIcon slideIc = new ImageIcon("testimg/slideTest.png"); // 슬라이드 모션
	private ImageIcon hitIc = new ImageIcon("testimg/hitTest.png"); // 부딛히는 모션

	// 젤리 이미지 아이콘들
	private ImageIcon jelly1Ic = new ImageIcon("testimg/jelly1Test.png");
	private ImageIcon jelly2Ic = new ImageIcon("testimg/jelly2Test.png");
	private ImageIcon jelly3Ic = new ImageIcon("testimg/jelly3Test.png");
	private ImageIcon jellyHPIc = new ImageIcon("testimg/jellyHPTest.png");

	private ImageIcon jellyEffectIc = new ImageIcon("testimg/effectTest.png");

	// 발판 이미지 아이콘들
	private ImageIcon field1Ic = new ImageIcon("testimg/footTest.png"); // 발판
	private ImageIcon field2Ic = new ImageIcon("testimg/footTest2.png"); // 공중발판

	// 장애물 이미지 아이콘들
	private ImageIcon tacle10Ic = new ImageIcon("testimg/tacleTest10.png"); // 1칸 장애물
	private ImageIcon tacle20Ic = new ImageIcon("testimg/tacleTest20.png"); // 2칸 장애물
	private ImageIcon tacle30Ic = new ImageIcon("testimg/tacleTest30.png"); // 3칸 장애물
	private ImageIcon tacle40Ic = new ImageIcon("testimg/tacleTest40.png"); // 3칸 장애물

	// 리스트 생성
	private List<Jelly> jellyList = new ArrayList<>(); // 젤리 리스트

	private List<Field> fieldList = new ArrayList<>(); // 발판 리스트

	private List<Tacle> tacleList = new ArrayList<>(); // 장애물 리스트

	private int runPage = 0; // 한 화면 이동할때마다 체력을 깎기 위한 변수

	private int runStage = 1; // 스테이지를 확인하는 변수이다. (미구현)

	private int resultScore = 0; // 결과점수를 수집하는 변수

	private int gameSpeed = 3; // 게임 속도

	private int nowField = 2000; // 발판의 높이를 저장.

	private boolean escKeyOn = false; // 일시정지를 위한 esc키 확인

	private boolean downKeyOn = false; // 다운키 눌렀는지 여부

	int face; // 쿠키의 정면
	int foot; // 쿠키의 발

	// 이미지 파일로 된 맵을 가져온다.
	private int[] sizeArr; // 이미지의 넓이와 높이를 가져오는 1차원 배열
	private int[][] colorArr; // 이미지의 x y 좌표의 픽셀 색값을 저장하는 2차원배열

	private Image buffImage; // 더블버퍼 이미지
	private Graphics buffg; // 더블버퍼 g

	private AlphaComposite alphaComposite; // 투명도 관련 오브젝트

	Cookie c1; // 쿠키 오브젝트
	Back b11; // 배경1-1 오브젝트
	Back b12; // 배경1-2 오브젝트

	class MyPanel extends JPanel {

		public MyPanel() {

			setFocusable(true);

			// 쿠키 인스턴스 생성 / 기본 자료는 클래스안에 내장 되어 있기 때문에 이미지만 넣었다.
			c1 = new Cookie(cookieIc.getImage());

			// 쿠키의 정면 위치 / 쿠키의 x값과 높이를 더한 값
			face = c1.getX() + c1.getWidth();

			// 쿠키의 발밑 위치 / 쿠키의 y값과 높이를 더한 값
			foot = c1.getY() + c1.getHeight();

			// 배경1-1 인스턴스 생성
			b11 = new Back(backIc.getImage(), 0, 0, // y 값 (조정 필요)
					backIc.getImage().getWidth(null), backIc.getImage().getHeight(null));

			// 배경1-2 인스턴스 생성
			b12 = new Back(backIc.getImage(), backIc.getImage().getWidth(null), 0, // y 값 (조정 필요)
					backIc.getImage().getWidth(null), backIc.getImage().getHeight(null));

			// 맵 정보 불러오기
			try {
				sizeArr = Util.getSize("testimg/firstMap1.png"); // 맵 사이즈를 배열에 저장
				colorArr = Util.getPic("testimg/firstMap1.png"); // 맵 픽셀값을 배열에 저장
			} catch (Exception e1) {
				e1.printStackTrace();
			}

			int maxX = sizeArr[0]; // 맵의 넓이
			int maxY = sizeArr[1]; // 맵의 높이

			for (int i = 0; i < maxX; i += 1) { // 젤리는 1칸을 차지하기 때문에 1,1사이즈로 반복문을 돌린다.
				for (int j = 0; j < maxY; j += 1) {
					if (colorArr[i][j] == 16776960) { // 색값이 16776960일 경우 기본젤리 생성
						// 좌표에 40을 곱하고, 넓이와 높이는 30으로 한다.
						jellyList.add(new Jelly(jelly1Ic.getImage(), i * 40, j * 40, 30, 30, 1234));

					} else if (colorArr[i][j] == 13158400) { // 색값이 13158400일 경우 노란젤리 생성
						// 좌표에 40을 곱하고, 넓이와 높이는 30으로 한다.
						jellyList.add(new Jelly(jelly2Ic.getImage(), i * 40, j * 40, 30, 30, 2345));

					} else if (colorArr[i][j] == 9868800) { // 색값이 9868800일 경우 노란젤리 생성
						// 좌표에 40을 곱하고, 넓이와 높이는 30으로 한다.
						jellyList.add(new Jelly(jelly3Ic.getImage(), i * 40, j * 40, 30, 30, 3456));

					} else if (colorArr[i][j] == 16737280) { // 색값이 16737280일 경우 피 물약 생성
						// 좌표에 40을 곱하고, 넓이와 높이는 30으로 한다.
						jellyList.add(new Jelly(jellyHPIc.getImage(), i * 40, j * 40, 30, 30, 4567));
					}

				}
			}

			for (int i = 0; i < maxX; i += 2) { // 발판은 4칸을 차지하는 공간이기 때문에 2,2사이즈로 반복문을 돌린다.
				for (int j = 0; j < maxY; j += 2) {
					if (colorArr[i][j] == 0) { // 색값이 0 일경우 (검은색)
						// 좌표에 40을 곱하고, 넓이와 높이는 80으로 한다.
						fieldList.add(new Field(field1Ic.getImage(), i * 40, j * 40, 80, 80));

					} else if (colorArr[i][j] == 6579300) { // 색값이 6579300 일경우 (회색)
						// 좌표에 40을 곱하고, 넓이는 80으로 높이는 40 한다.
						fieldList.add(new Field(field1Ic.getImage(), i * 40, j * 40, 80, 40));
					}
				}
			}

			for (int i = 0; i < maxX; i += 2) { // 장애물은 4칸 이상을 차지한다. 추후 수정
				for (int j = 0; j < maxY; j += 2) {
					if (colorArr[i][j] == 16711680) { // 색값이 16711680일 경우 (빨간색) 1칸
						// 좌표에 40을 곱하고, 넓이와 높이는 80으로 한다.
						tacleList.add(new Tacle(tacle10Ic.getImage(), i * 40, j * 40, 80, 80, 0));

					} else if (colorArr[i][j] == 16711830) { // 색값이 16711830일 경우 (분홍) 2칸
						// 좌표에 40을 곱하고, 넓이와 높이는 160으로 한다.
						tacleList.add(new Tacle(tacle20Ic.getImage(), i * 40, j * 40, 80, 160, 0));

					} else if (colorArr[i][j] == 16711935) { // 색값이 16711830일 경우 (핫핑크) 3칸
						// 좌표에 40을 곱하고, 넓이와 높이는 240으로 한다.
						tacleList.add(new Tacle(tacle30Ic.getImage(), i * 40, j * 40, 80, 240, 0));
					}
				}
			}

			// 리페인트 전용 쓰레드
			new Thread(new Runnable() {

				@Override
				public void run() {
					while (true) {
						repaint();

						if (escKeyOn) { // esc 키를 누를경우 리페인트를 멈춘다
							while (escKeyOn) {
								try {
									Thread.sleep(10);
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
						}

						try {
							Thread.sleep(10);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}).start();

			mapMove(); // 배경 발판 장애물 작동 메서드

			fall(); // 낙하 스레드 발동 메서드

			addKeyListener(new KeyAdapter() { // 키 리스너 추가

				@Override
				public void keyPressed(KeyEvent e) {
					if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { // esc키를 눌렀을 때
						if (!escKeyOn) {
							escKeyOn = true;
							add(escButton);
							repaint(); // 화면을 어둡게 하기위한 리페인트
						} else {
							remove(escButton);
							escKeyOn = false;
						}
					}

					if (!escKeyOn) {
						if (e.getKeyCode() == KeyEvent.VK_SPACE && c1.getCountJump() < 2) { // 스페이스 키를 누르고 더블점프가 2가 아닐때

							jump(); // 점프 메서드 가동

						}
						if (e.getKeyCode() == KeyEvent.VK_DOWN) { // 다운키를 눌렀을 때

							downKeyOn = true; // downKeyOn 변수를 true로

							if (c1.getImage() != slideIc.getImage() // 쿠키이미지가 슬라이드 이미지가 아니고
									&& !c1.isJump() // 점프 중이 아니며
									&& !c1.isFall()) { // 낙하 중도 아닐 때

								c1.setImage(slideIc.getImage()); // 이미지를 슬라이드이미지로 변경

							}
						}
					}
				}

				@Override
				public void keyReleased(KeyEvent e) {

					if (e.getKeyCode() == KeyEvent.VK_DOWN) { // 다운키를 뗐을 때

						downKeyOn = false; // downKeyOn 변수를 false로

						if (c1.getImage() != cookieIc.getImage() // 쿠키이미지가 기본이미지가 아니고
								&& !c1.isJump() // 점프 중이 아니며
								&& !c1.isFall()) { // 낙하 중도 아닐 때

							c1.setImage(cookieIc.getImage()); // 이미지를 기본이미지로 변경
						}
					}
				}
			});
		}

		@Override
		protected void paintComponent(Graphics g) {

		}

	}

	void mapMove() {

	}

	void hit() {

	}

	void fall() {

	}

	void jump() {

	}

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					CookieRun2 window = new CookieRun2();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public CookieRun2() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 800, 500);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		panel = new MyPanel();
		frame.getContentPane().add(panel, BorderLayout.CENTER);
		panel.setLayout(null);

		escButton = new Button("재시작");
		escButton.setBounds(350, 240, 50, 30);
		escButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				panel.remove(escButton);
				escKeyOn = false;
			}
		});
	}
}

 

설명

 

setFocusable 키입력 우선권획득

내가 만든 패널에 키보드나 마우스 리스너의 우선권을 준다.

 

인스턴스 생성

쿠키와 배경 인스턴스를 생성하자

 

맵정보 로딩

게임을 플레이할 맵 정보를 로딩한다.

Util클래스 안의 getSize와 getPic메서드를 이용하여 사이즈와 색값을 가져온다.

 

아래는 맵 예시이다.

 

색값을 이용하여 맵을 불러오자.

 

젤리 객체 생성

저장한 픽셀 정보를 이용하여 색값별로 젤리 객체 생성하여를 jellyList에 저장한다.

 

발판 객체 생성

발판은 바닥에 있는 발판과 공중에 있는 발판 2가지이다.

색깔로 구분하여 로딩한다.

 

장애물 객체 생성

장애물 객체를 생성한다.

장애물은 1칸 2칸 3칸 (4단도 있으나 미구현)이 있으니 각각 색값을 달리하여 리스트에 추가한다.

 

리페인트 전용 쓰레드

리페인트만 전담하는 쓰레드이다. 

추가 사항으로 esc를 누르면 해제될 때까지 그림을 그리지 않도록 하였다.

 

맵이동, 낙하 쓰레드를 실행하는 메서드 (추후 제작)

원래는 맵이동과 낙하 쓰레드를 직접 적었으나 메서드로 따로 분리하였다.

추후 블로깅에서 알아보도록 하자.

 

키리스너 추가

키리스너를 추가한다.

내용은 아래와 같다.

 

키를 눌렀을 때

키를 눌렀을 경우,

esc키를 누르면 escKeyOn 변수가 true가 되고 버튼을 화면에 보이게한다.

스페이스 와 다운키 등은 esc메뉴가 없을 때에만 작동하도록 하였고,

스페이스 키를 누르면 점프 메서드가 작동,

다운키를 누르면 슬라이드 이미지로 변경 되도록 하였다.

 

키를 뗐을 때

키 릴리즈 메서드이다.

다운키를 떼었을 때 슬라이드 이미지를 달리는 이미지로 다시 바꿀 것이다.

 

다음편에 계속

더보기

쿠키런 프로젝트 시리즈
1.준비
https://ondolroom.tistory.com/297
2.전역공간
https://ondolroom.tistory.com/298
3.JPanel생성자
https://ondolroom.tistory.com/299
4.mapMove메서드
https://ondolroom.tistory.com/300
5.hit메서드
https://ondolroom.tistory.com/301
6.fall메서드
https://ondolroom.tistory.com/302
7.jump메서드
https://ondolroom.tistory.com/303
8.paintComponent 및 결과
https://ondolroom.tistory.com/304

 

들어가기 전에...

아래 내용을 숙지하고 시작하자

https://ondolroom.tistory.com/279

 

자바 WindowBuilder 설치

들어가기 전에... 필자는 STS툴(이클립스)를 사용하고 있으며, WindowBuilder로 스윙을 간단히 구현하고, 자세한 코드는 직접 짜는 것을 추천한다. 이클립스 마켓에서 윈도우빌더를 설치하자. WindowBuilder생성..

ondolroom.tistory.com

 

더보기를 눌러서 전체 코드를 확인하자.

더보기
package Test4;

import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicTreeUI.TreeCancelEditingAction;

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;

public class CookieRun2 {

	private JFrame frame;
	
	JPanel panel; // 패널
	
	Button escButton; // esc 버튼 (테스트 중)
	
	
	// 배경 이미지
	private ImageIcon backIc = new ImageIcon("testimg/backTest.png"); // 제일 뒷 배경
	private ImageIcon secondBackIc = new ImageIcon("배경이미지2"); // 2번째 배경

	
	// 쿠키 이미지 아이콘들
	private ImageIcon cookieIc = new ImageIcon("testimg/cookieTest.png"); // 기본모션
	private ImageIcon jumpIc = new ImageIcon("testimg/jumpTest.png"); // 점프모션
	private ImageIcon doubleJumpIc = new ImageIcon("testimg/doubleJumpTest.png"); // 더블점프모션
	private ImageIcon fallIc = new ImageIcon("testimg/fallTest.png"); // 낙하모션(더블 점프 후)
	private ImageIcon slideIc = new ImageIcon("testimg/slideTest.png"); // 슬라이드 모션
	private ImageIcon hitIc = new ImageIcon("testimg/hitTest.png"); // 부딛히는 모션
	
	
	// 젤리 이미지 아이콘들
	private ImageIcon jelly1Ic = new ImageIcon("testimg/jelly1Test.png");
	private ImageIcon jelly2Ic = new ImageIcon("testimg/jelly2Test.png");
	private ImageIcon jelly3Ic = new ImageIcon("testimg/jelly3Test.png");
	private ImageIcon jellyHPIc = new ImageIcon("testimg/jellyHPTest.png");
	
	private ImageIcon jellyEffectIc = new ImageIcon("testimg/effectTest.png");
	
	
	// 발판 이미지 아이콘들
	private ImageIcon field1Ic = new ImageIcon("testimg/footTest.png"); // 발판
	private ImageIcon field2Ic = new ImageIcon("testimg/footTest2.png"); //공중발판
	
	
	// 장애물 이미지 아이콘들
	private ImageIcon tacle10Ic = new ImageIcon("testimg/tacleTest10.png"); // 1칸 장애물
	private ImageIcon tacle20Ic = new ImageIcon("testimg/tacleTest20.png"); // 2칸 장애물
	private ImageIcon tacle30Ic = new ImageIcon("testimg/tacleTest30.png");	// 3칸 장애물
	private ImageIcon tacle40Ic = new ImageIcon("testimg/tacleTest40.png");	// 3칸 장애물
	
	
	// 리스트 생성
	private List<Jelly> jellyList = new ArrayList<>(); // 젤리 리스트

	private List<Field> fieldList = new ArrayList<>(); // 발판 리스트

	private List<Tacle> tacleList = new ArrayList<>(); // 장애물 리스트
	
	private int runPage = 0; // 한 화면 이동할때마다 체력을 깎기 위한 변수
	
	private int runStage = 1; // 스테이지를 확인하는 변수이다. (미구현)
	
	private boolean escKeyOn = false; // 일시정지를 위한 esc키 확인
	
	private int resultScore = 0; // 결과점수를 수집하는 변수
	
	private int gameSpeed = 3; // 게임 속도
	
	private int nowField = 2000; // 발판의 높이를 저장.
	
	private boolean downKeyOn = false; // 다운키 눌렀는지 여부
	
	
	// 이미지 파일로 된 맵을 가져온다.
	private int[] sizeArr; // 이미지의 넓이와 높이를 가져오는 1차원 배열
	private int[][] colorArr; // 이미지의 x y 좌표의 픽셀 색값을 저장하는 2차원배열
	
	
	private Image buffImage; // 더블버퍼 이미지
	private Graphics buffg; // 더블버퍼 g
	
	
	private AlphaComposite alphaComposite; // 투명도 관련 오브젝트
	
	Cookie c1; // 쿠키 오브젝트
	Back b11; // 배경1-1 오브젝트
	Back b12; // 배경1-2 오브젝트
	
	int face; // 쿠키의 정면
	int foot; // 쿠키의 발

	
	class MyPanel extends JPanel{
		
		public MyPanel() {
			
		}

		
		@Override
		protected void paintComponent(Graphics g) {
			
		}
		
	}
	
	void mapMove(){

	}
	
	void hit() {

	}
	
	void fall() {

	}
	
	void jump() {

	}
	
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					CookieRun2 window = new CookieRun2();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public CookieRun2() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 800, 500);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		panel = new MyPanel();
		frame.getContentPane().add(panel, BorderLayout.CENTER);
		panel.setLayout(null);
		
		escButton = new Button("재시작");
		escButton.setBounds(350, 240, 50, 30);
		escButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				panel.remove(escButton);
				escKeyOn = false;
			}
		});
	}	
}

 

설명

 

프레임과 패널 버튼 등을 전역공간에 배치

프레임과 패널 버튼 등을 전역공간에 두는 것은, 클래스 내의 다른객체나 메서드들이 이용 할 수 있도록 하기 위함이다.

 

이미지 배치

게임에 이용할 이미지들을 배치한다

 

리스트 배치

젤리와 발판, 장애물 객체들을 저장할 리스트를 배치한다.

 

게임관련 변수 배치

 

 

paintComponent 관련 레퍼런스 배치

 

 

기타 레퍼런스들

클래스 내부 어디서든 사용할 수 있도록 전역공간에 선언해둔다

 

커스텀 JPanel

내가 직접 커스텀한 패널을 사용하기 위해 클래스 안에 inner클래스로 만들어준다.

 

메서드

메서드 들을 채워나갈 예정이다.

 

기타

위 코드 대부분은 windowBuilder에서 만들어 준 것이고

수정한 것은

new JPanel을 new MyPanel로 내가 커스텀한 패널로 교체 해주었다.

그리고 재시작 버튼은 미리 만들어 두었다. (esc키를 누르면 생성 되었다가 다시 사라지게 할 예정)

더보기

쿠키런 프로젝트 시리즈
1.준비
https://ondolroom.tistory.com/297
2.전역공간
https://ondolroom.tistory.com/298
3.JPanel생성자
https://ondolroom.tistory.com/299
4.mapMove메서드
https://ondolroom.tistory.com/300
5.hit메서드
https://ondolroom.tistory.com/301
6.fall메서드
https://ondolroom.tistory.com/302
7.jump메서드
https://ondolroom.tistory.com/303
8.paintComponent 및 결과
https://ondolroom.tistory.com/304

 

준비물

이미지 파일이다.

그림판으로 만든 테스트용 이미지임.

testimg.zip
0.01MB

 

아래는 기본 클래스 파일들이다. 더보기로 볼 수 있다.
생성자 및 게터 세터는 lombok 라이브러리를 이용하였다.(모르시는 분들은 인터넷 검색 )

더보기

배경

package Test4;

import java.awt.Image;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Back {
	private Image image;
	private int x;
	private int y;
	private int width;
	private int height;
}

 

쿠키

package Test4;

import java.awt.Image;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Cookie {
	
	private Image image; // 쿠키 이미지
	
	// 쿠키의 좌표와 넓이 높이
	private int x = 160;
	private int y = 0;
	private int width = 80;
	private int height = 120;
	
	// 쿠키의 투명도 (0이 투명, 255가 완전 불투명)
	private int alpha = 255;
	
	// 쿠키의 체력
	private int health = 1000;
	
	// 쿠키의 상태 (거대화와 가속화 미구현)
	private int big = 0; // 거대화 남은 시간
	private int fast = 0; // 가속화 남은 시간
	private int countJump = 0; // 점프 횟수
	private boolean invincible = false; // 무적 여부
	private boolean fall = false; // 낙하 여부
	private boolean jump = false; // 점프 여부
	
	public Cookie(Image image){ // 이미지만 넣어주자
		this.image = image;
	}
}

 

발판

package Test4;

import java.awt.Image;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Field {
	
	private Image image; // 발판 이미지
	
	// 발판의 좌표와 넓이 높이
	private int x;
	private int y;
	private int width;
	private int height;
}

 

젤리

package Test4;

import java.awt.Image;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Jelly {
	private Image image; // 젤리 이미지
	
	// 젤리들의 좌표와 크기
	private int x;
	private int y;
	private int width;
	private int height;
	
	// 젤리의 점수
	private int score;
}

 

장애물

package Test4;

import java.awt.Image;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Tacle {
	
	private Image image; // 장애물 이미지
	
	// 장애물의 좌표와 넓이 높이
	private int x;
	private int y;
	private int width;
	private int height;
	
	// 장애물 상태
	private int state;
}

 

유틸

package Test4;

import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.sql.Timestamp;
import java.time.LocalDateTime;

import javax.imageio.ImageIO;

public class Util {

	// 이미지의 사이즈 가져오기
	public static int[] getSize(String src) throws Exception {
		File imgf = new File(src);
		BufferedImage img = ImageIO.read(imgf);
		int width = img.getWidth();
		int height = img.getHeight();
		int[] tempSize = {width, height};
		return tempSize;
	}
	
	// 이미지의 픽셀값 가져오기
	public static int[][] getPic(String src) throws Exception{
		File imgf = new File(src);
		BufferedImage img = ImageIO.read(imgf);
		int width = img.getWidth();
		int height = img.getHeight();
		int[] pixels=new int[width*height];
		PixelGrabber grab = new PixelGrabber(img, 0, 0, width, height, pixels, 0,width);
		grab.grabPixels();
		
		int[][] picture=new int[width][height];
		for(int i=0;i<pixels.length;i++)
		      picture[i%width][i/width]=pixels[i] + 16777216;
		return picture;
	}
	
	// 현재시간 가져오기
	public static long getTime() {
		return Timestamp.valueOf(LocalDateTime.now()).getTime();
	}
	
	// substring으로 발판 정보 검색
	// 배열로 장판 및 젤리 배치 할 때 사용 (현재 미사용)
//	public static int getGround(String ground, int index) {
//		return Integer.parseInt(ground.substring(index, index + 1));
//	}
	
}

 

 

배열로 발판과 젤리를 만드는 것은 직관적이지 않고 배치하기가 쉽지 않다.

그래서 이미지를 읽어들여서 발판과 젤리를 배치하도록 만들어 보려고 한다.

 

참고 사이트

https://sunnyholic.com/79

 

이미지에서 픽셀 배열 얻기.

File imgf = new File("source.png"); BufferedImage img = ImageIO.read(imgf); int width = img.getWidth(); int height = img.getHeight(); int[] pixels=new int[width*height]; PixelGrabber grab = new Pixe..

sunnyholic.com

 

 

맵이미지 그리기

맵의 크기는 200 * 12로 하였다.

아주 작게 보이니 돋보기로 확대를 하여 그리도록 하자.

8배로 확대한 사진이다.

발판은 검은색이며 2칸 2칸 마다 만들어 두면 된다. (귀찮음 때문에 쭉 그어 버렸다.)

젤리는 1칸1칸마다 만들 수 있다. 

 

이미지를 값으로 가져오는 클래스 생성

코드를 복사하려면 더보기 클릭

더보기
package Test3;

import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.File;

import javax.imageio.ImageIO;

public class Bf2 {
	
	static int[] getSize(String src) throws Exception { // 이미지의 사이즈를 가져오는 메서드
		File imgf = new File(src); // 이미지 경로를 입력받아서 파일객체를 만든다.
		BufferedImage img = ImageIO.read(imgf); // 이미지를 버퍼드이미지에 넣는다.
		int width = img.getWidth(); // 이미지의 넓이
		int height = img.getHeight(); // 이미지의 높이
		int[] tempPos = {width, height}; // 넓이 높이를 배열로 만든다.
		return tempPos; // 리턴한다.
	}
	
	static int[][] getPic(String src) throws Exception{ // 아래 코드는 어디다가 갖다두고 쓰자.
		File imgf = new File(src);
		BufferedImage img = ImageIO.read(imgf);
		int width = img.getWidth();
		int height = img.getHeight();
		int[] pixels=new int[width*height];
		PixelGrabber grab = new PixelGrabber(img, 0, 0, width, height, pixels, 0,width);
		grab.grabPixels();
		
		int[][] picture=new int[width][height];
		for(int i=0;i<pixels.length;i++)
		      picture[i%width][i/width]=pixels[i] + 16777216;
		return picture;
	}
	
	public static void main(String[] args) {
        int x = 10;
        int y = 21;
        try {
        	int[] tempArr1 = getSize("img/firstMap.png");
        	int maxX = tempArr1[0];
        	int maxY = tempArr1[1];
        	
        	int[][] tempArr = getPic("img/firstMap.png");
        	
        	for (int i = 0; i <	 maxX; i+=1) {
        		for (int j = 0; j < maxY; j+=1) {
        			System.out.println(tempArr[i][j]);
					
				}
			}
        	
        	
		} catch (Exception e) {
			e.printStackTrace();
		}
        
	}
}

 

 

전역공간에 젤리이미지와 리스트 추가

젤리리스트와 발판리스트를 만든다.

색값을 담을 2차원 배열과

이미지의 사이즈를 담을 배열을 선언한다.

 

패널에서 이미지 불러오기

sizeArr과 colorArr를 초기화 해준다.

미리만들어둔 fieldList와 jellyList에 발판과 젤리를 추가한다.

 

배경 및 발판 이동 쓰레드 수정

배경 및 발판 이동 쓰레드 내용에 아래 내용들을 추가하자

 

 

paintComponent에 발판과 젤리를 그려주자

buffg는 더블버퍼링 관련 내용이기 때문에, 쓰지않는 사람은 g로 바꾼다.

 

결과

 

 

리스트를 하나더 추가하여 아래와 같이 장애물도 만들어보자

들어가기 전에...

아래 페이지를 먼저보시고 어려우시다면 넘어오세요.

https://ondolroom.tistory.com/294

 

자바 스윙 다중 발판 구현하기 (프로젝트 대비)

들어가기 전에... 아래 페이지를 먼저 보시는 것이 빠른 이해에 도움이 됩니다. https://ondolroom.tistory.com/289 자바 스윙 발판 구현하기 (프로젝트 대비) 들어가기 전에... 아래 페이지를 먼저 보시는 것이..

ondolroom.tistory.com

 

* 2중 for문 없이 제작하려면 매우 노가다가 심하니 주의하세요.

 

 

전역공간에 변수 및 배열 추가

발판의 모습을 보여주는 스트링과 리스트들을 추가한다.

벌써부터 물량의 압박이 느껴진다. (이 글에서 빠르게 이해를 하고 이중포문으로 만들어보자.)

 

 

패널에서 발판 추가하기

각각 리스트에 위의 문자열에서 1이면 발판을 추가한다.

복붙하다가 숫자를 잘못적지 않도록 주의한다.

 

 

배경 및 발판 이동 쓰레드 수정

여기로 이동하자.

 

발판들이 왼쪽으로 이동할 수 있도록 -4씩 빼주자. 복붙하다보면 위의 숫자들이 같을 경우가 있다 주의하자.

 

마찬가지로 현재 캐릭터 범위 안에 발판들이 있는지 스캔한다.

footList0번까지 만들어주자.

 

마지막에 꼭 배열을 뒤집어주자.

 

현재 캐릭이 밟을 수 있는 발판 정보를 저장한다.

 

paintComponent로 그림을 그리자

buffg는 더블버퍼링 관련 코드이기때문에 쓰지않는 사람은 g로 바꿔주자.

 

 

결과

 

들어가기 전에...

아래 페이지를 먼저 보시는 것이 빠른 이해에 도움이 됩니다.

https://ondolroom.tistory.com/289

 

자바 스윙 발판 구현하기 (프로젝트 대비)

들어가기 전에... 아래 페이지를 먼저 보시는 것이 빠른 이해에 도움이 됩니다. https://ondolroom.tistory.com/288 자바 스윙 더블점프 구현하기 (프로젝트 대비) 들어가기 전에... 아래 페이지를 먼저 읽��

ondolroom.tistory.com

 

이전에는 문자열 하나로 발판을 만들었다면 이제는 발판을 배열로 저장하여 구현하려고 한다.

2중 배열 또는 2중 포문이 포함되어 있으니 천천히 따라해보자.

 

 

전역공간에 배열 추가하기

추후 문자열로 된 필드 정보를 담기위한 fieldStr 배열이다.

두번째로 발판 리스트를 담는 fieldList배열이다.(발판 정보를 담은 배열을 저장하는 배열이다.)

 

 

패널에 발판 정보를 입력

 

 

배경 및 발판이동 쓰레드를 수정

이전 글에서 배경이 왼쪽으로 이동하는 쓰레드를 만들어 두었다.

그 아래에 발판을 이동시키는 코드를 추가하자.

 

이중포문이라고 쫄지말자.

결국 개별발판을 불러오기 위함이다.

각각 발판을 -4씩 해주는 내용일 뿐이니 천천히 이해하도록하자.

 

이것도 마찬가지이다.

개별 발판이 캐릭터가 밟을 수 있는 범위 안에 있는지 판별하는 것이다.

 

마지막으로 범위 안에 발판이 있다면, 캐릭터에 높이에 따라 현재 밟을 수 있는 발판을 지정해준다.

 

그림 그리기

paintComponent에 발판코드를 추가하자

마찬가지로 개별발판을 각각 그려주는 것이다.

buffg는 더블버퍼링을 위한 변수로서, 더블버퍼링을 쓰지 않는다면  g로 변경하자.

 

결과

+ Recent posts