今からはじめるプログラミング66(対戦ゲーム、その2)
昔のゲームウォッチでこんなゲームやりませんでしたっけ?
というゲームができました。
単純に、シューティングゲームの敵みたいに上から落ちてくるものを自分で受け止めます。
1。上からおちてくる何かの追加。
とけいのみにするために?いろいろ消したところにシューティングゲームのEnemyに関する記述をコピーする感じ。まずリストを追加する。
2。何かの挙動の追加。
ランダムに画面上部にオブジェクトを生成する。yの値を加算して、落ちる表現。画面下までいったら、けす。
3。上から落ちてくる何かとプレイヤーの交差するときの記述。
交差したら、プレイヤーのスコアを加算。何かを削除。
4。どちらかのプレーヤーのスコアが10点になったら、ゲーム終了。
という感じです。
ただし、1回クリアしたあと次のスタート時にスコアが初期かされず、すぐに勝った方が勝つという、バグが残ってます。
どこぞの小学校でクラスの男子全員がたなばたのお願いに
「ゲームウォッチがほしい」
とか書いたとか、書かなかったとか。。。
今からはじめるプログラミング65(対戦ゲーム)
いろいろ考えてみたのですが、方向キーを1P。WASDを2P用のキーに割り当てれば、
2P対戦ゲームができるのではないだろうか?
と思って、とりあえずキーで移動できるだけの画面にしてみた。
基本構造はシューティングゲームと同じです。
【Java】1時間半でシューティングゲームを作ろう!【ゆっくり解説】 - YouTube
デバッグできるようにデバッグ用の場所と以前つくった時計をしたのほうにおいやって?わかりやすくした(わからなくなってたらごめんなさい)
ソースと実行形式ファイルはいかです。
https://aki.teracloud.jp/share/11b17c871a51e4e8
小学校のころ、ノートと鉛筆という、あなろぐな方法で以下のゲームを遊んでいました。中学かもしれないけど。こどもってすごくないですか?
今からはじめるプログラミング64(シューティングその7)
ボスをつかしておわりとしたかったけど。
台風のおかげで暇だったので、画面下をゆみちゃんの庭みたいにして、
敵をむし軍団(はちっぽいらくがき)の画像にして。
ついでにボスを倒すとレーザーの威力が増す(あたり判定のはばがひろがる)ようにして。
という感じで、おもにタワーディフェンス要素を追加したら、ボスがただのボーナスアイテムのやうになってしまいましたw
でもかなりゲームみたいになったような気がしませんか?
解説が細かくなりそうなので、いきなり
ソースです。※実行形式ファイルをふくみます。(ymMuso.jar)とはいえ画像ファイルを同じフォルだにおかないと画像が表示されないです、ご注意。
あと、いろいろ要素を追加していくと、だんだんバランスをとるのが難しくなってきますねw
ゲームプログラミングの一番難しいところではないでしょうか。
こんな本を見つけましたw
懐かしいですね。
今からはじめるプログラミング63(シューティングその6)
メリハリがないので、ボス(みたいなもの)を追加しました。
まずはEnemyを継承したEnemyBを追加。とくに追加しなくてもできるといえばできます。
EnemyBのプログラム
--------------------------------
package sample20;
import java.util.Random;
public class EnemyB extends Enemy {
public int hp = 100;
public EnemyB(int x, int y)
{
super.x = x;
super.y = y;
}
public void move(int x, int y){
Random random = new Random();
int direction = random.nextInt(100);
if(direction<25){
this.moveVertical(y+3);
}else if(2<direction && direction<50){
this.moveVertical(-y);
}else if(5<direction && direction<75){
this.moveHorizontal(x);
}else{
this.moveHorizontal(-x);
}
}
}
--------------------------------
そして、Shootingのプログラムは。。。
1.80行目付近(変数がいっぱい並んでるところ)のボス用の変数をようい。
---------------------------------
EnemyB boss = null;
--------------------------------
2.125行目付近(時間を取得してレベルにインクリメントしているところ)でボスのインスタンスを生成、描画。elseを作って、ボスの移動も追加。listではないのでnullで判断しています。
--------------------------------
if (System.currentTimeMillis() - levelTimer > 10 * 1000) {
levelTimer = System.currentTimeMillis();
level++;
//BOSS?
boss = new EnemyB(50,50);
//boss write
gra.setColor(Color.BLACK);
gra.fillRect(boss.x, boss.y, 50, 50);
}else{
if(boss!=null){
boss.move(3, 3);
gra.setColor(Color.BLACK);
gra.fillRect(boss.x, boss.y, 50, 50);
}
}
--------------------------------
3.180行目付近(弾の挙動の中で)ボスの存在(not null)とあたり判定、スコアの追加など。
--------------------------------
if(boss!=null){
if(boss.hp>0){
if (bullet.x >= boss.x
&& bullet.x <= boss.x + 50
&& bullet.y >= boss.y
&& bullet.y <= boss.y + 50) {
boss.hp--;
}
}else{
gra.drawImage(bossBImage, boss.x, boss.y, 50, 50, null);
boss= null;
score+=1000;
}
}
--------------------------------
※ボスのHPが0以下になったら爆発の画像を表示しようとしていますが、一瞬?なので、わかりませんw
点数が増えたことで、確認してください。
ソースと実行形式ファイルです。⬇️
おもしろそうな本です。⬇️
今からはじめるプログラミング62(シューティング?その2)
時計の部分がわからない?
というコメントが多そうなので、
10秒ごとに画像をかえるという感じに変更してみました。
・・・以上。
プログラムならオリジナル時計作り放題。本物がいい人は以下より?
今からはじめるプログラミング61(シューティング?)
シューティングにもいろいろ飽きてきたので。
(わからないことにつかれた)
プログラムの構造がよくわからいので、
(シンプルに上から流れないと理解できない)
わかるようにシンプルに修正して、
(エラーのないように機能を削って)
みよう。
という感じで、時計に改造しましたw
(どうしてこうなった?)
とはいえ、いろいろまだ残っているのですが。
(なんとなくプログラムの構造が?見えた?)
100行以上のプログラムは年寄りにはつらいので、100行以下になったShootingクラスが以下です。(なお、修正はパッケージごとコピーをとっておこなっています。取り返しのつかない修正をしてしまう前に、バックアップを忘れずにw)
-------------------------------
package sample27;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.imageio.ImageIO;
/**
* @author user
* @modify histories
* to ke i
*/
public class Shooting {
public static ShootingFrame shootingFrame;
public static boolean loop;
public static void main(String[] args) {
shootingFrame = new ShootingFrame();
loop = true;
Graphics gra = shootingFrame.panel.image.getGraphics();
// FPS
long startTime;
long fpsTime = 0;
int fps = 30;
int FPS = 0;
int FPSCount = 0;
//時計用ふぉーまった
DateFormat dt = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
EnumShootingScreen screen = EnumShootingScreen.START;
BufferedImage image=null;
try {
image = ImageIO.read(new File("./ぺんぎん.png"));
} catch (IOException e1) {
// TODO 自動生成された catch ブロック
e1.printStackTrace();
}
//むげんるーぷ
while (loop) {
//FPSけいさん
if *1 {
screen = EnumShootingScreen.GAME;
}
break;
case GAME:
// mod start 2022/8/2 ma2
// Player描画
gra.setColor(Color.BLUE);
font = new Font("SansSerif", Font.PLAIN, 20);
metrics = gra.getFontMetrics(font);
//とけい表示用日付のオブジェクトをフォーマッタを通して文字列に。
String drawString =dt.format(new Date());;
gra.drawString(drawString, 150 - (metrics.stringWidth(drawString) / 2), 50);
//えを1秒ごとにかえる
gra.drawImage(image,200,200,200,200,null);
break;
}
gra.setColor(Color.BLACK);
gra.setFont(new Font("SansSerif", Font.PLAIN, 10));
gra.drawString(FPS + "FPS", 0, 470);
shootingFrame.panel.draw();
try {
long runTime = System.currentTimeMillis() - startTime;
if (runTime < (1000 / fps)) {
Thread.sleep*2;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
--------------------------------------
実行結果は以下です。
普通の時計(⬇️)は高いですが、プログラムならただです?
*1:System.currentTimeMillis() - fpsTime) >= 1000) {
fpsTime = System.currentTimeMillis();
FPS = FPSCount;
FPSCount = 0;
}
FPSCount++;
startTime = System.currentTimeMillis();
gra.setColor(Color.WHITE);
gra.fillRect(0, 0, 500, 500);
switch (screen) {
case START:
gra.setColor(Color.BLACK);
Font font = new Font("SansSerif", Font.PLAIN, 50);
gra.setFont(font);
FontMetrics metrics = gra.getFontMetrics(font);
gra.drawString("Shooting?", 250 - (metrics.stringWidth("Shooting?") / 2), 100);
font = new Font("SansSerif", Font.PLAIN, 20);
gra.setFont(font);
metrics = gra.getFontMetrics(font);
gra.drawString("Press SPACE to Start", 250 - (metrics.stringWidth("Press SPACE to Start") / 2), 160);
if (Keyboard.isKeyPressed(KeyEvent.VK_SPACE
今からはじめるプログラミング60(シューティングその5)
弾の飛び方を編集というよりは、弾の描画を細長い四角にして、
あたり判定の範囲を編集することでレーザーを表現したけれど。
もう少し数学的な形でゲームを演出できないか、とか考えたけど無理でしたw
ま、x(よこ)とy(たて)という座標で普通に2次方程式とか連想できるかな?とか思ったんですが。
ゲームてきには、レーザーの次は散弾ができた、というだけのこと?
とはいえ、意外と面倒だった。
考え方としては、
・弾にも方向という属性を追加する。
そうすれば、プログラム的に判断できるのでは?
というところ。
そう思って、Bulletクラスに変更を加えたところ・・・。
以下(⬇️)のような感じ。
-----------------------------------
package sample20;
/***
* たま
***/
public class Bullet {
public int x, y;
public int direction;
public Bullet() {}
public Bullet(int x, int y,int direction) {
this.x = x;
this.y = y;
this.direction = direction;
}
}
-----------------------------------
おっと、コンストラクタまでいじってしまった。
するとどうでしょう?当たり前ですが、関連するクラス(Shooting)にエラーがいっぱい。
という感じで、おかしな方法で修正箇所を洗い出しました。
(業務プログラムでこんな洗い出し方法はやらないので参考にしないでね?)
修正箇所をみてみると。
・敵の弾を生成しているところ。240行目付近と280行目付近。(すいません、修正のたびにコメントを追加しているので、ソースのリビジョンごとに行数がかわります。リビジョンて。)
・味方の弾を生成しているところ。390行付近のスペースキーのif文あたり。
とはいえ、オブジェクトの生成(コンストラクタの実行)の所だけなので、追加した方向について、xもしくはyを加算(減算)しないと弾の方向がかわらないので、上記の修正に加え、弾が移動している場所。
・310行付近の敵の弾のyに10を足してるところ。
・140行目付近の味方の弾のyから10を引いているところ。
以上ですかね。弾の動きを散弾っぽく見せるには、最後の味方の弾の動きについて、まっすぐに飛ぶ、右斜め上に飛ぶ、左斜め上に飛ぶ、の3つに分けます。
というわけで、
方向としては、
まっすぐ、右上、左上
をそれぞれ、1,0,2としました。
ちょっとおかしくなってしまってすいません。0:左上、1:まっすぐ、2:右上というふうに、画面上のイメージで値を設定していまいました。
・・・こういうのを防ぐ効果もEnumにはあるのですね。それはまた今度。
というわけで、とりあえず敵の弾を生成するところは、1のまっすぐのみでコンストラクタを修正し、味方の弾は、今まで1つだったところに行をコピーして3つ生成するようにしました。
---------------------------------------------------
Shootingクラスのスペースキーのif文のところ。
bullets_player.add(new Bullet(playerX + 12, playerY, 0));
bullets_player.add(new Bullet(playerX + 12, playerY, 1));
bullets_player.add(new Bullet(playerX + 12, playerY, 2));
---------------------------------------------------
そして、プレイヤーの弾の移動も以下のように
if (1 == bullet.direction) {
// 1==まっすぐ
bullet.y -= 10;
} else {
if (0 == bullet.direction) {
// 0==右上に
bullet.y -= 8;
bullet.x += 2;
} else {
// may be 2 == 左上に
bullet.y -= 8;
bullet.x -= 2;
}
}
---------------------------------------------------
という感じで、yから10を引いていただけのところに、方向によって、xにも加算したり、減算したりしました。とはいえ、業務プログラム的にはあまりよろしい修正ではないので、できたら理想のかたち?を考えて修正してみてください。
⬇️無料だと思ったら、kindleUnlimitedの契約がないと無料ではないそうです。