5 Replies - 469 Views - Last Post: 06 October 2012 - 06:58 AM Rate Topic: -----

#1 alpha_x  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 55
  • Joined: 03-May 11

Applying a transform when selectively drawing parts of a source image

Posted 05 October 2012 - 08:35 AM

Hello all :)
I am having trouble on how I would go about not only drawing parts of an image but also applying a AffineTransform to the image without actually changing the frame's AffineTransform. I know that I can selectively draw parts of an image like so:

g2d.drawImage(image,(int)this.x,(int) this.y,(int) this.x+frameWidth,(int) this.y + frameHeight, frameX, frameY, frameX+frameWidth, frameY+frameHeight, getJFrame());


And I know that I can draw a image with a transform like so:


g2d.drawImage(image,at,getJFrame());


However I cannot quite figure out how to selectively draw an image as described above with a transform?

Any help is appreciated thanks, Entire source code is given below (The problem code is in the draw method of AnimatedSprite.java - see below).

Spoiler


Is This A Good Question/Topic? 0
  • +

Replies To: Applying a transform when selectively drawing parts of a source image

#2 alpha_x  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 55
  • Joined: 03-May 11

Re: Applying a transform when selectively drawing parts of a source image

Posted 05 October 2012 - 09:05 AM

Ok I made some changes to AnimatedSprite.java, I now rotate the player around the centerX and centerY of the image and I set the graphics transform of the frame to the player before drawing it and then reset to default once the image is drawn. Here are the changes:

	public void transform() {
		at.setToIdentity();
		//at.translate((int)getX() + getImageWidth()/2, (int)getY() + getImageHeight()/2);
		//at.translate(at.getTranslateX(), at.getTranslateY());
		at.rotate(Math.toRadians(getFaceAngle()),getCenterX(),getCenterY());
	//	at.translate(-getImageWidth()/2,  -getImageHeight()/2);
	}


public void draw() {
	
	AffineTransform original = g2d.getTransform();
	updateSprite();

	getFrame();
	//draw frame


	g2d.setTransform(getTransform());
	//g2d.drawImage(image,at,getJFrame());
	g2d.drawImage(image,(int)this.x,(int) this.y,(int) this.x+frameWidth,(int) this.y + frameHeight, frameX, frameY, frameX+frameWidth, frameY+frameHeight, getJFrame());
	g2d.setTransform(original);
}
	



And now the player is rotating which is good however it is not rotating and standing still but rotating in a wide arc, any ideas? Thanks!

Also, somewhat of a sidebug is that the boundaries when I use drawBound(Color c) does not update? I cannot ascertain if I am making a mistake with my rotation or?

This post has been edited by alpha_x: 05 October 2012 - 09:09 AM

Was This Post Helpful? 0
  • +
  • -

#3 alpha_x  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 55
  • Joined: 03-May 11

Re: Applying a transform when selectively drawing parts of a source image

Posted 06 October 2012 - 12:33 AM

I now am able to draw my animation whilst applying a transform to the image. It required a rework of the AnimatedSprite class whereby I extract the images into a BufferedImage array and then in my draw method, I draw the current image with a transformation like so:

g2d.drawImage(animation[getCurrentFrame()], at, getJFrame());

However the image itself is still not rotating around its center despite using the following rotate method which I thought would definitely work :(

at.rotate(Math.toRadians(getFaceAngle()), getCenterX(), getCenterY());

Below is my updated AnimatedSprite.java class:

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;

import javax.imageio.ImageIO;
import javax.swing.*;

import java.io.IOException;
import java.net.*;

public class AnimatedSprite extends Entity {
	private JFrame frame;
	private Graphics2D g2d;

	private BufferedImage spriteSheet;
	private BufferedImage[] animation;
	private AffineTransform at;
	private int animDirection;
	private int frameCount, frameDelay;
	private int currentFrame, totalFrames;
	private int frameWidth, frameHeight, columns;
	private int frameX, frameY;

	AnimatedSprite(JFrame frame, Graphics2D graphics) {
		super(); // call Entity constructor and set defaults
		this.frame = frame;
		g2d = graphics;
		spriteSheet = null;
		alive = true;
		currentState = State.ALIVE;
		currentFrame = 0;
		totalFrames = 1;
		animDirection = 1;
		frameCount = 0;
		frameDelay = 0;
		frameWidth = 0;
		frameHeight = 0;
		columns = 1;

	}

	public void setAnimDirection(int animDirection) {
		this.animDirection = animDirection;
	}

	public void setFrameCount(int frameCount) {
		this.frameCount = frameCount;
	}

	public void setFrameDelay(int frameDelay) {
		this.frameDelay = frameDelay;
	}

	public void setCurrentFrame(int currentFrame) {
		this.currentFrame = currentFrame;
	}

	public void setTotalFrames(int totalFrames) {
		this.totalFrames = totalFrames;
	}

	public int getAnimDirection() {
		return animDirection;
	}

	public int getFrameCount() {
		return frameCount;
	}

	public int getFrameDelay() {
		return frameDelay;
	}

	public int getTotalFrames() {
		return totalFrames;
	}

	public int getCurrentFrame() {
		return currentFrame;
	}

	public JFrame getJFrame() {
		return frame;
	}

	public Graphics2D getGraphicsObject() {
		return g2d;
	}

	public void setGraphicsObject(Graphics2D graphics) {
		g2d = graphics;
	}

	public void setImage(BufferedImage image) {
		this.spriteSheet = image;
		double x = frame.getSize().width / 2 - getImageWidth() / 2;
		double y = frame.getSize().height / 2 - getImageHeight() / 2;
		at = AffineTransform.getTranslateInstance(x, y);
	}

	public int getImageWidth() {
		if (spriteSheet != null)
			return spriteSheet.getWidth(frame);
		else
			return 0;
	}

	public int getImageHeight() {
		if (spriteSheet != null)
			return spriteSheet.getHeight(frame);
		else
			return 0;
	}

	public double getCenterX() {
		return this.x + getImageWidth() / 2;
	}

	public double getCenterY() {
		return this.y + getImageHeight() / 2;
	}

	public Rectangle getBounds() {
		Rectangle bounds = new Rectangle((int) this.x, (int) this.y,
				frameWidth, frameHeight);
		return bounds;
	}

	public void load(String filename, int columns, int totalFrames, int width,
			int height) {
		Toolkit tk = Toolkit.getDefaultToolkit();
		try {
			spriteSheet = ImageIO.read(getURL("players.png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		while (spriteSheet.getHeight(frame) <= 0)
			;
		double x = frame.getSize().width / 2 - getImageWidth() / 2;
		double y = frame.getSize().height / 2 - getImageHeight() / 2;
		at = AffineTransform.getTranslateInstance(x, y);
		this.columns = columns;
		this.totalFrames = totalFrames;
		this.frameWidth = width;
		this.frameHeight = height;
		animation = new BufferedImage[this.totalFrames]; // reserve space
		getAnimation();
	}

	public void transform() {
		at.setToIdentity();
		at.translate((int) getX() + getImageWidth() / 2, (int) getY()
				+ getImageHeight() / 2);
		at.rotate(Math.toRadians(getFaceAngle()), getCenterX(), getCenterY());
		at.translate(-getImageWidth() / 2, -getImageHeight() / 2);
	}

	public AffineTransform getTransform() {
		return at;
	}

	public void updateSprite() {
		// update position
		x += velX;
		y += velY;

		// update transform
		transform();

		// update rotation
		// faceAngle +=5;
		this.setFaceAngle(faceAngle);
		if (faceAngle < 0)
			faceAngle = 360 - 5;
		else if (faceAngle > 360)
			faceAngle = 5;

		// update animation
		if (totalFrames > 1) {
			frameCount++;
			if (frameCount > frameDelay) {
				frameCount = 0;
				currentFrame += animDirection;
				if (currentFrame > totalFrames - 1) {
					currentFrame = 0; // first frame
				} else if (currentFrame < 0) {
					currentFrame = totalFrames - 1; // last frame
				}
			}
		}
	}

	public Image getImage() {
		return spriteSheet;
	}

	// check for collision with a rectangular shape
	public boolean collidesWith(Rectangle rectangle) {
		return (rectangle.intersects(getBounds()));
	}

	// check for collision with another sprite
	public boolean collidesWith(AnimatedSprite sprite) {
		return (getBounds().intersects(sprite.getBounds()));
	}

	private URL getURL(String filename) {
		URL url = null;
		try {
			url = this.getClass().getResource(filename);
		} catch (Exception e) {
		}
		return url;
	}

	public BufferedImage grabTile(int xpos, int ypos, int width, int height) {
		return spriteSheet.getSubimage(xpos, ypos, width, height);
	}

	public void getAnimation() { // load animation and store in BufferedImage
									// array

		for (int i = 0; i < totalFrames; i++) {

			BufferedImage tile = grabTile(frameX, frameY, frameWidth, // grab
																		// needed
																		// tile
					frameHeight);
			getFrame();
			currentFrame++;
			animation[i] = tile;
			System.out.println(animation[i]);
		}
		currentFrame = 0;
	}

	public void getFrame() {
		frameX = (currentFrame % columns) * frameWidth;
		frameY = (currentFrame / columns) * frameHeight;
	}

	public void drawBounds(Color c) {
		g2d.setColor(c);
		g2d.draw(getBounds());
	}


	public void draw() {
		updateSprite();
		getFrame();
		// draw frame
		g2d.drawImage(animation[getCurrentFrame()], at, getJFrame());

	}

}



I will keep working on this but any help would be awesome thanks!

This post has been edited by alpha_x: 06 October 2012 - 12:35 AM

Was This Post Helpful? 0
  • +
  • -

#4 alpha_x  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 55
  • Joined: 03-May 11

Re: Applying a transform when selectively drawing parts of a source image

Posted 06 October 2012 - 03:00 AM

Sorry I just now realised that this may not be the right place for this question, if that is the case then can a moderator please move to the Game Programming sub-forum.
Was This Post Helpful? 0
  • +
  • -

#5 v0rtex  Icon User is offline

  • Caffeine: db "Never Enough!"
  • member icon

Reputation: 223
  • View blog
  • Posts: 773
  • Joined: 02-June 10

Re: Applying a transform when selectively drawing parts of a source image

Posted 06 October 2012 - 05:13 AM

The problem was not that apparent so I compiled your code. You are using a spritesheet I take it and this is partly your problem:

  public int getImageWidth() {
      if (spriteSheet != null)
         return spriteSheet.getWidth(frame);
      else
         return 0;
   }



However this returns the width of your spritesheet and not of an individual frame hence why the rotation is not at the center of an individual frame in your animation but is at the center of the size of your spritesheet.

A simple fix would be something like this:

 public int getImageWidth() {
         return x; //where x = the width of an individual frame
   }

 public int getImageHeight() {
         return x; //where x = the height an individual frame
   }



There are more "correct" ways to do this however.
Hope this helps!
Was This Post Helpful? 1
  • +
  • -

#6 alpha_x  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 55
  • Joined: 03-May 11

Re: Applying a transform when selectively drawing parts of a source image

Posted 06 October 2012 - 06:58 AM

Oops silly me, thanks that worked!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1