とりあえずサンプルをKotlinに変換する

westplain.sakuraweb.com

のソースをそのまま使ってしまいましょう。実行画面はこんな感じです。

f:id:turanukimaru:20170915231347p:plain

さてこのサンプルは当然ながらJavaなのでKotlinに変換する必要があります。

とはいっても、対象のファイルを選択してからメニュー>Code>convert Java File to Kotlin Fileを選択するだけです。

 

f:id:turanukimaru:20170915231703p:plain

無事Kotlinに変換されました。ソースは最下段。

 

とはいえ、このサンプルはそのまま使えません。FEHのコピーを作るには盤面の駒を操作しなければならず、タッチしたところにキャラを表示するだけのこのコードはほとんど役に立たないからです。

 if (Gdx.input.isTouched) {
val touchPos = Vector3()
touchPos.set(Gdx.input.x.toFloat(), Gdx.input.y.toFloat(), 0f) //タッチしたところの取得
camera!!.unproject(touchPos) // タッチしたところをLibGDX座標系(上下逆)に変換
bucket!!.x = touchPos.x - 64 / 2 //Imageの座標を変更する。
}

これがシューティングだったら雨の代わりに敵を表示して、バケツを自機にして弾が出るようにすればそれでいいのですが。

 

そこでActorを使います。

Actorとは文字通り俳優です。

Actorを使うことで、

「男優さん右に移動して」とか「男優さんと女優さんは同じ動きをして」とか「1秒右に移動してから一回転して」とか指示を出すように操作することができます。駒を動かすには駒がタッチされたとかドラッグされてどこに置かれたか、とかの判定が必要になりますが、これもActorに対してEventListenerを追加するだけでよくなります。というわけで次回はきっとActorの話です。

 

package com.mygdx.game

import ..
class MyGdxGame : ApplicationAdapter() {
private var dropImage: Texture? = null
private var bucketImage: Texture? = null
// private Sound dropSound;
// private Music rainMusic;
private var batch: SpriteBatch? = null
private var camera: OrthographicCamera? = null
private var bucket: Rectangle? = null
private var raindrops: Array<Rectangle>? = null
private var lastDropTime: Long = 0

override fun create() {
// load the images for the droplet and the bucket, 64x64 pixels each
dropImage = Texture(Gdx.files.internal("droplet.png"))
bucketImage = Texture(Gdx.files.internal("bucket.png"))

// load the drop sound effect and the rain background "music"
// dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
// rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));

// start the playback of the background music immediately
// rainMusic.setLooping(true);
// rainMusic.play();

// create the camera and the SpriteBatch
camera = OrthographicCamera()
camera!!.setToOrtho(false, 800f, 480f)
batch = SpriteBatch()

// create a Rectangle to logically represent the bucket
bucket = Rectangle()
bucket!!.x = (800 / 2 - 64 / 2).toFloat() // center the bucket horizontally
bucket!!.y = 20f // bottom left corner of the bucket is 20 pixels above the bottom screen edge
bucket!!.width = 64f
bucket!!.height = 64f

// create the raindrops array and spawn the first raindrop
raindrops = Array()
spawnRaindrop()
}

private fun spawnRaindrop() {
val raindrop = Rectangle()
raindrop.x = MathUtils.random(0, 800 - 64).toFloat()
raindrop.y = 480f
raindrop.width = 64f
raindrop.height = 64f
raindrops!!.add(raindrop)
lastDropTime = TimeUtils.nanoTime()
}

override fun render() {
// clear the screen with a dark blue color. The
// arguments to glClearColor are the red, green
// blue and alpha component in the range [0,1]
// of the color to be used to clear the screen.
Gdx.gl.glClearColor(0f, 0f, 0.2f, 1f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)

// tell the camera to update its matrices.
camera!!.update()

// tell the SpriteBatch to render in the
// coordinate system specified by the camera.
batch!!.projectionMatrix = camera!!.combined

// begin a new batch and draw the bucket and
// all drops
batch!!.begin()
batch!!.draw(bucketImage!!, bucket!!.x, bucket!!.y)
for (raindrop in raindrops!!) {
batch!!.draw(dropImage!!, raindrop.x, raindrop.y)
}
batch!!.end()

// process user input
if (Gdx.input.isTouched) {
val touchPos = Vector3()
touchPos.set(Gdx.input.x.toFloat(), Gdx.input.y.toFloat(), 0f)
camera!!.unproject(touchPos)
bucket!!.x = touchPos.x - 64 / 2
}
if (Gdx.input.isKeyPressed(Keys.LEFT)) bucket!!.x -= 200 * Gdx.graphics.deltaTime
if (Gdx.input.isKeyPressed(Keys.RIGHT)) bucket!!.x += 200 * Gdx.graphics.deltaTime

// make sure the bucket stays within the screen bounds
if (bucket!!.x < 0) bucket!!.x = 0f
if (bucket!!.x > 800 - 64) bucket!!.x = (800 - 64).toFloat()

// check if we need to create a new raindrop
if (TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRaindrop()

// move the raindrops, remove any that are beneath the bottom edge of
// the screen or that hit the bucket. In the later case we play back
// a sound effect as well.
val iter = raindrops!!.iterator()
while (iter.hasNext()) {
val raindrop = iter.next()
raindrop.y -= 200 * Gdx.graphics.deltaTime
if (raindrop.y + 64 < 0) iter.remove()
if (raindrop.overlaps(bucket!!)) {
// dropSound.play();
iter.remove()
}
}
}

override fun dispose() {
// dispose of all the native resources
dropImage!!.dispose()
bucketImage!!.dispose()
// dropSound.dispose();
// rainMusic.dispose();
batch!!.dispose()
}
}

 

一応Javaのソース

package com.mygdx.game;
import ..
public class MyGdxGame extends ApplicationAdapter {
private Texture dropImage;
private Texture bucketImage;
// private Sound dropSound;
// private Music rainMusic;
private SpriteBatch batch;
private OrthographicCamera camera;
private Rectangle bucket;
private Array<Rectangle> raindrops;
private long lastDropTime;

@Override
public void create() {
// load the images for the droplet and the bucket, 64x64 pixels each
dropImage = new Texture(Gdx.files.internal("droplet.png"));
bucketImage = new Texture(Gdx.files.internal("bucket.png"));

// load the drop sound effect and the rain background "music"
// dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
// rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));

// start the playback of the background music immediately
// rainMusic.setLooping(true);
// rainMusic.play();

// create the camera and the SpriteBatch
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
batch = new SpriteBatch();

// create a Rectangle to logically represent the bucket
bucket = new Rectangle();
bucket.x = 800 / 2 - 64 / 2; // center the bucket horizontally
bucket.y = 20; // bottom left corner of the bucket is 20 pixels above the bottom screen edge
bucket.width = 64;
bucket.height = 64;

// create the raindrops array and spawn the first raindrop
raindrops = new Array<Rectangle>();
spawnRaindrop();
}

private void spawnRaindrop() {
Rectangle raindrop = new Rectangle();
raindrop.x = MathUtils.random(0, 800-64);
raindrop.y = 480;
raindrop.width = 64;
raindrop.height = 64;
raindrops.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}

@Override
public void render() {
// clear the screen with a dark blue color. The
// arguments to glClearColor are the red, green
// blue and alpha component in the range [0,1]
// of the color to be used to clear the screen.
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

// tell the camera to update its matrices.
camera.update();

// tell the SpriteBatch to render in the
// coordinate system specified by the camera.
batch.setProjectionMatrix(camera.combined);

// begin a new batch and draw the bucket and
// all drops
batch.begin();
batch.draw(bucketImage, bucket.x, bucket.y);
for(Rectangle raindrop: raindrops) {
batch.draw(dropImage, raindrop.x, raindrop.y);
}
batch.end();

// process user input
if(Gdx.input.isTouched()) {
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
bucket.x = touchPos.x - 64 / 2;
}
if(Gdx.input.isKeyPressed(Keys.LEFT)) bucket.x -= 200 * Gdx.graphics.getDeltaTime();
if(Gdx.input.isKeyPressed(Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime();

// make sure the bucket stays within the screen bounds
if(bucket.x < 0) bucket.x = 0;
if(bucket.x > 800 - 64) bucket.x = 800 - 64;

// check if we need to create a new raindrop
if(TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRaindrop();

// move the raindrops, remove any that are beneath the bottom edge of
// the screen or that hit the bucket. In the later case we play back
// a sound effect as well.
Iterator<Rectangle> iter = raindrops.iterator();
while(iter.hasNext()) {
Rectangle raindrop = iter.next();
raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
if(raindrop.y + 64 < 0) iter.remove();
if(raindrop.overlaps(bucket)) {
// dropSound.play();
iter.remove();
}
}
}

@Override
public void dispose() {
// dispose of all the native resources
dropImage.dispose();
bucketImage.dispose();
// dropSound.dispose();
// rainMusic.dispose();
batch.dispose();
}
}