I have two graphics objects. Each object is made up of tens of thousands of triangle primitives. For the sake of this example, let`s just consider the two objects as triangles - blue triangle and orange triangles.
I want to draw the blue triangle once in the background, and use the animator to over lay the several orange triangles over the blue. Think about the blue triangle as a canvas and the orange triangles are drawn over them in a pattern. Now the canvas and the orange triangles are rotated as a whole. Also, how can I scale the whole set up and rotate them around a different axes?
In this example, I want all the orange triangles to over lay on the blue.
Here is the SSCCE. If you see in the example, the blue triangles over lay on the orange. I want all the orange triangles to be on top of blue.
Also, how do I clear the canvas from an external event like a button click and completely start redrawing the scene?
import java.awt.EventQueue;
import javax.swing.JFrame;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.Animator;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class MainWin implements GLEventListener {
private JFrame frame;
private int iter = 0;
private float rotAng = 0;
private GLProfile profile;
private GLCapabilities capabilities;
private GLCanvas canvas;
private Animator animator;
private int totIter = 15;
private float scaleFac = 1f;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWin window = new MainWin();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainWin() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 600, 450);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnZoom = new JButton("Zoom");
btnZoom.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
zoomObj();
}
private void zoomObj() {
canvas.invalidate();
scaleFac -= 0.5f;
}
});
frame.getContentPane().add(btnZoom, BorderLayout.NORTH);
// Initilaize graphics profile, capabilites, canvas and animator
profile = GLProfile.get(GLProfile.GL2);
capabilities = new GLCapabilities(profile);
capabilities.setNumSamples(2);
capabilities.setSampleBuffers(true);
canvas = new GLCanvas(capabilities);
canvas.addGLEventListener(this);
canvas.requestFocusInWindow();
animator = new Animator();
animator.add(canvas);
animator.start();
frame.getContentPane().add(canvas); // add to the frame
}
#Override
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glRotatef(15, 0, 1, 0); // rotate both blue and orange objects around Y axis
gl.glScalef(scaleFac, scaleFac, scaleFac);
//blue object
gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
gl.glEnable(GL2.GL_MULTISAMPLE);
gl.glPushMatrix();
gl.glCallList(2);
gl.glPopMatrix();
gl.glDisable(GL2.GL_MULTISAMPLE);
// orange object
gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
if (iter < totIter) {
iter++;
rotAng = 5;
gl.glRotatef((float) rotAng, 0, 0, 1); // rotate each iter by 5 aroung Z. Only the orange.
gl.glEnable(GL2.GL_MULTISAMPLE);
gl.glPushMatrix();
gl.glCallList(1);
gl.glPopMatrix();
gl.glDisable(GL2.GL_MULTISAMPLE);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (iter == totIter - 1) {
animator.stop();
}
gl.glFlush();
}
#Override
public void dispose(GLAutoDrawable drawable) {
}
#Override
public void init(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClearColor(.0f, .0f, .2f, 0.9f);
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
// buffers for multisampling
int buf[] = new int[1];
int sbuf[] = new int[1];
gl.glGetIntegerv(GL2.GL_SAMPLE_BUFFERS, buf, 0);
gl.glGetIntegerv(GL2.GL_SAMPLES, sbuf, 0);
initObj1(gl); // Orange
initObj2(gl); // Blue
}
/**
* Blue triangle. In actual code, this is a complicated 3D object made up of atleast a few tens of thousands of
* primitives in a mesh.
*
* #param gl
*/
private void initObj2(GL2 gl) {
gl.glNewList(2, GL2.GL_COMPILE);
gl.glColorMaterial(GL2.GL_FRONT, GL2.GL_DIFFUSE);
gl.glEnable(GL2.GL_COLOR_MATERIAL);
gl.glBegin(GL2.GL_TRIANGLES);
gl.glColor4f(.2f, .5f, 0.8f, 0.5f);
gl.glVertex3f(-0.5f, 0, 0);
gl.glVertex3f(0.5f, 0, 0);
gl.glVertex3f(0, 0.5f, 0);
gl.glEnd();
gl.glEndList();
}
/**
* Orange Triangle. In actual code, this is a complicated 3D object made up of atleast a few tens of thousands of
* primitives in a mesh.
*
* #param gl
*/
private void initObj1(GL2 gl) {
gl.glNewList(1, GL2.GL_COMPILE);
gl.glColorMaterial(GL2.GL_FRONT, GL2.GL_DIFFUSE);
gl.glEnable(GL2.GL_COLOR_MATERIAL);
gl.glBegin(GL2.GL_TRIANGLES);
gl.glColor4f(.95f, .45f, 0.15f, 0.5f);
gl.glVertex3f(-1, 0, 0);
gl.glVertex3f(1, 0, 0);
gl.glVertex3f(0, 1, 0);
gl.glEnd();
gl.glEndList();
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
}
}
Related
I have a simple custom Canvas
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.util.awt.TextRenderer;
import java.awt.*;
public class MyCanvas extends GLCanvas implements GLEventListener {
private GLU glu;
public MyCanvas() {
this.addGLEventListener(this);
}
TextRenderer renderer;
#Override
public void init(GLAutoDrawable drawable) {
renderer = new TextRenderer(new Font("SansSerif", Font.BOLD, 16));
GL2 gl = drawable.getGL().getGL2();
glu = new GLU();
gl.glClearColor(1f, 1f, 1f, 1f);
gl.glClearDepth(1.0f);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
gl.glShadeModel(GL2.GL_SMOOTH);
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL2 gl = drawable.getGL().getGL2();
if (height == 0) height = 1;
float aspect = (float)width / height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(45.0, aspect, 0.1, 100.0);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
}
#Override
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -50f);
gl.glColor3f(0.5f, 0.5f, 0.5f);
gl.glBegin(GL2.GL_TRIANGLES);
gl.glVertex3f(0.0f, 1.0f, 0.0f);
gl.glVertex3f(-1.0f, -1.0f, 0.0f);
gl.glVertex3f(1.0f, -1.0f, 0.0f);
gl.glEnd();
String text = "Text";
renderer.setColor(Color.BLACK);
renderer.begin3DRendering();
gl.glPushMatrix();
gl.glTranslated(0, 0, 0);
renderer.draw(text, 0, 0);
renderer.flush();
gl.glPopMatrix();
renderer.end3DRendering();
}
#Override
public void dispose(GLAutoDrawable drawable) { }
}
And I have a simple JFrame for displaying this canvas.
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class App extends JFrame {
private static final int CANVAS_WIDTH = 640;
private static final int CANVAS_HEIGHT = 480;
private static final int FPS = 60;
public App() {
GLCanvas canvas = new MyCanvas();
canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
final FPSAnimator animator = new FPSAnimator(canvas, FPS, true);
this.getContentPane().add(canvas);
this.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
new Thread() {
#Override
public void run() {
if (animator.isStarted()) animator.stop();
System.exit(0);
}
}.start();
}
});
this.setTitle("JOGL (GLCanvas)");
this.pack();
this.setVisible(true);
animator.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(App::new);
}
}
When I run programm I see very blurry text.
And when I reduce text size, then text became is more and more blurry. What should I do to get a clear text?
The text is blurry, because the font size doesn't match the rendered size on screen and bi-linear interpolation is used to magnify the font/font-texture.
The problem might happen because you are mixing 2D and 3D text rendering functions. You should either use begin3DRendering, draw3D and end3DRendering, where you can control the actual size of the text with the scaling parameter, or you use beginRendering, draw and endRendering where a orthographic projection is used to map pixels from the font to the screen.
I am wanting to make a game that has each level loaded from an image.
I want to draw up the whole level in Photoshop, and then set it as the background and allow the player to walk over it.
I want another invisible image to go over top which will be black in all places that I want to collide with.
The reason I don't want to use tiles, which are much easier with rectangle collision and such, is because there will be complex corners and not everything will be rectangle.
Is this a good idea, and is it possible to do easily?
Would this be a big CPU hog or is there a better way to do this?
Level image
Obstacles shown in red
..there will be complex corners and not everything will be rectangle.
This could be achieved by drawing and dealing with Shape and Area instances. E.G.
Yellow is a little animated 'player'.
The bounds of the image represent walls that contain the path of the player (it bounces off them).
Obstacles are painted green when not in collision, red otherwise.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
class ShapeCollision {
private BufferedImage img;
private Area[] obstacles = new Area[4];
private Area walls;
int x;
int y;
int xDelta = 3;
int yDelta = 2;
/** A method to determine if two instances of Area intersect */
public boolean doAreasCollide(Area area1, Area area2) {
boolean collide = false;
Area collide1 = new Area(area1);
collide1.subtract(area2);
if (!collide1.equals(area1)) {
collide = true;
}
Area collide2 = new Area(area2);
collide2.subtract(area1);
if (!collide2.equals(area2)) {
collide = true;
}
return collide;
}
ShapeCollision() {
int w = 400;
int h = 200;
img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
final JLabel imageLabel = new JLabel(new ImageIcon(img));
x = w/2;
y = h/2;
//circle
obstacles[0] = new Area(new Ellipse2D.Double(40, 40, 30, 30));
int[] xTriangle = {330,360,345};
int[] yTriangle = {60,60,40};
//triangle
obstacles[1] = new Area(new Polygon(xTriangle, yTriangle, 3));
int[] xDiamond = {60,80,60,40};
int[] yDiamond = {120,140,160,140};
//diamond
obstacles[2] = new Area(new Polygon(xDiamond, yDiamond, 4));
int[] xOther = {360,340,360,340};
int[] yOther = {130,110,170,150};
// other
obstacles[3] = new Area(new Polygon(xOther, yOther, 4));
walls = new Area(new Rectangle(0,0,w,h));
ActionListener animate = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
animate();
imageLabel.repaint();
}
};
Timer timer = new Timer(50, animate);
timer.start();
JOptionPane.showMessageDialog(null, imageLabel);
timer.stop();
}
public void animate() {
Graphics2D g = img.createGraphics();
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.BLUE);
g.fillRect(0, 0, img.getWidth(), img.getHeight());
x+=xDelta;
y+=yDelta;
int s = 15;
Area player = new Area(new Ellipse2D.Double(x, y, s, s));
// Acid test of edge collision;
if (doAreasCollide(player,walls)) {
if ( x+s>img.getWidth() || x<0 ) {
xDelta *= -1;
}
if(y+s>img.getHeight() || y<0 ) {
yDelta *= -1;
}
}
g.setColor(Color.ORANGE);
for (Area obstacle : obstacles) {
if (doAreasCollide(obstacle, player)) {
g.setColor(Color.RED);
} else {
g.setColor(Color.GREEN);
}
g.fill(obstacle);
}
g.setColor(Color.YELLOW);
g.fill(player);
g.dispose();
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new ShapeCollision();
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
Edit
make it detect all the red color and set that as the collision bounds
At start-up, use the source seen in the Smoothing a jagged path question to get an outline of the red pixels (see the getOutline(Color target, BufferedImage bi) method). Store that Area as the single obstacle on start-up.
I'm trying to move the camera in jogl but my code doesn't seem to do anything. How do you move the camera with keyboard input? I'm drawing a rotating hexagon and I want to move the camera but I can't seem to get it working. This is my code:
import javax.media.opengl.*;
import javax.media.opengl.awt.*;
import com.sun.opengl.util.*;
import com.sun.opengl.util.gl2.GLUT;
import javax.media.opengl.glu.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class Rotation2 extends JFrame implements GLEventListener, KeyListener
{
GLCanvas canvas;
Animator an;
public Rotation2()
{
canvas=new GLCanvas();
an=new Animator(canvas);
add(canvas);
canvas.addGLEventListener(this);
canvas.addKeyListener(this);
setSize(600,400);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
an.start();
}
double eyeX = 0;
double eyeY = 0;
double eyeZ = 0;
public void init(GLAutoDrawable drawable)
{
GL2 gl=drawable.getGL().getGL2();
GLU glu = new GLU();
gl.glClearColor(0.0f,0.0f,0.0f,0.0f);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glOrtho(-300,300,-200,200,200,-200);
//gl.glLoadIdentity();
gl.glMatrixMode(GL2.GL_MODELVIEW);
//glu.gluLookAt(5, 5, 5,0, 0, 0, 1, 100, 0);
gl.glClearDepth(1.0f); // Set background depth to farthest
gl.glEnable(GL2.GL_DEPTH_TEST); // Enable depth testing for z-culling
gl.glDepthFunc(GL2.GL_LEQUAL); // Set the type of depth-test
}
double x=0;
public void display(GLAutoDrawable drawable)
{
GL2 gl=drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glLoadIdentity();
GLU glu=new GLU();
//gl.glPushMatrix();
gl.glScaled(2,2,2);
gl.glRotated(x,1,1,1);
x+=.05;
glu.gluLookAt(eyeX, eyeY, 2,0, 0, 0, 1, 100, 0);
gl.glColor3f(0,1f,0);
// front
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(25,50,25);
gl.glVertex3d(-25,50,25);
gl.glVertex3d(-50,0,25);
gl.glVertex3d(-25,-50,25);
gl.glVertex3d(25,-50,25);
gl.glVertex3d(50,0,25);
gl.glEnd();
//left
gl.glColor3f(1f,1f,0);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(25,50,-25);
gl.glVertex3d(-25,50,-25);
gl.glVertex3d(-50,0,-25);
gl.glVertex3d(-25,-50,-25);
gl.glVertex3d(25,-50,-25);
gl.glVertex3d(50,0,-25);
gl.glEnd();
gl.glColor3f(1f,0f,0);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(25,50,25);
gl.glVertex3d(25,50,-25);
gl.glVertex3d(-25,50,-25);
gl.glVertex3d(-25,50,25);
gl.glEnd();
gl.glColor3f(0f,0f,1f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(-25,50,25);
gl.glVertex3d(-25,50,-25);
gl.glVertex3d(-50,0,-25);
gl.glVertex3d(-50,0,25);
gl.glEnd();
gl.glColor3f(1f,1f,1f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(-50,0,25);
gl.glVertex3d(-50,0,-25);
gl.glVertex3d(-25,-50,-25);
gl.glVertex3d(-25,-50,25);
gl.glEnd();
gl.glColor3f(0,1f,1f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(-25,-50,25);
gl.glVertex3d(-25,-50,-25);
gl.glVertex3d(25,-50,-25);
gl.glVertex3d(25,-50,25);
gl.glEnd();
gl.glColor3f(1,0f,1f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(25,-50,25);
gl.glVertex3d(25,-50,-25);
gl.glVertex3d(50,0,-25);
gl.glVertex3d(50,0,25);
gl.glEnd();
gl.glColor3f(.2f,1f,.2f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(50,0,25);
gl.glVertex3d(50,0,-25);
gl.glVertex3d(25,50,-25);
gl.glVertex3d(25,50,25);
gl.glEnd();
//gl.glPopMatrix();
}
public void reshape(GLAutoDrawable drawable,int x,int y,int width,int height)
{}
public void dispose(GLAutoDrawable drawable)
{}
public static void main(String[] ar)
{
new Rotation2();
}
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_X) {
eyeX++;
}
else if (e.getKeyCode() == KeyEvent.VK_Y) {
eyeY++;
}
else if(e.getKeyCode() == KeyEvent.VK_Z) {
eyeZ++;
}
else {
}
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
that's deprecated opengl, forget it.
You are also using a very old jogl, update it, go on jogamp.org, under "Builds / Download" click on "zip", then download jogamp-all-platforms.7z extract it and set jogl as explained here
Take this Hello Triangle.
It uses already the keyListener, just copy the code you wrote for the keyTyped and paste it under keyPressed (you have to use the jogamp keyListener, what you use in your sample is instead the java awt one).
Let us know if you have any problem :)
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.
I am wanting to make a game that has each level loaded from an image.
I want to draw up the whole level in Photoshop, and then set it as the background and allow the player to walk over it.
I want another invisible image to go over top which will be black in all places that I want to collide with.
The reason I don't want to use tiles, which are much easier with rectangle collision and such, is because there will be complex corners and not everything will be rectangle.
Is this a good idea, and is it possible to do easily?
Would this be a big CPU hog or is there a better way to do this?
Level image
Obstacles shown in red
..there will be complex corners and not everything will be rectangle.
This could be achieved by drawing and dealing with Shape and Area instances. E.G.
Yellow is a little animated 'player'.
The bounds of the image represent walls that contain the path of the player (it bounces off them).
Obstacles are painted green when not in collision, red otherwise.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
class ShapeCollision {
private BufferedImage img;
private Area[] obstacles = new Area[4];
private Area walls;
int x;
int y;
int xDelta = 3;
int yDelta = 2;
/** A method to determine if two instances of Area intersect */
public boolean doAreasCollide(Area area1, Area area2) {
boolean collide = false;
Area collide1 = new Area(area1);
collide1.subtract(area2);
if (!collide1.equals(area1)) {
collide = true;
}
Area collide2 = new Area(area2);
collide2.subtract(area1);
if (!collide2.equals(area2)) {
collide = true;
}
return collide;
}
ShapeCollision() {
int w = 400;
int h = 200;
img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
final JLabel imageLabel = new JLabel(new ImageIcon(img));
x = w/2;
y = h/2;
//circle
obstacles[0] = new Area(new Ellipse2D.Double(40, 40, 30, 30));
int[] xTriangle = {330,360,345};
int[] yTriangle = {60,60,40};
//triangle
obstacles[1] = new Area(new Polygon(xTriangle, yTriangle, 3));
int[] xDiamond = {60,80,60,40};
int[] yDiamond = {120,140,160,140};
//diamond
obstacles[2] = new Area(new Polygon(xDiamond, yDiamond, 4));
int[] xOther = {360,340,360,340};
int[] yOther = {130,110,170,150};
// other
obstacles[3] = new Area(new Polygon(xOther, yOther, 4));
walls = new Area(new Rectangle(0,0,w,h));
ActionListener animate = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
animate();
imageLabel.repaint();
}
};
Timer timer = new Timer(50, animate);
timer.start();
JOptionPane.showMessageDialog(null, imageLabel);
timer.stop();
}
public void animate() {
Graphics2D g = img.createGraphics();
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.BLUE);
g.fillRect(0, 0, img.getWidth(), img.getHeight());
x+=xDelta;
y+=yDelta;
int s = 15;
Area player = new Area(new Ellipse2D.Double(x, y, s, s));
// Acid test of edge collision;
if (doAreasCollide(player,walls)) {
if ( x+s>img.getWidth() || x<0 ) {
xDelta *= -1;
}
if(y+s>img.getHeight() || y<0 ) {
yDelta *= -1;
}
}
g.setColor(Color.ORANGE);
for (Area obstacle : obstacles) {
if (doAreasCollide(obstacle, player)) {
g.setColor(Color.RED);
} else {
g.setColor(Color.GREEN);
}
g.fill(obstacle);
}
g.setColor(Color.YELLOW);
g.fill(player);
g.dispose();
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new ShapeCollision();
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
Edit
make it detect all the red color and set that as the collision bounds
At start-up, use the source seen in the Smoothing a jagged path question to get an outline of the red pixels (see the getOutline(Color target, BufferedImage bi) method). Store that Area as the single obstacle on start-up.