はじめに
Processingでゲームを作る場合、自分でいちから書く方法と、なんらかのライブラリを使う方法があります。宇宙空間を漂うシューティングゲームとかであれば、動きと衝突判定だけなので、自力でも楽ですが、アクションゲームとなると、衝突時の動きを計算するのがとてもに大変です。
なのでfisicaライブラリを使った場合、アクションゲームはどう書けばいいのか、というサンプルを示します。
環境
MacOS 13.4.1
Processing 4.2
Fisica
物理でうごかす
fisicaを使ってカーソルキーでキャラクタを動かそうとする場合、キャラクタの位置を直接操作するのではなくて、「力を加えて」、加速度->速度->位置、とfisicaの物理計算に合わせる必要があります。直接、位置を指定すると、予期せず、壁にめり込んだりすることが生じます。より具体的には、次の命令を使って操作します。(細かな違いはわかりませんでした)
addForce()
addImpulse()
サンプル
白い正方形をカーソルキーとスペースキーで操作して、のぼったりするサンプルです。
物理パラメータは、いい感じに調整済みです。
コード
気づき:
getMassはあるけど、setMassはなく、サイズで質量が決まる。質量を変えたいときはどうするのかというと、setDensityで濃度調整によって実現する。
キー入力は「key」と「keycode」の変数の中身は、最後に押された一つしか保持されないようで、カーソル移動しながらジャンプ(スペース)すると、カーソル移動ができなくなり、押し続けているのに、押されてない判定になってしまう。
なので、各キーに対し、boolean変数を用意して、keyPressedとkeyReleasedでtrue,falseを制御している。
import fisica.*;
FWorld world;
FBox me; //自分
boolean L_key, R_key;//キャラクタ左右操作用、trueのときは押されてる
void setup() {
size(1280, 720);//16:9(HD)
Fisica.init(this);
world = new FWorld();
world.setEdges();
// blockを作成(x,y,w,h)
addBlock( 400, 600, 200, 20);
addBlock( 700, 500, 200, 20);
addBlock(1000, 400, 200, 20);
addBlock( 800, 300, 100, 20);
addBlock( 600, 200, 50, 20);
//自分(x,y)
me = me(200, 500);
//重力
world.setGravity(0, 100);
}
void draw() {
background(255);
if(L_key){
me.addForce(-200, 0);
}
if(R_key){
me.addForce(200, 0);
}
//5回進めて、1回描画
world.step();
world.step();
world.step();
world.step();
world.step();
world.draw();
}
void keyPressed() {
//速度Yが0のときだけジャンプ
if ( key == ' ') {
if (me.getVelocityY()==0) {
me.addImpulse(0, -200); //me.addForce(0, -10000);
}
}
//左右移動準備
if (key == CODED) {
if (keyCode == LEFT) {
L_key = true;
}
if (keyCode == RIGHT) {
R_key = true;
}
}
}
void keyReleased(){
if (key == CODED) {
if (keyCode == LEFT) {
L_key = false;
}
if (keyCode == RIGHT) {
R_key = false;
}
}
}
void addBlock(int x, int y, int w, int h) {
FBox b = new FBox(w, h); //サイズ
b.setPosition(x, y); //位置
b.setFill(212, 72, 32); //色
b.setStatic(true); //固定
b.setFriction(0.2); //摩擦抵抗
b.setRestitution(0); //反発係数
b.setName("block"); //名前
world.add(b);
}
FBox me(int x, int y) {
FBox c = new FBox(40, 40); //サイズ
c.setDensity(0.25); //サイズが20x20のときdensity=1なので、40x40のときdensity=0.25にします。
c.setPosition(x, y); //位置
c.setFill(255, 255, 255); //色
c.setVelocity(0, 0); //速度
c.setDamping(0.3); //減衰(空気抵抗)
c.setFriction(0.2); //摩擦抵抗
c.setRestitution(0); //反発係数
c.setName("me"); //名前
c.setRotatable(false); //回転させない
world.add(c);
return(c);
}
画像を貼りたいとき
FBoxのattachImageメソッドを使います。
画像が伸びるのを避けるには、細かくブロックを分ける必要があります。
参考