今からはじめるプログラミング25
バトル・・・というのはあまり作りたくなかったのですが。。。
カードゲームもそもそもカードバトルということもあり、
そんなわけにもいかず。。。
そして、カードバトルというのはなかなか奥深いもので、、、とかいろいろ考えて、どうにかして面倒で無いプログラミングができないか試行錯誤の上、戦闘を実装しなかったRPGの戦闘を考えてみたw
我ながら天邪鬼だなです。
とはいえ、作っていたRPGではキャラクターの属性が少なすぎるので、まずはキャラクターの属性を追加してみた。
ドラクエとウィザードリィの属性を意識して、追加しています。そして、それだけでも随分多いです。
戦闘を実装したくなかったのも、こういう理由もあったり?(めんどくさすぎる。そんな心の叫びが。。。)
ユーザーとモンスターとを戦わせるので、追加するのは
GameCharactor
です。
以下のようになりました。
--------------------------------
package sample7;
public class GameCharactor {
private String name = null;
private int max_hp = 0;
private int hp = 0;
private int max_mp = 0;
private int mp = 0;
private int lv = 1;
// 外観
private ArrayList<String> items = new ArrayList<String>();
private String image_path = null;
// いち?
private int x = 0;
private int y = 0;
private int relativeX = 0;
private int relativeY = 0;
// 基本プロパティ
private int str = 0;
private int iq = 0;
private int pie = 0;
private int vit = 0;
private int agi = 0;
private int luk = 0;
// Itemで加算されるプロパティ
private int up_str = 0;
private int up_iq = 0;
private int up_pie = 0;
private int up_vit = 0;
private int up_agi = 0;
private int up_luk = 0;
private String selectCommand = "";
public String getSelectCommand() {
return selectCommand;
}
public void setSelectCommand(String selectCommand) {
this.selectCommand = selectCommand;
}
public int getUp_str() {
return up_str;
}
public void setUp_str(int up_str) {
this.up_str = up_str;
}
public int getUp_iq() {
return up_iq;
}
public void setUp_iq(int up_iq) {
this.up_iq = up_iq;
}
public int getUp_pie() {
return up_pie;
}
public void setUp_pie(int up_pie) {
this.up_pie = up_pie;
}
public int getUp_vit() {
return up_vit;
}
public void setUp_vit(int up_vit) {
this.up_vit = up_vit;
}
public int getUp_agi() {
return up_agi;
}
public void setUp_agi(int up_agi) {
this.up_agi = up_agi;
}
public int getUp_luk() {
return up_luk;
}
public void setUp_luk(int up_luk) {
this.up_luk = up_luk;
}
public int getLv() {
return lv;
}
public void setLv(int lv) {
this.lv = lv;
}
private String command = new String { "なでる", "しらべる", "にげる", "たたかう", "まほう", "まもる" };
private String fieldCommand = new String { "しらべる" };
public int getMax_mp() {
return max_mp;
}
public void setMax_mp(int max_mp) {
this.max_mp = max_mp;
}
public int getMp() {
return mp;
}
public void setMp(int mp) {
this.mp = mp;
}
public String getFieldCommand() {
return fieldCommand;
}
public void setFieldCommand(String fieldCommand) {
this.fieldCommand = fieldCommand;
}
public int getStr() {
return str + up_str;
}
public void setStr(int str) {
this.str = str;
}
public int getIq() {
return iq + up_iq;
}
public void setiq(int iq) {
this.iq = iq;
}
public int getPie() {
return pie + up_pie;
}
public void setPie(int pie) {
this.pie = pie;
}
public int getVit() {
return vit + up_vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getAgi() {
return agi + up_agi;
}
public void setAgi(int agi) {
this.agi = agi;
}
public int getLuk() {
return luk + up_luk;
}
public void setLuk(int luk) {
this.luk = luk;
}
public int getRelativeX() {
return relativeX;
}
public void setRelativeX(int relativeX) {
this.relativeX = relativeX;
}
public int getRelativeY() {
return relativeY;
}
public void setRelativeY(int relativeY) {
this.relativeY = relativeY;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMax_hp() {
return max_hp;
}
public void setMax_hp(int max_hp) {
this.max_hp = max_hp;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public ArrayList<String> getItems() {
return items;
}
public void setItems(ArrayList<String> items) {
this.items = items;
}
public String getImage_path() {
return image_path;
}
public void setImage_path(String image_path) {
this.image_path = image_path;
}
public String toString() {
StringBuffer sb = new StringBuffer("GameCharactor parameters{");
sb.append("name="+this.name + "\r\n");
sb.append("relativeX="+this.relativeX + "\r\n");
sb.append("relativeY="+this.relativeY + "\r\n");
sb.append("command="+this.command + "\r\n");
sb.append("image_path="+this.image_path + "\r\n");
sb.append("items="+this.items + "\r\n");
sb.append("hp="+this.hp + "\r\n");
sb.append("max_hp="+this.max_hp + "\r\n");
sb.append("x="+this.x + "\r\n");
sb.append("y="+this.y + "\r\n");
sb.append("agi="+this.agi + "\r\n");
sb.append("iq="+this.iq + "\r\n");
sb.append("vit="+this.vit + "\r\n");
sb.append("str="+this.str + "\r\n");
sb.append("luk="+this.luk + "\r\n");
sb.append("pie="+this.pie + "\r\n");
sb.append("mp="+this.mp + "\r\n");
sb.append("max_mp="+this.max_mp + "\r\n");
return sb.toString();
}
public GameCharactor copy() {
GameCharactor gameCharactor = new GameCharactor();
gameCharactor.setRelativeX(this.relativeX);
gameCharactor.setRelativeY(this.relativeY);
gameCharactor.setCommand(this.command);
gameCharactor.setHp(this.hp);
gameCharactor.setImage_path(this.image_path);
gameCharactor.setItems(this.items);
gameCharactor.setMax_hp(this.max_hp);
gameCharactor.setName(this.name);
gameCharactor.setX(this.x);
gameCharactor.setY(this.y);
gameCharactor.setAgi(this.agi);
gameCharactor.setiq(this.iq);
gameCharactor.setVit(this.vit);
gameCharactor.setStr(this.str);
gameCharactor.setLuk(this.luk);
gameCharactor.setPie(this.pie);
gameCharactor.setMp(this.mp);
gameCharactor.setMax_mp(this.max_mp);
return gameCharactor;
}
// 戦闘の要素
public int rndSpd() {
int ret = this.getStr() / 2 + this.getAgi() + this.getIq() / 2;
int dice = Sai.getInstance().castHexadDice() + Sai.getInstance().castDiceAny(this.lv);
return ret + dice;
}
public int rndPw() {
int ret = this.getStr() / 2 + this.getAgi() / 3 + this.getIq() / 3;
int dice = Sai.getInstance().castHexadDice() + Sai.getInstance().castDiceAny(this.lv);
return ret + dice;
}
public int rndDf() {
int ret = this.getStr() / 3 + this.getAgi() / 2 + this.getPie() / 2 + this.getLuk() / 2;
int dice = Sai.getInstance().castHexadDice() + Sai.getInstance().castDiceAny(this.lv);
return ret + dice;
}
public int rndPhigicalDmg() {
int ret = this.getStr() / 3 + this.getAgi() / 2 + this.getLuk() / 3;
int dice = Sai.getInstance().castHexadDice() + Sai.getInstance().castDiceAny(this.getLv());
return ret + dice;
}
public int rndMagicDmg() {
int ret = this.getIq() / 2 + this.getPie() / 3 + this.getLuk() / 3;
int dice = Sai.getInstance().castHexadDice() + Sai.getInstance().castDiceAny(this.getLv());
return ret + dice;
}
}
--------------------------------
属性を追加すれば、アクセサーは、自動生成すればいいので、簡単ですが、、、それでも一気に一番ステップ数の多いクラスに躍り出ましたw
戦闘時に使用しそうなメソッドも追加していますので、どんな時にどのように使うのか想像してみてください。
というか適当に作ったのですが、このへんはバランス調整が必要になってくるでしょうね。
そして、これまたざっくりと作ってみたのですが、「戦闘」の1ターンをプログラミングしてみました。
SimpleBattle
------------------------------
package sample7;
public class SimpleBattle {
private UserCharactor user = null;
private Monster monster = null;
private static SimpleBattle battle = null;
public static SimpleBattle getInstance(UserCharactor user, Monster monster) {
if (battle == null) {
battle = new SimpleBattle(user, monster);
}
return battle;
}
private SimpleBattle(UserCharactor user, Monster monster) {
this.user = user;
this.monster = monster;
}
public boolean turn() {
// TODO 速度を求めて比較する
// リストに詰めて整列してというほうが汎用性が高くなる?というか行数を減らせる
int spdU = user.rndSpd();
int spdM = monster.rndSpd();
System.out.println("spdU=" + spdU);
System.out.println("spdM=" + spdM);
if (spdU >= spdM) {
// user action
int atc = user.rndPw();
int def = monster.rndDf();
System.out.println("userの攻撃=" + atc);
System.out.println("monsterの防御=" + def);
if *1;
if (monster.getHp() <= 0) {
System.out.println("monsterを倒した");
return false;
}
} else {
System.out.println("ユーザーの攻撃があたらなかった");
}
} else {
// monster action
int atc = monster.rndPw();
int def = user.rndDf();
System.out.println("monsterの攻撃=" + atc);
System.out.println("userの防御=" + def);
if *2;
if (user.getHp() <= 0) {
System.out.println("userは力尽きた");
return false;
}
} else {
System.out.println("モンスターの攻撃を回避した");
}
}
//TODO いろんなアクション
//TODO 速度が速い方しか行動していない
return true;
}
public static void main(String args) {
UserCharactor user = UserCharactor.getInstance();
user.setLv(1);
user.setHp(10);
Monster monster = Monster.getInstance();
monster.setLv(1);
monster.setHp(10);
System.out.println("---------------------------------");
System.out.println(user.toString());
System.out.println(monster.toString());
System.out.println("---------------------------------");
SimpleBattle btl = SimpleBattle.getInstance(user, monster);
int num = 1;
//面倒なので終わるまでまわす
while (btl.turn()) {
System.out.println("turn " + num + " 終了");
num++;
}
System.out.println("user hp =" + user.getHp());
System.out.println("monster hp =" + monster.getHp());
if (user.getHp() > 0 && monster.getHp() <= 0) {
System.out.println("end=user win");
} else {
System.out.println("end=monster win");
}
System.out.println("---------------------------------");
System.out.println(user.toString());
System.out.println(monster.toString());
System.out.println("---------------------------------");
}
}
------------------------------
サンプルでどっちが力尽きるまでループしてみました。
実行結果は以下のようになります。(システムアウトですいません。)というかtoString()の出力が微妙ですね。能力値0でレベル1、hp10でサイコロの値でのみ比較される感じです。
-----------------------
---------------------------------
GameCharactor parameters{name=null
relativeX=0
relativeY=0
command=[Ljava.lang.String;@7852e922
image_path=null
items=
hp=10
max_hp=0
x=0
y=0
agi=0
itl=0
vit=0
str=0
luk=0
pie=0
mp=0
max_mp=0
GameCharactor parameters{name=あざらし
relativeX=0
relativeY=0
command=[Ljava.lang.String;@4e25154f
items=
hp=10
max_hp=8
x=0
y=0
agi=0
itl=0
vit=0
str=0
luk=0
pie=0
mp=0
max_mp=0
---------------------------------
spdU=4
spdM=7
monsterの攻撃=5
userの防御=7
モンスターの攻撃を回避した
turn 1 終了
spdU=6
spdM=2
userの攻撃=4
monsterの防御=2
userの攻撃=が当たった
monsterにダメージ7を与えた
monsterのヒットポイント=3
turn 2 終了
spdU=3
spdM=5
monsterの攻撃=6
userの防御=2
monsterの攻撃=が当たった
userにdmg=7のダメージ
userのHp=3
turn 3 終了
spdU=4
spdM=4
userの攻撃=4
monsterの防御=4
userの攻撃=が当たった
monsterにダメージ4を与えた
monsterのヒットポイント=-1
monsterを倒した
user hp =3
monster hp =-1
end=user win
---------------------------------
GameCharactor parameters{name=null
relativeX=0
relativeY=0
command=[Ljava.lang.String;@7852e922
image_path=null
items=
hp=3
max_hp=0
x=0
y=0
agi=0
itl=0
vit=0
str=0
luk=0
pie=0
mp=0
max_mp=0
GameCharactor parameters{name=あざらし
relativeX=0
relativeY=0
command=[Ljava.lang.String;@4e25154f
items=[]
hp=-1
max_hp=8
x=0
y=0
agi=0
itl=0
vit=0
str=0
luk=0
pie=0
mp=0
max_mp=0
---------------------------------
物理攻撃の戦闘のみでこれなので、ドラクエやウィザードリィの戦闘がどれくらい複雑化が想像できますね。そしてバグもあるので、、、素直にゲームプログラミングというものが、すごいなぁという感じです。これだけのパラメータでこの複雑さ。
先が思いやられますね。
あふぅ。
// 攻撃があたった
System.out.println("userの攻撃=が当たった");
int dmg = user.rndPhigicalDmg();
System.out.println("monsterにダメージ" + dmg + "を与えた");
monster.setHp(monster.getHp() - dmg);
System.out.println("monsterのヒットポイント=" + monster.getHp(
// 攻撃があたった
System.out.println("monsterの攻撃=が当たった");
int dmg = monster.rndPhigicalDmg();
System.out.println("userにdmg=" + dmg + "のダメージ");
user.setHp(user.getHp() - dmg);
System.out.println("userのHp=" + user.getHp(