How to Get an Objects X position in processing - java

I am trying to make Space Invaders in Processing. I am currently working on getting the enemy to move correctly. I have got them to be drawn in the right spot but I haven't gotten them to be moved correctly. Here is my code:
PImage mainPlayer;
PImage enemyPlayer;
float Xspeed = 60;
float Yspeed = 60;
float X;
float Y;
Enemy EnemyPlayer = new Enemy("EnemyPlayerSpaceInvaders.png", 10, 10, 6);
void setup() {
size(1400, 800);
//enemyPlayer = loadImage("EnemyPlayerSpaceInvaders.png");
mainPlayer = loadImage("MainPlayerSpaceInvaders.png");
}
void draw() {
background(0);
Enemy[] enemyPlayer = new Enemy[60];
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
enemyPlayer[j *i] = new Enemy("EnemyPlayerSpaceInvaders.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
if(enemyPlayer[j * i].alive){
enemyPlayer[j * i].Draw();
}
enemyPlayer[j *i].moveAndDraw(6);
}
}
}
class Enemy {
boolean alive = true;
float x;
float y;
float speed;
String playerTexFile;
PImage playerTex;
Enemy(String PlayerTexFile, float X, float Y, float Speed){
x = X;
y = Y;
speed = Speed;
playerTexFile = PlayerTexFile;
}
void Draw(){
playerTex = loadImage(playerTexFile);
image(playerTex, x, y);
}
void moveAndDraw(float Speed){
playerTex = loadImage(playerTexFile);
if(alive){
x += Speed;
if (x >= 1300) {
x = 100;
y += 50;
}
}
}
}
Here is my result:
The Draw function works but what you're seeing that is messing it up is the moveAndDraw() function.
And the enemy drawings aren't moving. I have made this before with c++ SFML but in that there is a very basic getPosition function. The reason I want to get position is that right now I'm having to use inaccurate numbers as the X and Y position and for the enemy to move correctly I need to know exactly what it's position is. I have checked multiple pages on processing.org but none of them helped. I haven't found any getPosition void and all the ones I've seen other people using a void to do this I just haven't been able to get it to work. If there is some code that could get me this to work or just some function I've looked over and even a website page I could look at I'd be open to it. Please tell me anything I can do to get this working.

The issue is that you recreate the enemies in every frame at it's initial position:
void draw() {
background(0);
Enemy[] enemyPlayer = new Enemy[60];
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
enemyPlayer[j *i] = new Enemy("EnemyPlayerSpaceInvaders.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
// [...]
}
You've to:
Create a global array of enemies Enemy[] enemyPlayer (and delete PImage enemyPlayer).
Create and initialize the enemies in setup.
Use and move the existing enemies in draw:
Further note, that your loops doesn't do what you expect it to do. Create the enemies in 2 nested loops. If i runs from o to 6 and j from 0 to 10, the the index of an enemy is i*10 + j.
The enemies can be moved in a single loop from 0 to enemyPlayer.length.
//PImage enemyPlayer; <--- DELETE
// global array of enemies
Enemy[] enemyPlayer = new Enemy[60];
// [...]
void setup() {
size(1400, 800);
mainPlayer = loadImage("MainPlayerSpaceInvaders.png");
// create enemies
for (int i = 0; i < 6; i += 1) {
for (int j = 0; j < 10; j += 1) {
enemyPlayer[i*10 + j] = new Enemy("rocket64.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
}
void draw() {
background(0);
// move enemies
for(int i = 0; i < enemyPlayer.length; ++i ) {
if(enemyPlayer[i].alive){
enemyPlayer[i].Draw();
}
enemyPlayer[i].moveAndDraw(6);
}
}

Related

Why won't it revolve?

I'm trying to make a rotating ellipse to the center, and I'm having trouble as to how it isn't moving besides being in the draw and having an offset in x and y changing. I mapped the initial x and y position of the ellipses at first and try and calculated its distance from the center I was wondering if any of you could help, it'll be much appreciated. ^^ (beginner here) [IDE processing]
I dunno what's wrong with the revolution from polar to cartesian coord.
Heart heart = new Heart();
int h = 500;
int w = 500;
void setup(){
size(500,500);
heart = new Heart();
heart.init();
//heart.display();
}
void draw(){
background(0);
heart.rotate();
}
class Heart {
float[][] pos;
float[] dist;
int hold;
float xOff;
float yOff;
Heart(){
hold = 10;
dist = new float[hold];
pos = new float[hold][hold];
}
void init(){
for(int i = 0; i < hold; i++){
for(int j = 0; j < hold; j++){
pos[i][j] = random(0,h);
}
}
}
/*void display(){
for (int k = 0; k < hold; k++){
fill(0,10,255,50);
ellipse(pos[k][0],pos[0][k],15,15);
stroke(255);
line(w/2,h/2,pos[k][0],pos[0][k]);
}
}*/
void rotate(){
float[] r = new float[hold];
int theta;
for(int k = 0; k < hold; k++){
r[k] = dist(w/2,h/2,pos[k][0],pos[0][k]);
for(theta = 0; theta <= TWO_PI; theta++){
xOff = r[k] * cos(theta);
yOff = r[k] * sin(theta);
stroke(255);
println(pos[k][0] + xOff);
ellipse(pos[k][0] + xOff,pos[0][k] + yOff,15,15);
}
}
}
}
I expect the ellipses to revolve, no error.
Use a global variable angle of type float. Increment the angle in every frame and pass it to the method Heart.rotate():
float angle = 0.0;
void draw(){
background(0);
heart.rotate(angle);
angle += 0.01;
}
The method Heart.rotate() hast to draw the the ellipse with one certain angle i every frame, rather than all the possible angles in a loop in each frame.
class Heart {
// ...
void rotate(float theta){
float[] r = new float[hold];
for(int k = 0; k < hold; k++){
r[k] = dist(w/2,h/2,pos[k][0],pos[0][k]);
xOff = r[k] * cos(theta);
yOff = r[k] * sin(theta);
stroke(255);
println(pos[k][0] + xOff);
ellipse(pos[k][0] + xOff,pos[0][k] + yOff,15,15);
}
}
}
Note, the display is updated once after global draw() has been executed. There is no update of the display in the inner loop of the method Heart.rotate().

How to convert the mouse position in pixels into the row and column on the grid?

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 ++;
}
}
}

How can I check if values in one array are equal are equal without checking the same thing

I have this array
Ball[] balls = new Ball[7]; // 7 just being an example
In my Ball class, I have getters and setters for x and y values.
I'm trying to compare the x and y values to make sure that they don't intersect.
My first thought was to make a loop looking like
for(Ball b1 : balls) {
for(Ball b2 : balls) {
if(b1.intersects(b1, b2)) {. . .} // I made intersects, not my issue
}
}
But this is no good, as it compares:
balls 0 to balls 0
balls 1 to balls 1
etc.
for(int i = 0; i < balls.length; i++) {
System.out.println(f.getContentPane().getWidth() + "\n" + f.getContentPane().getHeight());
int radius = 10 + rand.nextInt(20);
balls[i] = new Ball(360, radius,
rand.nextInt(f.getContentPane().getWidth() - 4 * radius - 5) + radius + 5,
rand.nextInt(f.getContentPane().getHeight() - 4 * radius - 5) + radius + 5
);
}
for(Ball b1 : balls) {
for (Ball b2 : balls) {
while (b1.intersects(b1, b2)) {
System.out.println("Ball started out inside of another, replacing now.");
b1.setX(rand.nextInt(f.getContentPane().getWidth() - 2 * b1.getRadius() - 5) + b1.getRadius() + 5);
b1.setY(rand.nextInt(f.getContentPane().getHeight() - 2 * b1.getRadius() - 5) + b1.getRadius() + 5);
}
}
}
////////////// class change //////////////////
class Ball {
private int direction;
private int radius;
private int x,y;
Ball(int direction, int radius, int x, int y) {
this.direction = direction;
this.radius = radius;
this.x = x;
this.y = y;
}
// Getters + Setters here
boolean intersects(Ball b1, Ball b2) {
double x = Math.pow((b2.getX() - b1.getX()), 2); // Distance formula
double y = Math.pow((b2.getY() - b1.getY()), 2); // Distance formula
double r = b1.getRadius() + b2.getRadius();
//System.out.println(x + " + " + y + " <= " + r );
return x + y <= r;
}
}
(Ignore that I didn't put my first hunk of code in a method and class, I've done that in my actual code.)
I, for whatever reason, can't think of a way to do this without a whole lot of if statements
(So I'm asking for the best way to do this)
One way to compare every distinct (i.e., no ball with itself) pair of Balls, without comparing any pair more than once would be:
for (int i = 0; i < balls.length; ++i) {
Ball b1 = balls[i];
for (int j = i+1; j < balls.length; ++j) {
Ball b2 = balls[j];
if (b1.intersects(b1, b2)) {
// ...
}
}
}
Detecting new collisions introduced in the process of resolving previous ones just means making multiple passes over balls until you no longer have any collisions. A simple, perhaps naive, way of doing this would be something like this:
boolean foundCollision;
int numTries = 0;
int maxTries = 1000000;
do {
foundCollision = false;
for (int i = 0; i < balls.length; ++i) {
Ball b1 = balls[i];
for (int j = i+1; j < balls.length; ++j) {
Ball b2 = balls[j];
if (b1.intersects(b1, b2)) {
foundCollision = true;
// resolve collision...
}
}
++numTries;
} while (foundCollision && numTries < maxTries);
if (numTries >= maxTries)
System.err.println("Couldn't sort out balls after " + maxTries + "tries: what now?");

Tile change color on mouse hover - prevent selecting more than one tile at once

I am creating a battle ship game, where each round the player can select 4 ship routes by selecting the 4 closest tiles to him, with a mouse.
Now in the following gif, you can see if I will hover on the very edge of a tile, it will select two tiles at once, or even 4 at once if you're holding your mouse in middle of 4 tiles:
(source: gyazo.com)
This should not really be happening in the game, how can I prevent that?
This is the updating code:
/**
*
* #param x mouse X
* #param y mouse Y
*/
public void checkHover(int x, int y) {
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[1].length; j++) {
// get coordinates from tile
int x1 = i * (sprite.getWidth() - 1);
int y1 = j * (sprite.getHeight() - 1);
// If we have screen translate, we can cancel it for
// this situation
int realX = x - this.translate.getX();
int realY = y - this.translate.getY();
// checking if mouse inside tile
if (realX >= x1 && realX <= x1 + sprite.getWidth() &&
realY >= y1 && realY <= y1 + sprite.getHeight()) {
// set tile to hovered sprite
this.tiles[i][j].setHover(true);
}
else {
// cancel hovered sprite
this.tiles[i][j].setHover(false);
}
}
}
}
How can I prevent that?
Instead of the two loops I would calculate the index of the 2d array based off the x and y position of the mouse, by dividing the x and y position by how much space there is from one tile to the next (which looks to be the tile width plus 1, the empty border). This will cause border hovers to favor a certain side, but it looks like you don't want to select two tiles anyways.
Once you have the index of the tile, switch the highlight on, and keep a reference to it with an instance variable like lastHighlightedTile, but before you do that, also call lastHighlightedTile.setHover(false);.
If the index of the tile is invalid, as if the mouse is out of the tile area, don't access the array and still call lastHighlightedTile.setHover(false);.
This should fix highlighting multiple tiles, and will also allow you to turn off the previous highlight (the solution of breaking out of the current loop might not turn off the previous highlight).
Assuming width of sprite is equal to 50, I see that first title has x1 to x2 coordinate (0 - 50), second title has (49 - 100), third has (99 - 150)... Same for y dimension.
So when pointer is at (x) = (50), it hovers (x1 - x2) (0-50) and (49-100) titles.
Why are you subtracting 1 from sprite width / height?
try with this:
// get coordinates from tile
int x1 = i * (sprite.getWidth());
int y1 = j * (sprite.getHeight());
Edit: I wrote sample app, which shoved me solution:
public class App {
Tile[][] tiles;
Sprite sprite;
public static void main(String[] args) {
App app = new App();
app.init();
app.checkHover(50, 50);
app.printHovers();
}
private void init() {
sprite = new Sprite();
tiles = new Tile[10][10];
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[1].length; j++) {
tiles[i][j] = new Tile();
}
}
}
public void checkHover(int x, int y) {
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[i].length; j++) {
// get coordinates from tile
int x1 = i * (sprite.getWidth());
int y1 = j * (sprite.getHeight());
// If we have screen translate, we can cancel it for
// this situation
// int realX = x - this.translate.getX();
// int realY = y - this.translate.getY();
int realX = x;
int realY = y;
// checking if mouse inside tile
if (realX >= x1 && realX < x1 + sprite.getWidth()
&& realY >= y1 && realY < y1 + sprite.getHeight()) {
// set tile to hovered sprite
this.tiles[i][j].setHover(true);
} else {
// cancel hovered sprite
this.tiles[i][j].setHover(false);
}
}
}
}
public void printHovers() {
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[i].length; j++) {
System.out.print((tiles[i][j].isHover() ? "Y" : "O") + " ");
}
System.out.println();
}
}
public class Sprite {
public int getWidth() {
return 50;
}
public int getHeight() {
return 50;
}
}
public class Tile {
private boolean hover;
public boolean isHover() {
return hover;
}
public void setHover(boolean hover) {
this.hover = hover;
}
}
}
It works fine for (49, 49), (49, 50), (50, 49) and (50, 50) coords.
So, first you have to remove -1 subtractions, and change <= test to <.
EDIT: Different solution:
Simply declare a boolean at the beginning of the method, and set only if that boolean is still false. Once you set the tile on, also set the boolean to true, which will prevent others from being set on.
public void checkHover(int x, int y) {
boolean hasTurnedOneOn = false;
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[1].length; j++) {
// get coordinates from tile
int x1 = i * (sprite.getWidth() - 1);
int y1 = j * (sprite.getHeight() - 1);
// If we have screen translate, we can cancel it for
// this situation
int realX = x - this.translate.getX();
int realY = y - this.translate.getY();
// checking if mouse inside tile
if (realX >= x1 && realX <= x1 + sprite.getWidth() &&
realY >= y1 && realY <= y1 + sprite.getHeight() && !hasTurnedOneOn) {
// set tile to hovered sprite
this.tiles[i][j].setHover(true);
hasTurnedOneOn = true;
}
else {
// cancel hovered sprite
this.tiles[i][j].setHover(false);
}
}
}
}

I need some help understanding arrays of pixels

I'm using Processing to divide a large image into a series of smaller, rectangular nodes.
Processing stores the color value for the pixels of a PImage in a pixels array, which I am accessing to break up the image into smaller parts. For some reason, I am getting this output, when my intent was for the entire image to be displayed when the nodes are arranged in draw().
Here is my main class:
ArrayList node = new ArrayList();
PImage grid;
PVector nodeDimensions = new PVector(210, 185);
PVector gridDimensions = new PVector(2549, 3300);
String name = "gridscan.jpeg";
void setup() {
size(500, 500);
grid = loadImage(name);
grid.loadPixels();
fillPixels();
noLoop();
}
void fillPixels() {
int nodeNum = 0;
for (int startX = 0; startX < 2549 - nodeDimensions.x; startX += nodeDimensions.x) {
for (int startY = 0; startY < 3300 - nodeDimensions.y; startY += nodeDimensions.y) {
node.add(new Node());
sendPixels(new PVector(startX, startY), nodeNum);
nodeNum++;
}
}
}
void sendPixels(PVector start, int nodeNum) {
for (int x = int(start.x); x < start.x + nodeDimensions.x; x++) {
for (int y = int(start.y); y < start.x + nodeDimensions.y; y++) {
Node _node = (Node) node.get(node.size() - 1);
_node.fillPixel(new PVector(x, y), grid.pixels[int(y*gridDimensions.x+x)]);
}
}
}
void draw() {
drawNodes();
}
void drawNodes() {
int nodeNum = 0;
for (int x = 0; x < width; x += nodeDimensions.x) {
for (int y = 0; y < height; y += nodeDimensions.y) {
Node _node = (Node) node.get(nodeNum);
_node.drawMe(new PVector(x - (nodeDimensions.x/2), y - (nodeDimensions.y/2)));
nodeNum++;
}
}
}
And here is the Node class:
class Node {
color[] pixel;
Node() {
pixel = new color[int(nodeDimensions.x * nodeDimensions.y)];
}
void fillPixel(PVector pos, color pixelValue) {
if(int(pos.y * nodeDimensions.y + pos.x) < 38850) pixel[int(pos.y * nodeDimensions.y + pos.x)] = pixelValue;
}
void drawMe(PVector centerPos) {
pushMatrix();
translate(centerPos.x, centerPos.y);
for(int x = 0; x < nodeDimensions.x; x++) {
for(int y = 0; y < nodeDimensions.y; y++) {
stroke(getPixelColor(new PVector(x, y)));
point(x,y);
}
}
popMatrix();
}
color getPixelColor(PVector pos) {
return pixel[int(pos.y * nodeDimensions.x + pos.x)];
}
}
Hopefully my code makes sense. I suspect the issue is in the sendPixels() method of the main class.
I used this this page from the Processing reference as a guide for creating that function, and I'm not sure where my logic is wrong.
Any help would be appreciated, and please let me know if I can clarify something.
According to getPixelColor(), it seems that it uses rows.
So if you have a 5x5 square image then 2x2 would be 7.
To get the index you use this formula:
index = (y - 1) * width + x
Explained this way it's look pretty simple, doesn't it?
Alternatively, you may be able to use getSubimage() on the BufferedImage returned by the getImage method of PImage. There's a related example here.

Categories

Resources