へっぽこ技術ブログです

【プロ生ちゃんアドカレ】ドット絵のプロ生ちゃんを動かせるだけ(2016年版)

ドット絵のプロ生ちゃんを動かせるだけ(2016年版)

この記事はプロ生ちゃん Advent Calendar の13日目分です。

qiita.com

 

昨日の記事は orange_recさんの「プロ生ちゃん アプリ開発支援プログラムと作ったやつ」です。

対して本日の記事には目新しさも知見もありませんのでゴメンなさい。プログラミングに詳しくない人向けの記事っぽい何かということでご容赦を。

 

動機

最初は「なんやかんやで忙しいし、別に書けることないし...」と参加を日和ってたんですが、プロ生ちゃんから「みなさんAdvent Calendarに記事を書いてください」といった旨のメールが来たから参加させていただきました。義理を果たさなければ!(昨年開催した勉強会でプロ生ちゃんグッズ配布の提供を受けてましたので ^^; その節は誠にありがとうございました)

ちなみに、メール来る前は超絶過疎ってましたけどメール来てすぐにたくさん埋まりましたね。でもこれを書いてる12月7日現在で、まだ6個ほどが空欄ですが...

 

概要

昨年はこんなチュートリアルっぽい記事を書いてました。

hiesuke.hatenablog.com

というわけで今年も「サイトや本をひもときながらアプリ作成した経緯を書く」ことで、「マスコットアプリ文化祭の参加賞を貰うための初心者向けチュートルアルっぽいもの」になればと考えて記事を書きます。せっかくなので昨年と同じUnityではなく別の開発環境でプロ生ちゃんを動かすアプリを書いてみようかと思います。今年使ってみようと思ったのは「JavaFX」です。ちなみに、単純に「使ってみたかったから」選びました。自分、勉強始めるきっかけがないとなかなか新しいことに取り掛かる機会がないもので。しかもAdvent Calendarの締め切りに追われるってことは、こりゃ身が入るってもんです。...たぶん。

 

JavaFXとは?

AWT、Swingに続く Javaに用意された最新のGUIライブラリですね。最新といっても、2007年5月のJavaOneでお披露目されたってことなのでもう10年近く経ちますね。詳しくはWikipediaをご覧ください。

JavaFX - Wikipedia

 

マスコットアプリ文化祭とは?

マスコットアプリ文化祭 2016(MASCOT CHARACTER APPS CONTEST 2016)は、指定されたキャラクターを使用したアプリ作品のコンテストです。

マスコットアプリ文化祭

応募規定の詳細はこちらをご覧ください。

応募規定・応募方法 | マスコットアプリ文化祭2016

プロ生ちゃん以外にもたくさんのキャラクターが用意されています。過去にはこんな参加賞が貰えてますよ、ほれほれ。

マスコットアプリ 参加賞 - Google 検索

 

使うマスコットキャラクターは?

もちろん我らがプロ生ちゃんです。こちらに素材が用意されています。プロ生ちゃんの紹介部分にある「ダウンロード」からクリエイター向け素材のダウンロードページに移動できます。他のキャラクターの素材や賞品も魅力的なので目移りしてしまいますが...イカンイカン

mascot-apps-contest.azurewebsites.net

今回は以下の「dot_illust.zip」に入っている画像を使いますので、ダウンロードして展開をしておいてください。

  f:id:Hiesuke:20161207133003p:plain

 

JDKの準備

Java言語での開発をするために JDKJava SE Development Kit)をインストールしましょう。JavaFXのアプリを開発するので Java 8を選んでください。同じ Java 8でも古いバージョンだとJavaFXの最新機能が使えないので、最新版に上げておきましょう。

Java SE - Downloads | Oracle Technology Network | Oracle

現在の最新バージョンは以下の通りです。

Java SE Development Kit 8u112

 

開発環境の準備

統合開発環境である IntelliJ IDEAのオープンソース版、IntelliJ IDEA Community Editionを使います。自分は、IntelliJ IDEAを元に作られた Android Studioという開発環境にほんの少しだけ慣れているのでここは一択です。

www.jetbrains.com

現在の最新のバージョンは以下の通りです。

IntelliJ IDEA 2016.3
Build #IC-163.7743.44, built on November 18, 2016
JRE: 1.8.0_112-release-408-b2 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o

 

JavaFXアプリ作成開始

それでは作成開始です。

(1) IntelliJ IDEA を起動し、「Create New Project」を選ぶ。

  f:id:Hiesuke:20161207151907p:plain

 (2) 左の領域にある「Java FX」を選んで「Next」ボタンを押す。

  f:id:Hiesuke:20161207152103p:plain

(3) Project name 欄に「ProNamaWalk」と入力して「Finish」ボタンを押す。

  f:id:Hiesuke:20161207155833p:plain

※これで、ProNamaWalkというサンプルプロジェクト(雛形となるファイル群)が作成されました。

 

サンプルプロジェクトの構成を確認する

どのようなファイルが用意されたかを確認しましょう。

(1) 左の領域にある三角形を順次クリックして開く(内容表示をする)。

  f:id:Hiesuke:20161207160452p:plain

    ↓

  f:id:Hiesuke:20161207160626p:plain

(2) 「Controller」「Main」「sample.fxml」をそれぞれダブルクリックして開く(右側の領域に表示させる)。

 それぞれの役割は以下の通りです。

  ・Controller 処理を記述する。Javaプログラムファイル。

  ・Main アプリケーション本体。Javaプログラムファイル。

  ・sample.fxml 画面レイアウトを記述する。XMLファイル。

 sample.fxml中に「Controllerに処理が書かれています」と記載されています。 

 Mainの中に「sample.fxmlのレイアウトを使います」と記載されています。

 どの行にどのように記載されているか、確認してみてください。

 

サンプルの動作を確認する

(1) 「Run」メニューから「Run 'Main'」を選ぶか、以下のボタンをクリックする。

  f:id:Hiesuke:20161207165409p:plain

 ※アプリが実行されて、次のようなウインドウが表示されます。

  f:id:Hiesuke:20161207165756p:plain

タイトル表示を変えてみる

(1) ウインドウのタイトルを変更する。

 Main中の「primaryStrage.setTitle("Hello World")」を以下のように変更。

f:id:Hiesuke:20161207170159p:plain

 

プロ生ちゃんを表示させてみる

(1) 先ほど展開したプロ生ちゃん素材の中から「02.png」ファイルを、IntelliJ IDEAの画面のProNamaWalkという部分にコピー&ペースト(またはドラッグ&ドロップ)する。

  f:id:Hiesuke:20161208102506p:plain

  以下のようになればOK!

  f:id:Hiesuke:20161208102755p:plain

 

(2) sample.fxmlに以下の2行を追加する。追加する場所は画像の通り。

<?import javafx.scene.canvas.Canvas?>
<Canvas fx:id="canvas" width="300" height="275" onKeyPressed="#keyPressed" focusTraversable="true"/> 

f:id:Hiesuke:20161208100632p:plain

  ※(参考)追加した行は以下のような意味です。

Canvasという部品を使用しますので準備してください」

「画面にCanvasを表示します。幅は300ドット。高さは275ドット。キーが押されたらkeyPressedという命令を実行します。キー入力を受け付けます」

 JavaFXでグラフィックを描画するときに使うパネルのような部品が Canvas です。現実世界で絵を描くときに使うキャンバスと同じですね。

 

(3) Controllerを以下のように変更する。

package sample;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.input.KeyEvent;

import java.net.URL;
import java.nio.file.Paths;
import java.util.ResourceBundle;

public class Controller implements Initializable {
@FXML
Canvas canvas;
GraphicsContext gc;
Image image;

@Override
public void initialize(URL location, ResourceBundle resources) {
gc = canvas.getGraphicsContext2D();
image = new Image(Paths.get("02.png").toUri().toString());
gc.drawImage(image, 200, 100);
}

@FXML
void keyPressed(KeyEvent event) {

}
}

  簡単に解説します。

  • 直前に @FXML を付けるとsample.fxmlから参照できるようになる
    canvasという部品と、keyPressedという命令が参照可能になっています)
  • グラフィック表示の要となるのがGraphicsContext。略してGC。例えばキャンバスのGCを取得してそのGCを使うことで、キャンバスへの線や画像の描画、色の変更などができる。
  • Imageが画像を使うための部品。Imageに画像ファイルからイメージを読み込んでおくことで、後からキャンバスなどに描画ができる。

 ちなみに、キーを押されたときに行わせたい処理(keyPressed) の中身はまだ空っぽですのでどのキーを押しても何も変化は起こりません。

 

  ※ここまでの変更でプロ生ちゃんが表示されます。確認してみてください。

  f:id:Hiesuke:20161208111519p:plain

プロ生ちゃんを歩かせてみる

(1) 歩かせるために必要なものを用意する。

  画像

  f:id:Hiesuke:20161208133815p:plain 01-1.png  f:id:Hiesuke:20161208133834p:plain 01-4.png

 

 歩いている姿をアニメーションっぽく表示するために2枚の画像を使います。

 02.png の時と同様にプロジェクトに追加をしてください。

 以下のようになればOKです。

  f:id:Hiesuke:20161209111606p:plain

 

(2) Controllerを修正する

 以下の通り修正をしてください。

package sample;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;

import java.net.URL;
import java.nio.file.Paths;
import java.util.ResourceBundle;
import java.util.Timer;
import java.util.TimerTask;

public class Controller implements Initializable {
@FXML
Canvas canvas;
GraphicsContext gc;
Image image;
int x, y;
Image[] imageWalk;
Timer timer;
int timerCounter;


@Override
public void initialize(URL location, ResourceBundle resources) {
gc = canvas.getGraphicsContext2D();
image = new Image(Paths.get("02.png").toUri().toString());
gc.drawImage(image, 200, 100);
x = 200;
y = 100;
imageWalk = new Image[2];
imageWalk[0] = new Image(Paths.get("01-1.png").toUri().toString());
imageWalk[1] = new Image(Paths.get("01-4.png").toUri().toString());
}

@FXML
void keyPressed(KeyEvent event) {
System.out.println("keyPressed.");
if (timer == null) {
timer = new Timer();
timer.schedule(
new TimerTask() {
@Override
public void run() {
if (timerCounter < 10) {
gc.setFill(Color.WHITE);
gc.fillRect(x, y, 32, 64);
x -= 4;
gc.drawImage(imageWalk[timerCounter % 2], x, y);
timerCounter += 1;
} else {
gc.setFill(Color.WHITE);
gc.fillRect(x, y, 32, 64);
gc.drawImage(image, x, y);
timerCounter = 0;
timer.cancel();
timer = null;
cancel();
}
}
},
0, 100);
}

}
}

  簡単に解説します。

  • キャラクタの表示位置を示す値を保持するために、 x と y というものを用意している。
  •  imageWalk[0] というもの 02-1.png の画像を、imageWalk[1]というものに 02-4.png の画像を持たせている。
  • 1秒間だけ歩くようにタイマー(Timer)を使う。
  • 1秒間を数えるために timerCount というものに値を保持させている。(0.1秒ごとに 0, 1, 2, 3, ... , 9 と数えさせています)
  • キーが押された場合、タイマーの予定(スケジュール)として歩く処理を作業(TimerTask)として割り当てる。
  • 歩いている間は 0.1秒ごとに横方向(x方向)の描画位置を4ずつ減らす。これにより左方向に移動して見える。
  • 1秒間(timerCountが 0,1,2,3,...,9 の間)は、プロ生ちゃんが歩いている2つの画像(01-1.pngと01-4.pmg)を交互に描画する。これによりアニメーションしているっぽく見える。
  • 1秒間経ったら、立ち絵の画像(02.png)を描画とタイマーの消去をして、歩く作業自体も終了させる。

   ※動作確認してください。

  何かのキーを押すたびに1秒間だけプロ生ちゃんが左に歩きます。

 

終わりに

 説明を端折り過ぎていてチュートリアルにさえなってない気もしますがご容赦ください。

一応、ソースをこちらに置いておきます。もちろん好きにお使いください。

github.com

 

まだ間に合いますので、みなさんも「マスコットアプリ文化祭」に応募しましょう。

昨年は下記のような歩くだけの作品でも参加賞をいただけましたので、優しい運営の方々はきっと上記のプログラムを元にちょっと改良したものでも、きっと、多分、きっと...

mascot-apps-contest.azurewebsites.net

 

 

それではみなさん、 Happy Programming!

おしまい