2011年11月6日日曜日
Steve Jobs スティーブジョブズの伝記買いました
スティーブ・ジョブズ Ⅰと
スティーブ・ジョブズ Ⅱを買いました。
まだ1冊目を100ページぐらいしか読んでないんですが、ジョブズは小さい頃から特別な子だったようです。
親の影響や、シリコンバレーに住んでいたことなどが影響していて、エレクロニクスに長けた子と知り合うことができたみたいです。
スティーブ・ジョブズ Ⅱを買いました。
まだ1冊目を100ページぐらいしか読んでないんですが、ジョブズは小さい頃から特別な子だったようです。
親の影響や、シリコンバレーに住んでいたことなどが影響していて、エレクロニクスに長けた子と知り合うことができたみたいです。
ラベル:
本
2011年8月17日水曜日
本
本を2冊買いました。
6年前と11年前に出版された本です。
ーデザインパターンとともに学ぶー オブジェクト指向のこころ
リファクタリング プログラミングの体質改善テクニック
これらを読み終える頃には、ソースを書く意識が変わっていますように。
6年前と11年前に出版された本です。
ーデザインパターンとともに学ぶー オブジェクト指向のこころ
リファクタリング プログラミングの体質改善テクニック
これらを読み終える頃には、ソースを書く意識が変わっていますように。
ラベル:
本
2011年8月13日土曜日
ノーマルマップ
3Dで凸凹を表現するのにバンプマップとノーマルマップというのがあります。
バンプマップはグレーを基準の色にして、白に近ければ凸に、黒に近ければ凹になるようにレンダリングされます。
ノーマルマップはRGBで凸凹の情報を持たせているので、バンプマップより詳細な凸凹をレンダリングできるということです。
リンク:
WBS+のサイトで紹介されています。
ノーマルマップのBlenderでの作り方がこちらで紹介されています。
○×つくろーどっとコムのサイトで原理が詳しく解説されています。
バンプマップはグレーを基準の色にして、白に近ければ凸に、黒に近ければ凹になるようにレンダリングされます。
ノーマルマップはRGBで凸凹の情報を持たせているので、バンプマップより詳細な凸凹をレンダリングできるということです。
リンク:
WBS+のサイトで紹介されています。
ノーマルマップのBlenderでの作り方がこちらで紹介されています。
○×つくろーどっとコムのサイトで原理が詳しく解説されています。
2011年7月19日火曜日
アクションゲームの当たり判定
アクションゲームの当たり判定を教えてくれと頼まれたので、久しぶりに当たり判定のソースを書いてみました。
C#でXNA用に書いてます。
3段階に分けて書いてみました。
最初は四角と四角の当たり判定。
2つ目は四角と複数の四角の当たり判定。
3つ目はジャンプができる四角と複数の四角の当たり判定。
もっとシンプルにできそうな気もしますが、一応書きたてのものを載せてみました。
四角と四角の当たり判定
四角と複数の四角の当たり判定。
C#でXNA用に書いてます。
3段階に分けて書いてみました。
最初は四角と四角の当たり判定。
2つ目は四角と複数の四角の当たり判定。
3つ目はジャンプができる四角と複数の四角の当たり判定。
もっとシンプルにできそうな気もしますが、一応書きたてのものを載せてみました。
四角と四角の当たり判定
using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; namespace Hit_Test_01 { ////// This is the main type for your game /// public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D player; Texture2D map; Vector2 playerPosition; Vector2 mapPosition; const int PLAYER_WIDTH = 60; const int PLAYER_HEITHT = 90; const int MAP_WIDTH = 100; const int MAP_HEIGHT = 100; KeyboardState keyboardState; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } ////// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// protected override void Initialize() { // TODO: Add your initialization logic here playerPosition = new Vector2(0, 0); mapPosition = new Vector2(100, 100); base.Initialize(); } ////// LoadContent will be called once per game and is the place to load /// all of your content. /// protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); player = Content.Load("players16"); map = Content.Load ("map"); // TODO: use this.Content to load your game content here } /// /// UnloadContent will be called once per game and is the place to unload /// all content. /// protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } ////// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// /// Provides a snapshot of timing values. protected override void Update(GameTime gameTime) { keyboardState = Keyboard.GetState(); // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); if (keyboardState.IsKeyDown(Keys.Escape)) { this.Exit(); } if (keyboardState.IsKeyDown(Keys.Left)) { playerPosition.X -= 1.0f; if (Hit()) { playerPosition.X = mapPosition.X + MAP_WIDTH; } } if (keyboardState.IsKeyDown(Keys.Right)) { playerPosition.X += 1.0f; if (Hit()) { playerPosition.X = mapPosition.X - PLAYER_WIDTH; } } if (keyboardState.IsKeyDown(Keys.Up)) { playerPosition.Y -= 1.0f; if (Hit()) { playerPosition.Y = mapPosition.Y + MAP_HEIGHT; } } if (keyboardState.IsKeyDown(Keys.Down)) { playerPosition.Y += 1.0f; if (Hit()) { playerPosition.Y = mapPosition.Y - PLAYER_HEITHT; } } // TODO: Add your update logic here base.Update(gameTime); } private bool Hit() { if (playerPosition.X + PLAYER_WIDTH > mapPosition.X && playerPosition.X < mapPosition.X + MAP_WIDTH && playerPosition.Y + PLAYER_HEITHT > mapPosition.Y && playerPosition.Y < mapPosition.Y + MAP_HEIGHT) { return true; } return false; } ////// This is called when the game should draw itself. /// /// Provides a snapshot of timing values. protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(); spriteBatch.Draw( map, new Rectangle((int)mapPosition.X, (int)mapPosition.Y, MAP_WIDTH, MAP_HEIGHT), new Rectangle(0, 0, MAP_WIDTH, MAP_HEIGHT), Color.White); spriteBatch.Draw( player, new Rectangle((int)playerPosition.X, (int)playerPosition.Y, PLAYER_WIDTH, PLAYER_HEITHT), new Rectangle(0, 0, PLAYER_WIDTH, PLAYER_HEITHT), Color.White); spriteBatch.End(); base.Draw(gameTime); } } }
四角と複数の四角の当たり判定。
using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; namespace Hit_Test_02 { ///ジャンプができる四角と複数の四角の当たり判定。/// This is the main type for your game /// public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D player; Texture2D map; const int MAP_DIVISION_MAX_X = 8; const int MAP_DIVISION_MAX_Y = 5; Vector2 playerPosition; Vector2 playerSpeed; Vector2[,] mapPosition = new Vector2[MAP_DIVISION_MAX_X, MAP_DIVISION_MAX_Y]; Boolean[,] mapActivity = new Boolean[MAP_DIVISION_MAX_X, MAP_DIVISION_MAX_Y]; const int PLAYER_WIDTH = 60; const int PLAYER_HEITHT = 90; const int MAP_WIDTH = 100; const int MAP_HEIGHT = 100; const int MAP_OFFSET_X = 0; const int MAP_OFFSET_Y = 0; const float HIT_ADJUST_LENGTH = 1.01f; KeyboardState keyboardState; enum DIRECTION { LEFT, TOP, BOTTOM, RIGHT } public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } ////// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// protected override void Initialize() { // TODO: Add your initialization logic here playerPosition = new Vector2(MAP_WIDTH * 3, MAP_HEIGHT * 1); playerSpeed = new Vector2(0.0f, 0.0f); for (int x = 0; x < MAP_DIVISION_MAX_X; ++x) { for (int y = 0; y < MAP_DIVISION_MAX_Y; ++y) { mapPosition[x, y] = new Vector2(x * MAP_WIDTH + MAP_OFFSET_X, y * MAP_HEIGHT + MAP_OFFSET_Y); mapActivity[x, y] = true; } // mapActivity[x, 0] = false; } mapActivity[3, 1] = false; mapActivity[3, 2] = false; mapActivity[4, 1] = false; mapActivity[4, 2] = false; base.Initialize(); } ////// LoadContent will be called once per game and is the place to load /// all of your content. /// protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); player = Content.Load("players16"); map = Content.Load ("map"); // TODO: use this.Content to load your game content here } /// /// UnloadContent will be called once per game and is the place to unload /// all content. /// protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } ////// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// /// Provides a snapshot of timing values. protected override void Update(GameTime gameTime) { keyboardState = Keyboard.GetState(); // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); if (keyboardState.IsKeyDown(Keys.Escape)) { this.Exit(); } if (keyboardState.IsKeyDown(Keys.Left)) { playerSpeed.X = -1.0f; } if (keyboardState.IsKeyDown(Keys.Right)) { playerSpeed.X = 1.0f; } if (keyboardState.IsKeyDown(Keys.Up)) { playerSpeed.Y = -1.0f; } if (keyboardState.IsKeyDown(Keys.Down)) { playerSpeed.Y = 1.0f; } playerPosition += playerSpeed; Hit(); playerSpeed.X = 0.0f; playerSpeed.Y = 0.0f; // TODO: Add your update logic here base.Update(gameTime); } private void Hit() { if (playerSpeed.X < 0.0f) { int x = (int)(playerPosition.X) / MAP_WIDTH; int y = (int)(playerPosition.Y + PLAYER_HEITHT - HIT_ADJUST_LENGTH) / MAP_HEIGHT; if (mapActivity[x, y] && playerPosition.X + PLAYER_WIDTH > mapPosition[x, y].X && playerPosition.X < mapPosition[x, y].X + MAP_WIDTH && playerPosition.Y + PLAYER_HEITHT > mapPosition[x, y].Y && playerPosition.Y < mapPosition[x, y].Y + MAP_HEIGHT) { playerPosition.X = mapPosition[x, y].X + MAP_WIDTH; playerSpeed.X = 0.0f; } } if (playerSpeed.X > 0.0f) { int x = (int)(playerPosition.X + PLAYER_WIDTH) / MAP_WIDTH; int y = (int)(playerPosition.Y + PLAYER_HEITHT - HIT_ADJUST_LENGTH) / MAP_HEIGHT; if (mapActivity[x, y] && playerPosition.X + PLAYER_WIDTH > mapPosition[x, y].X && playerPosition.X < mapPosition[x, y].X + MAP_WIDTH && playerPosition.Y + PLAYER_HEITHT > mapPosition[x, y].Y && playerPosition.Y < mapPosition[x, y].Y + MAP_HEIGHT) { playerPosition.X = mapPosition[x, y].X - PLAYER_WIDTH; playerSpeed.X = 0.0f; } } if (playerSpeed.Y < 0.0f) { int x = (int)(playerPosition.X) / MAP_WIDTH; int y = (int)(playerPosition.Y) / MAP_HEIGHT; if (mapActivity[x, y] && playerPosition.X + PLAYER_WIDTH > mapPosition[x, y].X && playerPosition.X < mapPosition[x, y].X + MAP_WIDTH && playerPosition.Y + PLAYER_HEITHT > mapPosition[x, y].Y && playerPosition.Y < mapPosition[x, y].Y + MAP_HEIGHT) { playerPosition.Y = mapPosition[x, y].Y + MAP_HEIGHT; playerSpeed.Y = 0.0f; } } if (playerSpeed.Y > 0.0f) { int x = (int)(playerPosition.X) / MAP_WIDTH; int y = (int)(playerPosition.Y + PLAYER_HEITHT) / MAP_HEIGHT; if (mapActivity[x, y] && playerPosition.X + PLAYER_WIDTH > mapPosition[x, y].X && playerPosition.X < mapPosition[x, y].X + MAP_WIDTH && playerPosition.Y + PLAYER_HEITHT > mapPosition[x, y].Y && playerPosition.Y < mapPosition[x, y].Y + MAP_HEIGHT) { playerPosition.Y = mapPosition[x, y].Y - PLAYER_HEITHT; playerSpeed.Y = 0.0f; } } } ////// This is called when the game should draw itself. /// /// Provides a snapshot of timing values. protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(); for (int x = 0; x < MAP_DIVISION_MAX_X; ++x) { for (int y = 0; y < MAP_DIVISION_MAX_Y; ++y) { if (mapActivity[x, y]) { spriteBatch.Draw( map, new Rectangle((int)mapPosition[x, y].X, (int)mapPosition[x, y].Y, MAP_WIDTH, MAP_HEIGHT), new Rectangle(0, 0, MAP_WIDTH, MAP_HEIGHT), Color.White); } } } spriteBatch.Draw( player, new Rectangle((int)playerPosition.X, (int)playerPosition.Y, PLAYER_WIDTH, PLAYER_HEITHT), new Rectangle(0, 0, PLAYER_WIDTH, PLAYER_HEITHT), Color.White); spriteBatch.End(); base.Draw(gameTime); } } }
using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; namespace Hit_Test_03 { ////// This is the main type for your game /// public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D player; Texture2D map; const int MAP_DIVISION_MAX_X = 8; const int MAP_DIVISION_MAX_Y = 5; Vector2 playerPosition; Vector2 playerSpeed; const float GRAVITY = 1.0f; Vector2[,] mapPosition = new Vector2[MAP_DIVISION_MAX_X, MAP_DIVISION_MAX_Y]; Boolean[,] mapActivity = new Boolean[MAP_DIVISION_MAX_X, MAP_DIVISION_MAX_Y]; const int PLAYER_WIDTH = 60; const int PLAYER_HEITHT = 90; const int MAP_WIDTH = 100; const int MAP_HEIGHT = 100; const int MAP_OFFSET_X = 0; const int MAP_OFFSET_Y = 0; const float HIT_ADJUST_LENGTH = 1.01f; KeyboardState keyboardState; enum DIRECTION { LEFT, TOP, BOTTOM, RIGHT } public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } ////// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// protected override void Initialize() { // TODO: Add your initialization logic here playerPosition = new Vector2(MAP_WIDTH * 3, MAP_HEIGHT * 1); playerSpeed = new Vector2(0.0f, 0.0f); for (int x = 0; x < MAP_DIVISION_MAX_X; ++x) { for (int y = 0; y < MAP_DIVISION_MAX_Y; ++y) { mapPosition[x, y] = new Vector2(x * MAP_WIDTH + MAP_OFFSET_X, y * MAP_HEIGHT + MAP_OFFSET_Y); mapActivity[x, y] = true; } // mapActivity[x, 0] = false; } mapActivity[2, 1] = false; mapActivity[2, 2] = false; mapActivity[2, 3] = false; mapActivity[3, 1] = false; // mapActivity[3, 2] = false; mapActivity[3, 3] = false; mapActivity[4, 1] = false; mapActivity[4, 2] = false; mapActivity[4, 3] = false; mapActivity[5, 1] = false; // mapActivity[5, 2] = false; mapActivity[5, 3] = false; mapActivity[6, 1] = false; mapActivity[6, 2] = false; mapActivity[6, 3] = false; base.Initialize(); } ////// LoadContent will be called once per game and is the place to load /// all of your content. /// protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); player = Content.Load("players16"); map = Content.Load ("map"); // TODO: use this.Content to load your game content here } /// /// UnloadContent will be called once per game and is the place to unload /// all content. /// protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } ////// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// /// Provides a snapshot of timing values. protected override void Update(GameTime gameTime) { keyboardState = Keyboard.GetState(); // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); if (keyboardState.IsKeyDown(Keys.Escape)) { this.Exit(); } if (keyboardState.IsKeyDown(Keys.Left)) { playerSpeed.X = -1.0f; } if (keyboardState.IsKeyDown(Keys.Right)) { playerSpeed.X = 1.0f; } if (keyboardState.IsKeyDown(Keys.Up)) { playerSpeed.Y = -10.0f; } if (keyboardState.IsKeyDown(Keys.Down)) { playerSpeed.Y = 1.0f; } playerPosition += playerSpeed; Hit(); playerSpeed.X = 0.0f; playerSpeed.Y += GRAVITY; // TODO: Add your update logic here base.Update(gameTime); } private void Hit() { if (playerSpeed.X < 0.0f) { int x = (int)(playerPosition.X) / MAP_WIDTH; int y = (int)(playerPosition.Y + PLAYER_HEITHT - HIT_ADJUST_LENGTH - playerSpeed.Y) / MAP_HEIGHT; if (mapActivity[x, y] && playerPosition.X + PLAYER_WIDTH > mapPosition[x, y].X && playerPosition.X < mapPosition[x, y].X + MAP_WIDTH && playerPosition.Y + PLAYER_HEITHT > mapPosition[x, y].Y && playerPosition.Y < mapPosition[x, y].Y + MAP_HEIGHT) { playerPosition.X = mapPosition[x, y].X + MAP_WIDTH; playerSpeed.X = 0.0f; } } if (playerSpeed.X > 0.0f) { int x = (int)(playerPosition.X + PLAYER_WIDTH) / MAP_WIDTH; int y = (int)(playerPosition.Y + PLAYER_HEITHT - HIT_ADJUST_LENGTH - playerSpeed.Y) / MAP_HEIGHT; if (mapActivity[x, y] && playerPosition.X + PLAYER_WIDTH > mapPosition[x, y].X && playerPosition.X < mapPosition[x, y].X + MAP_WIDTH && playerPosition.Y + PLAYER_HEITHT > mapPosition[x, y].Y && playerPosition.Y < mapPosition[x, y].Y + MAP_HEIGHT) { playerPosition.X = mapPosition[x, y].X - PLAYER_WIDTH; playerSpeed.X = 0.0f; } } if (playerSpeed.Y < 0.0f) { int x = (int)(playerPosition.X - playerSpeed.X) / MAP_WIDTH; int y = (int)(playerPosition.Y) / MAP_HEIGHT; if (!mapActivity[x, y] && mapActivity[x + 1, y] && playerPosition.X <= mapPosition[x + 1, y].X) { x += 1; } if (mapActivity[x, y] && playerPosition.X - HIT_ADJUST_LENGTH + PLAYER_WIDTH > mapPosition[x, y].X && playerPosition.X - HIT_ADJUST_LENGTH < mapPosition[x, y].X + MAP_WIDTH && playerPosition.Y + PLAYER_HEITHT > mapPosition[x, y].Y && playerPosition.Y < mapPosition[x, y].Y + MAP_HEIGHT) { playerPosition.Y = mapPosition[x, y].Y + MAP_HEIGHT; playerSpeed.Y = 0.0f; } } if (playerSpeed.Y > 0.0f) { int x = (int)(playerPosition.X) / MAP_WIDTH; int y = (int)(playerPosition.Y + PLAYER_HEITHT) / MAP_HEIGHT; if (!mapActivity[x, y] && mapActivity[x + 1, y] && playerPosition.X <= mapPosition[x + 1, y].X) { x += 1; } if (mapActivity[x, y] && playerPosition.X + PLAYER_WIDTH > mapPosition[x, y].X && playerPosition.X < mapPosition[x, y].X + MAP_WIDTH && playerPosition.Y + PLAYER_HEITHT > mapPosition[x, y].Y && playerPosition.Y < mapPosition[x, y].Y + MAP_HEIGHT) { playerPosition.Y = mapPosition[x, y].Y - PLAYER_HEITHT; playerSpeed.Y = 0.0f; } } } ////// This is called when the game should draw itself. /// /// Provides a snapshot of timing values. protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(); for (int x = 0; x < MAP_DIVISION_MAX_X; ++x) { for (int y = 0; y < MAP_DIVISION_MAX_Y; ++y) { if (mapActivity[x, y]) { spriteBatch.Draw( map, new Rectangle((int)mapPosition[x, y].X, (int)mapPosition[x, y].Y, MAP_WIDTH, MAP_HEIGHT), new Rectangle(0, 0, MAP_WIDTH, MAP_HEIGHT), Color.White); } } } spriteBatch.Draw( player, new Rectangle((int)playerPosition.X, (int)playerPosition.Y, PLAYER_WIDTH, PLAYER_HEITHT), new Rectangle(0, 0, PLAYER_WIDTH, PLAYER_HEITHT), Color.White); spriteBatch.End(); base.Draw(gameTime); } } }
2011年6月17日金曜日
PSVita
PSVitaの開発環境はどうなるんだろう?
開発機材があるのかな。もしPSVita実機だけでデバッグできたら、個人の開発者が増えるんではなかろうか。
統合開発環境とかもeclipseとかが使えたら、ぐっと開発者が増えると思う。
SCEにできるだけオープンな開発環境を整えてもらいたいと願ってます。
開発機材があるのかな。もしPSVita実機だけでデバッグできたら、個人の開発者が増えるんではなかろうか。
統合開発環境とかもeclipseとかが使えたら、ぐっと開発者が増えると思う。
SCEにできるだけオープンな開発環境を整えてもらいたいと願ってます。
2011年5月18日水曜日
OpenGLES入門 その3 テクスチャの表示
今回はテクスチャを表示させます。
今回は表示させる画像にこのimage.pngを使用します。
そしてOpenGL入門その2で使用したソースコードを流用します。
MyApplication.javaはそのままで、Renderer.javaとScene.javaの中身を少し変更します。
■Renderer.java■
■Scene.java■
画像をdrawable-hdpiに登録してから実行すると下のように表示されます。
今回は表示させる画像にこのimage.pngを使用します。
そしてOpenGL入門その2で使用したソースコードを流用します。
MyApplication.javaはそのままで、Renderer.javaとScene.javaの中身を少し変更します。
■Renderer.java■
package test.sample; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.app.Activity; import android.opengl.GLSurfaceView; import android.view.Display; public class GLRenderer implements GLSurfaceView.Renderer { private Scene mScene; private boolean mOnce = true; private Activity mActivity; public GLRenderer(Activity activity, Display display) { mScene = new Scene(display); mActivity = activity; } @Override public void onDrawFrame(GL10 gl) {//毎フレーム呼ばれるメインループ if (mOnce) { mScene.setTexture(gl, mActivity.getResources().openRawResource(R.drawable.image)); mOnce = false; } mScene.draw(gl); } @Override public void onSurfaceChanged(GL10 arg0, int arg1, int arg2) { } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { } }
■Scene.java■
package test.sample; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLU; import android.opengl.GLUtils; import android.view.Display; import android.view.MotionEvent; import android.view.View; public class Scene implements View.OnTouchListener{ private FloatBuffer vertexBuffer; private FloatBuffer textureBuffer; private int mTextureNumber; private int mWidth; private int mHeight; public Scene(Display display) { mWidth = display.getWidth(); mHeight = display.getHeight(); float x = 0.0f; float y = 0.0f; float z = 0.0f; float sizeX = 10.0f; float sizeY = 10.0f; float sizeZ = 0.0f; float[] vertex = { //左側の三角形 x + sizeX, y + sizeY, z + sizeZ,//右下 x - sizeX, y - sizeY, z + sizeZ,//左上 x - sizeX, y + sizeY, z + sizeZ,//左下 //右側の三角形 x + sizeX, y + sizeY, z + sizeZ,//右下 x + sizeX, y - sizeY, z + sizeZ,//右上 x - sizeX, y - sizeY, z + sizeZ,//左上 }; ByteBuffer vb = ByteBuffer.allocateDirect(6 * 3 * 4); vb.order(ByteOrder.nativeOrder()); //ビッグエンディアンかリトルエンディアンにあわせてくれる vertexBuffer = vb.asFloatBuffer(); vertexBuffer.put(vertex); vertexBuffer.position(0); float[] texture = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //左側の三角形に貼る 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f //右側の三角形に貼る }; ByteBuffer tb = ByteBuffer.allocateDirect(2 * 3 * 2 * 4); tb.order(ByteOrder.nativeOrder()); //ビッグエンディアンかリトルエンディアンにあわせてくれる textureBuffer = tb.asFloatBuffer(); textureBuffer.put(texture); textureBuffer.position(0); } public void setTexture(GL10 gl, InputStream is) { Bitmap bitmap; try { bitmap = BitmapFactory.decodeStream(is); } finally { try { is.close(); } catch(IOException e) {} } int[] textureNumber = new int[1]; gl.glGenTextures(1, textureNumber, 0); mTextureNumber = textureNumber[0]; gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureNumber); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); gl.glTexParameterx( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT ); gl.glTexParameterx( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT ); gl.glTexParameterx( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR ); gl.glTexParameterx( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR ); } public void draw(GL10 gl) { gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //ビューポート行列(ウィンドウへの出力領域)設定 gl.glViewport(0,0,mWidth,mHeight); //射影行列設定 gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); //視界(視野角、画面のアスペクト、比近視点、遠視点)の設定 float aspect = (float)mWidth / (float)mHeight; GLU.gluPerspective(gl, 45.0f, aspect, 0.1f, 3000.0f); GLU.gluLookAt( gl, 0.0f, 0.0f, 100.0f, //位置(視点) 0.0f, 0.0f, 0.0f, //見つめているところ 0.0f, 1.0f, 0.0f //水平 ); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glEnable(GL10.GL_TEXTURE_2D); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); int triangleNum = 2; gl.glDrawArrays(GL10.GL_TRIANGLES, 0, triangleNum * 3); } @Override public boolean onTouch(View arg0, MotionEvent arg1) { // TODO 自動生成されたメソッド・スタブ return false; } }
画像をdrawable-hdpiに登録してから実行すると下のように表示されます。
2011年3月28日月曜日
OpenGLES入門 その2
今回は三角ポリゴンを2枚表示させます。
下のような青と緑のポリゴンが表示できると思います。
■MyApplication.java■
■GLRenderer.java■
下のような青と緑のポリゴンが表示できると思います。
■MyApplication.java■
import android.app.Activity; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.view.WindowManager;public class MyApplication extends Activity {private GLSurfaceView mGLSurfaceView; private GLRenderer mGLRenderer; @Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); mGLSurfaceView = new GLSurfaceView(this); setContentView(mGLSurfaceView); WindowManager windowmanager = (WindowManager)getSystemService(WINDOW_SERVICE); mGLRenderer = new GLRenderer(this, windowmanager.getDefaultDisplay()); mGLSurfaceView.setRenderer(mGLRenderer);}/** * */ public void onPause() {mGLSurfaceView.onPause(); super.onPause();}/** * */ public void onResume() {}super.onResume(); mGLSurfaceView.onResume();}
■GLRenderer.java■
■Scene.java■import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.app.Activity; import android.opengl.GLSurfaceView; import android.opengl.GLU; import android.view.Display;public class GLRenderer implements GLSurfaceView.Renderer { private Scene mScene; public GLRenderer(Activity activity, Display display) { mScene = new Scene(display); } @Override public void onDrawFrame(GL10 gl) {//毎フレーム呼ばれるメインループ mScene.draw(gl); } @Override public void onSurfaceChanged(GL10 arg0, int arg1, int arg2) { } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { } }
import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLU; import android.view.Display; import android.view.MotionEvent; import android.view.View; public class Scene implements View.OnTouchListener{ private FloatBuffer vertexBuffer; private FloatBuffer colorBuffer; private int mWidth; private int mHeight; public Scene(Display display) { mWidth = display.getWidth(); mHeight = display.getHeight(); float x = 0.0f; float y = 0.0f; float z = 0.0f; float sizeX = 10.0f; float sizeY = 10.0f; float sizeZ = 0.0f; float[] vertex = { //左側の三角形 x + sizeX, y - sizeY, z + sizeZ, x - sizeX, y - sizeY, z + sizeZ, x - sizeX, y + sizeY, z + sizeZ, //右側の三角形 x - sizeX, y + sizeY, z + sizeZ, x + sizeX, y + sizeY, z + sizeZ, x + sizeX, y - sizeY, z + sizeZ, }; ByteBuffer vb = ByteBuffer.allocateDirect(6 * 3 * 4); vb.order(ByteOrder.nativeOrder()); //ビッグエンディアンかリトルエンディアンにあわせてくれる vertexBuffer = vb.asFloatBuffer(); vertexBuffer.put(vertex); vertexBuffer.position(0); float[] color = { //左側の三角形(青) 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //右側の三角形(緑) 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f }; ByteBuffer vbc = ByteBuffer.allocateDirect(6 * 4 * 4); vbc.order(ByteOrder.nativeOrder()); //ビッグエンディアンかリトルエンディアンにあわせてくれる colorBuffer = vbc.asFloatBuffer(); colorBuffer.put(color); colorBuffer.position(0); } public void draw(GL10 gl) { gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);//ビューポート行列(ウィンドウへの出力領域)設定 gl.glViewport(0,0,mWidth,mHeight); //射影行列設定 gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); //視界(視野角、画面のアスペクト、比近視点、遠視点)の設定 float aspect = (float)mWidth / (float)mHeight; GLU.gluPerspective(gl, 45.0f, aspect, 0.1f, 3000.0f); GLU.gluLookAt(gl, 0.0f, 0.0f, 100.0f, //位置(視点) 0.0f, 0.0f, 0.0f, //見つめているところ 0.0f, 1.0f, 0.0f //水平 );gl.glMatrixMode(GL10.GL_MODELVIEW);gl.glLoadIdentity();gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer); int triangleNum = 2; gl.glDrawArrays(GL10.GL_TRIANGLES, 0, triangleNum * 3); } @Override public boolean onTouch(View arg0, MotionEvent arg1) { return false; } }
2011年3月23日水曜日
Androidアプリ公開
「ポリゴンワールド」をマーケットに公開しました。
無料です。
https://market.android.com/developer?pub=minmin0530
初めて作ったAndroidアプリです。
Android持ってる方は是非ダウンロードしてみて下さい。
無料です。
https://market.android.com/developer?pub=minmin0530
初めて作ったAndroidアプリです。
Android持ってる方は是非ダウンロードしてみて下さい。
2011年3月1日火曜日
OpenGLES入門 その1
AndroidでのOpenGLESの使い方をおおまかに書いておきます。
■1
MyApplicationを作る。まずActivityを継承する
class MyApplication extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//AbsoluteLayoutを使うのは、後でボタンやテキストを表示させるため。
AbsoluteLayout layout=new AbsoluteLayout(this);
setContentView(layout);
//GLサーフェイスビューを生成して設定
GLSurfaceView mGLSurfaceView = new GLSurfaceView(this);
GLRenderer glRenderer = new GLRenderer(this);
mGLSurfaceView.setRenderer(glRenderer);
layout.addView(mGLSurfaceView);
}
}
■2
GLRendererクラスはGLSurfaceView.Rendererを継承する
public class GLRenderer implements GLSurfaceView.Renderer {
private Scene mScene;
private Resources mResource;
public GLRenderer(Activity activity) {
mResource = activity.getResources();//これは後でテクスチャを読み込むときに使う。
mScene = new Scene();
}
//このonDrawFrameメソッドが毎フレーム呼ばれるので、ここで描画処理、更新処理を行う。
public void onDrawFrame(GL10 gl) {
mScene.draw(gl);
mScene.update();
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//ここにOpenGLの初期化処理を書いておく
}
}
■3
SceneクラスはView.OnTouchListenerを継承する
public class Scene implements View.OnTouchListener{
public void draw(GL10 gl) {
//ここにポリゴンの描画処理を書く
}
public void update() {
//ここに物体の移動処理などを書く
}
public boolean onTouch(View v, MotionEvent event) {
//ここにタッチ操作処理を書く
return false;
}
}
これをコピペしても動きません。すみません。
これで大体の流れをつかんで下さい。
■1
MyApplicationを作る。まずActivityを継承する
class MyApplication extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//AbsoluteLayoutを使うのは、後でボタンやテキストを表示させるため。
AbsoluteLayout layout=new AbsoluteLayout(this);
setContentView(layout);
//GLサーフェイスビューを生成して設定
GLSurfaceView mGLSurfaceView = new GLSurfaceView(this);
GLRenderer glRenderer = new GLRenderer(this);
mGLSurfaceView.setRenderer(glRenderer);
layout.addView(mGLSurfaceView);
}
}
■2
GLRendererクラスはGLSurfaceView.Rendererを継承する
public class GLRenderer implements GLSurfaceView.Renderer {
private Scene mScene;
private Resources mResource;
public GLRenderer(Activity activity) {
mResource = activity.getResources();//これは後でテクスチャを読み込むときに使う。
mScene = new Scene();
}
//このonDrawFrameメソッドが毎フレーム呼ばれるので、ここで描画処理、更新処理を行う。
public void onDrawFrame(GL10 gl) {
mScene.draw(gl);
mScene.update();
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//ここにOpenGLの初期化処理を書いておく
}
}
■3
SceneクラスはView.OnTouchListenerを継承する
public class Scene implements View.OnTouchListener{
public void draw(GL10 gl) {
//ここにポリゴンの描画処理を書く
}
public void update() {
//ここに物体の移動処理などを書く
}
public boolean onTouch(View v, MotionEvent event) {
//ここにタッチ操作処理を書く
return false;
}
}
これをコピペしても動きません。すみません。
これで大体の流れをつかんで下さい。
2011年1月26日水曜日
Androidで音を鳴らす
resフォルダの中にrawフォルダを作って、その中に音声ファイルを保存。
そしてR.javaファイルにrawクラスとtest_bgm定数が自動で書き込まれるのを待つ。ここの自動的に書き込まれるっていう部分がまだよくわからないが、とにかくR.javaに自動的に書き込まれるようにする。自分で書き込むとビルドできなかったりした。
あとは簡単。
ViewとMediaPlayer.OnCompletionListenerを継承する。
コンストラクタの中で
super(context);
を書いておいて、後は音を鳴らしたいところでplaySound()を呼んでやる。stopSound()で音の終了。
mediaPlayer=MediaPlayer.create(getContext(),R.raw.test_bgm);javaファイルの中にこんな感じで音声ファイルを登録処理を書くが、eclipseはエラーを出しています。しかしそのまま保存。
そしてR.javaファイルにrawクラスとtest_bgm定数が自動で書き込まれるのを待つ。ここの自動的に書き込まれるっていう部分がまだよくわからないが、とにかくR.javaに自動的に書き込まれるようにする。自分で書き込むとビルドできなかったりした。
あとは簡単。
private MediaPlayer mediaPlayer; //プレーヤー
//サウンドの再生
public void playSound() {
try {
mediaPlayer=MediaPlayer.create(getContext(),R.raw.test_bgm3);
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(this);
} catch (Exception e) {
}
}
//サウンドの停止
public void stopSound() {
try {
mediaPlayer.stop();
mediaPlayer.setOnCompletionListener(null);
mediaPlayer.release();
mediaPlayer=null;
} catch (Exception e) {
}
}
@Override//サウンド再生終了時に呼ばれる
public void onCompletion(MediaPlayer arg0) {}
ViewとMediaPlayer.OnCompletionListenerを継承する。
コンストラクタの中で
super(context);
を書いておいて、後は音を鳴らしたいところでplaySound()を呼んでやる。stopSound()で音の終了。
2011年1月25日火曜日
Androidでキーリピート
アンドロイドでボタンを押しているあいだ(タッチしているあいだ)毎回呼ばれる処理を実装する話です。
ゲーム作るときには必須の処理だと思います。
onTouch(View v, MotionEvent me)の中でボタンが押されたら(DOWN)リピートフラグをtrueにする。ボタンが離されたら(UP)リピートフラグをfalseにする。
メインループであるonDrawFrame(GL10 gl)の中でキーリピートしているときにコールバックされるオブジェクトを登録する。
ゲーム作るときには必須の処理だと思います。
onTouch(View v, MotionEvent me)の中でボタンが押されたら(DOWN)リピートフラグをtrueにする。ボタンが離されたら(UP)リピートフラグをfalseにする。
メインループであるonDrawFrame(GL10 gl)の中でキーリピートしているときにコールバックされるオブジェクトを登録する。
private Runnable mLongPressAction = new Runnable() {
public void run() {//コールバックされる
//ここにキーリピートされたときの処理を書く
}
};
private boolean repeat = false;
public boolean onTouch(View v, MotionEvent me) {
if(me.getAction() == me.ACTION_DOWN) {
repeat = true;
}
if(me.getAction() == me.ACTION_UP) {
repeat = false;
}
return false;
}
private int LONG_PRESS_DELAY = 1;//ミリ秒
private Handler mHandler = new Handler();
public void onDrawFrame(GL10 gl) {//毎回呼ばれる
if(repeat)
{//キーリピートされているあいだは毎回コールバックされるオブジェクトを登録
mHandler.postDelayed(mLongPressAction, LONG_PRESS_DELAY);
}
}
2011年1月22日土曜日
2011年1月20日木曜日
Android 画面サイズ取得
yossi'sさんの記事で紹介されてましたが、画面サイズを取得するには
Activity継承クラスの場合
WindowManager windowmanager = (WindowManager)getSystemService(WINDOW_SERVICE);
Display disp = windowmanager.getDefaultDisplay();
int width = disp.getWidth();
int height = disp.getHeight();
というふうにします。
このサイズから好きな割合でボタンやテキストの大きさを作ると、どのAndroidでも統一したレイアウトが作れるんじゃないかと思います。
Activity継承クラスの場合
WindowManager windowmanager = (WindowManager)getSystemService(WINDOW_SERVICE);
Display disp = windowmanager.getDefaultDisplay();
int width = disp.getWidth();
int height = disp.getHeight();
というふうにします。
このサイズから好きな割合でボタンやテキストの大きさを作ると、どのAndroidでも統一したレイアウトが作れるんじゃないかと思います。
2011年1月18日火曜日
Android OpenGLES テクスチャ
Androidでテクスチャが表示できない状態になっちゃって、おっかしーなー、コード間違ってないような気がするのになー、と思っていたら.gif画像がダメだったみたいです。.jpgとか.pngの画像なら表示されました。
2011年1月17日月曜日
2011年1月14日金曜日
android-NDK-r5
cygwinをインストールした後、android-NDK-r5のサンプルをビルドしようとしました。
しかし、わからないところがあって色々調べたら解決したことがあったので書いておきます。
bashの.bashrcに、ndkのインストール場所の設定を以下のようにexportしました。
export ANDROID_NDK_ROOT=C:/android-ndk-r5
export PATH=$PATH:/cygdrive/c/minao/android-ndk-r5
そしてネットの記事http://monoist.atmarkit.co.jp/fembedded/articles/android/02/android02b.htmlを参考に、C-Nativeライブラリをコンパイルするための環境設定シェルスクリプト「host-setup.sh」をコマンドで実行しようとしました。
しかし「host-setup.sh」がC:/android-ndk-r5/build/のフォルダの中に無かったので、環境設定シェルスクリプトは後回しにしました。
続いて、サンプルとして提供されているC-Nativeライブラリ「hello-jni」を以下のコマンドでコンパイルしようとしました。
$ make APP=hello-jni
しかし、以下のようなエラーが出ました。
Android NDK: APP variable defined to unknown appllications: hell-jni
Android NDK: You might want to use one of the following:
build/core/main.mk:81: *** Android NDK: Aborting . Stop.
これは環境設定シェルスクリプト「host-setup.sh」を実行してないからいけないのかと思っていたのですが、そうではなくて、android-ndk-r3からandroid-ndk-r4になるときにmake APP=appnameとやっていたのが、Application.xml がある場所で ndk-build を実行する、 に変わってたようです。
そして、android-ndk-r4からandroid-ndk-r5になるときにApplication.xmlのなまえがAndroidManifest.xmlに変わったようです。
なので、cygwin を起動して、アプリの Application.xml があるところで、
ndk-build
をしてやるとビルドができました。
しかし、わからないところがあって色々調べたら解決したことがあったので書いておきます。
bashの.bashrcに、ndkのインストール場所の設定を以下のようにexportしました。
export ANDROID_NDK_ROOT=C:/android-ndk-r5
export PATH=$PATH:/cygdrive/c/minao/android-ndk-r5
そしてネットの記事http://monoist.atmarkit.co.jp/fembedded/articles/android/02/android02b.htmlを参考に、C-Nativeライブラリをコンパイルするための環境設定シェルスクリプト「host-setup.sh」をコマンドで実行しようとしました。
しかし「host-setup.sh」がC:/android-ndk-r5/build/のフォルダの中に無かったので、環境設定シェルスクリプトは後回しにしました。
続いて、サンプルとして提供されているC-Nativeライブラリ「hello-jni」を以下のコマンドでコンパイルしようとしました。
$ make APP=hello-jni
しかし、以下のようなエラーが出ました。
Android NDK: APP variable defined to unknown appllications: hell-jni
Android NDK: You might want to use one of the following:
build/core/main.mk:81: *** Android NDK: Aborting . Stop.
これは環境設定シェルスクリプト「host-setup.sh」を実行してないからいけないのかと思っていたのですが、そうではなくて、android-ndk-r3からandroid-ndk-r4になるときにmake APP=appnameとやっていたのが、Application.xml がある場所で ndk-build を実行する、 に変わってたようです。
そして、android-ndk-r4からandroid-ndk-r5になるときにApplication.xmlのなまえがAndroidManifest.xmlに変わったようです。
なので、cygwin を起動して、アプリの Application.xml があるところで、
ndk-build
をしてやるとビルドができました。
登録:
投稿 (Atom)