Echoハッカソンに参加したよ - ReDo

2011年8月 7日

Echoハッカソンに参加したよ

20110806_echo00.jpg

ATND:横浜支部のハッカソン#2 Echoでハッカソンしてみよう♪
http://atnd.org/events/17299
に参加してきました。

なんか僕には似合わない感じのお上品なボールペンもらいました。わーい。

「画面の半分が反転している対面対戦ゲーム」を作ってみました。 ちなみにyoutenは当日触るまでなぜかEchoがハの字に固定できると勘違いしてました。

人 液晶→/Echo?←液晶 人

(タッチ&トライで遠巻きに眺めたり、ごっつさんに触らせてもらっていたりしたのに...。)

Echoの2画面を活かすアイディアって難しいですね。「2台」でも「大きな1台」でもできないことって思いつかない。

以下、画面キャプチャと微妙なコード。

20110806_echo01.png 20110806_echo02.png
20110806_echo03.png 20110806_echo04.png

文字を180度反転させて書く部分はAnimation使うんじゃなかったと大後悔時代です。 1年ぐらい前にもAnimationの無限ループに負けた覚えがあるんですが、今回もまた敗北しました。Fsck!

短時間でプレイアブルな紙芝居を作成する際の1手法...ぐらいの気分で生暖かく見てやってください。

main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <!-- player 1 -->
        <FrameLayout
            android:id="@+id/player1_frame"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1">
            <GridView
                android:id="@+id/player1_grid"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:verticalSpacing="4dip"
                android:horizontalSpacing="4dip"
                android:numColumns="5" />
            <TextView
                android:id="@+id/player1_text"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal|top"
                android:layout_marginTop="40dip"
                android:layout_marginLeft="20dip"
                android:layout_marginRight="20dip"
                android:padding="4dip"
                android:gravity="center"
                android:visibility="invisible"
                android:background="@drawable/blue_round"
                android:textSize="20sp"
                android:text="p1_textテキスト" />
        </FrameLayout>

        <!-- player 2 -->
        <FrameLayout
            android:id="@+id/player2_frame"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1">
            <GridView
                android:id="@+id/player2_grid"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:verticalSpacing="4dip"
                android:horizontalSpacing="4dip"
                android:numColumns="5" />
            <TextView
                android:id="@+id/player2_text"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal|bottom"
                android:layout_marginBottom="40dip"
                android:layout_marginLeft="20dip"
                android:layout_marginRight="20dip"
                android:padding="4dip"
                android:gravity="center"
                android:visibility="invisible"
                android:background="@drawable/blue_round"
                android:textSize="20sp"
                android:text="p2_textテキスト" />
        </FrameLayout>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/effect_frame"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_gravity="center">
        <ImageView
            android:id="@+id/effect_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:visibility="invisible" />
    </FrameLayout>
</FrameLayout>

MainActivity.java


package youten.redo.navyshoot;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity implements OnItemClickListener {
    /** log tag */
    private static final String TAG = "NavyShoot11";
    /** map 5x3 */
    private static final int MAP_SIZE = 15;

    // anim loop
    private boolean isLoop = false;
    private Handler handler = null;
    private TextView p1Text = null;
    private TextView p2Text = null;
    private GridView p1Grid = null;
    private GridView p2Grid = null;
    private MapArrayAdapter p1Adapter = null;
    private MapArrayAdapter p2Adapter = null;

    // mode
    private static final int MODE_INIT = 0;
    private static final int MODE_SHOOT_P1 = 1;
    private static final int MODE_SHOOT_P2 = 2;
    private static final int MODE_END = 3;
    private int mode = MODE_INIT;

    // position
    private int position_p1 = -1;
    private int position_p2 = -1;
    private ArrayList<String> p1List = null;
    private ArrayList<String> p2List = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        p1Text = (TextView) findViewById(R.id.player1_text);
        p2Text = (TextView) findViewById(R.id.player2_text);
        p1Grid = (GridView) findViewById(R.id.player1_grid);
        p2Grid = (GridView) findViewById(R.id.player2_grid);
        handler = new Handler();

        // 初期モード
        init();
    }

    @Override
    protected void onResume() {
        super.onResume();
        isLoop = true;
        handler.post(animRunnable);
    };

    @Override
    protected void onPause() {
        super.onPause();
        isLoop = false;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
        Log.d(TAG, "position_p1=" + position_p1 + " position_p2=" + position_p2);
        boolean isP1 = true;
        if (parent == p1Grid) {
            Log.d(TAG, "P1 position=" + position);
        } else if (parent == p2Grid) {
            Log.d(TAG, "P2 position=" + position);
            isP1 = false;
        } else {
            Log.d(TAG, "Unknown AdapterView position=" + position);
        }
        switch (mode) {
            case MODE_INIT:
                setSenkan(isP1, position);
                break;
            case MODE_SHOOT_P1:
                if (isP1) {
                    shootP1(position);
                }
                break;
            case MODE_SHOOT_P2:
                if (!isP1) {
                    shootP2(position);
                }
                break;
            case MODE_END:
                init();
                break;
        }
    }

    private void init() {
        // map set
        position_p1 = -1;
        position_p2 = -1;
        p1List = MapArrayAdapter.creatList(true, MAP_SIZE); // P1
        p2List = MapArrayAdapter.creatList(false, MAP_SIZE); // P2
        p1Adapter = new MapArrayAdapter(this, R.layout.celldata, p1List);
        p2Adapter = new MapArrayAdapter(this, R.layout.celldata, p2List);
        p1Grid.setAdapter(p1Adapter);
        p2Grid.setAdapter(p2Adapter);
        p1Grid.setOnItemClickListener(this);
        p2Grid.setOnItemClickListener(this);

        // msg set
        p1Text.setText(getString(R.string.msg_set));
        p2Text.setText(getString(R.string.msg_set));

        mode = MODE_INIT;
    }

    private void setSenkan(boolean isP1, int position) {
        if (isP1) { // P1
            if (position_p1 == -1) {
                position_p1 = MAP_SIZE - 1 - position;
                p1List.set(position, MapArrayAdapter.TYPE_SENKAN1);
                p1Adapter.notifyDataSetChanged();
                p1Text.setText(getString(R.string.msg_wait));
            }
        } else { // P2
            if (position_p2 == -1) {
                position_p2 = position;
                p2List.set(position, MapArrayAdapter.TYPE_SENKAN2);
                p2Adapter.notifyDataSetChanged();
                p2Text.setText(getString(R.string.msg_wait));
            }
        }

        // 二人とも配備完了
        if ((position_p1 != -1) && (position_p2 != -1)) {
            p1Text.setText(getString(R.string.msg_shoot));
            p2Text.setText(getString(R.string.msg_enemy_turn));

            // P1 先行
            mode = MODE_SHOOT_P1;
        }
    }

    /**
     * P1が打った
     *
     * @param position
     */
    private void shootP1(int position) {
        shootEffectP1();

        // P1は逆なので座標を反転する
        int hitPosition = MAP_SIZE - 1 - position;

        if (hitPosition == position_p2) { // 命中
            p1Text.setText(getString(R.string.msg_win));
            p2Text.setText(getString(R.string.msg_lose));
            p2List.set(position_p2, MapArrayAdapter.TYPE_BROKEN2);
            p2Adapter.notifyDataSetChanged();

            mode = MODE_END;
        } else { // はずれ
            p1Text.setText(getString(R.string.msg_miss));
            p2Text.setText(getString(R.string.msg_shoot));
            p2List.set(hitPosition, MapArrayAdapter.TYPE_MIZUSIBUKI2);
            p2Adapter.notifyDataSetChanged();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (mode == MODE_SHOOT_P2) {
                        p1Text.setText(getString(R.string.msg_enemy_turn));
                    }
                }
            }, 2000);

            mode = MODE_SHOOT_P2;
        }
    }

    /**
     * P2が打った
     *
     * @param position
     */
    private void shootP2(int position) {
        shootEffectP2();

        // P2は順なので反転しない
        int hitPosition = position;

        if (hitPosition == position_p1) { // 命中
            p2Text.setText(getString(R.string.msg_win));
            p1Text.setText(getString(R.string.msg_lose));
            p1List.set(MAP_SIZE - 1 - position, MapArrayAdapter.TYPE_BROKEN1);
            p1Adapter.notifyDataSetChanged();

            mode = MODE_END;
        } else { // はずれ
            p2Text.setText(getString(R.string.msg_miss));
            p1Text.setText(getString(R.string.msg_shoot));
            p1List.set(MAP_SIZE - 1 - position, MapArrayAdapter.TYPE_MIZUSIBUKI1);
            p1Adapter.notifyDataSetChanged();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (mode == MODE_SHOOT_P1) {
                        p2Text.setText(getString(R.string.msg_enemy_turn));
                    }
                }
            }, 2000);

            mode = MODE_SHOOT_P1;
        }
    }

    // messgageBox loop
    private Runnable animRunnable = new Runnable() {
        @Override
        public void run() {
            Animation anim1 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.text_p1);
            Animation anim2 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.text_p2);
            anim1.setAnimationListener(new AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    if (isLoop) {
                        handler.post(animRunnable);
                    }
                }
            });
            MainActivity.this.findViewById(R.id.player1_text).startAnimation(anim1);
            MainActivity.this.findViewById(R.id.player2_text).startAnimation(anim2);
        }
    };

    private void shootEffectP1() {
        ImageView effectImage = (ImageView)findViewById(R.id.effect_image);
        effectImage.setImageResource(R.drawable.gyorai_p1);
        Animation anim = AnimationUtils.loadAnimation(this, R.anim.upshoot_p1);
        anim.setAnimationListener(new AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
            @Override
            public void onAnimationEnd(Animation animation) {
                ImageView effectImage = (ImageView)findViewById(R.id.effect_image);
                effectImage.setImageDrawable(null);
            }
        });
        effectImage.startAnimation(anim);
    }

    private void shootEffectP2() {
        ImageView effectImage = (ImageView)findViewById(R.id.effect_image);
        effectImage.setImageResource(R.drawable.gyorai_p2);
        Animation anim = AnimationUtils.loadAnimation(this, R.anim.upshoot_p2);
        anim.setAnimationListener(new AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
            @Override
            public void onAnimationEnd(Animation animation) {
                ImageView effectImage = (ImageView)findViewById(R.id.effect_image);
                effectImage.setImageDrawable(null);
            }
        });
        effectImage.startAnimation(anim);
    }

}

MapArrayAdapter.java


package youten.redo.navyshoot;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

public class MapArrayAdapter extends ArrayAdapter<String> {
    public static final String TYPE_SEA1 = "sea1";
    public static final String TYPE_SEA2 = "sea2";
    public static final String TYPE_SENKAN1 = "senkan1";
    public static final String TYPE_SENKAN2 = "senkan2";
    public static final String TYPE_BROKEN1 = "broken1";
    public static final String TYPE_BROKEN2 = "broken2";
    public static final String TYPE_MIZUSIBUKI1 = "mizusibuki1";
    public static final String TYPE_MIZUSIBUKI2 = "mizusibuki2";

    /** Mapリスト */
    private ArrayList<String> list = null;
    /** inflater */
    private LayoutInflater inflater = null;
    /** ViewのresId */
    private int viewId = 0;

    /**
     * コンストラクタ
     *
     * @param context コンテキスト
     * @param viewId 構成するViewのResourceId
     * @param list 機種データリスト
     */
    public MapArrayAdapter(Context context, int viewId, ArrayList<String> list) {
        super(context, viewId, list);
        this.list = list;
        this.viewId = viewId;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = inflater.inflate(viewId, null);
        }

        if (list != null) {
            ImageView iv = (ImageView) convertView;
            if (TYPE_SEA1.equals(list.get(position))) {
                iv.setImageResource(R.drawable.sea_p1);
            } else if (TYPE_SEA2.equals(list.get(position))) {
                iv.setImageResource(R.drawable.sea_p2);
            } else if (TYPE_SENKAN1.equals(list.get(position))) {
                iv.setImageResource(R.drawable.senkan_p1);
            } else if (TYPE_SENKAN2.equals(list.get(position))) {
                iv.setImageResource(R.drawable.senkan_p2);
            } else if (TYPE_BROKEN1.equals(list.get(position))) {
                iv.setImageResource(R.drawable.broken_p1);
            } else if (TYPE_BROKEN2.equals(list.get(position))) {
                iv.setImageResource(R.drawable.broken_p2);
            } else if (TYPE_MIZUSIBUKI1.equals(list.get(position))) {
                iv.setImageResource(R.drawable.mizusibuki_p1);
            } else if (TYPE_MIZUSIBUKI2.equals(list.get(position))) {
                iv.setImageResource(R.drawable.mizusibuki_p2);
            } else {
                iv.setImageResource(R.drawable.sea_p1);
            }
        }
        return convertView;
    }

    public static ArrayList<String> creatList(boolean isP1, int size) {
        ArrayList<String> ret = new ArrayList<String>();
        for (int i = 0; i < size; i++) {
            if (isP1) {
                ret.add(TYPE_SEA1);
            } else {
                ret.add(TYPE_SEA2);
            }
        }
        return ret;
    }
}

コメントする