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
Entity.java - controls basics that all entities will possess
THE PROBLEM CODE IS IN HERE, SEE THE DRAW METHOD OF THE SPRITE
AnimatedSprite - controls the drawing and animation of the sprite
And finally some code to test the program:
MainFrame.java
Entity.java - controls basics that all entities will possess
public class Entity {
//enum to represent Entity's state
protected enum State { ALIVE, COLLIDED, DEAD }; //base State types
protected State currentState;
//member data
protected boolean alive;
protected double x,y;
protected double faceAngle;
protected double velX, velY;
//accessors
public boolean isAlive() { return alive; }
public double getY() { return y; }
public double getX() { return x; }
public double getVelY() { return velY; }
public double getVelX() { return velX; }
public double getFaceAngle() { return faceAngle; }
//mutators
public void setX(double x) { this.x = x; }
public void setY(double y) { this.y = y; }
public void setVelX(double velX) { this.velX = velX; }
public void setVelY(double velY) { this.velY = velY; }
public void setFaceAngle (double angle) { this.faceAngle = angle; }
public void setAlive(boolean alive) { this.alive = alive; }
Entity() {
currentState = State.DEAD;
setAlive(false);
setX(0.0);
setY(0.0);
setVelX(0.0);
setVelY(0.0);
setFaceAngle(0.0);
}
}
THE PROBLEM CODE IS IN HERE, SEE THE DRAW METHOD OF THE SPRITE
AnimatedSprite - controls the drawing and animation of the sprite
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import javax.swing.*;
import java.net.*;
public class AnimatedSprite extends Entity {
private JFrame frame;
private Graphics2D g2d;
// animation
private Image image;
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;
image = 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(Image image) {
this.image = 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 (image != null)
return image.getWidth(frame);
else
return 0;
}
public int getImageHeight() {
if (image != null)
return image.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();
image = tk.getImage(filename);
while (image.getHeight(frame) <= 0);//
double x = frame.getSize().width/2 - getImageWidth()/2;
// System.out.println("framewidth: " + frame.getSize().width);
double y= frame.getSize().height/2 - getImageHeight()/2;
//System.out.println("frameheight: " + frame.getSize().width);
at = AffineTransform.getTranslateInstance(x, y);
this.columns = columns;
this.totalFrames = totalFrames;
this.frameWidth = width;
this.frameHeight = height;
}
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()));
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 image; }
//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()));
}
public void getFrame() {
frameX = (currentFrame % columns) * frameWidth;
frameY = (currentFrame / columns) * frameHeight;
}
public void drawBounds(Color c) {
g2d.setColor(c);
g2d.draw(getBounds());
}
/* PROBLEM CODE: */
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 finally some code to test the program:
MainFrame.java
import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;
import java.awt.image.*;
import java.net.*;
public class MainFrame extends JFrame implements Runnable, KeyListener {
static int ScreenWidth = 640;
static int ScreenHeight = 480;
AffineTransform transform = new AffineTransform();
Thread gameloop;
Random rand = new Random();
//double buffer objects
BufferedImage backbuffer;
Graphics2D g2d;
//sprite variables
AnimatedSprite sprite;
public MainFrame() {
super("Animation Demo");
setSize(ScreenWidth, ScreenHeight);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create the backbuffer to remove flicker
backbuffer = new BufferedImage(ScreenWidth, ScreenHeight, BufferedImage.TYPE_INT_RGB);
g2d= backbuffer.createGraphics();
//load explosion animation
sprite = new AnimatedSprite(this,g2d);
sprite.load("players.png", 4, 8, 48, 48); //4 columns, 8 total frames, each image is 48x48
sprite.setX(300);
sprite.setY(200);
sprite.setFrameDelay(60);
sprite.setTotalFrames(8);
sprite.setGraphicsObject(g2d);
//sprite.velX = 1.0;
//sprite.velY = 1.0;
addKeyListener(this);
gameloop = new Thread(this);
gameloop.start();
}
public void run() {
Thread t = Thread.currentThread();
while (t == gameloop) {
try {
Thread.sleep(5);
}
catch (InterruptedException e) {
e.printStackTrace();
}
gameUpdate();
}
}
int faceAngle = 0; //test debug
public void gameUpdate() {
g2d.setTransform(transform);
//draw background
g2d.setColor(Color.WHITE);
g2d.fill(new Rectangle(0,0,ScreenWidth-1,ScreenHeight-1));
sprite.transform();
sprite.draw();
sprite.drawBounds(Color.RED);
// faceAngle++;
//sprite.setFaceAngle(faceAngle);
//g2d.setTransform(sprite.getTransform());
//sprite.transform();
//draw the sprite
//sprite.draw();
//g2d.setTransform(temp);
//keep the sprite in the screen boundary
if (sprite.x < 0 || sprite.x > ScreenWidth - 48)
sprite.velX *= -1;
if (sprite.y < 0 || sprite.y > ScreenHeight - 48)
sprite.velY *= -1;
g2d.setColor(Color.BLACK);
g2d.drawString("Position: " + sprite.x + "," +
sprite.y, 10, 40);
g2d.drawString("Velocity: " + sprite.x + "," +
sprite.y, 10, 60);
g2d.drawString("Animation: " + sprite.getCurrentFrame(), 10, 80);
g2d.drawString("Face Angle: " + sprite.getFaceAngle(), 10, 100);
repaint();
}
public void paint(Graphics g) {
//draw the back buffer to the screen
g.drawImage(backbuffer, 0, 0, this);
}
public static void main(String[] args) {
new MainFrame();
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_LEFT:
//left arrow rotates ship left 5 degrees
sprite.setFaceAngle((sprite.getFaceAngle()-5));
if (sprite.getFaceAngle() < 0) sprite.setFaceAngle(360-5);
break;
case KeyEvent.VK_RIGHT:
//left arrow rotates ship left 5 degrees
sprite.setFaceAngle((sprite.getFaceAngle()+5));
if (sprite.getFaceAngle() > 360) sprite.setFaceAngle(0+5);
break;
}
}
@Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}

New Topic/Question
Reply



MultiQuote




|