疲れたらやすむ

Javaを学ぶ上でハマったところを書いていきます。iPhoneアプリ開発や日常ネタもあるかも。

【Xcode】Teamの設定

今回はチームの設定についてです。

Xcodeのチームとは、プロジェクト作成時に選択することが出来る項目です。
デフォルトではNONEとなっています。

f:id:chibiCat:20190430011445p:plain

プロジェクト作成後もチームの変更は可能です。

ではデフォルトのNONEだとなにか不都合があるのでしょうか。
まず当然と言えば当然ですが、ストアにアプリを公開することが出来ません。
ただしチームを設定していたとしても、デベロッパ登録をしないと公開はできませんが。
デベロッパ登録は年間1万円ほど費用のかかる有料の登録です。

じゃあその他は問題ないのかと言うと、チームがNONEだと実機でのテストが出来ません。
どちらかと言えばこっちの方が痛手ですね。
以前は実機テストも有料のデベロッパ登録をしていないと出来なかったようですが、Xcode7からは制限が無くなったようです。
ですので、チームの設定はしておいて損はありません。

あともう1点。
これは気になる方のみですが、チームがNONEだとチームが設定されていない旨のエラーが出ます。
シミュレータでビルドは通るので実害はないと言えばないのですが見た目はあんまりよくないですね。

f:id:chibiCat:20190506013833p:plain


では設定方法の手順。

Apple IDを準備する

まずはApple IDが必要になります。
Apple公式サイトよりアカウントを作成します。

f:id:chibiCat:20190501021655p:plain

ページ右上の赤枠部分の「Apple IDを作成」から作成を行います。
メールアドレスが必要になります。
クレジットカードの登録などはありません。

Xcodeのアカウント設定でApple IDを追加する

Apple IDを用意したらXcodeでアカウントを追加します。
「Xcode」→「Preferences...」をクリックします。

f:id:chibiCat:20190506014832p:plain

「Accounts」タブを選択し、左側のApple IDsの「+」ボタンをクリックします。

f:id:chibiCat:20190501025547p:plain

「Apple ID」を選択し、「Continue」をクリックします。

f:id:chibiCat:20190501025545p:plain

先ほど作成したApple IDとパスワードを入力し「Next」をクリックします。

f:id:chibiCat:20190501025542p:plain

Apple IDsに追加されていればOKです。

f:id:chibiCat:20190501025539p:plain

右側にTeamが載っています。

Teamの設定

プロジェクト作成時のチームの設定。

f:id:chibiCat:20190501032211p:plain

既存プロジェクトのチームの変更。

f:id:chibiCat:20190506013839p:plain

両方ともプルダウンリストから選択するだけです。


簡単にまとめますと、Teamを設定するメリットとして
・実機でのテストが出来る
・チーム未設定の旨のエラー表示が消える
・ストアにアプリを公開できる(有料デベロッパ登録も必要)
の3つが挙げられます。

Xcodeでアプリ開発をする際は、実機テストの可否からTeamの設定はほぼ必須と言えますね。

今回は以上になります。

【Java】参照渡しと値渡し

今回は参照渡しと値渡しについてです。

一応最初に銘打っておきますが、ここで言う「参照渡し」と「値渡し」は以下の定義とさせていただきます。
参照渡し:呼び出したメソッド内で値を変更した場合、呼び出し元にも影響がある
値渡し:呼び出したメソッド内で値を変更しても、呼び出し元には影響がない

まずはそもそも参照渡しや値渡しの「渡し」ってなんぞや?というところからいきます。
渡しとはメソッドに引数を渡すことです。
例えば以下のメソッドを呼び出す場合にint型の変数を1つ渡す必要があります。

public void method(int value) {
	// 処理
}

その際の引数の渡し方に参照渡しと値渡しがあります。

それでは具体的に参照渡しと値渡しとはなんぞやと。
実際にプログラムを動かして確認してみます。

まず参照渡し。

ソース

public class Main {
	public static void main(String[] args) {
		Apple apple = new Apple(5);

		change(apple);
		System.out.println(apple.quantity);
	}

	public static void change(Apple apple) {
		apple.quantity = 10;
	}
}

class Apple {
	String name;
	int quantity;

	public Apple(int quantity) {
		this.name = "apple";
		this.quantity = quantity;
	}
}

実行結果

10

独自クラスであるApple型の変数を定義し、nameをapple、quantityを5で初期化しています。
その後、changeメソッドで引数のappleのquantityを10に変更します。
呼び出し元に戻り、変数appleのquantityの値を出力すると10となっています。
呼び出した先で値を変更した場合に、呼び出し元にもその影響が出ています。


続いて値渡し。

ソース

public class Main {
	public static void main(String[] args) {
		int value = 5;

		change(value);
		System.out.println(value);
	}

	public static void change(int value) {
		value = 10;
	}
}

実行結果

5

int型の変数valueを5で初期化し、changeメソッドで引数に渡されたvalueを10に変更します。
呼び出し元に戻り変数valueの値を出力すると5のままです。

以上の結果から、参照渡しと値渡しでは呼び出し元に影響があるかないかに差が出ることがわかります。
Apple型の変数の値を変更した場合は呼び出し元でも変更されています。
しかしint型の変数の値を変更しても呼び出し元では変更前の値のままです。

実は参照渡しと値渡しは渡す変数の型で決まります。
int型などのプリミティブ型を渡す場合は値渡しになります。
そしてプリミティブ型以外のオブジェクト型を渡す場合は参照渡しとなります。
ただし、StringやIntegerなどのラッパークラスはオブジェクト型ではありますが値渡しとなります。


つまり値渡しであるint型などを値を変更したい場合は、以下のように戻り値を利用する必要があります。

ソース

public class Main {
	public static void main(String[] args) {
		int value = 5;

		value = change(value);
		System.out.println(value);
	}

	public static int change(int value) {
		return 10;
	}
}

実行結果

10

さらに言うと、参照渡しであっても戻り値で明示的に設定する方が良いのではないかと思います。
というのも、「値を変えている」というのが他の人から見てもわかりやすいからです。


逆に、オブジェクト型の値をメソッド内で変更しても呼び出し元に影響させたくない場合。
その場合は複製を作成し、複製されたものを変更するようにします。

ソース

public class Main {
	public static void main(String[] args) {
		Apple apple = new Apple(5);

		change(apple);
		System.out.println(apple.quantity);
	}

	public static void change(Apple apple) {
		Apple cloneApple = apple.clone();
		cloneApple.quantity = 10;
	}
}

class Apple implements Cloneable {
	String name;
	int quantity;

	public Apple() {
	}

	public Apple(int quantity) {
		this.name = "apple";
		this.quantity = quantity;
	}

	@Override
	public Apple clone() {
		Apple apple = new Apple();

		try {
			apple = (Apple) super.clone();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return apple;
	}
}

実行結果

5

cloneメソッドで複製を作成し、複製された変数を変更しても複製元には影響がありません。

ちなみにcloneメソッドを使用するにはCloneableインターフェースを実装する必要があります。
また、CloneNotSupportedExceptionを投げる可能性があるのでAppleクラスでcloneメソッドをオーバーライドしtry~catchで囲みます。

実際に複製を作ってまで変数に変更を加えることがあるのか?という疑問もあると思います。
体験談としては、Listをソートして取り出したいが、そのリスト自体はソートされてほしくないようなパターンの時に使いました。
Listのコピーは以下のように簡単に作成できます。

List<String> list = new ArrayList<>();

List<String> copyList = new ArrayList<String>(list);

変数copyListは変数listの複製であるため、copyListを変更してもlistに影響はありません。

今回は以上になります。

【Java】Listから特定の要素を抽出し新規Listを作成

今回は独自クラスのListから特定の条件で要素を抽出し、抽出されたものから新しいListを作成します。
前提としてJava8であること。

まずは独自クラス。

Human.java

public class Human {

	String name;
	String gender;
	int age;

	public Human(String name, String gender, int age) {
		this.name = name;
		this.gender = gender;
		this.age = age;
	}
}

このHumanクラスのListを定義し、ある条件で新しいHumanクラスを作ります。
具体的には、男女混合のHumanクラスをListを作成した上でそのListからgenderが男だけのListを新規生成します。
実装はこんな感じです。

Main.java

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
	public static void main(String[] args) {

		final String MAN = "男";

		List<Human> humanList = new ArrayList<Human>();

		Human human1 = new Human("太郎", "男", 15);
		humanList.add(human1);

		Human human2 = new Human("花子", "女", 17);
		humanList.add(human2);

		Human human3 = new Human("慎吾", "男", 22);
		humanList.add(human3);

		// humanListから「gender=男」を条件に新しいリストを作成
		List<Human> manList = humanList.stream().filter(human -> MAN.equals(human.gender))
				.collect(Collectors.toList());

		for (Human human : manList) {
			System.out.print("名前 = " + human.name);
			System.out.print(", 性別 = " + human.gender);
			System.out.print(", 年齢 = " + human.age);
			System.out.println();
		}
	}
}

実行結果

名前 = 太郎, 性別 = 男, 年齢 = 15
名前 = 慎吾, 性別 = 男, 年齢 = 22

filter()の中に条件を指定し、抽出できたHumanクラスからCollectors.toList()でListを作成しています。

今回は抽出条件をgenderの値が男である場合にしていますが、複数条件にすることももちろん可能です。
例えば以下のようにすればgenderが男、かつageが20以上の条件で抽出します。

List<Human> manList = humanList.stream().filter(human -> MAN.equals(human.gender) && 20 <= human.age)
				.collect(Collectors.toList());

今回は以上になります。

【Java】【Minecraft】プログラミング未経験でModが作れるか

今回は「Modを作ってみたい」でも「プログラミングの経験がない」という方のための記事です。

結論から言うと、作れなくはないと思います。

とても曖昧な言い方になってしまいましたが、目指すところによっては作成可能です。
特に機能を持たないブロックやアイテムであれば可能かなと。
それって需要あるの?と思うかもしれませんが、好きなテクスチャのブロックの追加くらいならしたい人も多いはず。
でもそれが、設置する向きによってテクスチャが違うブロックを作るとなるとちょっと大変です。

実際に試していないですが、Modを作るツールとかも調べると出てきますね。
プログラミングの知識がほぼなくても作れるのでしょうか。

で、なんでプログラミングの経験がないと難しいかです。
もちろんif文やfor文などの基本的なところが押さえられていないとコーディングができないというのはありますが。
一番は「デバッグ」が使えないと既存のMinecraftがどんなソースで動いているかわからないからです。

何より大事なのが、既存のブロックやアイテムはどうやって出来ているの?がわかることです。
チェストやかまどを右クリックしたときにどんなメソッドが呼ばれているかがわかれば、右クリック時の動作はどのソースを参考にすれば良いかわかります。
つまりデバッグを使えればModの作成は大体できます。
そのレベル感で問題ないと思います。
ちなみに、デバッグを使えるというのは「このメソッドでこういう変化が起きる」がわかる程度で大丈夫です。

あとは、わからないことを検索する技術があれば良いと思います。
これが結構難しくて、どんなワードだったら検索に引っかかるか?欲しい情報を得るには何を参考にするか?が重要になります。
実際にModの作成はたくさんの方が挑戦されており、手法を説明しているサイトやブログもいくつかあります。
英語で読みづらいですが外国の方の質問投稿も参考になります。
まずは「何がわからないのかを知ること」が大事です。


自分の世界観を表現するためにModを自作するってなんかいいですよね。
恐らくModの作成をしようと思う方の大半はプログラムの知識がある方だと思います。
そして普段からIT業界で働いている方だと思います。
趣味としてプログラミングをすることで知識も高まり、仕事への恩恵も得られます。
私はそういう意味でもModの作成はやって損はないと思います。

また、逆にMinecraftやModに興味を持ったからこそプログラミングを学びたいと思う方もいるかもしれません。
プログラムの世界の入り口として、Minecraftは正直かなりアリだと思います。
好きなことで学んでいく方が断然学べます。

今後、Mod作成に関する記事も書いていく予定です。
もし質問等があればコメントやTwitterで気軽にお声かけください。

今回は以上になります。

【Java】【Minecraft】Modの開発環境構築

今回はMinecraftの記事になります。

はじめにこの記事を書くに至った経緯を書きます。
開発環境構築まで進む場合は目次まで飛ばしちゃってください。

それでは前置き的なやつ。
実際にプレイされている方はご存知だと思いますが、PC版のMinecraftはJavaで動いています。
そしてMinecraftにはModというものが存在します。
Modとは言わば拡張機能のようなもので、新しいアイテムを追加したりゲームのシステムを変更したり様々なものがあります。
Minecraft以外のゲームでもModは存在しており、主に海外のゲームに多い傾向があります。

じゃあModはゲームの開発元が作っているのかというと必ずしもそうではありません。
むしろほとんどが違うと思っています。
個人のプレイヤーさんだったり何人かのチームで作成していたり様々です。

Minecraftの楽しみ方は人それぞれで、Modを入れない(バニラ)で遊ぶ方もいればModを入れて遊ぶ方もいます。
私は入れちゃうタイプ。

MinecraftのModはとても数が多いため、こんなModあるかな?と思うModは大抵探せば見つかります。
しかし細かいところまでこだわった場合は手が届かないこともしばしば。
私はその口でした。
Modの開発言語はJavaなので、やってやれないことはないだろうという思いもありつつ、どうしても実現させたいことがありModの作成を決心。

そもそも何をやりたいのか?

「任意の時間でレッドストーン出力を行いたい」だけです。
実はComputerCraftというModで実現できます。
実現できるはずなのですが、残念ながら私の環境ではComputerCraftは動作に支障が出てしまい泣く泣く導入を諦めました。
症状としては、sleep()メソッドを呼ぶ度に画面がカクっと固まってしまいます。
1秒感覚でsleepを入れたら1秒ごとに画面が一瞬固まってしまう感じ。
どうやらプチフリーズに縁があるようで。
なので代用となるModを作成します。

ひとまず今回は環境構築まで進めます。
ちなみにMinecraftのバージョンは1.7.10を想定。
Modを導入するなら定番のバージョンだと思います。Modの数が豊富なので。

それでは開発環境構築手順です。

Eclipseの導入

Eclipseとは、統合開発環境と呼ばれる開発の効率を高めるツールです。
エディタでコーディングを行い、実行やデバッグもスムーズに可能です。
Java以外の言語にも対応していますが、基本的にはJavaでの使用が一般的だと思います。

Pleiades
上記サイトからEclipseをダウンロードします。

リンク先はこんな感じになっています。

f:id:chibiCat:20190409225833p:plain

赤枠内の好きなバージョンを選んでクリックしてください。
私は4.8にしました。
なるべく新しくて、でもちゃんと数字が振ってあるやつということで。

f:id:chibiCat:20190409225828p:plain

次にJavaの中から自分のOSに合ったものを選んでください。
ちなみにFull EditionかStandard Editionかは何も考えずFull Editionを選んでおけば問題ありません。

容量が1GBを超えるためダウンロードに少々時間がかかります。
ダウンロード完了後、Windowsの方はzipを解凍して出てくる「pleiades」フォルダを任意の場所に移動します。
移動と言ってもCドライブ直下とかで良いと思います。
Macの方はダウンロードしたものをダブルクリックして、アイコンをApplicationsフォルダにドラッグ&ドロップ。
以上でEclipseの導入は完了です。

JDKのインストールと環境変数の設定

JDKとは、Java Development Kitの略であり、直訳だとJava開発キットになります。
ざっくりですがJavaで開発を行うために必要なソフトウェアがまとまっているものです。

Java SE Development Kit 8 Downloads
上記のサイトからJDKをダウンロードします。

f:id:chibiCat:20190410232353p:plain

Accept License Agreementにチェックを入れ、任意のOSのものをダウンロード、インストールを行ってください。

インストールが完了したら、一応環境変数の設定を行っておきます。
最近Macで試したところ未設定でもビルドは通ったのですが一応。

環境変数の設定の仕方はOSによって変わります。
Windowsの場合。
1.コントロールパネルを開きます。
2.システムとセキュリティ→システム→システムの詳細設定へと進みます。
3.システムのプロパティが開くので「環境変数(N)...」をクリック。
4.システム環境変数の「新規(W)...」をクリック。
5.変数名に「JAVA_HOME」、変数値にJDKをインストールしたディレクトリを入力しOK。

Macの場合。
1.ターミナルを開きます。
2.「open ~/.bash_profile」を入力しENTER。テキストが開きますが放置で。
3.「export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)」を入力しENTER。
4.ターミナルを開き直すか、もしくは「source ~/.bash_profile」を入力しENTER。
5.「echo $JAVA_HOME」を入力しENTERで「/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home」が表示されます。

Minecraft Forgeのソース入手とワークスペースの準備

Minecraft Forgeとは、MinecraftにModを導入するための機能を持ったModです。
Forgeを入れることで初めてMinecraftにModを入れて遊ぶことができます。

普段はModを入れる場合、Forgeをインストールする形で使用しますが、
今回はそのForgeのソースを使ってEclipseからMinecraftを実行できるようにします。

Minecraft Forge
上記のサイトから「Src」をダウンロードします。
今回は1.7.10で、さらに1.7.10の中にも細かなバージョン指定ができます。
特にバージョンを決めていない場合はRecommendedで問題ないと思います。

f:id:chibiCat:20190410011132p:plain

どのバージョンで遊んでいるのか、またはどのバージョンで遊ぶのかわかっていて、
LatestでもRecommendedでもないバージョンの場合は、
上記の画像の下側に見える「+Show all Versions」をクリックすると出てきます。

「Src」をクリックすると若干怪しげなサイトに飛びますが大丈夫です。
右上のSkipをクリックするとダウンロードできます。

余談ですが、最近のMinecraftのバージョンでは「Src」ではなく「Mdk」だそうです。

ダウンロード完了後、zip形式になっているため解凍します。
解凍したフォルダの中にある「eclipse」フォルダが後にワークスペースとなるフォルダです。

ビルド

コマンドラインで解凍したフォルダまで行きます。
「forge-1.7.10〜src」のフォルダです。
Windowsの場合はエクスプローラーで解凍したフォルダを開き、ウインドウのアドレスバーに「cmd」を入力しENTER。
Macの場合はターミナルを開き「cd 」と入力後、解凍したフォルダをターミナルにドラッグ&ドロップでENTER。

コマンドラインで以下を入力しENTER。
Windowsの場合は「gradlew setupDecompWorkspace」。
Macの場合は「./gradlew setupDecompWorkspace」です。
5分ほどで終わります。

何をやってるのかというと、たぶんデコンパイルだと思います。
成功すれば「BUILD SUCCESSFUL」と表示されます。

もし「BUILD FAILURE」と表示され失敗した場合。
エラーの原因が「JAVA HOME~....」のようなキーワードだった場合はJDKの環境変数の設定の問題です。
手順2のJAVA_HOMEの設定の見直しをしてください。

次にもう一度ビルドを行います。
Eclipseのプロジェクトファイルを追加します。

コマンドラインで以下を入力しENTER。
Windowsの場合は「gradlew eclipse」。
Macの場合は「./gradlew eclipse」です。
こちらは数十秒で終わると思います。

先ほどと同じく「BUILD SUCCESSFUL」が表示されればOKです。

動作確認

Eclipseを起動しワークスペースにビルドしたフォルダ内にある「eclipse」フォルダを選択します。
ここ何気に注意です。
「forge-1.7.10〜...」のフォルダではなく「forge-1.7.10〜...」の中の「eclipse」フォルダです。

起動直後はこんな状態です。

f:id:chibiCat:20190411004023p:plain

Minecraftというプロジェクトがありますね。
特になんの設定もせず起動してみます。

「実行」から「実行の構成...」を開きます。

f:id:chibiCat:20190411004019p:plain

Javaアプリケーションの一番上にある「Client」を選択し「実行」。

f:id:chibiCat:20190411004016p:plain

無事にMinecraftが起動できればModの開発環境は無事に構築完了です。

f:id:chibiCat:20190411004012p:plain


今回は以上になります。