読者です 読者をやめる 読者になる 読者になる

Challenge Java EE !

Java EEを中心に趣味や仕事における開発メモを書いています。

Java EEを使って10分で作れる「いろふさんを探せ!」ゲーム #irof_history

AdventCalendar PrimeFaces JSF NetBeans Java EE 6

この記事はいろふ Advent Calendar 2013の11日目の記事です。
昨日は@pocketberserkerさんの「いろふさんとの遭遇記」 でした。
明日は@akuraruさんです。
http://atnd.org/events/44814

「いろふさんを探せ!」ゲーム

こんなゲーム(?といえるのか)を10分くらいで作りました。細かい解説は後ほど。


そもそも@irofさんって何なん…

去年Javaを触り始めて、一番理解が難しかったのが「いろふさん」の存在でした。
でも今年の春にJJUG CCCで実物を見て、おぉ、実際に存在する方だったのか…と理解(^^;
そのときの参加ブログ↓
JJUG CCC 2013 Springに参加しました~!

いろふAdvent Calendarとは…

謎でした。書いてる今も謎です…w

数日前まで参加する気も全然なかったのですが、以下、鬼のような行為によって参加に至ります…。

@bitter_foxさんが「動くirofさんに会いたい!!」を書いていて、面白いなぁと何気なく、以下つぶやきました。

そこから





既に登録されてました…鬼に出会いました orz

いろふさんを探せ!解説編

気を取り直して、私のネタは、NetBeansJava EEが入っていればすぐ作れる簡単なゲーム紹介です。
ウォーリーを探せ!のいろふさん版的な。。。

本当はNetBeans7.4とGlassFish4.0のJava EE7でやる予定でしたが、かくかくしかじかで、NetBeans7.3.1、GlassFish3.1.2.2のJava EE6で作りました(^^;

先に流れから

まずは、Webアプリを起動すると以下画面が表示されます。
f:id:kikutaro777:20131211191131j:plain

デスクトップに、いろふさんがいます。
f:id:kikutaro777:20131211191205j:plain

ドラッグ&ドロップしましょう。(ちなみに召喚ボタン押すとファイル選択ダイアログ)
f:id:kikutaro777:20131211191227j:plain

召喚されました。
f:id:kikutaro777:20131211191453j:plain

ゲームの世界に連れ込みます(単なるアップロードボタン)
成功すると、消え去ります。
f:id:kikutaro777:20131211191517j:plain

ゲーム画面へボタンで次のページにいきます。
こんな画面です。
f:id:kikutaro777:20131211191549j:plain

召喚されたいろふさんを触ると、スライドしていろふさんが出てきます。
f:id:kikutaro777:20131211191654j:plain
f:id:kikutaro777:20131211191646j:plain

画像からマウスポイントを離すと崩れ去ります。
f:id:kikutaro777:20131211191718j:plain

これが本物のいろふさんです。

では次に、増殖ボタンを押します。すると、偽物のいろふさんをいくらでも発生することができます。
f:id:kikutaro777:20131211191746j:plain

本物のいろふさんも、偽物のいろふさんもドラッグで自由に移動できるので、ごちゃまぜにして準備完了です。

いろふさんを愛するプレイヤーに、どこに本当のいろふさんがいるか探してもらいましょう!

みつけると
f:id:kikutaro777:20131211191839j:plain

いいことあるかも!

コード

ドラッグ&ドロップとか、画像にマウスオーバーしてエフェクト(画像がスライドイン、コラスプしたり)、画像を移動したり…10分はうそでしょ!と思われるかもしれませんが、JSFのPrimeFacesというコンポーネントを使っていて、簡単に実現しています。

  • ドラッグ&ドロップのアップロードやアップ画像のサムネイル表示はFileUploadコンポーネント

http://www.primefaces.org/showcase/ui/tooltip.jsf

http://www.primefaces.org/showcase/ui/draggableBasic.jsf

を使ってます。

なので、ほとんどビュー定義のみで

最初のアップロードするページビューはこんな感じ。

<h:body>
    <h:form>
        <p:fileUpload mode="advanced" 
                  label="召喚する"
                  uploadLabel="ゲームの世界に連れ込む"
                  cancelLabel="現実世界に戻してあげる"
                  fileUploadListener="#{irofSanUploadBean.handleFileUpload}" />
        <p:commandButton value="ゲーム画面へ" ajax="false" action="irofSanCooking.xhtml" />
    </h:form>
</h:body>

次のゲームページはこんな感じ。

<h:body>
    <h:form id="frm">
        <p:commandButton value="増殖" actionListener="#{irofSanCookingBean.incrementIrofSan()}" update="@form"/>
        <p:graphicImage id="irofSan" url="/images/irof.jpeg" />
        <p:draggable for="frm:irofSan" />
        <p:tooltip for="frm:irofSan" showEffect="slide" hideEffect="explode">
            <p:graphicImage id="tooltipIrofSan1" url="/images/irof.jpeg" />
        </p:tooltip>
    </h:form>
</h:body>

コンポーネント置いてID指定するだけ…(^^;

増殖ボタンでコンポーネントが増える部分はプログラム側でコンポーネントを生成しています。

package jp.co.hoge.irofsanwebapp;

import java.io.Serializable;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.context.FacesContext;
import org.primefaces.component.dnd.Draggable;
import org.primefaces.component.graphicimage.GraphicImage;

@Named
@SessionScoped
public class IrofSanCookingBean implements Serializable{
    
    private int cnt;
    
    public void incrementIrofSan(){
        cnt++;

        //プログラムでコンポーネントを追加
        UIForm form = (UIForm) findComponent(":frm");
        GraphicImage img = new GraphicImage();
        img.setId("irofSan" + cnt);
        img.setUrl("/images/irof.jpeg");
        img.setStyle(randomPosition());
        form.getChildren().add(img);
        
        Draggable dra = new Draggable();
        dra.setFor(img.getId());
        form.getChildren().add(dra);
    }
    
    private String randomPosition(){
        StringBuilder posStr = new StringBuilder();
        posStr.append("position:absolute;left:");
        posStr.append(Math.round(Math.random() * 1280));
        posStr.append("px;top:");
        posStr.append(Math.round(Math.random() * 640));
        posStr.append("px;");
        return posStr.toString();
    }
    
    private UIComponent findComponent(String componentId){
        return FacesContext.getCurrentInstance().getViewRoot().findComponent(componentId);
    }
}

ちなみに昨日の時点では、アップロードした画像をImageCropperコンポーネントでバラバラにするという残酷なネタだったのですが、ImageCropperが動かなくて、デバッグしてもわからなかったので断念しました(^^;
http://www.primefaces.org/showcase/ui/imageCropper.jsf
うーん、なぜ動かない。。。

にほんブログ村 IT技術ブログへ
にほんブログ村
にほんブログ村 IT技術ブログ Javaへ
にほんブログ村