Algorithm that searches a 2D array - java

I'm trying to recreate a tetris-like game. I have a 2D array, "_tiles" that stores objects called "ColorShape" .
private ColorShape[][] _tiles = new ColorShape[8][17];;
im trying to make a quickDrop() method for when I hit the down arrow key to find the next available slot in the array to quickly place the shapes. I am having a hard time figuring out the algorithm that will search the rows below the current piece in the column that the piece is in.
This is what I tried to do so far but I think that I am going about this all wrong: (the Pieces are 30x30 pixels thats why they are being divided by 30, so that the array location corresponds to the x and y locations of the shape)
public void quickDrop(){
// j is the column that the piece is currently in
int j = _proxyPiece.getXLocation()/30;
for (int i=0; i<17;i++){
if(_tiles[j][i] == null)
continue;
else if (_tiles[j][i] != null){
_tiles[j][i-2] = _proxyPiece.getFirstPiece();
_tiles[j][i-1] = _proxyPiece.getSecondPiece();
repaint();
_proxyPiece.setPiece(this.newPiece());
repaint();
break;
}
}
}
public void paintComponent(Graphics g) {
if (_pauseState == false){
_pauseText.setVisible(false);
super.paintComponent(g);
// simplify the positioning of things.
g.translate(0, 0);
//Draws the board outline and fills it white
g.setColor(Color.WHITE);
g.drawRect(0, 0, 240, 480);
g.fillRect(0, 0, 240, 480);
//Draws a dark gray grid
g.setColor(Color.DARK_GRAY);
for(int x = 0; x < COL_COUNT + 1; x++) {
for(int y = 0; y < VISIBLE_ROW_COUNT+1; y++) {
g.drawLine(0, y * TILE_SIZE, COL_COUNT * TILE_SIZE, y * TILE_SIZE);
g.drawLine(x * TILE_SIZE, 0, x * TILE_SIZE, VISIBLE_ROW_COUNT * TILE_SIZE);
}
}
Graphics2D aBetterPen = (Graphics2D)g;
_proxyPiece.fill(aBetterPen);
for (int i = 0; i<16; i++){
for(int j=0; j<8;j++){
if(_tiles[j][i] != null)
_tiles[j][i].fill(aBetterPen);
}
}
}
else if (_pauseState == true){
_pauseText.setVisible(true);
super.paintComponent(g);
// simplify the positioning of things.
g.translate(0, 0);
g.setColor(Color.WHITE);
g.drawRect(0, 0, 240, 480);
g.fillRect(0, 0, 240, 480);
}
}

One algorithm to solve this:
Take the current dropping piece and move it over every Y value from its current position downwards.
If it collides with a previously placed piece, or exceeds the bottom of your grid, the last Y position you checked is a valid solution.
If you want all valid solutions instead of just one, repeat this algorithm for all possible rotations of the currently selected piece.
Here's an example of the algorithm. It won't work with your code as is, but it will get you off to a quick start.
ColorShape[][] grid = new ColorShape[width][height];
TetrisShape shape = new TetrisShape(Shape.L_SHAPE);
//position will be bottom left coordinate of bounding rectangle of dropping shape.
Point position = new Point(shape.getPosition());
int resultY = -1;
for(int dy=0;dy<height;dy++){
for(int y=0;y<height;y++){
int shapeY = position.y+y;
if(shapeY>=height || shape.intersectsGrid(grid)){
resultY = shapeY -1;
break;
}
}
}

Related

How to create multicolor rasterized picture in processing

I followed this tutorial on Youtube, and I have successfully added colors to the black and white picture. However, my intention was to create a multi-color or gradient effect (like here or here) instead of switching colors when I move the cursor.
I very new at processing, and I have tried to play with the variable, with no success.
Here is the code snippet of the sketch:
`
PImage img;
void setup() {
size(598,336);
colorMode(HSB);
img = loadImage("picture-in-data-folder.jpg");
img.resize(598,336);
//ellipseMode(RADIUS);
frameRate(30);
}
void draw() {
background(255);
noStroke();
// fill(0);
float tiles = mouseX/10;
float tileSize = width/tiles;
// color section
fill(color(tiles, 255, 255));
tileSize++;
if (tiles > width / 2) {
tileSize = 0;
}
// end color section
translate(tileSize/2, tileSize/2);
for (int x = 0; x < tiles; x++) {
for (int y = 0; y < tiles; y++) {
color c = img.get(int(x*tileSize),int(y*tileSize));
float size = map(brightness(c), 0, 255, tileSize, 0);
ellipse(x*tileSize, y*tileSize, size, size);
// image(img, mouseX, mouseY);
}
}
}
I would be grateful if you had any hints, or if you could provide an advice.
Thanks.
Short answer: you need to put a fill() command inside the for loop.
Long answer:
Right now, your code is doing the following:
Define tiles based on mouseX
Set the fill color to (tiles, 255, 255)
Draw all the circles
I think what you want it to do is something like this:
Set the fill color to (21, 255, 255) (or whatever you want the first color to be)
draw the first circle
set the fill color to the next color in the gradient
draw the second circle
etc.
In order to do this, you need to put a command into the for loop which changes the fill color. Here is one way to do that:
for (int x = 0; x < tiles; x++) {
for (int y = 0; y < tiles; y++) {
color c = img.get(int(x*tileSize),int(y*tileSize));
float size = map(brightness(c), 0, 255, tileSize, 0);
fill(map(x, 0, tiles, 0, 255), 255, 255);
ellipse(x*tileSize, y*tileSize, size, size);
}
}
I just added that fill command as a function of x, but you can make it whatever you want. In order for it to be a gradient, it needs to vary somewhat with x or y.

node's are not intersection while using loops inside of an array?

My problem is wherever i click a node appears and for the second click another node appears with connected edge...so i want that When i click at any location, the node should be generated at the closest grid intersection point. I tried using loops.
and i'm trying to do that without "class"
int n_partition=10;
int length = 101;
PVector[] position = new PVector[length];
int BallNum;
void setup() {
size(600, 360);
background(255);
}
void draw() {
fill(255);
grid();
fill(0);
}
void mousePressed(){
stroke(0);
BallNum++;
position[BallNum]= new PVector(mouseX, mouseY);
circle(position[BallNum].x, position[BallNum].y, 10);
if (BallNum > 1) {
line(position[BallNum].x,position[BallNum].y,position[BallNum-
1].x,position[BallNum-1].y);
line(position[1].x,position[1].y,position[BallNum].x,position[BallNum] .y);
}
for (int i = 0; i < position[BallNum].length; ++ i) {
position[BallNum] = position[BallNum].get(i);
position[BallNum] = position[BallNum].get((i+1) % position[BallNum].length);
line(position[BallNum].x, position[BallNum].y,
position[BallNum].x, position[BallNum].y);
}
}
I EXPECT THE NODE SHOULD GO TO THE CLOSEST INTERSECTION.
You've to calculate the nearest position of the mouse to a point on the grid. For that you've to know the width (tile_width) and the height (tile_height) of cell.
The index of the cell can be calculated by the dividing the mouse position to the size of a tile and round() the result to an integral value (e.g. round(mouseX / (float)tile_width)).
Don't draw anything in int the mousePressed callback. The only thing you've to do there is to add a pint to the list:
void mousePressed(){
int tile_width = width / n_partition; // adapt this for your needs
int tile_height = height / n_partition;
int x = round(mouseX / (float)tile_width) * tile_width;
int y = round(mouseY / (float)tile_height) * tile_height;
position[BallNum]= new PVector(x, y);
BallNum++;
}
All the drawing has to be done in draw(). Draw the lines and points in separate loops:
void draw() {
background(255);
grid();
// draw the lines in a loop
strokeWeight(3);
stroke(0, 0, 255);
for (int i = 0; i < BallNum; ++ i) {
int i2 = (i+1) % BallNum;
line(position[i].x, position[i].y, position[i2].x, position[i2].y);
}
// draw balls in a loop
strokeWeight(1);
stroke(0, 0, 0);
fill (255, 0, 0);
for (int i = 0; i < BallNum; ++i) {
circle(position[i].x, position[i].y, 10);
}
}
Note, the scene is consecutively redrawn in every frame. Before the scene is drawn, the entire window has to be "cleared" by background().
See the result:

curveVertex() not drawling in Processing?

I'm trying to create a script that drawls a curve through 'n' vertexes equally spaced around the center of an ellipse.
The reason I'm not just drawling an ellipse around the center ellipse is because I eventually want to connect a micro-controller to Processing where the data points acquired from the 'n' amount of sensors will vary the height ('y') of each vertex, creating constantly changing, irregular curves around the center ellipse such as this possible curve:
Essentially, this is supposed to be a data visualizer, but I cannot figure out why this is not working or how to achieve this effect after going through examples and the documentation on https://processing.org/reference/.
Here is my code:
color WHITE = color(255);
color BLACK = color(0);
void setup() {
size(500, 500);
}
void draw() {
background(WHITE);
translate(width/2, height/2); // move origin to center of window
// center ellipse
noStroke();
fill(color(255, 0, 0));
ellipse(0, 0, 10, 10); // center point, red
fill(BLACK);
int n = 10;
int y = 100;
float angle = TWO_PI / n;
beginShape();
for (int i = 0; i < n; i++) {
rotate(angle);
curveVertex(0, y);
}
endShape();
}
The matrix operations like rotate do not transform the single vertices in a shape. The current matrix is applied to the entire shape when it is draw (at endShape). You've to calculate all the vertex coordinates:
Create a ArrayList of PVector, fill it with points and draw it in a loop:
color WHITE = color(255);
color BLACK = color(0);
ArrayList<PVector> points = new ArrayList<PVector>();
void setup() {
size(500, 500);
int n = 10;
int radius = 100;
for (int i = 0; i <= n; i++) {
float angle = TWO_PI * (float)i/n;
points.add(new PVector(cos(angle)*radius, sin(angle)*radius));
}
}
void draw() {
background(WHITE);
translate(width/2, height/2);
noFill();
stroke(255, 0, 0);
beginShape();
PVector last = points.get(points.size()-1);
curveVertex(last.x, last.y);
for (int i = 0; i < points.size(); i++) {
PVector p = points.get(i);
curveVertex(p.x, p.y);
}
PVector first = points.get(0);
curveVertex(first.x, first.y);
endShape();
}

Java: Drawing single dots at specified (x,y) coordinates?

I am working on science research and am getting strange results from my code, and as a visual learner I thought it efficient to print my data to screen as it is analysed to try and see where the code is going wrong. For reference, I am analyzing a nonlinear waveform.
Here is the code for analysis:
public void getMachineCode(int trial, int wave){
double[] tempwave = new double[5000];
int index = 0;
for(int x = 0; x < 5000; x++){
tempwave[x] = waves[trial][wave][x];
}
for(int repeat = 5; repeat > 0; repeat--){
int tempstart = index;
if(tempwave[index] > 0){
while(tempwave[index] > 0){
index++;
}
}else{
while(tempwave[index] < 0){
index++;
}
}
int midwave = index - tempstart;
if(tempwave[midwave] > 0){
System.out.println(0);
}else{
System.out.println(1);
}
}
}
Here, all I want is to print the (x,y) coordinates of my trial to the screen as the index increases so it is a constantly changing graph, something like:
if(tempwave[index] > 0){
while(tempwave[index] > 0){
index++;
printpixel(index,y); //something to show where the code is scanning
}
}else{
while(tempwave[index] < 0){
index++;
printpixel(index,y);
}
I am not very familiar with java graphics and was looking into using a JFrame but it is hard for me to implement. There will be about 4000 data points to plot, so I might also have to only print every few points or is there a way to make a better visual? Any ideas? Thanks!
This should give you basic idea.
Normally with Swing graphics, you override the paintComponent() method and draw from some shared state
Instead you can just draw to a large image, and then draw that image using paintComponent()
I've compressed this into a single self contained example, this can be separated out in a larger application
Example
public static void main(String[] args) throws Exception {
final BufferedImage image = new BufferedImage(1280, 768,
BufferedImage.TYPE_INT_RGB);
JPanel canvas = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
};
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout()); // <== make panel fill frame
frame.add(canvas, BorderLayout.CENTER);
frame.setSize(500, 500);
frame.setVisible(true);
// do you drawing somewhere else, maybe a different thread
Graphics g = image.getGraphics();
g.setColor(Color.red);
for (int x = 0; x < 100; x += 5) {
for (int y = 0; y < 100; y += 5) {
g.drawRect(x, y, 1, 1);
}
}
g.dispose();
canvas.repaint();
}

Draw a string on a shape

I have an oval and I want to label what it is, for my chess game. I want to use ovals with the names of the pieces on them as strings but I can't seem to get it to work.
Is it even possible to drawString on a shape?
My code
public void drawPieces(Graphics2D g2d){
for(int x = 0; x < 8; x++) {
for(int y = 0; y < 8; y++) {
//reds
if(board[x][y]==24){
g2d.setColor(Color.red);
g2d.fillOval(x*80, y*80, 80, 80);
//drawstring goes here
g2d.setColor(Color.blue);
g2d.drawString("test", x*80, y*80);
}
Any suggestions are welcome
Edit, my grid method in case it helps.
public void drawGrid(Graphics2D g2d){
g2d.drawLine(0, 0, 0, 639);
g2d.drawLine(0, 0, 639, 0);
g2d.drawLine(0, 639, 639, 639);
g2d.drawLine(639, 0, 639, 639);
// draw the horizontal lines using a loop from one to 7, coordiates of each line is (0, x*80, 640, x*80) also
// draw vertical lines with coordinates of (x*80, 0, x*80, 640)
for(int i = 1; i < 8; i++) {
g2d.drawLine(0, i*80, 640, i*80);
g2d.drawLine(i*80, 0, i*80, 640);
}
//drawing the black and white squares
for (int row = 0; row < 8; row++)
for (int col = 0; col < 8; col++) {
if ( (row % 2 == 0 && col % 2 == 0) || ( row % 2 == 1 && col % 2 == 1) ){
g2d.setColor(black);
g2d.fillRect(row*80,col*80,80,80);
}
}
}
I can only say that it is possible to draw a string over an oval, and I'm doing just that in my own game. The top drawing code should be fine. You just need to check the parameter you pass to the drawing method and the if-condition. Here is the excerpt from my code where i draw
over the oval using slightly different method, but your should work too:
public void draw(Graphics g){
Graphics2D g2d = (Graphics2D) g;
g2d.fill(new Ellipse2D.Double(center.x, center.y, itemSize, itemSize));
g2d.setColor(Color.white);
g2d.setFont(new Font("Arial", Font.BOLD, 14));
g2d.drawString(itemName, (int)center.x, (int)center.y+18);
}
itemName is some string, and just not to confuse I thing that first two parametres to
g2d.fill(...(-,-,itemSize, itemSize)) are not the center of elipse but the top left corner of its sourounding rectangle.

Categories