Related
I created an application which allows instantiating shapes which can be circle rectangle or anything and used sorting technique (Bubble Sort) to sort the six shapes based on interfaces.
The problem is I am not familiar with Design patterns and what patterns are being used- I am new so i followed youtube videos and played around with it and it worked.
I have 1 main class where I have
MAIN :
public class Main {
public static void main(String[] args) {
JButton btnLoadShapes, btnSortShapes;
btnLoadShapes = new JButton("Load Shapes");
btnLoadShapes.setBounds(150, 10, 150, 30);
btnSortShapes = new JButton("Sort Shapes");
btnSortShapes.setBounds(310, 10, 150, 30);
JPanel panelShapes = new JPanel() {
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Shape shape = new Shape();
g2d.setColor(Color.RED);
Square s = shape.getS();
g2d.fillRect(s.getX(),s.getY(),s.getWidth(), s.getHeight());
g2d.setColor(Color.BLUE);
Circle c = shape.getC();
g2d.fillOval(c.getX(),c.getY(), c.getWidth(), c.getHeight());
g2d.setColor(new Color(131, 21, 1));
Rectangle r = shape.getR();
g2d.fillRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
g2d.setColor(Color.PINK);
Circle C1 = shape.getC1();
g2d.fillOval(C1.getX(),C1.getY(), C1.getWidth(), C1.getHeight());
g2d.setColor(Color.green);
Square S1 = shape.getS1();
g2d.fillRect(S1.getX(),S1.getY(),S1.getWidth(), S1.getHeight());
g2d.setColor(Color.magenta);
Rectangle r2 = shape.getR2();
g2d.fillRect(r2.getX(),r2.getY(),r2.getWidth(), r2.getHeight());
}
};
panelShapes.setBounds(10, 50, 560, 500);
panelShapes.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panelShapes.setVisible(false);
btnLoadShapes.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
panelShapes.setVisible(true);
}
});
and i have created 3 different classes Circle Rectangle and Square - from which i call for rectangle = shape.getC();
For example
public class Circle {
private int x, y, width, height;
public Circle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
Now the lastly I created 2 more classes called Shape and Sorting
where in shape i intiated public shape s = new Square with dimensions and set getters and setters and lastly i used sorting technique.
Can someone help me understand what are the design patterns that are being used here?
( I assume that Factory method is being used = since i defined main (* interface) and created subclasses ( Shapes rectangle circle) to instantiate.
Sorry if i sound out the place- I am just trying to understand and learn it.
A "factory" creates "something", the important thing in this context is, you don't care "how" it's created, only that it conforms to the specified type.
For example, you have a ShapeFactory which can create different shapes, you don't care "how" those shapes are defined or implemented, only that they conform to the notion of a "shape"
So, lets start with a basic concept...
public interface Shape {
public void paint(Graphics2D g2d);
}
This just defines a basic concept and states that it can be painted.
Next, we need something to create those shapes...
public class ShapeFactory {
enum ShapeType {
CIRCLE, RECTANGE, SQUARE;
}
public static Shape create(ShapeType type, int x, int y, int width, int height, Color storkeColor, Color fillColor) {
return null;
}
}
Ok, as it stands, that's pretty boring, it's only ever going to return null right now, but this gives us a basic contract.
"Please factory, create me shape of the specified type, within the specified bounds, with the specified colors"
Now, as I said, the implementation is unimportant, to the caller, and we could have a dynamic factory which could delegate the creation to other factories which could create shapes differently based on a wide ranging set of needs ... but that's getting ahead of ourselves.
Let's go about creating some actual shapes...
public abstract class AbstractShape implements Shape {
private int x;
private int y;
private int width;
private int height;
private Color storkeColor;
private Color fillColor;
public AbstractShape(Color storkeColor, Color fillColor) {
this.storkeColor = storkeColor;
this.fillColor = fillColor;
}
public AbstractShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
this(storkeColor, fillColor);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
protected void setX(int x) {
this.x = x;
}
protected void setY(int y) {
this.y = y;
}
protected void setWidth(int width) {
this.width = width;
}
protected void setHeight(int height) {
this.height = height;
}
public Color getStorkeColor() {
return storkeColor;
}
public Color getFillColor() {
return fillColor;
}
#Override
public void paint(Graphics2D g2d) {
Graphics2D g = (Graphics2D) g2d.create();
Color storkeColor = getStorkeColor();
Color fillColor = getFillColor();
if (fillColor != null) {
g.setColor(fillColor);
paintFilled(g);
}
if (storkeColor != null) {
g.setColor(storkeColor);
paintStroked(g);
}
g.dispose();
}
abstract protected void paintFilled(Graphics2D g2d);
abstract protected void paintStroked(Graphics2D g2d);
}
public class CircleShape extends AbstractShape {
public CircleShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
super(storkeColor, fillColor);
int size = Math.min(width, height);
x = x + ((width - size) / 2);
y = y + ((height - size) / 2);
setX(x);
setY(y);
setWidth(size);
setHeight(size);
}
#Override
protected void paintFilled(Graphics2D g2d) {
g2d.fillOval(getX(), getY(), getWidth(), getHeight());
}
#Override
protected void paintStroked(Graphics2D g2d) {
g2d.drawOval(getX(), getY(), getWidth(), getHeight());
}
}
public class SquareShape extends AbstractShape {
public SquareShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
super(storkeColor, fillColor);
int size = Math.min(width, height);
x = x + ((width - size) / 2);
y = y + ((height - size) / 2);
setX(x);
setY(y);
setWidth(size);
setHeight(size);
}
#Override
protected void paintFilled(Graphics2D g2d) {
g2d.fillRect(getX(), getY(), getWidth(), getHeight());
}
#Override
protected void paintStroked(Graphics2D g2d) {
g2d.drawRect(getX(), getY(), getWidth(), getHeight());
}
}
public class RectagleShape extends AbstractShape {
public RectagleShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
super(x, y, width, height, storkeColor, fillColor);
}
#Override
protected void paintFilled(Graphics2D g2d) {
g2d.fillRect(getX(), getY(), getWidth(), getHeight());
}
#Override
protected void paintStroked(Graphics2D g2d) {
g2d.drawRect(getX(), getY(), getWidth(), getHeight());
}
}
I always like a abstract class to carry the "common" functionality and to help make life a little simpler.
The important thing here is to note that both CircleShape and SquareShape, by their nature are, well, square (they have equal width and height). So, in this implementation, I define them to fit within the middle of the specified bounds - this is a "implementation" detail.
"But isn't that what I'm doing you?" you ask. Well, no, not really. When you call shape.getS(), for example, it's return a concrete class, which I assume has the same properties as the last object created by it, otherwise it will move all over the place.
Instead, what I'm doing is allowing you to define the properties you want the shape to have and then making it.
You want a cake? Sure, pass me the ingredients and I'll make you a cake, you still end up with a cake, but depending on the ingredients it's a different "type" of cake.
So, based on the above, we could do something like...
public class TestPane extends JPanel {
private List<Shape> shapes = new ArrayList<>(25);
public TestPane() {
shapes.add(ShapeFactory.create(ShapeFactory.ShapeType.CIRCLE, 10, 10, 200, 100, Color.RED, Color.BLUE));
shapes.add(ShapeFactory.create(ShapeFactory.ShapeType.RECTANGE, 10, 120, 200, 100, Color.BLUE, Color.GREEN));
shapes.add(ShapeFactory.create(ShapeFactory.ShapeType.SQUARE, 10, 240, 200, 100, Color.GREEN, Color.YELLOW));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(220, 350);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Shape shape : shapes) {
shape.paint(g2d);
}
g2d.dispose();
}
}
I could have made the ShapeFactory with dedicated createCircle, createRectangle and createSquare methods, I could have had them return interfaces of Circle, Square and Rectangle (and I would have based those of Shape because I'm like that) and it would still be a factory.
One of things to keep in mind is, a "factory" should be implementation independent. I should be able to make use of "different" shape factories to get different effects, but at the end of the day, they'd still just be generating Shapes
Remember, a factory will take something and it will create something from it.
i need to change the colour of a car PNG image when it crash to a block, like a kind of filter here's the 2 class
public class Sprite {
//classe estendibile a tutti gli oggetti
protected int x;
protected int y;
protected int width;
protected int height;
protected boolean visible;
protected Image image;
public Sprite(int x, int y) {
this.x = x;
this.y = y;
visible = true;
}
protected void getImageDimensions() {
width = image.getWidth(null);
height = image.getHeight(null);
}
protected void loadImage(String imageName) {
ImageIcon ii = new ImageIcon(imageName);
image = ii.getImage();
}
public Image getImage() {
return image;
public Rectangle getBounds() {
return new Rectangle(x, y, width,
height);
}
}`
public class Car extends Sprite {
public Car(int x, int y) {
super(x, y);
loadImage("src/car.png");
getImageDimensions();
}
Well I suppose it depends on the picture. If your picture looks like this
I suppose that going pixel by pixel and using image.setRGB(x, y, newColour) on pixels, that satisfy a condition of image.getRGB(x, y) == colourToChange will work. If you want to process a picture like
you would probably first need to run some recognition algorithm to find out which pixels are actually of the car and which are the background (wheels, shadows, etc.) and then run a filter over those. While this time based on the RGB of the original pixel you would need to calculate the new colour so that what was originally dark, remains dark and what was originally light remains light and so on.
I have a java application that i have been coding, it is an application that can allow me to draw shapes like a rectangle. My application can draw shapes but I cannot save them because when i try to draw a new shape and I click somewhere else the previously drawn shape disappears and is replaced by a new one. I tried array list to save my shapes but it does not work.
here is my code:
public class Toile extends JPanel {
Vector<Forme> forme = new Vector<Forme>();
private Color couleur;
private int x;
private int y;
private int x2;
private int y2;
private Oval oval;
private Rectangl rect;
public Toile(){
initComponents();
}
public void initComponents(){
addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent evt) {
formMousePressed(evt); }
public void mouseReleased(java.awt.event.MouseEvent evt) {
formMouseReleased(evt); } });
addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseDragged(java.awt.event.MouseEvent evt) {
formMouseDragged(evt); } });
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(couleur);
drawfillRect(g, x, y, x2, y2);
}
public void setStartPoint(int x, int y) {
this.x = x;
this.y = y;
}
public void setEndPoint(int x, int y) {
x2 = (x);
y2 = (y);
}
public void drawfillRect(Graphics g, int x, int y, int x2, int y2) {
int px = Math.min(x,x2);
int py = Math.min(y,y2);
int pw=Math.abs(x-x2);
int ph=Math.abs(y-y2);
//g.fillRect(px, py, pw, ph);
Rectangl rect = new Rectangl(px,y,x2,py,pw,ph,couleur,true);
rect.dessinerfrect(g);
forme.add(rect);
}
}
private void formMousePressed(java.awt.event.MouseEvent evt) {
setStartPoint(evt.getX(), evt.getY());
repaint();
}
private void formMouseReleased(java.awt.event.MouseEvent evt) {{
setEndPoint(evt.getX(), evt.getY());
repaint();
//dessiner(this.getGraphics());
}
}
private void formMouseDragged(java.awt.event.MouseEvent evt){{
setEndPoint(evt.getX(), evt.getY());
repaint();
//dessiner(this.getGraphics());
}
}
As you can see this is the class that does the drawings, the rectangle that will be drawn is an object from a class that I created and this class is a subclass of a super class Forme. As I said previously, the application can draw shapes but the shapes that are drawn are not saved. Also I removed the getters and setters from my post because I wanted to keep only what was essential and I wanted to make my post clearer.
Here is the class Rectangl:
public class Rectangl extends Forme {
private int largeur;
private int hauteur;
private Rectangle rectangle;
public Rectangl(int x1,int y1, int x2 ,int y2,int largeur,int hauteur,Color couleur,Boolean plein){
super(x1,y1,x2,y2,couleur,plein);
this.largeur = largeur;
this.hauteur = hauteur;
}
public void dessinerrect(Graphics g){
g.setColor(couleur);
g.drawRect((int)point1.getX(), (int)point2.getY(), largeur, hauteur);
}
public void dessinerfrect(Graphics g){
g.setColor(couleur);
g.fillRect((int)point1.getX(), (int)point2.getY(), largeur, hauteur);
}
}
You'll need to implement a display list. This is a data structure that represents all the items currently in the drawing. The component painter just traverses the list and draws each item (usually after erasing the screen so that deleted objects don't appear in the new drawing). It also optionally draws the "rubberband cursor" if the mouse has been pressed and not yet released. The mouse actions (usually releasing the mouse button just modify status variables including display list (add, select, delete, etc.) and then repaint the drawing surface so the component painter is called.
A Java ArrayList is a reasonable way to implement a simple display list. The items themselves are a classical use of interfaces and/or inheritance:
interface DisplayListItem {
void draw(Graphics g);
}
abstract class AbstractRectangle implements DisplayListItem {
protected int x, y, w, h;
protected Color color;
Rectangle(int x, int y, int w, int h, Color color) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
}
}
class Rectangle extends AbstractRectangle {
Rectangle(int x, int y, int w, int h, Color color) {
super(x, y, w, h, color);
}
#Override
void draw(Graphic g) {
g.setColor(color);
g.drawRect(x, y, w, h);
}
}
class FilledRectangle extends AbstractRectangle {
FilledRectangle(int x, int y, int w, int h, Color color) {
super(x, y, w, h, color);
}
#Override
void draw(Graphic g) {
g.setColor(color);
g.fillRect(x, y, w, h);
}
}
private List<DisplayListItem> displayList = new ArrayList<>();
private int xPress, yPress, xDrag, yDrag;
private boolean mousePressed = false;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (DisplayListItem item : displayList) {
item.draw(g);
}
if (mousePressed) {
// Draw the click-and-drag cursor.
g.setColor(Color.RED);
g.drawRect(xPress, yPress, xDrag - xPress, yDrag - yPress);
}
}
private void formMousePressed(MouseEvent evt) {
xPress = evt.getX();
yPress = evt.getY();
mousePressed = true;
}
private void formMouseDragged(MouseEvent evt) {
if (!mousePressed) return;
xDrag = evt.getX();
yDrag = evt.getY();
repaint();
}
private void formMouseReleased(MouseEvent evt) {
if (!mousePressed) return;
xDrag = evt.getX();
yDrag = evt.getY();
// Adding a rectangle to the display list makes it permanent.
displayList.add(new Rectangle(xPress, yPress, xDrag - xPress, yDrag - yPress));
mousePressed = false;
repaint();
}
Caveat: This is uncompiled, untested code. Use at your own risk.
Swing has the useful Shape interface which has been implemented into several concrete classes that could serve your purpose well.
There are several different Shapes (Ellipse2D, Rectangle2D, RoundRectangle2D) are stored in an ArrayList of Shape objects, and then these are drawn within the JPanel's paintComponent method after first casting the Graphics object into a Graphics2D.
I have a class called vbPop (which is basically just a player) and it is just a rectangle right now, i wanted to ask how to load an image instead of just a rectangle?
This is the constructor:
public vbPop(Color c, int x, int y, int n) {
this.colour = c;
this.posX = x;
this.posY = y;
this.vakNummer = n;
}
and the code to draw is:
public void draw (Graphics g){
g.setColor(this.colour);
g.fillRect(posX, posY, width, height);
g.setColor(Color.BLACK);
g.drawRect(posX, posY, width, height);
}
You have to add a BufferedImage to your player object, e.g
try {
img = ImageIO.read(getClass().getResourceAsStream("/img.png"));
} catch(IOException e){
e.printStackTrace();
}
"/img.png" is a relativ path, in this case img.png is located in your source folder.
afterwards you can display your image in the draw() method so:
g.drawImage( img, posX, posY, width, heigth, null);
EDIT: this bug only happens when I run my game on my Ubuntu 14.04 laptop. When I run it on the Windows school computers it works fine.
the window lags when running normally, but stops lagging while I resize the window with my mouse
I'm trying to make a simple game in java, however when ever I run it, it lags like crazy, I've looked over the code, and done some checks with System.out.println and System.currentTimeMillis and the code runs in much less than a millisecond, so that's not the problem.
The program stops when I drag to resize the window and constantly change the size of the window (presumably forcing a screen redraw), it has nice smooth animation when I do this.
When my program is running, it starts of with smooth animation, then about 1 second later it goes to about 2 FPS, then another second later to goes to 1 FPS, then about 0.5FPS and stays there until I force a repaint by resizing the window
my code is:
public class WindowSetup extends JPanel{
private static final long serialVersionUID = 6486212988269469205L;
static JFrame frame;
static JPanel panel;
protected void paintComponent(Graphics g){
super.paintComponent(g);
GameClass.draw(g);
}
public static void main(String[] args) {
frame = new JFrame("Evolver");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
panel = new WindowSetup();
frame.add(panel);
panel.setVisible(true);
frame.setVisible(true);
GameClass.init();
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
GameClass.tick();
panel.repaint();
}
};
Timer timer = new Timer(50,al); // lower numbers here make it run faster, but it still ends up slowing down to 1FPS
timer.start();
}
}
My GameClass:
public class GameClass {
static Random random;
static ArrayList<Enemy> enemies = new ArrayList<Enemy>();
static Wall wall;
static void init(){
random = new Random();
wall=new Wall();
for(int i=0;i<5;i++){
enemies.add(new Enemy(random.nextInt(200)+100,random.nextInt(200)+100,10,10,(float) (random.nextFloat()*(Math.PI*2)),1));
}
}
static void tick(){
for(Enemy d:enemies){
d.tick();
}
}
static void draw(Graphics g){
for(Enemy d:enemies){
d.draw(g);
}
wall.draw(g);
}
}
Enemy Class:
public class Enemy {
float x;
float y;
float width;
float height;
float direction;
float speed;
public Enemy(float x, float y, float width, float height, float direction, float speed) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.direction = direction;
this.speed = speed;
}
public void tick() {
direction += 0.01;
if (!(GameClass.wall.collides((int) (x + (Math.cos(direction) * speed)), (int) (y + (Math.sin(direction) * speed)),(int)width,(int)height))) {
x += Math.cos(direction) * speed;
y += Math.sin(direction) * speed;
}
}
public void draw(Graphics g) {
g.drawRect((int) x, (int) y, (int) width, (int) height);
}
}
Wall code:
public class Wall {
ArrayList<Rectangle> rectlist = new ArrayList<Rectangle>();
public Wall() {
// create list of walls here
rectlist.add(new Rectangle(10, 10, 50, 400));
rectlist.add(new Rectangle(410,10,50,400));
rectlist.add(new Rectangle(60,10,350,50));
rectlist.add(new Rectangle(60,360,350,50));
}
public void draw(Graphics g) {
for (Rectangle d : rectlist) {
g.drawRect(d.x, d.y, d.width, d.height);
}
}
public boolean collides(int x,int y,int width,int height){
for(Rectangle d:rectlist){
if(d.intersects(x, y, width, height)){
return true;
}
}
return false;
}
}
There's a problem with linux's graphics scheduling meaning it gets slower and slower for some reason. The solution to this is using Toolkit.getDefaultToolkit().sync() after you do panel.repaint(), this stops the slowdown.
This function doesn't seem to help anything on other OSes, but it does take up precious CPU cycles (quite a lot of them, actually), so use System.getProperty("os.name") to determine if you need to use it.
As a workaround, I guess you can 'simulate' the resize behavior by adding setVisible(false) and setVisible(true) around your action listener:
public void actionPerformed(ActionEvent e) {
panel.setVisible(false);
GameClass.tick();
panel.repaint();
panel.setVisible(true);
}