コンテンツにスキップ

逆走レースゲーム

img01.png

逆走して他の車に当たらないように距離を伸ばそう。 スピードをあげてハイスコアを目指そう。

作り方

Lv.0 基本の型

void setup(){
}
void draw(){
}

Lv.1 600x600の画面を作ろう

void setup(){
size(600, 600);
}
void draw(){
}

Lv.2 背景を緑色にしよう

void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
}

Lv.3 白色の道路を作ろう

void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
}

Lv.4 プレイヤーの車を作ろう

void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
// 追加
fill(0);
rect(300, 500, 50, 80);
}

でも変数にしておこう。

// 追加
float x = 300;
float y = 500;
void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
// 変更
// rect(300, 500, 50, 80);
rect(x, y, 50, 80);
}

Lv.5 左右の矢印キーで移動させよう

void keyPressed(){
if(keyCode == RIGHT){
x += 50;
}
if(keyCode == LEFT){
x -= 50;
}
}

Lv.6 道路からはみ出さないようにしよう

void keyPressed(){
if(keyCode == RIGHT){
x += 50;
}
if(keyCode == LEFT){
x -= 50;
}
if(x < 100){
x = 100;
}
if(x > 450){
x = 450;
}
}

Lv.10 敵の車を作ろう

void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
// 追加
fill(255, 0, 0);
rect(300, 0, 50, 80);
}

同じく変数にしておこう。

float x = 300;
float y = 500;
// 追加
float tekix = 300;
float tekiy = 0;
void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
fill(255, 0, 0);
// 変更
// rect(300, 0, 50, 80);
rect(tekix, tekiy, 50, 80);
}

Lv.11 敵を自動的に動かそう

void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
// 追加
tekiy += 1;
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
}

Lv.12 敵をもう一度出現させよう

void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
tekiy += 1;
// 追加
if(tekiy > 600){
tekiy = 0;
}
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
}

Lv.13 敵の再出現位置をランダムにしよう

void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
tekiy += 1;
if(tekiy > 600){
tekiy = 0;
// 追加
tekix = random(100, 450);
}
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
}

Lv.14 上下キーで敵のスピードを変化させよう

float x = 300;
float y = 500;
float tekix = 300;
float tekiy = 0;
// 追加
float speed = 1;
void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
// 変更
// tekiy += 1;
tekiy += speed;
if(tekiy > 600){
tekiy = 0;
tekix = random(100, 450);
}
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
}
void keyPressed(){
if(keyCode == RIGHT){
x += 50;
}
if(keyCode == LEFT){
x -= 50;
}
if(x < 100){
x = 100;
}
if(x > 450){
x = 450;
}
// 追加
if(keyCode == UP){
speed += 0.5;
}
if(keyCode == DOWN){
speed -= 0.5;
}
}

Lv.15 早すぎたり、speedがマイナスになるのを防ごう

void keyPressed(){
if(keyCode == RIGHT){
x += 50;
}
if(keyCode == LEFT){
x -= 50;
}
if(x < 100){
x = 100;
}
if(x > 450){
x = 450;
}
if(keyCode == UP){
speed += 0.5;
}
if(keyCode == DOWN){
speed -= 0.5;
}
// 追加
if(speed > 50){
speed = 50;
}
if(speed < 1){
speed = 1;
}
}

Lv.20 敵と衝突したらスピードを0にしよう

考え方。 以下の4つの条件が全てそろったとき、衝突している。

1) プレイヤーの左端が、敵の右端より小さい
2) プレイヤーの右端が、敵の左端より大きい
3) プレイヤーの上端が、敵の下端より小さい
4) プレイヤーの下端が、敵の上端より大きい

プログラム的に考えると、、、

1) プレイヤーの左端(x)が、敵の右端(tekix + 50)より小さい
2) プレイヤーの右端(x + 50)が、敵の左端(tekix)より大きい
3) プレイヤーの上端(y)が、敵の下端(tekiy + 80)より小さい
4) プレイヤーの下端(y + 80)が、敵の上端(tekiy)より大きい
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
tekiy += speed;
if(tekiy > 600){
tekiy = 0;
tekix = random(100, 450);
}
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
// 追加
if(x < tekix + 50 && x + 50 > tekix && y < tekiy + 80 && y + 80 > tekiy){
speed = 0;
}
}

Lv.30 スコアを表示しよう

float x = 300;
float y = 500;
float tekix = 300;
float tekiy = 0;
float speed = 1;
// 追加
int score = 0;
void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
tekiy += speed;
if(tekiy > 600){
tekiy = 0;
tekix = random(100, 450);
}
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
if(x < tekix + 50 && x + 50 > tekix && y < tekiy + 80 && y + 80 > tekiy){
speed = 0;
}
// 追加
score += speed;
fill(255, 0, 0);
text("SCORE: " + score, 50, 50);
}

Lv.31 時間制限をつけよう

float x = 300;
float y = 500;
float tekix = 300;
float tekiy = 0;
float speed = 1;
int score = 0;
// 追加。約60で1秒。600で10秒。
int time = 600;
void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
tekiy += speed;
if(tekiy > 600){
tekiy = 0;
tekix = random(100, 450);
}
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
if(x < tekix + 50 && x + 50 > tekix && y < tekiy + 80 && y + 80 > tekiy){
speed = 0;
}
score += speed;
fill(255, 0, 0);
text("SCORE: " + score, 50, 50);
// 追加
time -= 1;
if(time <= 0){
time = 0;
}
fill(255, 0, 0);
text("TIME: " + time, 50, 100);
}

Lv.32 制限時間になったらスピードを0にし、操作できないようにしよう

float x = 300;
float y = 500;
float tekix = 300;
float tekiy = 0;
float speed = 1;
int score = 0;
int time = 600;
void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
tekiy += speed;
if(tekiy > 600){
tekiy = 0;
tekix = random(100, 450);
}
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
if(x < tekix + 50 && x + 50 > tekix && y < tekiy + 80 && y + 80 > tekiy){
speed = 0;
}
score += speed;
fill(255, 0, 0);
text("SCORE: " + score, 50, 50);
time -= 1;
if(time <= 0){
time = 0;
// 追加
speed = 0;
}
fill(255, 0, 0);
text("TIME: " + time, 50, 100);
}
void keyPressed(){
// 追加
if(time <= 0){
return;
}
if(keyCode == RIGHT){
x += 50;
}
if(keyCode == LEFT){
x -= 50;
}
if(x < 100){
x = 100;
}
if(x > 450){
x = 450;
}
if(keyCode == UP){
speed += 0.5;
}
if(keyCode == DOWN){
speed -= 0.5;
}
if(speed > 50){
speed = 50;
}
if(speed < 1){
speed = 1;
}
}

Lv.40 車のデザインをカスタマイズしよう

float x = 300;
float y = 500;
float tekix = 300;
float tekiy = 0;
float speed = 1;
int score = 0;
int time = 600;
void setup(){
size(600, 600);
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
rect(100, 0, 400, 600);
fill(0);
rect(x, y, 50, 80);
// プレイヤー機のデザイン
fill(0);
rect(x, y, 50, 80);
rect(x-5, y+20, 5, 5);
rect(x+50, y+20, 5, 5);
fill(255);
rect(x + 5, y + 20, 40, 20);
rect(x + 5, y + 60, 40, 10);
tekiy += speed;
if(tekiy > 600){
tekiy = 0;
tekix = random(100, 450);
}
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
// 敵機のデザイン
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
rect(tekix-5, tekiy+55, 5, 5);
rect(tekix+50, tekiy+55, 5, 5);
fill(255);
rect(tekix + 5, tekiy + 40, 40, 20);
rect(tekix + 5, tekiy + 10, 40, 10);
if(x < tekix + 50 && x + 50 > tekix && y < tekiy + 80 && y + 80 > tekiy){
speed = 0;
}
score += speed;
fill(255, 0, 0);
text("SCORE: " + score, 50, 50);
time -= 1;
if(time <= 0){
time = 0;
speed = 0;
}
fill(255, 0, 0);
text("TIME: " + time, 50, 100);
}
void keyPressed(){
if(time <= 0){
return;
}
if(keyCode == RIGHT){
x += 50;
}
if(keyCode == LEFT){
x -= 50;
}
if(x < 100){
x = 100;
}
if(x > 450){
x = 450;
}
if(keyCode == UP){
speed += 0.5;
}
if(keyCode == DOWN){
speed -= 0.5;
}
if(speed > 50){
speed = 50;
}
if(speed < 1){
speed = 1;
}
}

Lv.99

BGMだとか背景だとかリスタート機能だとか、もう好きに改造しまくろう。

ゲームアイディアヒント集

・加速しておかないと徐々に減速してしまう。操作性の難易度アップ。
・アイテムを取ると急加速プラス一定時間無敵。爽快感のアップ。
・いかに短時間で目標スピードに達するか、というゲームの目的変更。
・スコアアップにつながるコイン。車を避けるのに専念するか、コインを取りに行くか選択肢の広がり。

その他

  • 制限時間やスコア、スピードがわかりやすく画面配置。
  • 道路上の表現をアップ。
  • 当たり判定を緩くして、ギリギリでかわす気持ち良さをプラス。
  • スムーズな横移動。

img02.png

int SECONDS = 60;
float x = 300;
float y = 500;
float toX = x;
float tekix = 300;
float tekiy = 0;
float speed = 1;
float maxSpeed = 0;
int score = 0;
int time = 60 * SECONDS;
float liney = 0;
int starCount = 200;
PVector[] stars = new PVector[starCount];
void setup(){
size(600, 600);
reset();
for(int i=0; i<starCount; i++){
stars[i] = new PVector(random(0, 600), random(0, 600));
}
}
void draw(){
background(0, 255, 0);
noStroke();
fill(255);
for(int i=0; i<starCount; i++){
stars[i].y += speed;
if(stars[i].y > 600) stars[i].y = -10;
rect(stars[i].x, stars[i].y, 8, 1);
}
fill(200);
rect(100, 0, 400, 600);
liney += speed;
if(liney > 600){
liney = 0;
}
for(int i=0; i<2; i++){
for(int j=-6; j<6; j++){
float _linex = 80;
if(i == 1) _linex = 500;
float _liney = liney + (j * 100);
color c = color(255, 0, 0);
if(j % 2 != 0) c = color(255);
fill(c);
rect(_linex, _liney, 20, 100);
}
}
fill(255);
for(int i=0; i<3; i++){
for(int j=-6; j<6; j++){
if(j % 2 == 0) continue;
float _linex = i * 100 + 200 - 5;
float _liney = liney + (j * 100);
rect(_linex, _liney, 5, 120);
}
}
float attachX = (toX - x) * 0.3;
if(abs(attachX) < 0.1){
x = toX;
}else{
x += attachX;
}
// プレイヤー機のデザイン
fill(0);
rect(x, y, 50, 80);
rect(x-5, y+20, 5, 5);
rect(x+50, y+20, 5, 5);
fill(255);
rect(x + 5, y + 20, 40, 20);
rect(x + 5, y + 60, 40, 10);
tekiy += speed * 1.1;
if(tekiy > 600){
tekiy = -80;
tekix = (int)random(0, 8) * 50 + 100;
}
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
// 敵機のデザイン
fill(255, 0, 0);
rect(tekix, tekiy, 50, 80);
rect(tekix-5, tekiy+55, 5, 5);
rect(tekix+50, tekiy+55, 5, 5);
fill(255);
rect(tekix + 5, tekiy + 40, 40, 20);
rect(tekix + 5, tekiy + 10, 40, 10);
if(x < tekix + 50 - 25 && x + 50 - 25 > tekix && y < tekiy + 80 - 40 && y + 80 - 40 > tekiy){
speed = 0;
}
if(speed > maxSpeed){
maxSpeed = speed;
}
fill(0);
textSize(40);
textAlign(RIGHT);
text(speed * 5 + "km", 590, 580);
fill(255, 0, 0);
textSize(10);
text("HIGH: " + maxSpeed * 5 + "km", 590, 540);
time -= 1;
if(time <= 0){
time = 0;
speed = 0;
}
fill(255);
ellipse(30, 50, 50, 50);
fill(0);
textAlign(CENTER);
textSize(16);
text("TIME", 30, 30);
fill(255, 0, 0);
textAlign(CENTER);
textSize(32);
text(time / 60, 30, 60);
score += speed;
fill(0, 0, 255);
textSize(16);
textAlign(RIGHT);
text("SCORE: " + nfc(score), 590, 30);
if(time <= 0){
fill(0, 0, 0, 100);
rect(0, 0, 600, 600);
fill(255);
textAlign(CENTER);
textSize(120);
text("SCORE\n" + nfc(score), 300, 250);
textSize(20);
text("Push Enter Key to Retry", 300, 550);
}
}
void keyPressed(){
if(time <= 0){
if(keyCode == ENTER){
reset();
}
return;
}
if(keyCode == RIGHT){
toX += 50;
}
if(keyCode == LEFT){
toX -= 50;
}
if(toX < 100){
toX = 100;
}
if(toX > 450){
toX = 450;
}
if(keyCode == UP){
speed += 0.5;
}
if(keyCode == DOWN){
speed -= 1;
}
if(speed > 50){
speed = 50;
}
if(speed < 1){
speed = 1;
}
}
void reset(){
x = 300;
y = 500;
toX = x;
tekix = 300;
tekiy = 0;
speed = 1;
maxSpeed = 0;
score = 0;
time = 60 * SECONDS;
}