ImageBuffer not printing in JPanel - java

I have a drawShapeAt method in a class that should print a shape at a given location
#Override
public void drawShapeAt(int x, int y) {
try {
canvas.removeMouseListener(ml);
} catch (Exception e) {
}
polygon = new RegularPolygon(x, y, Integer.parseInt(polygonRadius), Integer.parseInt(polygonLines));
BufferedImage image = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();
Random rand = new Random();
graphics.setColor(new Color(rand.nextInt(0xFFFFFF)));
graphics.fill(polygon);
System.out.println("Painting polygon..");
canvas.paintComponents(graphics);
}
}
If I write for example canvas.setBackground it will change the background, yet it will not print the shape. My RegularPolygon is as follows:
public class RegularPolygon extends Polygon {
public RegularPolygon(int x0, int y0, int radius, int sides) {
double alpha = 2 * Math.PI / sides;
for (int i = 0; i < sides; i++) {
double x = x0 + radius * Math.cos(alpha * i);
double y = y0 + radius * Math.sin(alpha * i);
this.addPoint((int) x, (int) y);
}
}
}
I checked for wrong variables, but all are ok (x,y, polygonRadius, polygonLines).

Related

Circle to Circle collision in Java

So I am doing circle to circle collision in java. I am aware that there are many similiar questions like mine on this website but my problem is unique from all of them. When I run my code, the circle's collide with each other once every 4 times. Meaning: 3 times they will go through without colliding with one another but one time they will collide. Any help is greatly appreciated.
public class Ball {
float x, y; // coordinates of ball rectangle
float xo, yo;
float vx = 2, vy = 2; // coordinates of velocity vector
Color colour; // ball colour
float d; // diameter of the ball or sizes of ball rectangle
Ellipse2D.Float circle;
// overloaded constructor
Ball(int x, int y, int vx, int vy, int d, Color colour) {
this.x = x;
this.y = y;
this.d = d;
xo = x;
yo = y;
this.setColour(colour);
this.setVelocity(vx, vy);
circle = new Ellipse2D.Float(x, y, d, d);
}
public void setColour(Color colour) {
this.colour = colour;
}
public void setVelocity(int vx, int vy) {
this.vx = vx;
this.vy = vy;
}
public void show(Graphics g) {
((Graphics2D) g).setPaint(colour);
circle.setFrame(x, y, d, d);
((Graphics2D) g).fill(circle);
xo = x;
yo = y;
}
public void hide(Graphics g) {
Color c = ((Graphics2D) g).getBackground();
((Graphics2D) g).setPaint(c);
circle.setFrame(xo, yo, d, d);
((Graphics2D) g).fill(circle);
}
public void setPosition(float x, float y) {
this.x = x;
this.y = y;
}
public void move(int a, int b, int xh, int yh) {
if (vy > 0) {
if (y + d + vy - yh - b > 0) {
y = yh + b - d;
vy = -vy;
} else
y += vy;
} else {
if (y + vy <= b) {
y = b;
vy = -vy;
} else
y += vy;
}
if (vx > 0) {
if (x + d + vx - xh - a > 0) {
x = xh + a - d;
vx = -vx;
} else
x += vx;
} else {
if (x + vx <= a) {
x = a;
vx = -vx;
} else
x += vx;
}
}
The Collision Detector is in the class below
public class Game extends JFrame {
int ah, bh, xh, yh; // parameters of the rectangle frame
Color[] ColorAr = { Color.red, Color.blue, Color.pink, Color.green,
Color.yellow, Color.magenta, Color.black, Color.orange, Color.gray,
Color.cyan };
Ball b[];
int quantity = 4;
public void paint(Graphics g) {
int i;
((Graphics2D) g).setPaint(Color.black);
((Graphics2D) g).drawRect(ah, bh, xh, yh);
for (i = quantity - 1; i >= 0; i--) {
b[i].hide(g);
}
for (i = 0; i < quantity; i++) {
b[i].show(g);
}
}
public void prepare() {
int i;
ah = 20;
bh = 40;
xh = 400;
yh = 400;
b = new Ball[quantity];
for (i = 0; i < quantity; i++) {
b[i] = new Ball((int) (Math.random() * (300 - 1 + 1)) + 1, 100, 1,
1, 26, ColorAr[(int) (Math.random() * 9)]);
}
}
public void collision() {
int radius = 13;
int distance = 2 * radius;
if (b[1].x + distance == b[0].x && b[1].y == b[0].y
|| b[1].x - distance == b[0].x && b[1].y == b[0].y) {
b[1].vx = -b[1].vx;
b[0].vx = -b[0].vx;
}
}
public void run() {
int i;
while (true) {
for (i = 0; i < quantity; i++)
b[i].move(ah, bh, xh, yh);// move balls
collision();
for (int j = 0; j < 10000000; j++)
; // delay;
// collision();
repaint();
}
}
public static void main(String args[]) {
Game frame = new Game();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame.setBackground(Color.white);
frame.setSize(450, 470);
frame.prepare();
frame.setVisible(true);
frame.run();
}
}
For two circles:
First calculate the sum of lengths: radius_1 + radius_2 (the first and the second circle).
Collision of two circles can be detected if you calculate the length of (imaginary) line between centers. If THAT length <= radius_1 + radius_2, two circles are colliding.

How do I apply different textures to multiple polygons in LWJGL?

I am drawing a grid of hexagon tiles. I have six different images that I want to use as the fill for these tiles. I use my hexagon class to loop through each point in the tile. The textures are stored in an array list which is then shuffled into a random order. The problem with my script right now is that the same texture is applied to each tile. What am I doing wrong?
public class LWJGLHelloWorld {
public static int SCREEN_WIDTH;
public static int SCREEN_HEIGHT;
public static int WINDOW_WIDTH;
public static int WINDOW_HEIGHT;
public double WIDTH;
public double HEIGHT;
public ArrayList<Hexagon> hexagons = new ArrayList<Hexagon>();
public ArrayList<String> resources = new ArrayList<String>();
public Texture brick;
public Texture stone;
public Texture lumber;
public Texture wool;
public Texture wheat;
public Texture wasteland;
private static enum State {
INTRO, MAIN_MENU, GAME;
}
private State state = State.INTRO;
public LWJGLHelloWorld(){
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double SCREEN_WIDTH = screenSize.getWidth();
double SCREEN_HEIGHT = screenSize.getHeight();
double WIDTH = SCREEN_WIDTH * .85;
double HEIGHT = SCREEN_HEIGHT * .85;
try {
Display.setDisplayMode(new DisplayMode((int)WIDTH, (int)HEIGHT));
Display.setTitle("Hello, LWJGL!");;
Display.create();
} catch (LWJGLException e){
e.printStackTrace();
}
resetResources();
brick = loadTexture("brick");
stone = loadTexture("stone");
lumber = loadTexture("lumber");
//Texture wheat = loadTexture("wheat");
wool = loadTexture("wool");
wasteland = loadTexture("wasteland");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WIDTH, HEIGHT, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
int originX = (int)(Display.getDisplayMode().getWidth() / 2);
int originY = (int)(Display.getDisplayMode().getHeight() / 2);
int radius = (int)(HEIGHT * .1);
int padding = (int)(HEIGHT * .005);
findHexCoords(originX, originY, 5, radius, padding);
while(!Display.isCloseRequested()){
glClear(GL_COLOR_BUFFER_BIT);
for(int h = 0; h < hexagons.size(); h++){
String rsrc = resources.get(h);
bindTexture(rsrc);
glBegin(GL_POLYGON);
Hexagon hex = hexagons.get(h);
for(int p = 0; p < hex.points.length; p++){
Point point = hex.points[p];
glTexCoord2f(point.x, point.y);
glVertex2f(point.x, point.y);
}
glEnd();
}
Display.update();
Display.sync(60);
}
Display.destroy();
}
private void bindTexture(String rsrc){
switch(rsrc){
case "brick":
brick.bind();
break;
case "stone":
stone.bind();
break;
case "lumber":
lumber.bind();
break;
case "wheat":
//wheat.bind();
break;
case "wool":
wool.bind();
break;
case "wasteland":
wasteland.bind();
break;
}
}
private void findHexCoords(int x, int y, int size, int radius, int padding) {
Point origin = new Point(x, y);
double ang30 = Math.toRadians(30);
double xOff = Math.cos(ang30) * (radius + padding);
double yOff = Math.sin(ang30) * (radius + padding);
int half = size / 2;
int i = 0;
for (int row = 0; row < size; row++) {
int cols = size - Math.abs(row - half);
for (int col = 0; col < cols; col++) {
int xLbl = row < half ? col - row : col - half;
int yLbl = row - half;
int centerX = (int) (origin.x + xOff * (col * 2 + 1 - cols));
int centerY = (int) (origin.y + yOff * (row - half) * 3);
Hexagon hex = new Hexagon(centerX, centerY, radius);
System.out.println(centerX+","+centerY);
hexagons.add(hex);
i++;
}
}
}
private Texture loadTexture(String key){
try {
return TextureLoader.getTexture("PNG", new FileInputStream(new File("img/" + key + ".png")));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
new LWJGLHelloWorld();
}
public void resetResources(){
resources.clear();
resources.add("Brick");
resources.add("Brick");
resources.add("Brick");
resources.add("Wool");
resources.add("Wool");
resources.add("Wool");
resources.add("Wool");
resources.add("Lumber");
resources.add("Lumber");
resources.add("Lumber");
resources.add("Lumber");
resources.add("Stone");
resources.add("Stone");
resources.add("Stone");
resources.add("Wheat");
resources.add("Wheat");
resources.add("Wheat");
resources.add("Wheat");
long seed = System.nanoTime();
Collections.shuffle(resources, new Random(seed));
int randomIndex = ThreadLocalRandom.current().nextInt(0, 19);
resources.add(randomIndex, "Wasteland");
for(int r = 0; r < resources.size(); r++){
System.out.println(resources.get(r));
}
}
The first letter of the strings that you are adding in resources is uppercase (e.g. Brick).
In the bindTexture switch you are searching strings from resources that have a lowercase first letter (e.g. brick). Therefore the switch should always fail and not able to bind the correct texture.
Either fix the switch or the resources array accordingly.

Moving ball at an Angle

I am a newbie and trying to move a ball at a slope. Here is the code where I am giving coordinates (100,300,300,600) to move the ball in a slope but it's getting away from the the slope line. Here's the code: -
import javax.swing.*;
import java.awt.*;
public class AgentMotion extends JPanel implements Runnable
{
Color color = Color.red;
int dia = 0;
long delay = 40;
private double x;
private double y;
private double x1;
private double y1;
private int dx = 1;
private int dy = 1;
private int dv = 1;
private double direction;
double a;
double b;
double a1;
double b1;
public void abc(double x, double y, double x2, double y2) {
this.x = x;
this.y = y;
this.x1 = x2;
this.y1 = y2;
this.direction=Math.toRadians(Math.atan2(x1-x,y1-y));
System.out.println("segfewg"+direction);
this.a = x;
this.b = y;
this.a1 = x1;
this.b1 = y1;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
//int x=100;
//int y=200;
int x3=(int)this.x;
int y3=(int)this.y;
g.fillOval(x3,y3,5,5); // adds color to circle
g.setColor(Color.black);
g2.drawOval(x3,y3,5,5); // draws circle
g2.drawLine(100, 300, 300, 600);
}
public void run() {
if(direction<0)
{
System.out.println("refregreg");
while(dy!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
else
{
while(dx!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
}
public void move() {
if(direction>0)
{
if(x + dv*Math.cos(direction) <a ||x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x += dx;
}
else
{
System.out.println(x + dia + dv * Math.cos(direction));
if(x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x -= dx;
}
}
public void move2() {
if(direction>0)
{
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y > b1) {
dy *= 0;
color = getColor();
}
y += dy;
}
else
{
System.out.println(dv * Math.sin(direction) + dia + y);
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y < b1) {
dy *= 0;
color = getColor();
}
y -= dy;
}
}
public Color getColor() {
int rval = (int)Math.floor(Math.random() * 256);
int gval = (int)Math.floor(Math.random() * 256);
int bval = (int)Math.floor(Math.random() * 256);
return new Color(rval, gval, bval);
}
public void start() {
while(dx==0) {
try {
System.out.println("jiuj");
Thread.sleep(25);
} catch(InterruptedException e) {
System.out.println("dwdwdwd");
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
A few suggestions
dx and dy should be double
atan is overkill as #Spektre says. What you want is much more simple to calculate direction.
this.direction = (y2 - y) / (x2 - x)
If we give (100,300,300,600) as the arguments to abc (which would presumably be a constructor for this class), the slope is 1.5. Therefore we could say:
dx = 1.0
dy = 1.5
and this would keep on the line perfectly. For the general case where you want to change the begin and the end point, you have to calculate the ratio. So you could set either dx or dy to 1.0 and then set the other one so that the ratio is maintained. Something like the following mathematical pseudocode:
dx = (x2 - x) / minimum(x2-x, y2-y)
dy = (y2 - y) / minimum(x2-x, y2-y)

Calculate x y of Point after increasing distance

I am trying to get the x and y value of a point after increasing the distance r. Perhaps there is a better way of calculate the angle phi too, so that I don't need to check in which quadrant the point is. The 0-point is at the half of the width and height of the window. Here is my attempt:
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public final class Laser extends java.applet.Applet implements Runnable{
private static final long serialVersionUID = -7566644836595581327L;
Thread runner;
int width = 800;
int height = 600;
Point point = new Point(405,100);
Point point1 = new Point(405,100);
public void calc(){
int x = getWidth()/2;
int y = getHeight()/2;
int px = point.x;
int py = point.y;
int px1 = point1.x;
int py1 = point1.y;
double r = 0;
double phi = 0;
// Point is in:
// Quadrant 1
if(px > x && py < y){
r = Math.hypot(px1-x, y-py1);
phi = Math.acos((px1-x)/r)*(180/Math.PI);
}/*
// Quadrant 2
else if(px < x && py < y){
r = Math.hypot(x-px, y-py);
phi = Math.acos((px-x)/r)*(180/Math.PI);
}
// Quadrant 3
else if(px < x && py > y){
r = Math.hypot(x-px, py-y);
phi = Math.acos((px-x)/r)*(180/Math.PI)+180;
}
// Quadrant 4
else if(px > x && py > y){
r = Math.hypot(px-x, py-y);
phi = Math.acos((px-x)/r)*(180/Math.PI)+180;
}*/
r += 1;
point1.x = (int) (r*Math.cos(phi));
point1.y = (int) (r*Math.sin(phi));
System.out.println(r+";"+point1.x+";"+point1.y);
}
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
calc();
g.drawLine(point.x, point.y, point1.x, point1.y);
int h = getHeight();
int w = getWidth();
g.setColor(Color.GREEN);
g.drawLine(0, h/2, w, h/2);
g.drawLine(w/2, 0, w/2, h);
}
/*
public void initPoints(){
for(int i = 0; i < pointsStart.length; i++){
int x = (int)(Math.random()*getWidth());
int y = (int)(Math.random()*getHeight());
pointsStart[i] = pointsEnd[i] = new Point(x,y);
}
}
*/
public void start() {
if (runner == null) {
runner = new Thread(this);
setBackground(Color.black);
setSize(width, height);
//initPoints();
runner.start();
}
}
#SuppressWarnings("deprecation")
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
public void run() {
while (true) {
repaint();
try { Thread.sleep(700); }
catch (InterruptedException e) { }
}
}
public void update(Graphics g) {
paint(g);
}
}
You are changing (x,y) to be r from some other point, when it had previously been some distance r' from that point, correct? So why not avoid the trigonometry, and just scale each of the components from that point by r/r'?
Edit: ok, iterate over the pixels along whichever component (x or y) is longer (let's assume it's y); for each xi in (0..x), yi = xi*(y/x), and you plot (xi,yi).
Keep it simple! And use double variables for such computations, I changed it for you.
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Point2D;
public final class Laser extends java.applet.Applet implements Runnable {
private static final long serialVersionUID = -7566644836595581327L;
Thread runner;
int width = 800;
int height = 600;
Point2D.Double point = new Point2D.Double(400, 100);
Point2D.Double point1 = new Point2D.Double(405, 102);
public void calc() {
double px = point.x;
double py = point.y;
double px1 = point1.x;
double py1 = point1.y;
double dx = px1 - px;
double dy = py1 - py;
double len = Math.hypot(dx, dy);
double newlen = len+2;
double coeff = Math.abs((newlen-len)/len);
point1.x += dx * coeff;
point1.y += dy * coeff;
System.out.println(len+";"+point1.x+";"+point1.y);
}
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
calc();
g.drawLine((int)point.x, (int)point.y, (int)point1.x, (int)point1.y);
int h = getHeight();
int w = getWidth();
g.setColor(Color.GREEN);
g.drawLine(0, h / 2, w, h / 2);
g.drawLine(w / 2, 0, w / 2, h);
}
/*
* public void initPoints(){
*
* for(double i = 0; i < pointsStart.length; i++){ double x =
* (double)(Math.random()*getWidth()); double y =
* (double)(Math.random()*getHeight()); pointsStart[i] = pointsEnd[i] = new
* Point(x,y); }
*
* }
*/
public void start() {
if (runner == null) {
runner = new Thread(this);
setBackground(Color.black);
setSize(width, height);
// initPoints();
runner.start();
}
}
#SuppressWarnings("deprecation")
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
public void run() {
while (true) {
repaint();
try {
Thread.sleep(700);
}
catch (InterruptedException e) {
}
}
}
public void update(Graphics g) {
paint(g);
}
}

How can I put the circles at the center of the line?

I have a diagonal line and I have also a circles having a 100 meters in distance. The problem is that the circles are not really to the center of the line. I know this is quiet easy but I'm just confused on how to do it.. Could someone help me how to put the circles at the center of the line?
Here's what I've tried so far :
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.white);
int x0_pixel = 0;
int y0_pixel = 0;
int x1_pixel = getWidth();
int y1_pixel = getHeight();
int x0_world = 0;
int y0_world = 0;
double x1_world = 2000; // meters
double y1_world = 1125; // meters
double x_ratio = (double) x1_pixel / x1_world;
double y_ratio = (double) y1_pixel / y1_world;
int xFrom = 0;
int yFrom = 0;
double xTo = x1_world;
double yTo = y1_world;
int FromX_pixel = convertToPixelX(xFrom, x_ratio);
int FromY_pixel = convertToPixelY(y1_pixel, yFrom, y_ratio);
int ToX_pixel = convertToPixelX((int) xTo, x_ratio);
int ToY_pixel = convertToPixelY(y1_pixel, (int) yTo, y_ratio);
g2d.setColor(Color.RED);
g2d.drawLine(FromX_pixel, FromY_pixel, ToX_pixel, ToY_pixel);
double theta = Math.atan(yTo / xTo);
int len = (int) Math.sqrt(xTo * xTo + yTo * yTo);
int interval = 100;
final double cosTheta = Math.cos(theta);
final double sinTheta = Math.sin(theta);
for (int distance = xFrom; distance <= len; distance += interval)
{
double distance_x = distance * cosTheta;
double distance_y = distance * sinTheta;
int x_circle_pixel = convertToPixelX(distance_x, x_ratio);
int y_circle_pixel = convertToPixelY(y1_pixel, distance_y, y_ratio);
g2d.drawOval(x_circle_pixel, y_circle_pixel, 50, 50);
g2d.setColor(Color.BLUE);
}
Toolkit.getDefaultToolkit().
sync();
g2d.dispose();
}
private static int convertToPixelY(int y_offset, double y_world, double y_ratio)
{
return (int) (y_offset - (y_world * y_ratio));
}
private static int convertToPixelX(double x_world, double x_ratio)
{
return (int) (x_world * x_ratio);
}
When you draw an oval, the first two parameters are the upper-left corner of the rectangle that holds the oval. The next two parameters are the width and height of this same bounding rectangle. Your current code places the upper-left corner on the line itself, but what you actually want is that the center of the bounding rectangle be placed on the line. The solution to your problem is to simply shift the upper-left corner over by 1/2 the diameter. Your code should have something like so:
public class GraphicsFoo extends JPanel {
// avoid using magic numbers:
private static final int CIRCLE_DIAMETER = 50;
//....
// override a JComponent's paintComponent method, not its paint method
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.white);
// make your graphics smooth
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// ...
final double cosTheta = Math.cos(theta);
final double sinTheta = Math.sin(theta);
for (int distance = xFrom; distance <= len; distance += interval)
{
//....
// *** here's the key: ***
g2d.drawOval(
x_circle_pixel - CIRCLE_DIAMETER / 2,
y_circle_pixel - CIRCLE_DIAMETER / 2,
CIRCLE_DIAMETER, CIRCLE_DIAMETER);
g2d.setColor(Color.BLUE);
}

Categories