I am going to develop an app where I draw rectangles with this method:
private int columnWidth = 1;
private int rowHeight = 1;
private int nbColumns = 1;
private int nbRows = 1;
public static final int DEFAULT_SIZE = 150;
private void initWorld() {
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point point = new Point();
display.getSize(point);
// we calculate the number of columns and rows for our World
nbColumns = point.x / DEFAULT_SIZE;
nbRows = point.y / DEFAULT_SIZE;
// we calculate the column width and row height
columnWidth = point.x / nbColumns;
rowHeight = point.y / nbRows;
world = new World(nbColumns, nbRows);
}
// Method to draw each cell of the world on the canvas
private void drawCells(Canvas canvas) {
for (int i = 0; i < nbColumns; i++) {
for (int j = 0; j < nbRows; j++) {
Cell cell = world.get(i, j);
r.set((cell.x * columnWidth) - 1, (cell.y * rowHeight) - 1,
(cell.x * columnWidth + columnWidth) - 1,
(cell.y * rowHeight + rowHeight) - 1);
// we change the color according the alive status of the cell
p.setColor(cell.alive ? DEFAULT_ALIVE_COLOR : DEFAULT_DEAD_COLOR);
canvas.drawRect(r, p);
}
}
}
Can anyone tell me, how could I get some space or lines between the rectangles?
Related
I am basically making a battleship guessing game where you have to the position of a ship by the click of your mouse. When a position of the ship is guessed correctly it deletes that ship cell from the array and when every cell is guessed correctly, the game is over.
What I am now struggling on is to
keep the ship cells within the canvas
convert the mouse position in pixels into the row and column on the grid
if the guess is correct, add the guess to the hit array and if missed adding it to the miss array.
when a guess is made, in addition to colouring the cell, print either “Hit!” or “Miss!” on the cell
sinking the ship when all cells have been hit
In your code you've mixed rows and columns. The x coordinate goes from the left to the right, this are the columns. The y axis goes from the top to the bottom and corresponds to the rows.
Don't store column, row, hit and miss in arrays. But use 2-dimensional arrays to store the position of the ship and the positions of mouse clicks:
boolean [][] ship;
boolean [][] click;
keep the ship cells within the canvas
If the direction is horizontal, then the x start position of the ship has to be less than NUM_COLS - shipLength:
randomX = (int)random(NUM_COLS - shipLength);
randomY = (int)random(NUM_ROWS);
If the direction is horizontal, then the y start position of the ship has to be less than NUM_ROWS - shipLength:
randomX = (int)random(NUM_COLS);
randomY = (int)random(NUM_ROWS - shipLength);
Call randomShip in setup rather than draw:
void setup() {
size(600, 500);
randomShip();
println(store);
}
void draw() {
// randomShip(); <---- delete
drawCells (row, column, shipLength, (255) );
}
Generate the random position and size of the ship in randomShip;
void randomShip () {
ship = new boolean[NUM_COLS][NUM_ROWS];
click = new boolean[NUM_COLS][NUM_ROWS];
shipLength = (int)random (3, 8);
int store = (int)random(vert, horz);
if (store >= 0) {
int randomX = (int)random(NUM_COLS - shipLength);
int randomY = (int)random(NUM_ROWS);
for (int i = 0; i < shipLength; i++ ) {
ship[randomX + i][randomY] = true;
}
} else {
int randomX = (int)random(NUM_COLS);
int randomY = (int)random(NUM_ROWS - shipLength);
for (int i = 0; i < shipLength; i++ ) {
ship[randomX][randomY+1] = true;
}
}
println(shipLength);
}
convert the mouse position in pixels into the row and column on the grid
if the guess is correct, add the guess to the hit array and if missed adding it to the miss array.
The cell which was clicked can be get by the dividing the mouse coordinates mouseX and mouseY by CELLSIZE
int cell_x = mouseX / CELLSIZE;
int cell_y = mouseY / CELLSIZE;
Store mark the clicked cells and count the hits and miss in mouseClicked:
void mouseClicked () {
int cell_x = mouseX / CELLSIZE;
int cell_y = mouseY / CELLSIZE;
if (!click[cell_x][cell_y]) {
click[cell_x][cell_y] = true;
if ( ship[cell_x][cell_y] ) {
hitCount ++;
} else {
missCount ++;
}
}
}
when a guess is made, in addition to colouring the cell, print either “Hit!” or “Miss!” on the cell
Evaluate the ship position (ship[][]) and clicked positions (click[][]) in drawCells. Draw the cells and the text dependent on the states in 2 nested loops:
void drawCells(int colour) {
for (int i = 0; i < NUM_COLS; i++) {
for (int j = 0; j < NUM_ROWS; j++) {
float x = i * CELLSIZE;
float y = j * CELLSIZE;
if (ship[i][j]) {
fill (colour);
rect(x, y, CELLSIZE, CELLSIZE);
}
if (click[i][j]) {
fill(255, 0, 0);
textSize(15);
text(ship[i][j] ? "hit" : "miss", x+10, y+30);
}
}
}
}
sinking the ship when all cells have been hit
Handle the end of the game in draw:
e.g.
void draw() {
drawCells(255);
if (hitCount == shipLength ) {
// [...]
}
}
Full code listing:
final int CELLSIZE = 50;
final int NUM_ROWS = 10;
final int NUM_COLS = 12;
int horz = (int)random(50);
int vert = (int)random(-50);
int store;
int shipLength;
boolean [][] ship;
boolean [][] click;
int hitCount = 0;
int missCount = 0;
void setup() {
size(600, 500);
randomShip();
println(store);
}
void draw() {
drawCells(255);
if (hitCount == shipLength ) {
// [...]
}
}
void drawCells(int colour) {
for (int i = 0; i < NUM_COLS; i++) {
for (int j = 0; j < NUM_ROWS; j++) {
float x = i * CELLSIZE;
float y = j * CELLSIZE;
if (ship[i][j]) {
fill (colour);
rect(x, y, CELLSIZE, CELLSIZE);
}
if (click[i][j]) {
fill(255, 0, 0);
textSize(15);
text(ship[i][j] ? "hit" : "miss", x+10, y+30);
}
}
}
}
void randomShip () {
ship = new boolean[NUM_COLS][NUM_ROWS];
click = new boolean[NUM_COLS][NUM_ROWS];
hitCount = 0;
missCount = 0;
shipLength = (int)random (3, 8);
int store = (int)random(vert, horz);
if (store >= 0) {
int randomX = (int)random(NUM_COLS - shipLength);
int randomY = (int)random(NUM_ROWS);
for (int i = 0; i < shipLength; i++ ) {
ship[randomX + i][randomY] = true;
}
} else {
int randomX = (int)random(NUM_COLS);
int randomY = (int)random(NUM_ROWS - shipLength);
for (int i = 0; i < shipLength; i++ ) {
ship[randomX][randomY+1] = true;
}
}
println(shipLength);
}
void mouseClicked () {
int cell_x = mouseX / CELLSIZE;
int cell_y = mouseY / CELLSIZE;
if (!click[cell_x][cell_y]) {
click[cell_x][cell_y] = true;
if ( ship[cell_x][cell_y] ) {
hitCount ++;
} else {
missCount ++;
}
}
}
I have a class to separate and join image in tiles. It works fine when the sides of the tile correspond to the dimensions of the image, i.e. height 250, tile height 25. But when it's not it doesn't create smaller tiles at the borders as it should.
Where would be the problem to properly create the border tiles smaller than the rest?
Constructor:
public EdgeBufferedImage(BufferedImage image, int w, int h){
this.sourceImg = image;
this.setCol((int)Math.ceil(image.getWidth()/(double)w));
this.setRow((int)Math.ceil(image.getHeight()/(double)h));
this.setWidth(image.getWidth());
this.setHeight(image.getHeight());
this.setTilew(w);
this.setTileh(h);
this.setMatImg(new BufferedImage[row][col]);
}
Methods:
Image tiling
public void createSmallImages() {
int rows = getRow();
int columns = getCol();
int smallWidth = getTilew();
int smallHeight = getTileh();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (j == columns - 1) smallWidth = getWidth() - (getTilew() * j);
if (i == rows - 1) smallHeight = getHeight() - (getTileh() * i);
matImg[i][j] = getSourceImg().getSubimage(j * smallWidth, i
* smallHeight, smallWidth, smallHeight);
}
smallWidth = getTilew();
smallHeight = getTileh();
}
}
Image joining
public void joinTiles(){
int rows = getRow();
int columns = getCol();
int smallWidth = getTilew();
int smallHeight = getTileh();
BufferedImage comb = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) comb.getGraphics();
g.setColor(Color.RED);
for (int row = 0; row < rows; row++){
for (int col = 0; col < columns; col++){
BufferedImage piece = getMatImg()[row][col];
if (col == columns - 1) smallWidth = getWidth() - (getTilew() * col);
if (row == rows - 1) smallHeight = getHeight() - (getTileh() * row);
g.drawImage(piece, col * smallWidth, row * smallHeight, smallWidth, smallHeight, null);
g.drawRect(col * smallWidth, row * smallHeight, smallWidth, smallHeight);
}
smallWidth = getTilew();
smallHeight = getTileh();
}
g.dispose();
setSourceImg(comb);
}
Original image is 512*512
I have a script that draws a game board of hexagon shaped tiles. I want to add an InnerShadow effect to each tile but I also want each tile to have a semi-transparent background. The normal shadow should be on top of the transparent background(if that makes sense). For some reason unknown to me, the shadow shows up as artifacts. If I remove setFill from the tile, it automatically has a black background. In the screenshot, the little white dots are what I am referring to as artifacts. What am I doing wrong?
Update
After further investigation, I realized that the white dots are actually part of the image. But the problem of the InnerShadow not showing up remains. So I have changed the title of the question. How can I add an InnerShadow and a transparent background to my polygon?
private void drawHexGridLoop(GraphicsContext g, Point origin, int size, int radius, int padding, boolean blank) {
String rsrc;
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 - java.lang.Math.abs(row - half);
for (int col = 0; col < cols; col++) {
int xLbl = row < half ? col - row : col - half;
int yLbl = row - half;
int x = (int) (origin.x + xOff * (col * 2 + 1 - cols));
int y = (int) (origin.y + yOff * (row - half) * 3);
Hexagon hex = new Hexagon(x, y, radius);
int diceNum = diceSpaces.get(i);
if(!blank){
rsrc = resources.get(i);
} else {
rsrc = null;
}
//hex.draw(g, x, y, diceNum, rsrc);
Polygon tile = new Polygon();
for(int p = 0; p < hex.xpoints.length; p++){
double xpoint = hex.xpoints[p];
tile.getPoints().add(xpoint);
double ypoint = hex.ypoints[p];
tile.getPoints().add(ypoint);
}
tile.setFill(Color.web("rgba(255, 255, 255, 0.3)"));
InnerShadow innerShadow = new InnerShadow(5, Color.WHITE);
innerShadow.setOffsetX(4);
innerShadow.setOffsetY(4);
tile.setEffect(innerShadow);
wrapperPane.getChildren().add(tile);
tiles[i] = new Tile(i, xLbl, yLbl, rsrc, diceSpaces.get(i), hex.xpoints, hex.ypoints);
i++;
}
}
}
I am trying to create a Grid class to arrange elements the screen on rows and cols. The methods cellXCenter() and cellYCenter() are supposed to return the coordinates for a given i cell on the grid.
When running this code, which is supposed to draw an ellipse inside each grid cell, only the last element is given the correct coordinates.
What I am doing wrong?
Grid grid;
int columns = 3;
int rows = 2;
void setup() {
size(900,600);
background(0);
grid = new Grid(columns,rows);
fill(255,0,0);
for (int i = 0 ; i < columns * rows; i++) {
ellipse(grid.cellXCenter(i+1),grid.cellYCenter(i+1),100,100);
}
}
class Grid {
//grid width, height, number of columns, number of rows
int gw;
int gh;
int cols;
int rows;
int cells; //total de celdas desde 1
float cellWidth;
float cellHeight;
Grid(int cols_, int rows_) {
gw = width;
gh = height;
cols = cols_;
rows = rows_;
cells = rows * cols;
cellWidth = gw / cols;
cellHeight = gh / rows;
}
int rowPos(int index_) {
//all index arguments one based
float i = index_;
int position = (int)Math.ceil(i/cols);
return position;
}
int colPos(int index_) {
int i = index_;
int position = i - (cols * (rowPos(i) -1));
return position;
}
float cellX(int index_) {
int i = index_;
float xPos = gw * (colPos(i)/cols);
return xPos;
}
float cellXCenter(int index_) {
int i = index_;
float xCenterPos = cellX(i) - cellWidth/2;
return xCenterPos;
}
float cellY(int index_) {
int i = index_;
float yPos = gh * (rowPos(i)/rows);
return yPos;
}
float cellYCenter(int index_) {
int i = index_;
float yCenterPos = cellY(i) - cellHeight/2;
return yCenterPos;
}
}
You need to do some debugging. I'd start out by printing out the position of every cell:
for (int i = 0 ; i < columns * rows; i++) {
println(grid.cellXCenter(i+1) + ", " + grid.cellYCenter(i+1));
ellipse(grid.cellXCenter(i+1),grid.cellYCenter(i+1),10,10);
}
This prints out:
-150.0, -150.0
-150.0, -150.0
750.0, -150.0
-150.0, 450.0
-150.0, 450.0
750.0, 450.0
So you can see that all but one of your cells have negative coordinates, which cause them to be drawn off the edges of the window.
Now you need to keep debugging to figure out why these values are negative. Add more print statements to see exactly what's going on in your code, and find the line that's not behaving how you expect.
When you get it narrowed down to just a few lines that aren't behaving how you expect, then you can post a more specific question along with an MCVE. Good luck.
I have created a pdf where I have a table but if the length of the string exceeds then I want to use new line.
public static void drawtable1(PDPage page, PDPageContentStream contentStream, float y, float margin, String[][] content) throws IOException {
int rows = content.length;
int cols = content[0].length;
float rowHeight = 20f;
float tableWidth = page.getMediaBox().getWidth() - margin - margin;
float tableHeight = rowHeight * rows;
float colWidth = tableWidth / (float)cols;
float cellMargin = 5f;
PDFont font1 = PDType1Font.HELVETICA_BOLD;
PDFont font2 = PDType1Font.HELVETICA;
//draw the rows
float nexty = y;
for (int i = 0; i <= rows; i++) {
contentStream.moveTo(margin, nexty);
contentStream.lineTo(margin + tableWidth, nexty);
contentStream.setStrokingColor(220,220,220);
contentStream.stroke();
nexty -= rowHeight;
}
//draw the columns
float nextx = margin;
for (int i = 0; i <= cols ; i++) {
contentStream.moveTo(nextx, y);
contentStream.lineTo(nextx, y - tableHeight);
contentStream.setStrokingColor(220,220,220);
contentStream.stroke();
// contentStream.stroke();
if(content[0].length == 2){
if(i==0){
nextx += colWidth/2;
}if(i == 1){
nextx += colWidth + colWidth/2;
}
}else{
nextx += colWidth;
}
}
//now add the text
contentStream.setFont(PDType1Font.HELVETICA, 10);
float textx = margin + cellMargin;
float texty = y - 15;
float col = tableWidth / (float)cols;
for (int i = 0; i < content.length; i++) {
for (int j = 0; j < content[i].length; j++) {
String text = content[i][j];
contentStream.beginText();
// contentStream.setLeading(12.5f);
contentStream.newLineAtOffset(textx, texty);
if (j == 0 || j == 2){
if(font1.getStringWidth(content[i][j]) > col){
System.out.println(content[i][j]);
}
contentStream.setFont(font1, 10);
contentStream.showText(text);
contentStream.setFont(font2, 10);
}else{
contentStream.showText(text);
}
contentStream.endText();
if(content[0].length == 2){
if(j==0){
textx += colWidth/2;
}
if(j == 1){
textx += colWidth + colWidth/2;
}
}else{
textx += colWidth;
}
}
texty -= rowHeight;
textx = margin + cellMargin;
}
}
I tried comparing the length of the string and column width but it is not working. I have no idea how to display half string in the next line.
See actually only this thing worked for me,
String text = content[i][j];
List<String> strings = new ArrayList<String>();
int index = 0;
while (index < text.length()) {
strings.add(text.substring(index, Math.min(index + 25,text.length())));
index += 25;
}
for (String line: strings){
contentStream.showText(line);
contentStream.newLineAtOffset(0, -leading);
}
But here I have no idea how to increase height of the row which have many characters.