2014年12月3日水曜日

[swift]テキストRPGをswiftの練習がてら作ってみようと思った - 4

前回のまでを整理して、戦士と洞窟のクラスを変更しました。
洞窟は、一人だけでなく、複数の戦士の挑戦を受け入れます。
帰り道は冗長なので省略されました。

■戦士
public class Warrior{
    var name:String
    var hp:(Int,Int) // 現在のHP/HPの最大値
    var location:Int // 洞窟での位置
    
    public init(name:String,hpMax:Int){
        self.name=name
        self.hp=(hpMax,hpMax)
        self.location=0
    }
    
    public func isDead()->Bool{
        return (hp.0 <= 0)
    }
    
    public func walk(){
        
    }
    
    public func recoverFull(){
        hp.0=hp.1
    }
    
    public func recover(val:Int){
        if(hp.0 < hp.1){
            hp.0+=val
            if(hp.0 > hp.1){hp.0=hp.1}
        }
    }
    
    public func damage(val:Int)->Bool{
        if(hp.0 > 0){
            hp.0-=val
            if(hp.0 < 0){
                hp.0=0
                return false
            }
        }
        return true
    }


}


■洞窟

public class Cave{
    var name:String
    var item:String
    var size:Int
    var players:NSMutableArray;
    
    public init(name:String,size:Int,item:String){
        self.name=name
        self.size=size
        self.item=item
        self.players=[];
    }
    
    public func addPlayer(player:Warrior){
        player.location=0;
        self.players.addObject(player)
        print("\(player.name)\(name)の探索を始める\n")
    }
    
    public func step(){
        for a in players{ //ここがうまくない、下と一行で書きたい
            var player:Warrior=a as Warrior;
            var rand = arc4random()%100
            if(rand>90){
                player.damage(60)
                player.location+=2;
                println("\(player.name)は、罠にはまって大ダメージ!(HP:\(player.hp))")
            }else if(rand>60){
                player.damage(2)
                player.location+=2;
                println("\(player.name)が歩く(HP:\(player.hp))")
            }else if(rand>30){
                player.damage(6)
                player.location+=6;
                println("\(player.name)は走った(HP:\(player.hp))")
            }else{
                player.recover(6)
                println("\(player.name)は少し休んだ(HP:\(player.hp))")
            }
            
            if(player.isDead()){
                println("\(player.name)は死んでしまった(HP:\(player.hp))")
                players.removeObject(player)
            } else if(player.location>=size){
                player.recoverFull();
                println("\(player.name)\(item)を手に入れた。(HP:\(player.hp))")
                println("\(player.name)\(name)から出た")
                players.removeObject(player)

            }
        }
    }
    

}


■起動部分

    func testTextRPG() {
        var warrior:Warrior=Warrior(name: "アルテア", hpMax: 100)
        var warrior2:Warrior=Warrior(name: "カルテ", hpMax: 80)
        var cave:Cave=Cave(name: "泉の洞窟", size: 30, item: "泉の水")
        cave.addPlayer(warrior)
        cave.addPlayer(warrior2)
        
        for(var i=0;i<100000;i++){
            cave.step()
        }

    }

■Story
どちらが先に泉の水を手にいれるか、お互いの誇りをかけて戦士アルテアとカルテは洞窟に挑む。

アルテアは泉の洞窟の探索を始める
カルテは泉の洞窟の探索を始める
アルテアが歩く(HP:(98, 100))
カルテは少し休んだ(HP:(80, 80))
アルテアが歩く(HP:(96, 100))
カルテは走った(HP:(74, 80))
アルテアが歩く(HP:(94, 100))
カルテは走った(HP:(68, 80))
アルテアは少し休んだ(HP:(100, 100))
カルテは少し休んだ(HP:(74, 80))
アルテアは少し休んだ(HP:(100, 100))
カルテは少し休んだ(HP:(80, 80))
アルテアは少し休んだ(HP:(100, 100))
カルテは走った(HP:(74, 80))
アルテアは少し休んだ(HP:(100, 100))
カルテは走った(HP:(68, 80))
アルテアは走った(HP:(94, 100))
カルテは走った(HP:(62, 80))
カルテが泉の水を手に入れた。(HP:(80, 80))
カルテは泉の洞窟から出た
アルテアは少し休んだ(HP:(100, 100))
アルテアが歩く(HP:(98, 100))
アルテアは、罠にはまって大ダメージ!(HP:(38, 100))
アルテアは走った(HP:(32, 100))
アルテアは走った(HP:(26, 100))
アルテアは走った(HP:(20, 100))
アルテアが泉の水を手に入れた。(HP:(100, 100))

アルテアは泉の洞窟から出た

今のところ、 ルールは洞窟(フィールド)、戦士のキャラクタはできるだけデータにしていこうと考えてます。

2014年11月27日木曜日

[swift]テキストRPGをswiftの練習がてら作ってみようと思った - 3


戦士アルテアに色々させようととりあえず行動を追加してみた
(追記:この文を考えると、行動内容は戦士、何をするかは条件は洞窟というのが自然な気がしますね)

歩くとHPを消費
走るともっと消費
泉の水を飲むと回復

今回は泉の洞窟に変更を加える

public class Cave{
    var name="泉の洞窟"
    var item:String="泉の水"
    var size:Int=20
    var stepCount=0;
    var player:Warrior;
    var direction:Int=1;
    var progress:Bool;

    
    public init(player:Warrior){
        self.stepCount=0
        self.player=player
        self.progress=true;
        print("\(player.name)\(name)の探索を始める\n")
    }
    
    public func step(){
        if(!progress){
            return
        }
        var rand = arc4random()%100
        if(rand>60){
            stepCount+=direction;
            player.hp-=2;
            print("\(player.name)が歩く(HP:\(player.hp))\n")
        }else if(rand>30){
            stepCount+=direction;
            player.hp-=6;
            print("\(player.name)は走った(HP:\(player.hp))\n")
        }else{
            //stepCount+=direction;
            player.hp++;
            print("\(player.name)は少し休んだ(HP:\(player.hp))\n")
        }
        
        if(stepCount==20){
            direction = -1
            stepCount--;
            //満タンとかやるならここは、playerの役割なんだろう
            player.hp=100;
            print("\(player.name)\(item)を手に入れた。泉の水を少しだけ飲むと体の疲れとれたようだ。(HP:\(player.hp))\n")
        }
        if(stepCount<0){
            progress=false;
            print("\(player.name)\(name)から出た\n")
        }
    
    }
    
}


■出力
アルテアは泉の洞窟の探索を始める
アルテアは少し休んだ(HP:101)
アルテアが歩く(HP:99)
アルテアが歩く(HP:97)
アルテアは走った(HP:91)
アルテアは少し休んだ(HP:92)
アルテアが歩く(HP:90)
アルテアが歩く(HP:88)
アルテアは走った(HP:82)
アルテアは少し休んだ(HP:83)
アルテアが歩く(HP:81)
アルテアは走った(HP:75)
アルテアは走った(HP:69)
アルテアが歩く(HP:67)
アルテアは少し休んだ(HP:68)
アルテアが歩く(HP:66)
アルテアが歩く(HP:64)
アルテアが歩く(HP:62)
アルテアは少し休んだ(HP:63)
アルテアは走った(HP:57)
アルテアが歩く(HP:55)
アルテアは少し休んだ(HP:56)
アルテアは少し休んだ(HP:57)
アルテアは走った(HP:51)
アルテアは走った(HP:45)
アルテアは少し休んだ(HP:46)
アルテアは少し休んだ(HP:47)
アルテアは少し休んだ(HP:48)
アルテアは少し休んだ(HP:49)
アルテアが歩く(HP:47)
アルテアは少し休んだ(HP:48)
アルテアは少し休んだ(HP:49)
アルテアが歩く(HP:47)
アルテアは少し休んだ(HP:48)
アルテアが歩く(HP:46)
アルテアが泉の水を手に入れた。泉の水を少しだけ飲むと体の疲れとれたようだ。(HP:100)
アルテアは少し休んだ(HP:101)
アルテアは走った(HP:95)
アルテアは少し休んだ(HP:96)
アルテアが歩く(HP:94)
アルテアは走った(HP:88)
アルテアが歩く(HP:86)
アルテアは少し休んだ(HP:87)
アルテアが歩く(HP:85)
アルテアが歩く(HP:83)
アルテアは走った(HP:77)
アルテアは少し休んだ(HP:78)
アルテアは少し休んだ(HP:79)
アルテアが歩く(HP:77)
アルテアは走った(HP:71)
アルテアが歩く(HP:69)
アルテアは少し休んだ(HP:70)
アルテアは走った(HP:64)
アルテアは走った(HP:58)
アルテアは少し休んだ(HP:59)
アルテアは少し休んだ(HP:60)
アルテアが歩く(HP:58)
アルテアは少し休んだ(HP:59)
アルテアは走った(HP:53)
アルテアは少し休んだ(HP:54)
アルテアは少し休んだ(HP:55)
アルテアが歩く(HP:53)
アルテアは走った(HP:47)
アルテアは走った(HP:41)
アルテアは少し休んだ(HP:42)
アルテアが歩く(HP:40)
アルテアは少し休んだ(HP:41)
アルテアは少し休んだ(HP:42)
アルテアが歩く(HP:40)
アルテアは少し休んだ(HP:41)
アルテアは走った(HP:35)
アルテアは泉の洞窟から出た

気になる点ありありですね。

HPの最大値とかきになるし、ランダムすぎるので元気なのにやすんだり、走り続けすぎるのもどうか。
場所にいろいろと戦士アルテアを動かしてもらったけど、幾つかは、戦士自体が管理するようにした方がよさそうだ。
ランダムで動かしたけど、ロジック(簡易AI)で判断とかもいれたいね。

徐々に見直していこう。

2014年11月25日火曜日

[swift]テキストRPGをswiftの練習がてら作ってみようと思った - 2

とりあえず、冒険をシミュレーションするようにしたい
(コードに一切効率は考えない。継承しまくり、ネストとか気にしない)

■ 最初の物語
ある戦士アルテアが、泉の洞窟にいって、探索を開始する
洞窟にはコウモリがいて襲ってくるが撃退しながら
探索を継続し、一番奥にある泉の水をくんでくる。


■ 構成要素はなんだろう
戦士
コウモリ
洞窟
拾ってくるもの


うん、なんか大きいので、少し話を縮小しよう。
■最初の物語改
戦士アルテアは泉の洞窟にいく、洞窟の奥には泉があり、それを汲みにいく

(構成要素)
戦士  (Warrior)
洞窟  (Cave)


public class Warrior{
    var name:String
    var hp:Int
    public init(name:String,hp:Int){
        self.name=name
        self.hp=hp
    }

}


public class Cave{
    var name="泉の洞窟"
    var item:String="泉の水"
    var size:Int=20 //洞窟の大きさ
    var stepCount=0; //どれだけ進んだか
    var player:Warrior; //冒険者
    var direction:Int=1; //進んでいる方向
    var progress:Bool;//進行中かどうか

    
    public init(player:Warrior){
        self.stepCount=0
        self.player=player
        self.progress=true;
        print("\(player.name)\(name)の探索を始める\n")
    }
    
    public func step(){
        if(!progress){
            return
        }
        stepCount+=direction;
        print("\(player.name)が歩く(\(stepCount))\n")
        if(stepCount==20){
            direction = -1
            print("\(player.name)\(item)を手に入れた\n")
        }
        if(stepCount<0){
            progress=false;
            print("\(player.name)\(name)から出た\n")
        }
    
    }
    

}

動かす
    func testTextRPG() {
        var warrior:Warrior=Warrior(name: "アルテア", hp: 100)
        var cave:Cave=Cave(player: warrior)
        
        
        for(var i=0;i<100000;i++){
            cave.step()
        }

    }


アルテアは泉の洞窟の探索を始める
アルテアが歩く(1)
アルテアが歩く(2)
アルテアが歩く(3)
アルテアが歩く(4)
アルテアが歩く(5)
アルテアが歩く(6)
アルテアが歩く(7)
アルテアが歩く(8)
アルテアが歩く(9)
アルテアが歩く(10)
アルテアが歩く(11)
アルテアが歩く(12)
アルテアが歩く(13)
アルテアが歩く(14)
アルテアが歩く(15)
アルテアが歩く(16)
アルテアが歩く(17)
アルテアが歩く(18)
アルテアが歩く(19)
アルテアが歩く(20)
アルテアが泉の水を手に入れた
アルテアが歩く(19)
アルテアが歩く(18)
アルテアが歩く(17)
アルテアが歩く(16)
アルテアが歩く(15)
アルテアが歩く(14)
アルテアが歩く(13)
アルテアが歩く(12)
アルテアが歩く(11)
アルテアが歩く(10)
アルテアが歩く(9)
アルテアが歩く(8)
アルテアが歩く(7)
アルテアが歩く(6)
アルテアが歩く(5)
アルテアが歩く(4)
アルテアが歩く(3)
アルテアが歩く(2)
アルテアが歩く(1)
アルテアが歩く(0)
アルテアが歩く(-1)
アルテアは泉の洞窟から出た


うん、物語は動き出した。次は、アルテアが真面目に歩きすぎるので、それを調整しよう。

2014年11月24日月曜日

[swift]テキストRPGをswiftの練習がてら作ってみようと思った - 1

やりたいことが、言語やツールを覚えることが邪魔になるなら、前からの方法を使うというふうに焦って、とにかくアプリを出すことを優先してきましたが、ここに来て急いで出すものが見当たらなくなったので、swiftでできる範囲からちょこちょこやっていきながらゆっきり考えていきます。

題材は、いつも途中でめげるテキストRPGです。
本によく猫をclass定義して、にゃーと泣かす。とかありますよね。
そんな、テキストな世界でRPGな世界を定義したいのです。いろいろな人が、いろんな形でやっているのですが、自分ならどうするかを、考えなしに進行します。
ちゃんとしたゲームプログラマーではないので悪しからずご了承ください。
swiftも必要以上にがんばりません。

まずは、開発環境から
swiftなので当然xcode6、そしてios7より前は諦めなくてはいけません。これが、私がswiftにすぐ手を出さない言い訳の第1位です

さて、テキストRPGだから、アプリのUIベースでなくて、CIベースで開発しやすいかなとおもって、テストフレームワークを使ってやるぜと思ったら、クラスを読みまなくて、早くも諦めかけた...。

どうやら、APPモジュールとテストモジュールが名前空間が別らしい。

swiftはクラスを自動的に読んでくれるようだが、名前空間が別なのでしょうがない。
フレームワークのように

import ターゲットAPP

とやってやれば、クラスが見つかるようになった。

だけど、public なクラスでないとみつからない。さらに、public init()がないと、ビルドで怒られる。コマンドキー+u でテスト実行。


とりあえず、一歩。

2014年2月26日水曜日

iAd Workbench結果

結果的にこうなりました。



予算50$で
24356の表示
119回のタップ
1回のダウンロード
つまり、一ダウンロードに50$

結論、自分のアプリの宣伝の身の丈にはあっていない。
この予算で結果が同じくでるなら、50000$くらいかければ、順位の上位にいき
シナジーを生むかもしれない。中途半端にしてもたいした効果は得られない。

2014年2月20日木曜日

iAd Workbenchを使い始める

iAd Workbenchで76万表示され一つもダウンロードされなかったという話を聞いた。
実際は、どんなもんか試してみようと思いました。

すごく出稿手続きは簡単でした。
対象国は、iAdが強そうなUnited States
対象アプリはStrengthen (iPhonePLUS記事:http://iphone.ascii.jp/2014/02/18/88743764323/)
       ※リリース2週間で、Downloadがアメリカが70%なのでちょうどいいでしょう。
ユーザの属性は特に絞りませんでした。
表示対象は、ゲーム。
予算は50$




4時間程度で上記の結果に
17.26$を費やし9,666回表示され、52回タップされ、0ダウンロード。

半分を費やしてこの結果だったので、
ユーザの属性をファンタジー系にして継続中です。