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've created a class called Tile, wich render an image to the screen by giving it an image, x posit., y posit., width, height and graphic object.Here's the code of that class:
package tile;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import image.Assets;
public class Tile {
public static int x, y, width, height;
public static BufferedImage image;
Graphics graf;
public static int id;
public Tile(int tx, int ty, int twidth, int theight, Graphics g, BufferedImage timage, int tId)
{
this.width = twidth;
this.x = tx;
this.y = ty;
this.image = timage;
this.graf = g;
this.height = theight;
this.id = tId;
}
public void render()
{
this.graf.drawImage(this.image, this.x, this.y, this.width, this.height, null);
}
//And then here are the getters and setters methods...
I want to create an array of object Tile where everyone element of this array has different properies.
So i write this code in another class:
...
Tile []t = new Tile[216];
for(int i = 0; i < 100; i++)
{
t[i] = new Tile(x, y, width, height, graphic, image, id)
t[i].render();
}
...
but everytime it creates a new Tile object in this array, the other created before this one take the same properties as the new created.
Where's my error/s?
Thanks for the answers and excuse me for this bad english.
Do not use static variables. Instead of writing
public static int x, y, width, height;
public static BufferedImage image;
public static int id;
try
public int x, y, width, height;
public BufferedImage image;
public int id;
Static Variables are global, that means they are shared by all instances. That is why properties are overwritten when you create new instances.
I made these methods:
public Player(double x, double y){
this.x = x;
this.y = y;
ImageLoader loader = new ImageLoader();
SpriteSheet ss = new SpriteSheet(loader.loadImage("/Pics/TheSpriteSheet.png"));
this.image = ss.grabImage(1, 1, 32, 32);
}
public void tick(){
this.x++;
}
public void render(Graphics g){
g.drawImage(image, (int) x, (int) y, null);
}
Then I put it in my tick method in my main class which gets called every nanosecond or so.
public void tick(){
playerClass.tick();
}
It looks like you are only updating the space ship's x position but you are not redrawing the screen. Therefore, the x position is increased but you won't see it on your screen!
You might use something like spaceShip.repaint();
I have a problem I was trying to solve for almost 2 days. (It ended up by switching to OpenGL :D)
Anyway... I have Canvas and I am trying to do a simple snake game. Just for this problem imagine our snake is made up from 5x5 pixels rectangles, he is leaving the trail (no clearing) and moving to the right from 0, 50 position... here is the code:
public class Snake extends AnimationWallpaper {
#Override
public Engine onCreateEngine() {
return new SnakeEngine();
}
class SnakeEngine extends AnimationEngine {
int i = 0;
Paint paint = new Paint();
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
// By default we don't get touch events, so enable them.
setTouchEventsEnabled(true);
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xOffsetStep, float yOffsetStep, int xPixelOffset,
int yPixelOffset) {
super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
xPixelOffset, yPixelOffset);
}
#Override
public Bundle onCommand(String action, int x, int y, int z,
Bundle extras, boolean resultRequested) {
if ("android.wallpaper.tap".equals(action)) {
}
return super.onCommand(action, x, y, z, extras, resultRequested);
}
#Override
protected void drawFrame() {
SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
draw(c);
}
} finally {
if (c != null)
holder.unlockCanvasAndPost(c);
}
}
void draw(Canvas c) {
//c.save();
//c.drawColor(0xff000000);
paint.setAntiAlias(true);
// paint the fill
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
c.drawRect(i*5, 50, (i+1)*5, 55, paint);
//c.restore();
}
#Override
protected void iteration() {
i++;
super.iteration();
}
}
}
And here is output:
And that is not all, when it draws its kinda shifting... meaning what you see is shifted to the right side so it doesnt actualy stand in the same place...
If you have any idea why is it behave like that, please tell me!
In canvas, there's a reusability functionality which practically just add new drawings to whatever is in the canvas, hence if you are drawing 1 square at the time, the next time you will have whatever u had before +1, if you don't want that, and you want to fully manipulate every single draw from scratch, just add this line of code before to start drawing
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
It will clear anything you had in the previous state of the canvas, and you can start again drawing whatever you want...
Hope It Helps!
Regards!
I would like to have a loop that will run through each of the images i have. I would like to draw them to the screen and it works fine if i draw each image separately but it uses a lot of code. Whilst using a loop to paint each image should uuse a lot less code. This is my code.
String image[] = {"carA", "carB"};
for(int i = 0; i < image.length; i++){
g.drawImage(image[i].getImage(), image[i].getX(), image[i].getY(),
image[i].getWidth(), image[i].getHeight(), this);
}
It says the problem is that strings are being used. The getX() and getY() etc finds out the x and y coordinates.
How can I get this to work?
You are trying to call getImage /getX / getY on the String object.
You should load your Image first into the Image object like that
Image img1 = Toolkit.getDefaultToolkit().getImage(image[i]);
Use the drawString() method, it can draw strings:
You should initialize all data about images, try this example:
String imageDatas[][] = {
{"image_path_1.jpg", "0", "0", "100", "100"},
{"image_path_2.jpg", "100", "0", "100", "100"}
};
for (String[] imageData : imageDatas) {
String filePath = imageData[0];
int x = Integer.parseInt(imageData[1]);
int y = Integer.parseInt(imageData[2]);
int width = Integer.parseInt(imageData[3]);
int height = Integer.parseInt(imageData[4]);
Image img = Toolkit.getDefaultToolkit().getImage(filePath);
g.drawImage(img, x, y, width, height, this);
}
String is a type that store characters. So it can not be used for your requirements.
To meet the requirements you should crate own type.
Good place to start i to create a interface that your class will be using.
public interface IMichaelImage {
int getX();
int getY();
Image getImage();
}
Then you need to create a class that will be able to store the information that you program logic will use
public MichaelImage implements IMichaelImage {
private int x = 0;
private int y = 0;
private Image image;
public MichaelImage(Image image) {
this.image = image;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
#Override
public int getX() {
return this.x;
]
#Override
public int getY() {
return this.x;
}
public Image getImage() {
return this.image;
}
}
On the and you will have something like this
Collection<IMichaelImage> images = loadImages();
for(IMichaelImage image : images) {
g.drawImage(image.getImage(), image.getX(), image.getY());
}