今からはじめるプログラミング59(シューティングその4)
レーザーを追加したけど、なんかこう、爽快感がないですね。
本当はあたり判定とかとかも細かくいじるといいと重いますが、
難しいことは解析能力が不足していて、考えるだけでパンクするので、
とりあえず敵の種類を追加したいと思います。
下にむかってくる敵しかいないので、縦幅の長いレーザーの利点がいかせていない?気がしました。というか、本来は味方の移動に追従するようにレーザーを改造すれば、画面を掃除するような感覚が味わえるのでは?と思ったのですが、さらに難しそうなので、横に移動する敵がいれば、縦の攻撃での判定が大きくなる、という考えのもと、改造することにしました。
とはいえ、Enemyを継承してEnemyH(holizontal)というクラスを新規作成して、ちょっとjavaのオブジェクト指向(というほどのことはない)プログラミングしています。
・・・コンストラクタて継承できないんでしたっけ?(忘れました)
というわけで、今回は2つクラスを追加修正。
EnemyHクラス
-------------------------------------------
package sample20;
public class EnemyH extends Enemy {
public EnemyH(int x, int y)
{
this.x = x;
this.y = y;
}
}
-------------------------------------------
ま、こんなもんです。
そしてShootingクラスはコメントでどこをどうしたというのを記載しました。
Shootingクラス
-------------------------------------------
package sample20;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.util.Random;
/**
* @author user
* @modify histories 2022/7/30 レーザー風に 2022/7/31 横に動く敵の追加
*/
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;
EnumShootingScreen screen = EnumShootingScreen.START;
// GAME
int playerX = 0, playerY = 0;
int bulletInterval = 0;
int score = 0;
int level = 0;
long levelTimer = 0;
int playerHp = 0;// プレイヤーのHPをついか
ArrayList<Bullet> bullets_player = new ArrayList<>();
ArrayList<Bullet> bullets_enemy = new ArrayList<>();
ArrayList<Enemy> enemies = new ArrayList<>();
// add start 2022/7/31 1 ma2
// 横に移動する敵の追加
ArrayList<EnemyH> enemiesH = new ArrayList<>();
// add end 2022/7/31 1
ArrayList<Ally> allies = new ArrayList<>();
Random random = new Random();
while (loop) {
if *1 {
screen = EnumShootingScreen.GAME;
bullets_player = new ArrayList<>();
bullets_enemy = new ArrayList<>();
enemies = new ArrayList<>();
allies = new ArrayList<>();
playerX = 235;
playerY = 430;
score = 0;
level = 0;
// スタート時のHP値
playerHp = 5;
}
break;
case GAME:
if (System.currentTimeMillis() - levelTimer > 10 * 1000) {
levelTimer = System.currentTimeMillis();
level++;
}
// Player描画
gra.setColor(Color.BLUE);
gra.fillRect(playerX + 10, playerY, 10, 10);
gra.fillRect(playerX, playerY + 10, 30, 10);
// 玉の削除
for (int i = 0; i < bullets_player.size(); i++) {
Bullet bullet = bullets_player.get(i);
// mod start 2022/7/30 1 ma2
// たなのびょうが レーザー風雨に
// gra.fillRect(bullet.x, bullet.y, 5, 5);
gra.fillRect(bullet.x, bullet.y, 4, 20);
// mod end 2022/7/30 1
bullet.y -= 10;
if (bullet.y < 0) {
bullets_player.remove(i);
i--;
}
// 敵の削除=得点追加
for (int l = 0; l < enemies.size(); l++) {
Enemy enemy = enemies.get(l);
// mod start 2022/7/30 2 ma2
// あたり判定 レーザーのあたり判定が爽快感がないので
// if (bullet.x >= enemy.x && bullet.x <= enemy.x + 30
// && bullet.y >= enemy.y
// && bullet.y <= enemy.y + 20) {
if (bullet.x >= enemy.x && bullet.x <= enemy.x + 30 && bullet.y >= enemy.y
&& bullet.y <= enemy.y + 50) {
// mod end 2022/7/30 2
// 敵を削除
enemies.remove(l);
// 点数加算
score += 10;
}
}
// add start 2022/7/31 2 ma2
for (int l = 0; l < enemiesH.size(); l++) {
EnemyH enemyH = enemiesH.get(l);
// あたり判定 TODO
if (bullet.x >= enemyH.x && bullet.x <= enemyH.x + 30 && bullet.y >= enemyH.y
&& bullet.y <= enemyH.y + 30) {
// 敵を削除
enemiesH.remove(l);
// 点数加算
score += 10;
}
}
// add end 2022/7/31 2
// 味方の削除=HP追加
for (int j = 0; j < allies.size(); j++) {
Ally ally = allies.get(j);
// 玉と味方の判定
if (bullet.x >= ally.x && bullet.x <= ally.x + 10 && bullet.y >= ally.y
&& bullet.y <= ally.y + 10) {
allies.remove(j);
if (playerHp < 10) {
playerHp += 1;
}
}
}
}
// てき
gra.setColor(Color.RED);
for (int i = 0; i < enemies.size(); i++) {
Enemy enemy = enemies.get(i);
gra.fillRect(enemy.x, enemy.y, 30, 10);
gra.fillRect(enemy.x + 10, enemy.y + 10, 10, 10);
enemy.y += 3;
if (enemy.y > 500) {
enemies.remove(i);
i--;
}
if (random.nextInt(level < 50 ? 80 - level : 30) == 1)
bullets_enemy.add(new Bullet(enemy.x + 12, enemy.y));
if *2 {
// 敵と自分が命中
playerHp--;
if (playerHp <= 0) {
screen = EnumShootingScreen.GAME_OVER;
score += (level - 1) * 100;
} else {
// ぶつかった敵はけす
enemies.remove(i);
}
}
}
if (random.nextInt(level < 10 ? 30 - level : 10) == 1)
enemies.add(new Enemy(random.nextInt(470), 0));
// add S 2022/7/31 3 ma2
for (int i = 0; i < enemiesH.size(); i++) {
EnemyH enemyH = enemiesH.get(i);
gra.fillRect(enemyH.x, enemyH.y, 30, 10);
gra.fillOval(enemyH.x + 10, enemyH.y + 10, 10, 10);
enemyH.y += 2;// 下に移動するのは少し遅く
enemyH.x += 3;// 横に移動を追加(とりあえずみぎのみ)
if (enemyH.y > 500) {
enemiesH.remove(i);
i--;
}
if (random.nextInt(level < 50 ? 80 - level : 30) == 1)
bullets_enemy.add(new Bullet(enemyH.x + 12, enemyH.y));
if *3 {
// 敵と自分が命中
playerHp--;
if (playerHp <= 0) {
screen = EnumShootingScreen.GAME_OVER;
score += (level - 1) * 100;
} else {
// ぶつかった敵はけす
enemiesH.remove(i);
}
}
}
// 敵の生成
if (random.nextInt(level < 10 ? 30 - level : 10) == 1)
enemiesH.add(new EnemyH(random.nextInt(470), 0));
// add E 2022/7/31 3 ma2
// てきのたまのうごき
for (int i = 0; i < bullets_enemy.size(); i++) {
Bullet bullet = bullets_enemy.get(i);
gra.fillRect(bullet.x, bullet.y, 5, 5);
bullet.y += 10;
if (bullet.y > 500) {
bullets_enemy.remove(i);
i--;
}
if (bullet.x >= playerX && bullet.x <= playerX + 30 && bullet.y >= playerY
&& bullet.y <= playerY + 20) {
// 敵の玉と自分が命中
playerHp--;
if (playerHp <= 0) {
screen = EnumShootingScreen.GAME_OVER;
score += (level - 1) * 100;
} else {
// ぶつかったたまはけす
bullets_enemy.remove(i);
}
}
}
// 味方の動き
gra.setColor(Color.GREEN);
for (int i = 0; i < allies.size(); i++) {
Ally ally = allies.get(i);
gra.fillOval(ally.x, ally.y, 10, 10);
ally.y += 3;
if (ally.y > 500) {
allies.remove(i);
i--;
}
if *4 {
// みかたと自分が命中
if (playerHp < 10) {
playerHp += 1;
}
allies.remove(i);
i--;
}
}
// 味方の出現
if (random.nextInt(level < 10 ? 30 - level : 10) == 1)
allies.add(new Ally(random.nextInt(470), 0));
// キーボードの判定
if (Keyboard.isKeyPressed(KeyEvent.VK_LEFT) && playerX > 0)
playerX -= 8;
if (Keyboard.isKeyPressed(KeyEvent.VK_RIGHT) && playerX < 470)
playerX += 8;
if (Keyboard.isKeyPressed(KeyEvent.VK_UP) && playerY > 30)
playerY -= 8;
if (Keyboard.isKeyPressed(KeyEvent.VK_DOWN) && playerY < 450)
playerY += 8;
if (Keyboard.isKeyPressed(KeyEvent.VK_SPACE) && bulletInterval == 0) {
bullets_player.add(new Bullet(playerX + 12, playerY));
bulletInterval = 8;
}
if (bulletInterval > 0)
bulletInterval--;
gra.setColor(Color.BLACK);
font = new Font("SansSerif", Font.PLAIN, 20);
metrics = gra.getFontMetrics(font);
gra.setFont(font);
gra.drawString("SCORE:" + score, 470 - metrics.stringWidth("SCORE:" + score), 430);
gra.drawString("LEVEL:" + level, 470 - metrics.stringWidth("LEVEL:" + level), 450);
gra.drawString("HP:" + playerHp, 470 - metrics.stringWidth("HP:" + playerHp), 470);
break;
case GAME_OVER:
gra.setColor(Color.BLACK);
font = new Font("SansSerif", Font.PLAIN, 50);
gra.setFont(font);
metrics = gra.getFontMetrics(font);
gra.drawString("Game Over", 250 - (metrics.stringWidth("Game Over") / 2), 100);
font = new Font("SansSerif", Font.PLAIN, 20);
gra.setFont(font);
metrics = gra.getFontMetrics(font);
gra.drawString("Score:" + score, 250 - (metrics.stringWidth("Score:" + score) / 2), 150);
gra.drawString("Press ESC to Return Start Screen",
250 - (metrics.stringWidth("Press ESC to Return Start Screen") / 2), 200);
if (Keyboard.isKeyPressed(KeyEvent.VK_ESCAPE)) {
screen = EnumShootingScreen.START;
}
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*5;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
-------------------------------------------
今までの修正と違う修正のしかたするから、統一感が。。。ねぇ?
とても昔の修正履歴の残し方なので、現在ではGitなどではコミットコメントとして記述するのが正しいかな?
アマゾンでパロディウス検索したらいろいろ出てきた。
よろしくです。
遊んでるところ、だいぶ遊べてる?(頭が丸い敵がよこ・・・みぎしたにいどうしている。。。わかるか!って感じですいません。)
*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
*2:enemy.x >= playerX && enemy.x <= playerX + 30 && enemy.y >= playerY && enemy.y <= playerY + 20)
|| (enemy.x + 30 >= playerX && enemy.x + 30 <= playerX + 30 && enemy.y + 20 >= playerY
&& enemy.y + 20 <= playerY + 20
*3:enemyH.x >= playerX && enemyH.x <= playerX + 30 && enemyH.y >= playerY
&& enemyH.y <= playerY + 20)
|| (enemyH.x + 30 >= playerX && enemyH.x + 30 <= playerX + 30 && enemyH.y + 20 >= playerY
&& enemyH.y + 20 <= playerY + 20
*4:ally.x >= playerX && ally.x <= playerX + 10 && ally.y >= playerY && ally.y <= playerY + 10