Character 클래스
package f_game; public class Character { String name; //이름 int maxHp; //최대체력 int maxMp; //최대마나 int hp; //체력 int mp; //마나 int att; //공격력 int def; //방어력 int level; //레벨 int exp; //경험치 Item[] items; //보유아이템을 저장할 배열 Character(String name, int hp, int mp, int att, int def){ //생성자 만들어서 변수 초기화 this.name = name; this.maxHp = hp; this.maxMp = mp; this.hp = this.maxHp; this.mp = this.maxMp; this.att = att; this.def = def; this.level = 1; this.exp = 0; this.items = new Item[10]; } //상태를 보여주는 메서드 void showInfo(){ System.out.println("================================"); System.out.println("------------- 상태 ---------------"); System.out.println("이름 : "+ name); System.out.println("레벨 : "+ level + "("+ exp + "/100)"); System.out.println("체력 : "+ hp + "/" + maxHp); System.out.println("마나 : "+ mp + "/" + maxMp); System.out.println("공격 : "+ att); System.out.println("방어 : "+ def); System.out.println("------------ 아이템 --------------"); for(int i = 0; i < items.length; i++){ if(items[i] != null){ System.out.println(items[i]); } } System.out.println("================================"); } //공격메서드 -파라미터로 공격 대상을 받아야 함 void attack(Monster m){ int damage = att - m.def; damage = damage <= 0 ? 1 : damage; m.hp = m.hp < damage ? m.hp - m.hp : m.hp - damage; System.out.println(name + "이 공격적으로 " + m.name + "에게 " + damage + "만큼 데미지를 주었습니다."); System.out.println(m.name + "의 현재 HP : "+ m.hp); } //경험치를 얻는 메서드 void getExp(int exp){ System.out.println(exp + "의 경험치를 획득하였습니다."); this.exp += exp; while(100<=this.exp){ levelUp(); this.exp -= 100; } } //일정 경험치를 얻으면 레벨업, 능력치 증가?/ 아이템을 얻는 메서드 void levelUp(){ level++; maxHp += 10; maxMp += 5; att += 2; def += 2; hp = maxHp; mp = maxMp; System.out.println("LEVEL UP!!"); } //아이템 가지고 있으면 능력치 증가? void getItem(Item item){ System.out.println(item.name + "을 획득하였습니다."); for(int i = 0; i < items.length; i++){ if(items[i]==null){ items[i] = item; break; } } maxHp += item.hp; maxMp += item.mp; att += item.att; def += item.def; } }Item 클래스
package f_game; public class Item { String name; //이름 int hp; //체력 int mp; //마나 int att; //공격력 int def; //방어력 Item(String name, int hp, int mp, int att, int def){ this.name = name; this.hp = hp; this.mp = mp; this.att = att; this.def = def; } public String toString(){ //toString() 객체의 정보를 문자열로 반환해주는 메서드 String info = name + " :"; if(0 < hp) info += " 체력+"+hp; if(0 < mp) info += " 마나+"+mp; if(0 < att) info += " 공격+"+att; if(0 < def) info += " 방어+"+def; return info; } }Monster 클래스
package f_game; public class Monster { String name; //이름 int maxHp; //최대체력 int maxMp; //최대마나 int hp; //체력 int mp; //마나 int att; //공격력 int def; //방어력 Item[] items; //보유아이템을 저장할 배열 Monster(String name, int maxHp, int matMp, int hp, int mp, int att, int def, Item[] items){ this.name = name; this.maxHp = hp; this.maxMp = mp; this.hp = this.maxHp; this.mp = this.maxMp; this.att = att; this.def = def; this.items = items; } void attack(Character c){ int damage = att - c.def; damage = damage <= 0 ? 1 : damage; c.hp = c.hp < damage ? c.hp - c.hp : c.hp - damage; System.out.println(name + "가 공격적으로" + c.name + "에게" + damage + "만큼 데미지를 주었습니다."); System.out.println(c.name + "의 현재 HP :"+ c.hp); } Item itemDrop(){ return items[(int)(Math.random() * items.length)]; //보유한 아이템에 랜덤인덱스 생성해서 리턴 } }MyGame 클래스 (게임 실행)
package f_game; import e_oop.ScanUtil; public class MyGame { Character c; Item[] items; MyGame(){ c = new Character("구암동불주먹", 100, 50, 20, 10); items = new Item[10]; items[0] = new Item("무한의대검",0,0,10,0); items[1] = new Item("가시갑옷",0,0,10,0); } public static void main(String[] args) { new MyGame().start(); } void start(){ int input = 0; while(true){ System.out.println("1.내정보\t2.사냥\t0.종료"); input = ScanUtil.nextInt(); switch (input) { case 1 : c.showInfo(); break; case 2 : hunt(); break; case 0 : System.out.println("종료되었습니다."); System.exit(0); break; } } } void hunt(){ Monster m = new Monster("고블린", 20, 10, 15, 10 , 5, 5, new Item[]{items[0], items[1]}); System.out.println(m.name + "을 만났습니다. 전투를 시작합니다."); int input = 0; battle : while(true){ System.out.println("1.공격\t2.도망"); input = ScanUtil.nextInt(); switch (input) { case 1 : c.attack(m); if(m.hp <= 0){ System.out.println(m.name + "을 처치하였습니다."); c.getExp(150); c.getItem(m.itemDrop()); break battle; } m.attack(c); break; case 2 : System.out.println("도망쳤습니다."); break battle; } } } }자바로 RPG 게임 만들기 - 흉내내기~.
흉내내기 첫단계를 한번 해보겠습니다.
샛길로 한번 빠지게 되는 군요.
자 이번에 사용할 것은 이래도 되나 모르겠지만...
아시는 분은 아실 것입니다. 인터넷에서 구한것인데,
기본 캐릭터 칩셋 쯤 될 겁니다.
자연스럽게 걸어 가게 만들어 볼까 합니다.
슈팅게임 만들기에서 했던 방식이랑 똑같습니다.
자 그럼 소스로 들어가볼까요.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class RpgGame {
public static void main(String[] ar){
RpgGame_frame rg = new RpgGame_frame();
}
}
class RpgGame_frame extends JFrame implements Runnable,
KeyListener{
boolean keyUp = false;
boolean keyDown = false;
boolean keyLeft = false;
boolean keyRight = false;
boolean playerMove = false;
Toolkit tk = Toolkit.getDefaultToolkit();
Image img = new ImageIcon("rpg.png").getImage();
//위에 이미지 이름이 바로 rpg.png입니다. 이미지를 불러옵니다
Image buffimg;// 더블버퍼링용 입니다.
Graphics gc;
Thread th;
int x, y; // 케릭터의 현재 좌표를 받을 변수
int cnt; //무한 루프를 카운터 하기 위한 변수
int moveStatus; //케릭터가 어디를 바라보는지 방향을 받을 변수
RpgGame_frame(){
setTitle("테스트");
setSize(800, 600);
init();
start();
Dimension screen = tk.getScreenSize();
int xpos = (int)(screen.getWidth() / 2 - getWidth() / 2);
int ypos = (int)(screen.getHeight() / 2 - getHeight() / 2);
setLocation(xpos, ypos);
setResizable(false);
setVisible(true);
}
public void init(){
x = 100;
y = 100;
moveStatus = 2;
//케릭터가 시작할때 바라보는 방향은 아래쪽입니다.
// 0 : 위쪽, 1 : 오른쪽, 2 : 아래쪽, 3 : 왼쪽
}
public void start(){ // 기본적인 명령처리
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addKeyListener(this);
th = new Thread(this);
th.start();
}
public void run(){ // 스레드 메소드, 무한 루프
while(true){
try{
keyProcess();
repaint();
Thread.sleep(20);
cnt++;
}catch(Exception e){}
}
}
public void paint(Graphics g){ //더블버퍼링을 사용합니다.
buffimg = createImage(800, 600);
gc = buffimg.getGraphics();
update(g);
}
public void update(Graphics g){
//더블 버퍼링을 이용해 버퍼에 그려진것을 가져옵니다.
DrawImg();
g.drawImage(buffimg, 0, 0, this);
}
public void DrawImg(){
gc.setFont(new Font("Default", Font.BOLD, 20));
gc.drawString(Integer.toString(cnt), 50, 50);
gc.drawString(Integer.toString((playerMove)?1:0),200, 50);
//위는 단순히 무한루프 적용여부와 케릭터 방향 체크를 위해
//눈으로 보면서 테스트할 용도로 쓰이는 텍스트 표출입니다.
MoveImage(img, x, y, 100, 150);
//케릭터를 걸어가게 만들기 위해 추가로 만든 메소드 입니다.
}
public void MoveImage(Image img, int x, int y, int width,
int height){
//케릭터 이미지, 케릭터 위치, 케릭터 크기를 받습니다.
//받은 값을 이용해서 위의 이미지칩셋에서 케릭터를 잘라내
//표출하도록 계산하는 메소드 입니다.
gc.setClip(x , y, width, height);
//현재 좌표에서 케릭터의 크기 만큼 이미지를 잘라 그립니다.
if( playerMove ){ // 케릭터의 움직임 여부를 판단합니다.
if ( cnt / 10 % 4 == 0 ){gc.drawImage(img,
x - ( width * 0 ), y - ( height * moveStatus ), this);
}else if(cnt/10%4 == 1){ gc.drawImage(img,
x - ( width * 1 ), y - ( height * moveStatus ), this);
}else if(cnt/10%4 == 2){ gc.drawImage(img,
x - ( width * 2 ), y - ( height * moveStatus ), this);
}else if(cnt/10%4 == 3){ gc.drawImage(img,
x - ( width * 1 ), y - ( height * moveStatus ), this);
}
//케릭터의 방향에 따라 걸어가는 모션을 취하는
//케릭터 이미지를 시간차를 이용해 순차적으로 그립니다.
}else { gc.drawImage(img, x - ( width * 1 ),
y - ( height * moveStatus ), this);
//케릭터가 움직이지 않으면 정지한 케릭터를 그립니다.
}
}
public void keyProcess(){
//여기서는 단순 케릭터가 이동하는 좌표 말고도
//케릭터의 움직임 여부및 방향을 체크 합니다.
playerMove = false;
if ( keyUp ){
playerMove = true;
y -= 8;
moveStatus = 0;
}
if ( keyDown){
y += 8;
moveStatus = 2;
playerMove = true;
}
if ( keyLeft){
x -= 8;
moveStatus = 3;
playerMove = true;
}
if ( keyRight){
x += 8;
moveStatus = 1;
playerMove = true;
}
}
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_LEFT :
keyLeft = true;
break;
case KeyEvent.VK_RIGHT :
keyRight = true;
break;
case KeyEvent.VK_UP :
keyUp = true;
break;
case KeyEvent.VK_DOWN :
keyDown = true;
break;
}
}
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_LEFT :
keyLeft = false;
break;
case KeyEvent.VK_RIGHT :
keyRight = false;
break;
case KeyEvent.VK_UP :
keyUp = false;
break;
case KeyEvent.VK_DOWN :
keyDown = false;
break;
}
}
public void keyTyped(KeyEvent e) {}
}
--------------------------------------------------------------------
자 위와 같이 만드시면 아래와 같이 커다란 한장의 케릭터 칩셋 이미지로
걸어다니는 캐릭터를 만들 수 있습니다.
포토샵만 이용한다면 초록색 바탕없이 깔끔한 케릭터를
만들 수 있겠네요.
RPG 흉내내기는 이렇게 캐릭터 하나 움직여 보기로 일단 끝냅니다~