質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

1938閲覧

Java 画像の分割、透過ができない

java_beginner1

総合スコア4

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2021/09/06 09:11

Javaでシューティングゲームをつくっている者です。自機に敵の弾が触れると爆発するエフェクトを付けたいのですが分割、透過ができません。
これが重ねたい画像です↓

爆発
自機

分割、透過するにはどのようにすればよいでしょうか?回答のほどよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2021/09/06 10:03

現状が再現できるコードや設定、環境情報がないと何とも。
jimbe

2021/09/06 13:27

透過は、png 画像なのですからあらかじめ透過色で塗っておくことが出来ると思います。 分割は、画像の描画を Graphics.drawImage で行っているのでしたら、オーバーロードされたメソッドの中に、元画像の一部を書き込むものがありますので、それを使えば同じことになるかと思います。
java_beginner1

2021/09/10 11:00

ごめんなさい。学校が忙しく、返信できませんでした。コードを載せていないのはその必要がないと判断したからです。以後気を付けます。 jimbeさんへ プログラミング初心者なのでpng画像にそんな機能がもう備わっていたとは知らなかったです。アドバイスして頂きありがとうございます。 jimbeさんがおっしゃっているのはdrawImage(Image img,int x,int y,int width,int height,ImageObserver observer)のことであっていますでしょうか?
jimbe

2021/09/10 13:11

忙しいことを責める方はいらっしゃらないと思います^^ 忙しいのか放置なのかが分からないのでどうしたものか…という場合はありますが。 > ~ であっていますでしょうか ドキュメントを読む練習と思って、各メソッドの説明をよく読んでみてください。翻訳されていても結局カタカナばかりでよく分からないことも多くあるとは思いますが、そのキーワードをさらに検索する等を行っていくことで、少なくとも解決の糸口を探すスキル(?)の足しにはなるのではないでしょうか。 手掛かりとすれば、パラメータとして書き込むべきイメージ、書き込む先の位置等の情報の他に、書き込む元を示すための位置等の情報が増えるはずです。
java_beginner1

2021/09/11 07:30

m.ts10806さんへ そうですね。今回は解決できそうなので次回から気を付けます。 jimbeさんへ drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer)ですね!Javaって専門用語多くてデスティネーション矩形って何?って思ってたんですけど少し粘って検索してみるとよくわかりました。これでシューティングゲーム制作がはかどりそうです。ありがとうございました。 回答を書いておいてもらえますか?jimbeさんの回答をベストアンサーにしたいので。よろしくお願いします。
m.ts10806

2021/09/11 07:36 編集

質問は編集できますし、半永久的に残ります。 同じような問題をかかえた人が見る可能性も十二分にあるので、実際の現在のコードと解決するなら自身で理解した内容を回答として具体的に記載して「質問と解決策(自己解決)」とされたほうが良いと思います。 (自分だけ解決できればそれでいいってスタンスは回答者から避けられやすいです)
java_beginner1

2021/09/11 09:37

まあ僕とjimbeさんの問題なんですがね。なぜあなたが間に入るのか分かりませんが。 僕の疑問を解決してくださったのはjimbeさんです。なのでjimbeさんがベストアンサーに選ばれるべきです。jimbeさんがそう言うなら別ですが。 理解もしています。自分でやって透過も分割も出来ました。 あと”次回から気を付けます。”と書きました。僕もいつも丸投げ(?)の質問をしているわけではありません。コードを書かない方が質問が伝わりやすいと判断したのでコードを書きませんでした。
jimbe

2021/09/11 11:01 編集

まぁまぁ。私はお手伝い出来ただけで、実際にメソッドを探したり理解する為に検索したりをされたのは java_beginner1 さんですし、 teratail はコードレベルで実際に書いて動いてこそ「解決」とするのが本来のような気が致します。 また、このご質問はシューティングで無くとも何かしらゲームを作っていらっしゃる方々(なぜか最近そのような方をよく見るような^^; )への一つの知識としては結構有用なのではないでしょうか。 ですので(ゲーム全体を載せるわけにはいかないでしょうから) 例えば、実行すると自機が真ん中に表示されて、特定のキーを押したら自爆するようなプログラムをお作り頂いて自己回答としてご提示頂ければ、ご自身の習作としても有用と思いますし、また、後に一つの画像からアニメーションさせる方法を探してこちらを御覧になる方々にもかなり役立つものとなると思います。 まだお忙しい中かも知れませんが、ご一考頂けますと幸いです。 (やはり「今はちょっと時間的に」等があれば、こちらで上記のようなコードで回答させて頂きます。)
jimbe

2021/09/12 17:49

やはりお忙しそうですので、回答を書かせて頂きました。 余計なコードが多い気がしますが…スイマセン。
guest

回答1

0

ベストアンサー

透過は、png 画像は透明成分を含んだ色が使えますので、あらかじめそれで塗っておくことが出来ます。
分割は、画像の描画を Graphics.drawImage で行っているのでしたら、オーバーロードされたメソッドの中に元画像の一部を書き込むものがありますので、それを使えば同じことになります。

コードは、java_beginner1 さんの以前のご質問から個人的に作っていたモノを、爆発対応にしたうえで抜き出したものです。ですので、タイマーによる定周期処理の中でキー入力や描画を行う等結構余計なコードが含まれています。
実行すると小さいウインドウが出て、ESC キーを押すと中央で爆発します。
ご提示頂いている画像を読み込む際に外周を透明色にしていますので、背景の水色に対して黒い枠は出ません。

java

1package teratail_java.q358026; 2 3import java.awt.*; 4import java.awt.event.*; 5import java.awt.image.BufferedImage; 6import java.io.File; 7import java.io.IOException; 8import java.util.HashMap; 9import java.util.Map; 10import java.util.concurrent.*; 11 12import javax.imageio.ImageIO; 13import javax.swing.JFrame; 14import javax.swing.JPanel; 15 16public class ExplosionTest extends JFrame { 17 public static void main(String[] args) throws IOException { 18 new ExplosionTest().setVisible(true); 19 } 20 21 ExplosionTest() throws IOException { 22 super("ExplosionTest"); 23 setDefaultCloseOperation(EXIT_ON_CLOSE); 24 25 add(new MainPanel()); 26 27 pack(); 28 setResizable(false); 29 setLocationRelativeTo(null); 30 } 31 32 private static class MainPanel extends JPanel implements FocusListener, Runnable { 33 private static final String EXPLOSION_FILENANE = "Q358026_explosion.png"; //爆発画像 34 private ImageManager imageManager; 35 private KeyManager keyManager; 36 private Explosion explosion = null; 37 38 MainPanel() throws IOException { 39 super(null); 40 setPreferredSize(new Dimension(100, 100)); 41 setBackground(Color.CYAN); 42 43 setFocusable(true); 44 addFocusListener(this); 45 46 imageManager = new ImageManager(); 47 imageManager.readImage(EXPLOSION_FILENANE); 48 49 keyManager = new KeyManager(); 50 addKeyListener(keyManager); 51 } 52 53 //各キーの押下状態を管理. 54 private class KeyManager implements KeyListener { 55 private int keyBits = 0; 56 57 boolean pressedEscape() { return (keyBits & 32) != 0; } //ESC が押されていたら true 58 59 @Override 60 public void keyTyped(KeyEvent e) { } //ignore 61 @Override 62 public void keyPressed(KeyEvent e) { 63 //System.out.println("keyPressed: "+e.getKeyCode()); 64 switch(e.getKeyCode()) { 65 case KeyEvent.VK_ESCAPE: keyBits |= 32; return; 66 } 67 } 68 @Override 69 public void keyReleased(KeyEvent e) { 70 //System.out.println("keyReleased: "+e.getKeyCode()); 71 switch(e.getKeyCode()) { 72 case KeyEvent.VK_ESCAPE: keyBits &= ~32; return; 73 } 74 } 75 } 76 77 //画像ロード担当 78 private class ImageManager { 79 private Map<String,BufferedImage> imageMap = new HashMap<>(); 80 81 void readImage(String filename) throws IOException { 82 BufferedImage image = ImageIO.read(new File(filename)); 83 tranparent(image); 84 imageMap.put(filename, image); 85 } 86 BufferedImage getImage(String filename) { 87 return imageMap.get(filename); 88 } 89 //左上角の色と同じ色を透明にする 90 protected void tranparent(BufferedImage image) { 91 int w = image.getWidth(); 92 int h = image.getHeight(); 93 int target = image.getRGB(0,0); 94 for(int y=0; y<h; y++) { 95 for(int x=0; x<w; x++) { 96 if(image.getRGB(x,y) == target) image.setRGB(x,y,0); 97 } 98 } 99 } 100 } 101 102 //背景(当たり判定無し) 103 abstract class Background { 104 protected int count, max; 105 protected int x, y, w, h; 106 protected BufferedImage image; 107 Background(String filename) { 108 image = imageManager.getImage(filename); 109 w = image.getWidth(); 110 h = image.getHeight(); 111 } 112 //false ならまだ必要 113 abstract public boolean draw(Graphics g); 114 } 115 116 //爆発(背景) 117 private class Explosion extends Background { 118 static final int N = 4; // N回 draw 毎に絵が変わる 119 Explosion(int cx, int cy, int cw, int ch) { 120 super(EXPLOSION_FILENANE); 121 max = h / w * N; 122 //中心位置を合わせる 123 this.x = cx + (cw - w) / 2; 124 this.y = cy + (ch - w) / 2; 125 } 126 public boolean draw(Graphics g) { 127 int dy = count / N * w; 128 g.drawImage(image, x, y, x+w, y+w, 0, dy, w, dy+w, null); 129 return (++count < max); 130 } 131 } 132 133 @Override 134 public void paintComponent(Graphics g) { 135 super.paintComponent(g); 136 if(explosion != null && !explosion.draw(g)) explosion = null; 137 } 138 139 //メインループ 140 @Override 141 public void run() { 142 if(explosion == null && keyManager.pressedEscape()) { //ESC が押されたら爆発 143 explosion = new Explosion(50, 50, 20, 20); 144 } 145 repaint(); //再描画依頼 146 } 147 148 private boolean stop = false; 149 private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); 150 private ScheduledFuture<?> future; 151 @Override 152 public void focusGained(FocusEvent e) { 153 if(!stop) future = scheduler.scheduleAtFixedRate(this, 0, 20, TimeUnit.MILLISECONDS); //20ms毎に run()を呼ぶ 154 } 155 156 @Override 157 public void focusLost(FocusEvent e) { 158 if(future != null) { 159 future.cancel(false); 160 future = null; 161 } 162 } 163 } 164}

投稿2021/09/12 17:46

jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

java_beginner1

2021/09/13 10:17

ありがとうございます泣 学校忙しくて。。。 ベストアンサーにさせて頂きます。 あと覚えて下さってたんですね!嬉しかったです!
jimbe

2021/09/13 10:54

がむしゃらに何かを出来ることは、それが(したくても)出来なくなってから思い出すと懐かしくなるものです。 季節の変わり目でもありますのでお体だけはご注意して、堪能(?)なさってください ^^;;; 最近現在進行形でシューティング作成とご質問をされているのは、私の見ているタグではお一人だけです^^ まぁ、ご質問本文に書かれていないことを過去の関係情報で勝手に補完してしまうのは質問の独立性に関わりますので、あまり「誰々さんだから…」という前提は入れないようにしようとは思っています。 コードに付きましてちょっと補足です。 Explosion クラスのコンストラクタのパラメータ cx, cy, cw, ch は爆発する対象の矩形、つまり自機の爆発であれば自機の左上座標(cx,cy) とその幅(cw)・高さ(ch)を指定すると想定しています。 そこから計算される中心が爆発の中心となるように「中心位置を合わせる」で爆発の左上座標を求めています。 また、爆発画像の一枚々々の大きさは、幅は画像の幅、高さは幅と同じとしています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問