I'm doing a project in Java, using Android Studio, where I need to draw a polygon with the util vector. I need the user to insert the number of sides he wants for the polygon and then draw the polygon with the number on the input with the sides. I'd be very glad if someone could help me because I'm still starting on java.
This is my file Poligono.java:
import java.util.Vector;
public class Poligono extends Reta{
Vector<Ponto2D> pontos_poligono;
static int verifica_pontos=0;
public Poligono(Vector<Ponto2D> p5){
this.pontos_poligono=p5;
verifica_pontos=p5.size(); //Numero total de pontos no Vector (exemplo no array number=0 number=1 -> o size é 2)
}
public Double PerimetroPoligono(){
double perimetro=0;
for (int i=0; i < verifica_pontos ;i++){
Ponto2D pinicial = pontos_poligono.get(i);
Ponto2D pfinal = pontos_poligono.get(i+1);
perimetro+=pinicial.dist(pfinal);
}
return perimetro;
}
}
And this is Ponto2D.java:
public class Ponto2D {
int x, y;
public Ponto2D() {
this.x = 0;
this.y = 0;
}
public Ponto2D(int a, int b) {
x = a;
y = b;
}
}
And Reta.java:
public class Reta {
Ponto2D pinicial;
Ponto2D pfinal;
public Reta(){
pinicial = new Ponto2D();
pfinal = new Ponto2D();
}
public Reta(Ponto2D a, Ponto2D b){
pinicial = a;
pfinal = b;
}
}
Your post it's not 100% clear. First of all, you can't "draw" a polygon with vector (that is a way to store data). You have to use some Graphics library, create a window, create a canvas and so on...
If you want, instead, to conceptually represent the polygon, here my opinion.
Supposing that you want a regolar polygon, we can use sin ad cos to calculate the vertices position (see this).
You can create a Vector that stores all the polygon vertices. I suggest to extend Ponto2D, so you can store in x and y the center coordinates.
import java.util.Vector;
public class Poligono extends Ponto2D{
private Vector<Ponto2D> vertices;
private int num_vertices
public Poligono(int num_vertices){
super(); //If you use a center != (0,0) you have
//to add the center coordinates to all the vertices
//You also should add a radius (distance from
//the center to all vertices);
this.num_vertices=num_vertices;
this.radius=radius;
vertices=new Vector<>();
fillVector();
}
//This method calculate all the vertices position and
//store it in the Vector
private void fillVector(){
for(int i=0; i<num_vertices;i++){
//use sin and cos to calculate vertices
for (int i = 0; i < sides; ++i) {
x = (int) (Math.cos(theta * i));
y = (int) (Math.sin(theta * i));
vertices.add(new Ponto2D(x,y));
}
}
}
public Double PerimetroPoligono(){
//take every point of the vector, and add the distances between them.
}
}
Related
I'm building a small game in java where i have an Arraylist of Zombie objects that is used to select the next target for the player. The zombies are comprised of an x and y variable which dictates their initial position.
public Zombie(double positionX, double positionY){
this.image = new Image("res/images/zombie.png");
this.Position = new Point(positionX, positionY);
this.visible = true;
}
I have written this method which selects the next zombie in the array in which the player automatically targets, but I'm stuck trying to figure out how to dynamically sort the Arraylist so the player targets the closest zombie by distance, rather than the one next in the list.
public void zombieSpawn(){
for(int i = 0; i < zombies.size(); i++){
zombie = zombies.get(i);
if(!zombie.isVisible()){
removeZombie(zombie);
}
if(zombies.size() != 0){
this.zombie = zombies.get(0);
}
}
}
tl:dr I want to dynamically sort an Arraylist of zombies by shortest distance to the player.
Here I would use a custom ZombieSort class, which implements Comparator, that sorts the Zombies by comparing their distance from the player's coordinates.
Here is ZombieSort.java
public class ZombieSort implements Comparator<Zombie> {
private final double playerX, playerY;
public ZombieSort(double playerX, double playerY) {
this.playerX = playerX;
this.playerY = playerY;
}
#Override
public int compare(Zombie z1, Zombie z2) {
return Double.compare(getDistance(z1), getDistance(z2));
}
public double getDistance(Zombie zombie) {
return Math.sqrt(
Math.pow(zombie.x - playerX, 2) + Math.pow(zombie.y - playerY, 2)
);
}
}
And here would be your implementation for zombieSpawn(), which basically sorts the list of Zombies every time it is called.:
public void zombieSpawn(){
sortZombies(zombies, player);
for(int i = 0; i < zombies.size(); i++){
zombie = zombies.get(i);
if(!zombie.isVisible()){
removeZombie(zombie);
}
if(zombies.size() != 0){
this.zombie = zombies.get(0);
}
}
}
public void sortZombies(List<Zombie> zombies, Player player) {
Collections.sort(zombies, new ZombieSort(player.getX(), player.getY()));
}
I need to remove the recursion from the drawSquare method. There is a lot more I have to do after removing the recursion from that method however the rest I can figure out on my own. I just really need a working solution that does the exact same thing without recursion and I will figure out the rest.
Here is how I made the Square class:
import java.awt.Color;
public class Square {
final int BLACK = Color.BLACK.getRGB();
final int WHITE = Color.WHITE.getRGB();
protected int center_x;
protected int center_y;
protected int side;
protected int color;
protected Square parentSquare;
public Square(){
this.center_x = 0;
this.center_y = 0;
this.side = 0;
this.color = WHITE;
this.parentSquare = null;
}
public Square(int center_x,int center_y,int side,int color){
this.center_x = center_x;
this.center_y = center_y;
this.side = side;
this.color = color;
this.parentSquare = null;
}
public Square(int center_x,int center_y,int side,int color,Square parentSquare){
this.center_x = center_x;
this.center_y = center_y;
this.side = side;
this.color = color;
this.parentSquare = parentSquare;
}
public void setX(int center_x){
this.center_x = center_x;
}
public int getX(){
return center_x;
}
public void setY(int center_y){
this.center_x = center_y;
}
public int getY(){
return center_y;
}
public void setSide(int side){
this.side = side;
}
public int getSide(){
return side;
}
public void setColor(int color){
this.color = color;
}
public int getColor(){
return color;
}
public void setParent(Square parentSquare){
this.parentSquare = parentSquare;
}
public Square getParent(){
return parentSquare;
}
}
This is the original Tsquare.java that produces a fractal of squares branching from each squares 4 corners until the side = 0: (full TSquare.java class modified to use Square objects)
import java.awt.image.*;
import java.awt.Color;
import java.io.*;
import javax.imageio.*;
import java.util.*;
public class TSquare {
static final int SIDE = 1000; // image is SIDE X SIDE
static BufferedImage image = new BufferedImage(SIDE, SIDE, BufferedImage.TYPE_INT_RGB);
static final int WHITE = Color.WHITE.getRGB();
static final int BLACK = Color.BLACK.getRGB();
static Scanner kbd = new Scanner(System.in);
public static void main(String[] args) throws IOException{
String fileOut = "helloSquares.png";
System.out.print("Enter (x,y) coordinates with a space between: ");
int x = kbd.nextInt();
int y = kbd.nextInt();
System.out.println(x+","+y);//TESTLINE TESTLINE TESTLINE TESTLINE
// make image black
for (int i = 0; i < SIDE; i++) {
for (int j = 0; j < SIDE; j++) {
image.setRGB(i, j, BLACK);
}
}
Square square = new Square(SIDE/2,SIDE/2,SIDE/2,WHITE);
drawSquare(square);
// save image
File outputfile = new File(fileOut);
ImageIO.write(image, "jpg", outputfile);
}
private static void drawSquare(Square square){ // center of square is x,y length of side is s
if (square.side <= 0){ // base case
return;
}else{
// determine corners
int left = square.center_x - (square.side/2);
int top = square.center_y - (square.side/2);
int right = square.center_x + (square.side/2);
int bottom = square.center_y + (square.side/2);
int newColor =square.color-100000;
Square newSquareA = new Square(left,top,square.side/2,newColor);
Square newSquareB = new Square(left,bottom,square.side/2,newColor);
Square newSquareC = new Square(right,top,square.side/2,newColor);
Square newSquareD = new Square(right,bottom,square.side/2,newColor);
for (int i = left; i < right; i++){
for (int j = top; j < bottom; j++){
image.setRGB(i, j, square.color);
}
}
// recursively paint squares at the corners
drawSquare(newSquareA);
drawSquare(newSquareB);
drawSquare(newSquareC);
drawSquare(newSquareD);
}
}
}
I'm looking to reproduce the exact actions of this code just minus the recursion and everything I try doesn't seem to work. I cant even get a single white square to display on top of the original black canvas.
If we want readability without compromising speed I suggest first making some additions to Square:
public int half() {
return side/2;
}
public int left() {
return center_x - half();
}
public int top() {
return center_y - half();
}
public int right() {
return center_x + half();
}
public int bottom() {
return center_y + half();
}
public void draw(BufferedImage image) {
int left = left();
int top = top();
int right = right();
int bottom = bottom();
for (int i = left; i < right; i++){
for (int j = top; j < bottom; j++){
image.setRGB(i, j, color);
}
}
} //End Square
Also moving I/O out to enable unit testing.
package com.stackoverflow.candied_orange;
import java.awt.image.*;
import java.awt.Color;
import java.io.*;
import javax.imageio.*;
import java.util.*;
public class FractalSquareIterative {
public static void main(String[] args) throws IOException{
final int SIDE = 1000; // image is SIDE X SIDE
BufferedImage image = new BufferedImage(SIDE,SIDE,BufferedImage.TYPE_INT_RGB);
drawImage(SIDE, image);
saveImage(image);
}
//Removed IO to enable unit testing
protected static void drawImage(final int SIDE, BufferedImage image) {
final int BLACK = Color.BLACK.getRGB();
final int WHITE = Color.WHITE.getRGB();
final int HALF = SIDE / 2;
//Draw background on whole image
new Square(HALF, HALF, SIDE, BLACK).draw(image);
//Draw foreground starting with centered half sized square
Square square = new Square(HALF, HALF, HALF, WHITE);
drawFractal(square, image);
}
Now that Square is dealing with all the square things the fractal code is a little easier on the eyes.
private static void drawFractal(Square square, BufferedImage image){
Queue<Square> squares = new LinkedList<>();
squares.add(square);
while (squares.size() > 0) {
//Consume
square = squares.remove();
//Produce
int half = square.half();
if (half > 2) {
int left = square.left();
int top = square.top();
int right = square.right();
int bottom = square.bottom();
int newColor = square.color - 100000;
squares.add(new Square(left, top, half, newColor));
squares.add(new Square(left, bottom, half, newColor));
squares.add(new Square(right, top, half, newColor));
squares.add(new Square(right, bottom, half, newColor));
}
square.draw(image);
}
}
protected static void saveImage(BufferedImage image) throws IOException {
String fileOut = "helloSquares.png";
File outputfile = new File(fileOut);
ImageIO.write(image, "jpg", outputfile);
}
} //End FractalSquareIterative
Reliably faster than the recursive version but not significantly so at this size.
If you want a peek at my unit tests you'll find them here.
Here's one implementation using an ArrrayDeque ( https://docs.oracle.com/javase/7/docs/api/java/util/ArrayDeque.html ).
It's worth comparing ArrayDeque against some other Java types :
a) Stack is an interface, and the api page (https://docs.oracle.com/javase/8/docs/api/java/util/Stack.html) says
A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class.
b) I originally wrote this using good old familiar ArrayList, with Square square = squares.remove(0); instead of pop. I am quite surprised at how much faster this ArrayDeque implementation appears to be than that ArrayList (not that I have run any formal benchmarks)
private static void drawSquare(Square startSquare){
Deque<Square> squares = new ArrayDeque<Square>(400000);
squares.push(startSquare);
while (!squares.isEmpty()) {
Square square = squares.pop();
System.out.println(square);
// center of square is x,y length of side is s
if (square.side > 0){ // base case
// determine corners
int left = square.center_x - (square.side/2);
int top = square.center_y - (square.side/2);
int right = square.center_x + (square.side/2);
int bottom = square.center_y + (square.side/2);
int newColor =square.color-100000;
addSquare(squares, left,top,square.side/2,newColor);
addSquare(squares, left,bottom,square.side/2,newColor);
addSquare(squares, right,top,square.side/2,newColor);
addSquare(squares, right,bottom,square.side/2,newColor);
}
}
}
private static void addSquare(Deque<Square> squares, int x, int y, int side, int color) {
// STRONGLY recommend having this "if" statement !
// if (side > 0) {
squares.push(new Square(x, y, side, color));
// }
}
As noted in my comment, it is WELL worthwhile to not create squares of size 0 rather than creating them and simply ignoring them when their turn comes around. This would be true for the recursion-based operations as well - but especially so for these non-recursion based ones, since the multitude of squares would be really eating up memory and processing time.
I try to make my own simple game with pairs of images that player try to guess position of same ones and I have no clue how to have 2 same bufferedimages that are animated put on frame in random position that not extends frame size and what need to be done to images to dont put them on same x and y that previous ones. Can collision system do the work and remove the image put on similiar x and y or is there better solutions.
What I got for now is full one image animated that can be covered by the
covering image.
What I did to achieve this.
public Rozmiar(Game game, Textures tex) {
this.game = game;
this.tex = tex;
for (int x = 128; x < (Game.WIDTH * Game.SCALE - 128); x += 128) {
for (int y = 96; y < (Game.HEIGHT * Game.SCALE - 96); y += 128) {
addOdkryte(new Odkryte(x, y, tex));
}
}
}
public void addOdkryte(Odkryte block) {
os.add(block);
}
package com.game.src.main;
import java.awt.Graphics;
import java.util.LinkedList;
public class Odkryte {
private double x;
private double y;
private Textures tex;
Animation anim;
Animation anim1;
private int counter;
public Odkryte(double x, double y, Textures tex) {
this.x = x;
this.y = y;
this.tex = tex;
anim = new Animation(3, tex.odkimg1px128[0], tex.odkimg1px128[1], tex.odkimg1px128[2], tex.odkimg1px128[3],
tex.odkimg1px128[4], tex.odkimg1px128[5], tex.odkimg1px128[6], tex.odkimg1px128[7], tex.odkimg1px128[8],
tex.odkimg1px128[9]);
}
public void tick() {
anim.runAnimation();
}
public void render(Graphics g) {
anim.drawAnimation(g, x, y, 0);
}
}
Add the pairs of images to an ArrayList
Use the Collections.shuffle(...) method on the ArrayList to randomize the images
Iterate through the ArrayList and add each image to the frame.
So I can load a 2D map using tiles using a text file, which is great and all. However, one issue I have met with this method is that I can't add objects/actors to my map since the file is a 2D grid. (The game is similar to games like zelda and pokemon.) I've tried creating an object layer so I can overlap images, but it doesn't seem to work for me. To give an example of what I want, have objects such as trees to be solid and on top of the background grass.
I am also looking for better methods to creating these tile based maps if you want to pitch some ideas to me.
**Note: I am about beginner/intermediate at Java.
Here is my constructor for the GameState class that calls the Map.
public GameState(Game game) {
super(game);
player = new Player(game, 0, 0, 64, 64);
map = new Map(game, "res/saves/save1.txt");
}
Here is the Map class (which works) that also calls the object (2nd) layer.
private int width, height;
public static int spawnX, spawnY;
private int[][] mapTiles;
MapObjects mapObjects;
Game game;
public Map(Game game, String path) {
this.game = game;
mapObjects = new MapObjects(game, "res/saves/save1_obj.txt", width, height);
loadMap(path);
}
private void loadMap(String path) {
String file = Utils.loadFileAsString(path);
//Token is which number it is out of the total
String[] tokens = file.split("\\s+");
//Sets what is what
width = Utils.parseInt(tokens[0]);
height = Utils.parseInt(tokens[1]);
spawnX = Utils.parseInt(tokens[2]);
spawnY = Utils.parseInt(tokens[3]);
mapTiles = new int[width][height];
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
// (x+y*width) : calculates the nth token (+4) : The 4 prior tokens before the graph
mapTiles[x][y] = Utils.parseInt(tokens[(x + y *width) + 4]);
}
}
}
public void render(Graphics g) {
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
//Only renders what is seen.
getMapTile(x, y).render(g, (int)(x*Tile.TILE_WIDTH-game.getCamera().getxOffset()), (int)(y*Tile.TILE_HEIGHT-game.getCamera().getyOffset()));
}
}
}
public void tick() {
}
//Gets the specific tile at specific coordinates.
private Tile getMapTile(int x, int y) {
Tile t = Tile.tiles[mapTiles[x][y]];
if(t == null) {
return Tile.grassTile;
}
return t;
}
And lastly, the object layer that doesn't work. It does not give an error, just the overlapping objects aren't visible. I've made sure to load the object layer before the Map layer, but that doesn't seem to be the issue.
private int width, height;
private int[][] objTiles;
Game game;
public MapObjects(Game game, String path, int width, int height) {
this.game = game;
loadObjects(path, width, height);
}
public void loadObjects(String path, int width, int height) {
this.width = width;
this.height = height;
String file = Utils.loadFileAsString(path);
String[] tokens = file.split("\\s+");
objTiles = new int[width][height];
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
objTiles[x][y] = Utils.parseInt(tokens[(x + y *width)]);
}
}
}
public void render(Graphics g) {
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
//Only renders what is seen.
getObjTile(x, y).render(g, (int)(x*Tile.TILE_WIDTH-game.getCamera().getxOffset()), (int)(y*Tile.TILE_HEIGHT-game.getCamera().getyOffset()));
}
}
}
public void tick() {
}
//Gets the specific object tile at specific coordinates.
private Tile getObjTile(int x, int y) {
Tile t = Tile.tiles[objTiles[x][y]];
if(t == null) {
return Tile.nothingTile;
}
return t;
}
We may need a bit more info from you.
Do you use a different "container/component" to draw map tiles than you do for your objects? Because if you render objects first then they will disappear as soon as you render the map. You should draw the map first, and then do objects like so:
public Map(Game game, String path) {
this.game = game;
//swapped the order of the lines below so the map loads first:
loadMap(path);
mapObjects = new MapObjects(game, "res/saves/save1_obj.txt", width, height);
}
From what you have said then this does not work either, however if you use the same component to draw your map and objects then one will always override the other, and something will always be missing. To fix this you need to crease two separate panes, one for the map, and a transparent one that sits on top of the map that you can use to render your objects.
See this illustration as an example:
You basically need to add a new transparent "content plane" similar to the way that glass pane shown above.
So am working on a School Project, and I want to draw a game board made out of Rectangles which are saved in an array. I managed to do that, but only the last drawn Rectangle Stays on the Panel. I'm really desperate and i don't know where my mistake is.
The Field is a 4x5 field. The Coordinates saved in the Tile Class:
the first two represent the upper left Corner
the last two represent the bottom right corner of it
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class quoVadis{
public static void main(String[] args) {
new Frame();
}
}
class Tile {
Random rGen = new Random();
int sX,sY,eX,eY;
Color farbe;
public Tile(int sX, int sY,int eX,int eY){
this.sX = sX;
this.sY = sY;
this.eX = eX;
this.eY = eY;
farbe = new Color(rGen.nextInt(156)+100,rGen.nextInt(156)+100,rGen.nextInt(156)+100);
}
}
class Frame extends JFrame{
private Game game;
final int GAMESIZE = 400;
final int PANELSIZE = GAMESIZE/5;
public Frame() {
super("Quo Vadis");
this.setSize(GAMESIZE, GAMESIZE*5/4);
this.setLocation(50, 50);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game = new Game(GAMESIZE, PANELSIZE);
game.setLayout(null);
game.setBackground(Color.WHITE);
this.getContentPane().add(game);
this.setVisible(true);
}
}
class Game extends JPanel{
int GAMESIZE;
int PANELSIZE;
private Tile field[][]=new Tile[4][5];
Random rGen = new Random(4711);
Tile stein;
public Game(int g, int p) {
GAMESIZE = g;
PANELSIZE = p;
// The Mistake has to be in this following Part:
int idx=0;
for(Tile i:levels){
for(int j = i.sX; j <= i.eX; j++){
for(int k = i.sY; k <= i.eY; k++){
field[j][k] = levels[idx];
}
}
idx++;
}
for(int k = 0; k <= 4; k++){
for(int j = 0; j <= 3; j++){
if(field[j][k]==null)continue;
stein=field[j][k];
draw((field[j][k].sX * PANELSIZE) , (field[j][k].sY * PANELSIZE) , ((((field[j][k].eX-field[j][k].sX) + 1) * PANELSIZE) -1), ((((field[j][k].eY-field[j][k].sY)+ 1) * PANELSIZE) -1));
}
}
this.setVisible(true);
}
int rx, ry,rdx,rdy;
private void draw(int a, int b, int c, int d){
rx=a;
ry=b;
rdx=c;
rdy=d;
repaint(rx,ry,rdx,rdy);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(stein.farbe);
g.fillRect(rx, ry, rdx, rdy);
}
Tile[] levels = {
new Tile(1,0,2,1),
new Tile(0,0,0,1),
new Tile(3,0,3,1),
new Tile(0,2,0,3),
new Tile(1,2,2,2),
new Tile(3,2,3,3),
new Tile(0,4,0,4),
new Tile(1,3,1,3),
new Tile(2,3,2,3),
new Tile(3,4,3,4),
};
}
I already checked the Position of the Rectangles in numbers and they are correct in every way so they do not overlap or something like that.
Sorry for my bad english, it's not my primary language.
You need to draw each rectangle inside of your paintComponent method every time.
Currently you are calling your draw method for one rectangle then you call repaint and draw that single rectangle. paintComponent will redraw the entire panel each time it is called. This means that it will on preserve the last rectangle (the rest were "repainted over".
You want to loop through all of your tiles and use the drawRect method to draw them inside of your paintComponent method so they will be drawn every time.
public void paintComponent(Graphics g) {
super.paintComponent(g)
for(int k = 0; k <= 4; k++){
for(int j = 0; j <= 3; j++){
if(field[j][k]==null)continue;
stein=field[j][k];
g.setColor(stein.farbe);
g.fillRect((field[j][k].sX * PANELSIZE) , (field[j][k].sY * PANELSIZE) , ((((field[j][k].eX-field[j][k].sX) + 1) * PANELSIZE) -1), ((((field[j][k].eY-field[j][k].sY)+ 1) * PANELSIZE) -1));
}
}
}