Loading a subimage from a tile map - java

I'm trying to develop my first game. I have serious issues with loading Tiles extracted from a map.
Here's what I've coded so far, just willing to display the first tile.
public class TileMap {
//FIELDS
public int Tilemapx;
public int Tilemapy;
private int nRows = 8;
private int nColumns = 8;
public int TileWidth = Panel.WIDTH / nColumns;
public int TileHeight = Panel.HEIGHT / nRows;
public BufferedImage EntireMap;
public BufferedImage SingleTile;
public TileMap (){
String EntireMappath = "res/Tiles.png";
try {
EntireMap = ImageIO.read(new File (EntireMappath));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void drawTile (){
for (int Tilemapx = 0; Tilemapx < Panel.WIDTH / nColumns; Tilemapx++){
for (int Tilemapy = 0; Tilemapy < Pannel.HEIGHT / nRows; Tilemapy++){
BufferedImage SingleTile = EntireMap.getSubimage(100, 100, Tilemapx, Tilemapy);
}
}
}
}
and, in the Panel class, I'm trying to draw the tile, but nothing appears (the first two images work as intended)
public void draw() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawImage(bg, 0, 0, getWidth(), getHeight(), null);
g.drawImage(heroImg1, hero.cordX, hero.cordY, hero.diameter, hero.diameter, null);
g.drawImage(tiles.SingleTile, 100, 200, tiles.Tilemapx, tiles.Tilemapx, null);
g.dispose();
bs.show();
}

You should provide a method in TileMap that returns the appropriate sub image for a given tile. Then, in draw, you can call that method, obtain an image, and draw it on the graphics. If you would like to draw the whole board, simply use a loop.

public void drawTile (){
// THIS IMAGE SingleTile SHOULD BE GLOBAL AND THIS IMAGE SHOULD BE RETURNED GLOBAL FROM A METHOD
BufferedImage SingleTile = EntireMap.getSubimage(100, 100, Tilemapx, Tilemapy);
// get the graphics context from what you want to paint onto
Graphics ga = OTHERIMAGE_OR_BUFFERSTRATEGY_OR_PANEL.getGraphics(); //or getDrawGraphics() for bufferstrategy
//then draw on it ga.drawImge(....................
}//END METHOD

Related

Drawable and Clickable text for Visual Novel

This is not a duplicate. All other solutions I tried were outdated.
So first look at this Image
I made that in eclipse today in Java.
It looks like a Visual Novel.
The point is I want to draw some text on the screen but don't know how to.
At first I only want to know:
How to draw text on screen and change it
Make something, such as an image or some text, clickable to move to
the next scene
Here is my current code:
package textboxes;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.URL;
public class test extends Applet implements Runnable, KeyListener {
private Image Image, Background;
private Image actor1, actor2;
private Image textbox;
private Graphics graphics;
private URL base;
private static testbg bg;
#Override
public void init(){
setSize(960, 540);
setBackground(Color.LIGHT_GRAY);
setFocusable(true);
Frame frame = (Frame)this.getParent().getParent();
frame.setTitle("School Scene");
try{
base = getDocumentBase();
}catch(Exception e){};
//getImages from disk
Background = getImage(base, "res/background.jpg");
actor1 = getImage(base, "res/actor1.jpg");
actor2 = getImage(base, "res/actor2.jpg");
textbox = getImage(base, "res/textbox.jpg");
}
public test(){
}
#Override
public void start(){
bg = new testbg();
Thread thread = new Thread(this);
thread.start();
}
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void run() {
bg.update();
repaint();
try{
Thread.sleep(17);
}catch(InterruptedException e){
e.printStackTrace();
}
}
#Override
public void update(Graphics g){
if(Image == null){
Image = createImage(this.getWidth(), this.getHeight());
graphics = Image.getGraphics();
}
graphics.setColor(getBackground());
graphics.fillRect(0, 0, getWidth(), getHeight());
graphics.setColor(getForeground());
paint(graphics);
g.drawImage(Image, 0, 0, this);
}
#Override
public void paint(Graphics g){
super.paint(g);
g.drawImage(Background, bg.getBgX(), bg.getBgY(), this);
g.drawImage(actor2, 40, 20, this);
g.drawImage(textbox, 80, 350, this);
}
public static testbg getBg() {
return bg;
}
}
This piece of code above is what I call test.java
if you are wondering about the Background part
the following piece of code is what I call testbg.java
package textboxes;
public class testbg {
private int bgX, bgY;
public testbg(){
bgX = 0;
bgY = 0;
}
public void update(){
}
public int getBgX(){
return bgX;
}
public int getBgY(){
return bgY;
}
public void setBgX(int bgX) {
this.bgX = bgX;
}
public void setBgY(int bgY) {
this.bgY = bgY;
}
}
Thanks for reading this much till the end...Now so can I know how to do it ??
As for the text, I have two solutions, but for what you want (and for what I know of CG games), I guess the first is the best.
This first solution is one that I found a long time ago for a problem of mine in StackOverflow (I don't remember where, sorry), in which includes de use of the several classes together to draw directly in the panel.
private final String message;
private final java.awt.geom.Rectangle2D.Float aboutMessageBounds;
private final AttributedString aboutMessageAttributedString;
private final AttributedCharacterIterator paragraph;
// The LineBreakMeasurer used to line-break the paragraph.
private java.awt.font.LineBreakMeasurer lineMeasurer;
// index of the first character in the paragraph.
private final int paragraphStart;
// index of the first character after the end of the paragraph.
private final int paragraphEnd;
#Override
public void init(){
(...)
java.util.Hashtable<TextAttribute, Object> textAtributMap =
new java.util.Hashtable<TextAttribute, Object>();
textAtributMap.put(TextAttribute.FAMILY, "Serif");
textAtributMap.put(TextAttribute.SIZE, new Float(26.0));
textAtributMap.put(TextAttribute.JUSTIFICATION, TextAttribute.JUSTIFICATION_FULL );
textAtributMap.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_DEMIBOLD );
textAtributMap.put(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON );
message = "This is a sample of a message.";
aboutMessageAttributedString = new AttributedString( aboutMessage, textAtributMap );
paragraph = aboutMessageAttributedString.getIterator();
paragraphStart = paragraph.getBeginIndex();
paragraphEnd = paragraph.getEndIndex();
(...)
}
#Override
protected void paintComponent( Graphics g ) {
super.paintComponent( g ); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2 = (Graphics2D)g.create();
try {
g2.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
// Create a new LineBreakMeasurer from the paragraph.
// It will be cached and re-used.
if (lineMeasurer == null) {
FontRenderContext frc = g2.getFontRenderContext();
lineMeasurer = new java.awt.font.LineBreakMeasurer(paragraph, frc);
}
//You can scale it like I did. this part is not part of the code that I found.
g2.scale( ratio.scaleDx, ratio.scaleDy );
// Set break width to width of Component.
//these were the measures I used for a something in a game;
float breakWidth = 734.0f;
float drawPosY = 90.0f;
float posX0 = 30.0f;
// Set position to the index of the first character in the paragraph.
lineMeasurer.setPosition(paragraphStart);
// Get lines until the entire paragraph has been displayed.
while (lineMeasurer.getPosition() < paragraphEnd) {
int next = lineMeasurer.nextOffset(breakWidth);
int limit = next;
if (limit <= message.length()) {
for (int i = lineMeasurer.getPosition(); i < next; ++i) {
char c = aboutMessage.charAt(i);
if (c == '\n') {
limit = i + 1;
break;
}
}
}
java.awt.font.TextLayout layout = lineMeasurer.nextLayout( breakWidth, limit, false );
// Retrieve next layout. A cleverer program would also cache
// these layouts until the component is re-sized.
// Compute pen x position. If the paragraph is right-to-left we
// will align the TextLayouts to the right edge of the panel.
// Note: this won't occur for the English text in this sample.
// Note: drawPosX is always where the LEFT of the text is placed.
float drawPosX = layout.isLeftToRight()
? posX0 : breakWidth - layout.getAdvance();
// Move y-coordinate by the ascent of the layout.
drawPosY += layout.getAscent();
// Draw the TextLayout at (drawPosX, drawPosY).
layout.draw(g2, drawPosX, drawPosY);
// Move y-coordinate in preparation for next layout.
drawPosY += layout.getDescent() + layout.getLeading();
}
}
finally {
g2.dispose();
}
}
As for the second solution, you could use a JEditorPane or a JTextPane. See the Oracle tutorial for this mater:
https://docs.oracle.com/javase/tutorial/uiswing/components/editorpane.html
I hop I have helped.
Have a nice day. :)

Set pixels of BufferedImage as transparent

How can I quickly and efficiently set all pixels of a BufferedImage to transparent so that I can simply redraw what sprite graphics I want for each frame?
I am designing a simple game engine in java that updates a background and foreground BufferedImage and draws them to a composite VolatileImage for efficient scaling, to be drawn to a JPanel. This scalable model allows me to add more layers and iterate over each drawing layer.
I simplified my application into one class given below that demonstrates my issue. Use the arrow keys to move a red square over the image. The challenge is I want to decouple updating the game graphics from drawing the composite graphics to the game engine. I have studied seemingly thorough answers to this question but cannot figure out how to apply them to my application:
Java: Filling a BufferedImage with transparent pixels
Here is the critical section that does not clear the pixels correctly. The commented out section is from stack-overflow answers I have read already, but they either draw the background as a non-transparent black or white. I know the foregroundImage begins with transparent pixels in my implementation as you can see the random pixel noise of the backgroundImage behind the red sprite when the application begins. Right now, the image is not cleared, so the previous drawn images remain.
/** Update the foregroundGraphics. */
private void updateGraphics(){
Graphics2D fgGraphics = (Graphics2D) foregroundImage.getGraphics();
// set image pixels to transparent
//fgGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
//fgGraphics.setColor(new Color(0,0,0,0));
//fgGraphics.clearRect(0, 0, width, height);
//fgGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
// draw again.
fgGraphics.setColor(Color.RED);
fgGraphics.fillRect(sx, sy, spriteSize, spriteSize);
fgGraphics.dispose();
}
Here is my entire example code:
/**
* The goal is to draw two BufferedImages quickly onto a scalable JPanel, using
* a VolatileImage as a composite.
*/
public class Example extends JPanel implements Runnable, KeyListener
{
private static final long serialVersionUID = 1L;
private int width;
private int height;
private Object imageLock;
private Random random;
private JFrame frame;
private Container contentPane;
private BufferedImage backgroundImage;
private BufferedImage foregroundImage;
private VolatileImage compositeImage;
private Graphics2D compositeGraphics;
private int[] backgroundPixels;
private int[] foregroundPixels;
// throttle the framerate.
private long prevUpdate;
private int frameRate;
private int maximumWait;
// movement values.
private int speed;
private int sx;
private int sy;
private int dx;
private int dy;
private int spriteSize;
/** Setup required fields. */
public Example(){
width = 512;
height = 288;
super.setPreferredSize(new Dimension(width, height));
imageLock = new Object();
random = new Random();
frame = new JFrame("BufferedImage Example");
frame.addKeyListener(this);
contentPane = frame.getContentPane();
contentPane.add(this, BorderLayout.CENTER);
// used to create hardware-accelerated images.
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
backgroundImage = gc.createCompatibleImage(width, height,Transparency.TRANSLUCENT);
foregroundImage = gc.createCompatibleImage(width, height,Transparency.TRANSLUCENT);
compositeImage = gc.createCompatibleVolatileImage(width, height,Transparency.TRANSLUCENT);
compositeGraphics = compositeImage.createGraphics();
compositeGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
compositeGraphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
backgroundPixels = ((DataBufferInt) backgroundImage.getRaster().getDataBuffer()).getData();
foregroundPixels = ((DataBufferInt) foregroundImage.getRaster().getDataBuffer()).getData();
//initialize the background image.
for(int i = 0; i < backgroundPixels.length; i++){
backgroundPixels[i] = random.nextInt();
}
// used to throttle frames per second
frameRate = 180;
maximumWait = 1000 / frameRate;
prevUpdate = System.currentTimeMillis();
// used to update sprite state.
speed = 1;
dx = 0;
dy = 0;
sx = 0;
sy = 0;
spriteSize = 32;
}
/** Renders the compositeImage to the Example, scaling to fit. */
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// draw the composite, scaled to the JPanel.
synchronized (imageLock) {
((Graphics2D) g).drawImage(compositeImage, 0, 0, super.getWidth(), super.getHeight(), 0, 0, width, height, null);
}
// force repaint.
repaint();
}
/** Update the BufferedImage states. */
#Override
public void run() {
while(true){
updateSprite();
updateGraphics();
updateComposite();
throttleUpdateSpeed();
}
}
/** Update the Sprite's position. */
private void updateSprite(){
// update the sprite state from the inputs.
dx = 0;
dy = 0;
if (Command.UP.isPressed()) dy -= speed;
if (Command.DOWN.isPressed()) dy += speed;
if (Command.LEFT.isPressed()) dx -= speed;
if (Command.RIGHT.isPressed()) dx += speed;
sx += dx;
sy += dy;
// adjust to keep in bounds.
sx = sx < 0 ? 0 : sx + spriteSize >= width ? width - spriteSize : sx;
sy = sy < 0 ? 0 : sy + spriteSize >= height ? height - spriteSize : sy;
}
/** Update the foregroundGraphics. */
private void updateGraphics(){
Graphics2D fgGraphics = (Graphics2D) foregroundImage.getGraphics();
// set image pixels to transparent
//fgGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
//fgGraphics.setColor(new Color(255, 255, 255, 255));
//fgGraphics.clearRect(0, 0, width, height);
//fgGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
// draw again.
fgGraphics.setColor(Color.RED);
fgGraphics.fillRect(sx, sy, spriteSize, spriteSize);
fgGraphics.dispose();
}
/** Draw the background and foreground images to the volatile composite. */
private void updateComposite(){
synchronized (imageLock) {
compositeGraphics.drawImage(backgroundImage, 0, 0, null);
compositeGraphics.drawImage(foregroundImage, 0, 0, null);
}
}
/** Keep the update rate around 60 FPS. */
public void throttleUpdateSpeed(){
try {
Thread.sleep(Math.max(0, maximumWait - (System.currentTimeMillis() - prevUpdate)));
prevUpdate = System.currentTimeMillis();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
/** Ignore key typed events. */
#Override
public void keyTyped(KeyEvent e) {}
/** Handle key presses. */
#Override
public void keyPressed(KeyEvent e) {
setCommandPressedFrom(e.getKeyCode(), true);
}
/** Handle key releases. */
#Override
public void keyReleased(KeyEvent e) {
setCommandPressedFrom(e.getKeyCode(), false);
}
/** Switch over key codes and set the associated Command's pressed value. */
private void setCommandPressedFrom(int keycode, boolean pressed){
switch (keycode) {
case KeyEvent.VK_UP:
Command.UP.setPressed(pressed);
break;
case KeyEvent.VK_DOWN:
Command.DOWN.setPressed(pressed);
break;
case KeyEvent.VK_LEFT:
Command.LEFT.setPressed(pressed);
break;
case KeyEvent.VK_RIGHT:
Command.RIGHT.setPressed(pressed);
break;
}
}
/** Commands are used to interface with key press values. */
public enum Command{
UP, DOWN, LEFT, RIGHT;
private boolean pressed;
/** Press the Command. */
public void press() {
if (!pressed) pressed = true;
}
/** Release the Command. */
public void release() {
if (pressed) pressed = false;
}
/** Check if the Command is pressed. */
public boolean isPressed() {
return pressed;
}
/** Set if the Command is pressed. */
public void setPressed(boolean pressed) {
if (pressed) press();
else release();
}
}
/** Begin the Example. */
public void start(){
try {
// create and display the frame.
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
Example e = new Example();
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
// start updating from key inputs.
Thread t = new Thread(this);
t.start();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
/** Start the application. */
public static void main(String[] args){
Example e = new Example();
e.start();
}
}
Edits:
- Fixed a typo in the for-loop initializing the backgroundPixels to random.
Turns out I goofed in my method selection. I noticed I was clearing a one-pixel wide box that was the outline of my graphics. This is because I accidentally used drawRect() instead of fillRect(). Upon changing my code it works now. Here are examples I was able to get to work.
Example using AlphaComposite.CLEAR (draw with any opaque color):
// clear pixels
fgGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
fgGraphics.setColor(new Color(255,255,255,255));
fgGraphics.fillRect(0, 0, width, height);
fgGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
// draw new graphics
Example using AlphaComposite.SRC_OUT (draw with any color with alpha zero):
// clear pixels
fgGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT));
fgGraphics.setColor(new Color(255,255,255,0));
fgGraphics.fillRect(0, 0, width, height);
fgGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
// draw new graphics

issue when i try to display a background image using Canvas

I'm trying to display a background image using g.drawImage within Canvas Jframe but i have nothing displayed and the screen still white , and when i try to fill the screen with any color it works using g.fillRect
here is the Main class :
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.dynamics.World;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.ImageIcon;
public class Main extends Canvas implements Runnable, KeyListener {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 600, HEIGHT = WIDTH / 12 * 9;
// rate to convert meters to pixels in the physics engine
public static final float RATE = 30;
// counts how many loops are made in the main thread
private int counter = 49;
// image and graphics used for double buffering
private ImageIcon bgImage = new ImageIcon("res/bgImage.png");
private Image dbImage;
private Graphics dbg;
/* boolean to define when the game will be started and stopped */
private boolean running = false;
// variables for the Box2D world
Vec2 gravity = new Vec2(0.0f, 10.0f);
boolean doSleep = true;
World world = new World(gravity, doSleep);
// new array list to hold Ball references
ArrayList<Ball> balls = new ArrayList<Ball>();
// create a new player
Player character = new Player(world);
public Main() {
addKeyListener(this);
// add a ground floor to our Box2D world
BodyDef groundBodyDef = new BodyDef();
groundBodyDef.position.set(300.0f / RATE, 400.0f / RATE);
Body groundBody = world.createBody(groundBodyDef);
PolygonShape groundBox = new PolygonShape();
groundBox.setAsBox(300.0f / RATE, 0);
groundBody.createFixture(groundBox, 0.0f);
// wall fixture
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = groundBox;
fixtureDef.density = 2.0f;
fixtureDef.filter.groupIndex = -1;
// left wall
groundBodyDef.position.set(0.0f / RATE, 350.0f / RATE);
groundBody = world.createBody(groundBodyDef);
groundBox.setAsBox(0, 50.0f / RATE);
groundBody.createFixture(fixtureDef);
// right wall
groundBodyDef.position.set(600.0f / RATE, 350.0f / RATE);
groundBody = world.createBody(groundBodyDef);
groundBox.setAsBox(0, 50.0f / RATE);
groundBody.createFixture(fixtureDef);
/**
* #WIDHT : width of jpanel screen
* #HEIGHT : height of the jpanel screen
* #param : title of jpanel screen
* #this : refered to our main game instance
*/
new Window(WIDTH, HEIGHT, "Apocalypse 2D v0.0", this);
}
#Override
public int getWidth() { // Width of the CustomPanel
return WIDTH;
}
#Override
public int getHeight() { // Height of the CustomPanel
return HEIGHT;
}
#Override
public Dimension getPreferredSize() { // Dimension of the CustomPanel
return new Dimension(getWidth(), getHeight());
}
public void start() {
// starts a new thread
running = true;
Thread th = new Thread(this);
th.start();
}
public void stop() {
running = false;
}
public void destroy() {
}
public void run() {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
while (running) {
counter++;
// Simulate the world
float timeStep = 1.0f / 60.0f;
int velocityIterations = 6;
int positionIterations = 2;
world.step(timeStep, velocityIterations, positionIterations);
// add new balls to the world every 50th loop
if (counter % 80 == 0)
balls.add(new Ball(world));
repaint();
// pause for 10 milliseconds
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
// do nothing
}
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
}
public void paint(Graphics g) {
/*g.setColor(Color.black);*/
/*g.fillRect(0, 0, getWidth(), getHeight());*/
g.drawImage(bgImage, getWidth(), getHeight(), null);
// loop through each ball and call it's draw method
Iterator<Ball> itr = balls.iterator();
while (itr.hasNext()) {
Ball b = itr.next();
b.DrawBall(g);
// if the ball should be removed then remove it
if (b.shouldDelete())
itr.remove();
}
// draw the main character.
character.draw(g);
}
// sets up double buffering for graphics
public void update(Graphics g) {
if (dbImage == null) {
dbImage = createImage(this.getSize().width, this.getSize().height);
dbg = dbImage.getGraphics();
}
dbg.setColor(getBackground());
dbg.fillRect(0, 0, this.getSize().width, this.getSize().height);
dbg.setColor(getForeground());
paint(dbg);
g.drawImage(dbImage, 0, 0, this);
character.animplayer();
for (Ball ball : balls) {
ball.animBalls();
}
}
public void keyPressed(KeyEvent key) {
character.keyPress(key);
}
public void keyReleased(KeyEvent key) {
character.keyRelease(key);
}
public void keyTyped(KeyEvent key) {
}
public static void main(String[] args) {
new Main();
}
}
and this is the paint method where i'm trying to fill the image to the screen :
public void paint(Graphics g) {
/*g.setColor(Color.black);*/
/*g.fillRect(0, 0, getWidth(), getHeight());*/
g.drawImage(bgImage, getWidth(), getHeight(), null);
// loop through each ball and call it's draw method
Iterator<Ball> itr = balls.iterator();
while (itr.hasNext()) {
Ball b = itr.next();
b.DrawBall(g);
// if the ball should be removed then remove it
if (b.shouldDelete())
itr.remove();
}
// draw the main character.
character.draw(g);
}
The drawImage() method has several overloads, the one you are using is drawImage(BufferedImage img, int x, int y, ImageObserver observer), x and y being the top left coordinates on the canvas. Right now those are the width and the heigh of the canvas, so the image is being drawn outside of the panel. Try calling g.drawImage(dbImage, 0, 0, null).
edit:
Asuming your image is not the same size as your canvas, use g.drawImage(dbImage, 0, 0, getWidth(), getHeight(), null) to fill the canvas with your image.

Gif Image only playing once. Need it to replay each time

I don't want to post the entire program on here because that would be too much, but I will post snippets of it and detail where they came from so you have an idea.
Problem: For my class project, I am making a typical space invaders game. When a missile hits a ship an explosion gif is played. The gif only loops once (not continuous). The when the missile hits the alien craft, the gif plays just fine for the first spaceship. However, when I shoot a missile at the second or third,etc, ship the gif does not play again. I believe that it is just playing the last frame of the gif from what I have researched. Is there a way to either reload the gif image to play each time the missile is hits or is there another way to do this?
Here is the link to the image: http://postimg.org/image/v2lljr7cb/
Here is some code:
I have a class called Boom, where the explosion is happening. Here is the code in that class:
public void draw(Graphics2D g2d) {
g2d.drawImage(getEnemyImg(), x, y, null);
}
public Image getEnemyImg() {
ImageIcon ic = new ImageIcon("src/Boom.gif");
return ic.getImage();
}
I then have another class called GameFrame where everything happens. In it, there are these lines of code specially for the explosion. Here is the code from this class:
static ArrayList<Boom> booms = new ArrayList<Boom>();
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
ImageIcon ic = new ImageIcon("src/BackGround.jpg");
g2d.drawImage(ic.getImage(), 0, 0, null);
player.draw(g2d);
for (int i = 0; i < booms.size(); i++) {
Boom bm = booms.get(i);
bm.draw(g2d);
}
Enemy e = new Enemy(200, 400);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
player.update();
for (int i = 0; i < booms.size(); i++) {
Boom bm = booms.get(i);
bm.update();
}
checkEnd();
repaint();
}
public static void addBoom(Boom bm) {
booms.add(bm);
}
public static void removeBoom(Boom bm) {
booms.remove(bm);
}
public static ArrayList<Boom> getBoomList() {
return booms;
}
Finally, here is where the explosion is being added. This happens when the missile hits the alien space craft. This is happening in the Enemy class. Here is the code:
public void checkCollisions() {
for (int i = 0; i < GameFrame.getMissileList().size(); i++) {
Missile m = GameFrame.getMissileList().get(i);
if (getBounds().intersects(m.getBounds())) {
GameFrame.removeEnemy(this);
GameFrame.removeMissile(m);
GameFrame.addBoom(new Boom(m.getX() -40, m.getY()- 60));
for(int j = 0; i <GameFrame.getBoomList().size(); i++){
Boom bm = GameFrame.getBoomList().get(j);
}
}
}
}
I apologize for the wall of text. My professor was unsure of how to do this so I was hoping to get some help from here.
If you have any time to spare, your ideas would be helpful. Thank you.

Java crop and draw image using getsubimage

In the main class I'm drawing graphics objects like so:
//FIELDS
double FPS = 1000 / 60;
BufferStrategy bs;
public String ip;
private int cx = 0;
private Hero h;
private TileMap map;
private int speed = 12;
public mainCla (){
setPreferredSize(new Dimension(WIDTH, HEIGHT));
h = new Hero("Hero/res/hero.png",100,50);
map = new TileMap ("Hero/res/jun.png");
}
private void draw() {
bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.GREEN);
g.drawImage(h.hi, h.hx, h.hy, this);
g.fillOval(cx, 200, 40, 40);
bs.show();
}
Then in another class, I've set the cropping of the loaded image like so:
public class TileMap {
//FIELDS
public String livpath;
BufferedImage mappa;
public int imgmapwidth;
public int imgmapheight;
public TileMap (String livpath ){
this.livpath = livpath;
BuildBlock();
try {
mappa = ImageIO.read (new File (livpath));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void BuildBlock () {
for (int x = 0; x < 128; x++)
{ for (int y = 0; y < 128; y++) {
mappa.getSubimage (0,0,x,y);
}
}
}
After that, I've tried to draw the extracted tile with g.drawimage from the main class(obviously I've created an instance with the path of the image, as requested by the constructor) but the image itself is not showing. Any idea? Thanks

Categories

Resources