How to use mousePressed with 2D array - processing

I'm new to processing and programming in general and I'm having issues getting the mousePressed function to have the desired effect. I'd appreciate some assistance or advice on getting it to work as intended.
int[][] cave;
int caveSize = 50;
int PILLAR = 1;
int FIX = -1;
int EMPTY = -2;
int MINE = 2;
color pillar = color(255, 255, 255);
color mine = color(255, 0, 0);
color fix = color(0, 255, 0);
color empty = color(0, 0, 0);
boolean end = false;
void setup() {
size(602, 352);
stroke(100);
noSmooth();
cave = new int[width/caveSize][height/caveSize];
for(int x=0; x < width/caveSize; x++) {
for(int y=0; y< height/caveSize; y++) {
cave[x][y] = 0;
}
}
placePoints();
}
void draw() {
background(color(0, 0, 0));
for (int x=0; x < width/caveSize; x++) {
for (int y=0; y < height/caveSize; y++) {
if(cave[x][y] == PILLAR) {
fill(pillar);
}
if(cave[x][y] == MINE) {
fill(mine);
}
if (cave[x][y] == FIX) {
fill(fix);
}
if (cave[x][y] == EMPTY) {
fill(empty);
}
rect(x*caveSize, y*caveSize, caveSize, caveSize);
noFill();
}
}
if (end) {
textSize(50);
fill(255);
text("GAME OVER!", width/4, height/2);
noFill();
}
}
void mousePressed()
{
// int x = mouseX/8;
// int y = mouseY/8;
if(mouseX == PILLAR && mouseY == PILLAR)
{
fill(fix);
}
if(mouseX == MINE && mouseY == MINE)
{
fill(mine);
}
else
{
}
}
boolean game_over() {
for(int x=0; x < width/caveSize; x++) {
for(int y=0; y< height/caveSize; y++) {
if (cave[x][y] == PILLAR || cave[x][y] == MINE) {
return false;
}
}
}
end = true;
return true;
}
void end() {
if (game_over()) {
return;
}
}
void placePoints() {
cave[3][1] = MINE;
cave[7][2] = MINE;
cave[2][3] = MINE;
cave[9][4] = MINE;
cave[1][5] = MINE;
cave[6][4] = MINE;
cave[4][5] = MINE;
cave[6][3] = MINE;
cave[5][5] = MINE;
cave[7][6] = MINE;
cave[0][2] = MINE;
cave[1][0] = MINE;
cave[10][1] = MINE;
cave[11][3] = MINE;
cave[11][6] = MINE;
cave[6][4] = MINE;
cave[4][5] = MINE;
cave[6][3] = MINE;
cave[5][5] = MINE;
cave[7][6] = MINE;
cave[5][6] = PILLAR;
cave[6][6] = PILLAR;
cave[3][6] = PILLAR;
cave[4][6] = PILLAR;
cave[5][2] = PILLAR;
cave[5][3] = PILLAR;
cave[5][4] = PILLAR;
cave[0][0] = PILLAR;
cave[0][1] = PILLAR;
cave[11][2] = PILLAR;
cave[10][2] = PILLAR;
cave[9][2] = PILLAR;
}
Basically what I want to to click on a square to check for a condition and change the square's colour, similar to a form of 'Battleships' game. Thanks for your time.

mouseX/mouseY is the pixel X/y position of the mouse. To determine on which square it is, you have to divide the pixel position by the square width/height. Use this as parameters of the 2D array to find the right square. Then you have to check/assign the changed value to that square.
Something like this:
void mousePressed()
{
int x = mouseX/caveSize;
int y = mouseY/caveSize;
if (cave[x][y] == PILLAR) //if the value is PILLAR (=1)
{
cave[x][y] = FIX; //set the value to FIX (=-1)
}
if (cave[x][y] == MINE) //if the value is MINE (=2)
{
cave[x][y] = MINE; //set the value to MINE (=2) (the same??)
}
}
On the next frame the square will have its new color.

Related

Delete leftmost circle on the canvas

I was able to write a code that draws different circles on a canvas and i need to find a way i could delete the leftmost circle when any key is pressed. i've been at this for hours and i feel like i am close to the answer. i am most klikely going to look for the array whenever a key is pressed and delete the array position.
float colour = random(256);
final int DIAM = 20;
final int MAX_NUM = 1000;
int numPointsX = 0;
int numPointsY = 0;
int [] xPos = new int[MAX_NUM];
int [] yPos = new int [MAX_NUM];
boolean start = false;
void setup() {
size (500, 500);
}
void draw() {
background(150);
fill(random(256), random(256), random(256));
for (int i=0; i<numPointsX; i++) {
circle(xPos[i], yPos[i], DIAM);
}
println(xPos[0]);
}
void mouseClicked() {
insertXandY();
}
void insertXandY() {
int x = mouseX;
int y = mouseY;
xPos[numPointsX] = x;
yPos[numPointsY] = y;
numPointsX += 1;
numPointsY += 1;
start = true;
}
void printArrays() {
println("X Positions");
for (int i = 0; i < 20; i++) {
println("\t" + xPos[i]);
}
}
void keyPressed() {
if (key == 'p') {
printArrays();
}
}
You are on the right track.
In broad terms you'd need two steps:
find the smallest X
delete the data associated with the smallest X
The 1st part is trivial:
use a variable to keep track of the currently smallest value (initialised with a bigger than than your data has)
iterate through each value
compare each value with the current smallest:
if it's bigger ignore
if it's smallest: update the currently smallest value (and remember the index)
at the end of the iteration the currently smallest value is the smallest possible value and index can be used to associate between x,y arrays (which are incremented in sync)
Here's a slightly modified version of your code to illustrate this:
float colour = random(256);
final int DIAM = 20;
final int MAX_NUM = 1000;
int numPoints = 0;
int [] xPos = new int[MAX_NUM];
int [] yPos = new int [MAX_NUM];
void setup() {
size (500, 500);
}
void draw() {
background(150);
fill(random(256), random(256), random(256));
for (int i=0; i < numPoints; i++) {
circle(xPos[i], yPos[i], DIAM);
}
}
void mouseClicked() {
insertXandY();
}
void insertXandY() {
int x = mouseX;
int y = mouseY;
xPos[numPoints] = x;
yPos[numPoints] = y;
numPoints++;
}
void deleteLeftMost(){
// find leftmost index
// start with a large X value
int smallestX = width;
int smallestXIndex = -1;
// iterate through each X
for(int i = 0 ; i < numPoints; i++){
// if xPos[i] is smaller than the smallest value so far...
if (xPos[i] < smallestX){
// ...remember it's value and index
smallestX = xPos[i];
smallestXIndex = i;
}
}
// delete the item at this index: fake it for now: move coordinates offscreen (to the right so left search still works)
xPos[smallestXIndex] = width * 2;
}
void printArrays() {
println("X Positions");
for (int i = 0; i < 20; i++) {
println("\t" + xPos[i]);
}
}
void keyPressed() {
if (key == 'p') {
printArrays();
}
if (keyCode == DELETE || keyCode == BACKSPACE){
deleteLeftMost();
}
}
I've made a few of other minor adjustments:
deleted start since it was assigned but not used (when debugging delete anything that isn't necessary)
renamed numPointsX to numPoints and deleted numPointsY: you are using two arrays indeed, however there is only one index for each point that could be re-used to access each array
numPoints++ is shorthand for numPoints = numPoints + 1;
Also, I've used a hacky placeholder for the remove a point just visually.
This means in terms of memory the xPos/yPos for deleted points will still be allocated.
To actually delete the array is a bit tricker since the array datatype does not change size, however you could manually put something together using subset() and concat(). You can achieve a similar effect to deleting an element by concatenating two subset array: from the start to the index to delete and from the index next to the one to delete to the end of the array.
Something like this:
void setup(){
println(deleteIndex(new int[]{1,2,3,4,5,6},-1));
println(deleteIndex(new int[]{1,2,3,4,5,6},2));
println(deleteIndex(new int[]{1,2,3,4,5,6},6));
}
int[] deleteIndex(int[] sourceArray, int indexToDelete){
if(sourceArray == null){
System.err.println("can't process null array");
return null;
}
if(indexToDelete < 0){
System.err.println("invalid index " + indexToDelete + "\nit's < 0");
return null;
}
if(indexToDelete >= sourceArray.length){
System.err.println("invalid index " + indexToDelete + "\nmax index = " + sourceArray.length);
return null;
}
return concat(subset(sourceArray, 0, indexToDelete),
subset(sourceArray, indexToDelete + 1, sourceArray.length - indexToDelete - 1));
}
It's a good idea to check arguments to a method to ensure they are valid and test with at least a few edge cases.
Here's a version of the above sketch using this delete method:
float colour = random(256);
final int DIAM = 20;
final int MAX_NUM = 1000;
int numPoints = 0;
int [] xPos = new int[MAX_NUM];
int [] yPos = new int [MAX_NUM];
void setup() {
size (500, 500);
}
void draw() {
background(150);
fill(random(256), random(256), random(256));
for (int i=0; i < numPoints; i++) {
circle(xPos[i], yPos[i], DIAM);
}
}
void mouseClicked() {
insertXandY();
}
void insertXandY() {
int x = mouseX;
int y = mouseY;
xPos[numPoints] = x;
yPos[numPoints] = y;
numPoints++;
}
void deleteLeftMost(){
// find leftmost index
// start with a large X value
int smallestX = width;
int smallestXIndex = -1;
// iterate through each X
for(int i = 0 ; i < numPoints; i++){
// if xPos[i] is smaller than the smallest value so far...
if (xPos[i] < smallestX){
// ...remember it's value and index
smallestX = xPos[i];
smallestXIndex = i;
}
}
// delete xPos item at this index
xPos = deleteIndex(xPos, smallestXIndex);
// delete yPos as well
yPos = deleteIndex(yPos, smallestXIndex);
// update size counter
numPoints--;
}
int[] deleteIndex(int[] sourceArray, int indexToDelete){
if(sourceArray == null){
System.err.println("can't process null array");
return null;
}
if(indexToDelete < 0){
System.err.println("invalid index " + indexToDelete + "\nit's < 0");
return null;
}
if(indexToDelete >= sourceArray.length){
System.err.println("invalid index " + indexToDelete + "\nmax index = " + sourceArray.length);
return null;
}
return concat(subset(sourceArray, 0, indexToDelete),
subset(sourceArray, indexToDelete + 1, sourceArray.length - indexToDelete - 1));
}
void printArrays() {
println("X Positions");
for (int i = 0; i < xPos.length; i++) {
println("\t" + xPos[i]);
}
}
void keyPressed() {
if (key == 'p') {
printArrays();
}
if (keyCode == DELETE || keyCode == BACKSPACE){
deleteLeftMost();
}
}
If manually deleting an item from an array looks tedious it's because it is :)
Array is meant to be fixed size: deleting an item actually allocates 3 arrays: two subset arrays and one for concatenation.
A better option is to use a dynamic sized array data structure like ArrayList. Speaking of data structures, to represent a point you can use the PVector class (which has x,y properties, but can also do much more).
You might have not encountered ArrayList and PVector yet, but there are plenty of resources out there (including CodingTrain/NatureOfCode videos).
Here's an example using these:
final int DIAM = 20;
final int MAX_NUM = 1000;
ArrayList<PVector> points = new ArrayList<PVector>();
void setup() {
size (500, 500);
}
void draw() {
background(150);
fill(random(256), random(256), random(256));
for (PVector point : points) {
circle(point.x, point.y, DIAM);
}
}
void mouseClicked() {
insertXandY();
}
void insertXandY() {
if(points.size() < MAX_NUM){
points.add(new PVector(mouseX, mouseY));
}
}
void deleteLeftMost(){
// find leftmost index
// start with a large X value
float smallestX = Float.MAX_VALUE;
int smallestXIndex = -1;
// iterate through each X
for(int i = 0 ; i < points.size(); i++){
PVector point = points.get(i);
// if xPos[i] is smaller than the smallest value so far...
if (point.x < smallestX){
// ...remember it's value and index
smallestX = point.x;
smallestXIndex = i;
}
}
// remove item from list
points.remove(smallestXIndex);
}
void keyPressed() {
if (key == 'p') {
println(points);
}
if (keyCode == DELETE || keyCode == BACKSPACE){
deleteLeftMost();
}
}
Hopefully this step by step approach is easy to follow.
Have fun learning !

Is there a way for me to distribute points so that they're more compact near a different set of points?

I want to make a Voronoi tiling which fits itself to some text in Processing 3.5.3. I've got the algorithm for standard Voronoi tiling implemented, but I initialise all points to just be randomly distributed across the window.
I've got a list of points which make up some letters, generated by the geomerative package. They're all in the standard (x, y) format.
I'm looking for a function which would take the text points and the window size into account and give me back a sort of distribution, or, better yet, a list of points already following that distribution.
My code:
import geomerative.*;
public class Point {
public RPoint p = new RPoint(0, 0);;
public color c;
public boolean isTextPt;
public Point(int _w, int _h, float[][] distribution) {
this.p.x = random(_w);
this.p.y = random(_h);
//this.c = color(random(100, 250), random(100, 250), random(100, 250));
this.c = color(map(p.x, 0, _w, 50, 160), map(p.y, 0, _h, 0, 150), 255);
this.isTextPt = false;
}
public Point(float _x, float _y) {
this.p.x = _x;
this.p.y = _y;
this.c = color(random(50, 160), random(100, 250), 255);
this.isTextPt = true;
}
}
int baseAmountOfCells = 50;
RShape shape;
RPoint[] textPts;
Point[] points;
void setup() {
RG.init(this);
shape = new RFont("RobotoMono-Medium.ttf", 140, RFont.CENTER).toShape("voronoi songs for worley days");
textPts = shape.getPoints();
fullScreen();
colorMode(HSB);
points = new Point[baseAmountOfCells + textPts.length];
for (int i = 0; i < baseAmountOfCells; i ++) {
points[i] = new Point(width, height);
}
for (int i = 0; i < textPts.length; i ++) {
points[baseAmountOfCells + i] = new Point(textPts[i].x / 2 + width / 2, textPts[i].y / 2 + height / 2);
}
println("Amount of text points: " + str(textPts.length));
}
void draw() {
loadPixels();
int index = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float record = width * height; //it can never be more than this
int recIndex = 0;
for (int i = 0; i < points.length; i++) {
float d = dist(x, y, points[i].p.x, points[i].p.y);
if (d < record) {
record = d;
recIndex = i;
}
}
Point pt = points[recIndex];
pixels[index] = color(pt.c);
index++;
}
}
updatePixels();
for (Point pt : points) {
if (pt.isTextPt) {
stroke(0);
strokeWeight(2);
point(pt.p.x, pt.p.y);
}
}
noLoop();
}

Asteroids Game - Buggy Collision Detection

I am making an asteroid game using Processing 3.5.3. As you will see the collision detection is very buggy. When it detects collision between ship/asteroid sometimes it is greater than the asteroid size, sometimes it is smaller. Also, when the asteroids get smaller, the collision detect still seems to be calling the larger size asteroid. The collision between bullet and asteroid seems to only be a hit when the bullet is in the center of the asteroid.
Apologies for all the comments - they are required for my internal documentation.
Here is my code, it is broken up into classes.
Ship
class Ship {
PVector shipAcceleration;
PVector shipVelocity;
PVector shipPosition;
PShape shipShape;
float shipDirection;
int shipLastFire; //holds the time in millis that the last bullet was fired
int shipDelayTime;
Ship() {
shipAcceleration = new PVector();
shipVelocity = new PVector();
shipPosition = new PVector(width/2, height/2); // player starts in middle of screen
shipDirection = 0; // set to 0 to so "up" is a sense of direction
shipLastFire = 0;
shipDelayTime = 300;
keys = new boolean[5];
shipShape = createShape();
shipShape.beginShape();
shipShape.fill(255, 0, 0);
shipShape.vertex(0, -4);
shipShape.vertex(2, 0);
shipShape.vertex(2, 2);
shipShape.vertex(0, 1);
shipShape.vertex(-2, 2);
shipShape.vertex(-2, 0);
shipShape.vertex(0, -4);
shipShape.endShape();
}
void moveShip() {
shipShape.resetMatrix();
// reset.Matrix sourced from https://processing.org/reference/resetMatrix_.html
shipShape.rotate(radians(shipDirection)); // rotates ship
shape(shipShape, shipPosition.x, shipPosition.y, 10, 10);
}
void updateShip() {
// motion sourced from Chapter 22 of 'Processing: A programming handbook
// for visual designers and asrtists' by Casey Reas and Ben Fry
shipAcceleration.x = 0;
shipAcceleration.y = 0;
if (keys[0]) {
shipAcceleration.x = 0.5 * cos(radians(shipDirection) - PI/2);
shipAcceleration.y = 0.5 * sin(radians(shipDirection) - PI/2);
}
if (keys[1] && !keys[2])
{
shipDirection -= 5;
}
if (keys[2] && !keys[1])
{
shipDirection += 5;
}
shipVelocity.add(shipAcceleration);
// add sourced from https://processing.org/reference/PVector_add_.html
shipPosition.add(shipVelocity);
shipVelocity.mult(.95);
// mult sourced from https://processing.org/reference/PVector_mult_.html
shipPosition.x %= width;
if (shipPosition.x < -10)
{
shipPosition.x = width;
}
shipPosition.y %= height;
if (shipPosition.y < -10)
{
shipPosition.y = height;
}
if (keys[4]) {
if (millis() - shipLastFire > shipDelayTime) {
shipLastFire = millis();
fireBullet(shipPosition, shipVelocity, shipDirection);
}
}
}
}
Bullet
class Bullet {
PVector bulletPosition;
PVector bulletVelocity;
boolean bulletHidden; // used if lifespan is max and to help recycle
int bulletSize;
int bulletCreationTime;
int bulletLifespan; //the time in milli seconds that bullets last
int bulletSpeed;
Bullet() {
bulletHidden = true;
bulletSize = 5;
bulletPosition = new PVector();
bulletVelocity = new PVector();
bulletCreationTime = 0;
bulletLifespan = 3000;
bulletSpeed = 5;
}
void updateBullet() {
if (!bulletHidden) {
bulletPosition.add(bulletVelocity);
if (millis() - bulletCreationTime > bulletLifespan)
// millis sourced from https://processing.org/reference/millis_.html
{
bulletHidden = true;
}
bulletPosition.x %= width;
if (bulletPosition.x < -1)
{
bulletPosition.x = width;
}
bulletPosition.y %= height;
if (bulletPosition.y < -1)
{
bulletPosition.y = height;
}
}
}
void drawBullet() {
if (!bulletHidden) {
updateBullet();
ellipse(bulletPosition.x, bulletPosition.y, bulletSize, bulletSize);
}
}
void reset(PVector pos, PVector spe, float direct) {
bulletPosition = new PVector(pos.x + (20 * cos(radians(direct) - PI/2)), pos.y + (20 * sin(radians(direct) - PI/2)));
bulletVelocity.x = bulletSpeed * cos(radians(direct) - PI/2) + spe.x;
bulletVelocity.y = bulletSpeed * sin(radians(direct) - PI/2) + spe.y;
bulletCreationTime = millis();
bulletHidden = false;
}
}
Asteroid
class Asteroid {
float asteroidSize = (width/80*12);
float x;
float y;
float velocityX;
float velocityY;
PVector[] vertices = new PVector[8];
boolean active = true; //false after collision
int level = 1; // how many times has it been shot. Level 1 is not yet shot
Asteroid(float xPos, float yPos, int aLevel) {
if (xPos == 0 && yPos == 0) { //if begin level asteroids
x = random(width) ; // set random start positions
y = random (height);
} else { // if collision generating 2 smaller asteroids
x = xPos; // set from asteroid x, y
y = yPos;
}
velocityX = random(-2, 2);
velocityY = random(-2, 2);
level = aLevel; //sets asteroid level (how many times shot)
//create polygon. /aLevel generates smaller polygons with each collision.
vertices[0] = new PVector(random (width/80*3/aLevel), random(height/80*3/aLevel) );
vertices[1] = new PVector(random((width/80*4/aLevel), (width/80*8/aLevel)), random(height/80*3/aLevel) );
vertices[2] = new PVector(random((width/80*9/aLevel), (width/80*12/aLevel)), random(height/80*3/aLevel) );
vertices[3] = new PVector(random((width/80*9/aLevel), (width/80*12/aLevel)), random((height/80*4/aLevel), (height/80*8/aLevel)) );
vertices[4] = new PVector(random((width/80*9/aLevel), (width/80*12/aLevel)), random((height/80*9/aLevel), (height/80*12/aLevel)) );
vertices[5] = new PVector(random((width/80*4/aLevel), (width/80*8/aLevel)), random((height/80*9/aLevel), (height/80*12/aLevel)) );
vertices[6] = new PVector(random(width/80*3/aLevel), random((height/80*9/aLevel), (height/80*12/aLevel)) );
vertices[7] = new PVector(random(width/80*3/aLevel), random((height/80*4/aLevel), (height/80*8/aLevel)) );
}
void moveAsteroid() {
x = x + velocityX; //asteroids to move with a random velocity
y = y + velocityY;
if ( x < -1 * asteroidSize ) {
x = width + asteroidSize;
} //if off screen left, come back in right
if ( x > width + asteroidSize ) {
x = -1 * asteroidSize;
} // if off screen right, come back in left
if ( y < -1 * asteroidSize ) {
y = height + asteroidSize;
} //if off top of screen, come back in bottom
if ( y > height + asteroidSize ) {
y = -1 * asteroidSize ;
} //if off bottom of screen, come back in top
}
void asteroidDraw() {
if (active == false) { // If not active don't draw
return;
}
stroke(150);
fill(255);
// this was how I orginally coded. Have kept commented out for now, so I can see what I did, but will delete before submission.
/*beginShape();
vertex(vertices[0].x, vertices[0].y );
vertex(vertices[1].x, vertices[1].y );
vertex(vertices[2].x, vertices[2].y );
vertex(vertices[3].x, vertices[3].y );
vertex(vertices[4].x, vertices[4].y );
vertex(vertices[5].x, vertices[5].y );
vertex(vertices[6].x, vertices[6].y );
vertex(vertices[7].x, vertices[7].y );
endShape(CLOSE); */
beginShape();
for (PVector v : vertices) {
vertex(x+v.x, y+v.y);
}
endShape(CLOSE);
}
void manDown() {
active = false; //sets to in active so will stop drawing
// add 2 new asteroids to array
asteroids = (Asteroid[]) append( asteroids, new Asteroid( x+20, y+20, level + 1 ) ); // Appends asteroid to array. Changing level makes the asteroid smaller.
asteroids = (Asteroid[]) append( asteroids, new Asteroid( x-20, y-20, level + 1 ) ); // Appends two smaller asteroids to array.
}
}
Game Manager
class GameManager {
int scoreCount;
boolean gameState = true;
int lifeCount;
void newGame()
{
gameState = true; //sets game state to in play
scoreCount = 0; //set counter of flies killed to 0
lifeCount = 3;
}
void scoreUpdate()
{
textSize(width*3/100);
textAlign(LEFT);
fill(255);
text("Score " + scoreCount, (width*2/100), (height*4/100));
}
void lifeLost()
{
lifeCount = lifeCount - 1;
if (lifeCount <= 0) {
gameState = false;
gameOver();
}
}
void lifeUpdate()
{
textSize(height*3/100);
textAlign(LEFT);
fill(255);
text("Lives " + lifeCount, (width*2/100), ((height*4/100) + (height*3/100)) );
}
void gameOver()
{
background(0);
textSize(height*5/100);
textAlign(CENTER);
fill(255);
text("Game over", width/2, height/2.6);
//play again button
fill(255);
rect(((width/2)-(width/4)), (((height/2)- (height/12))), width/2, height/8);
fill(0);
text("Play Again", width/2, height/2);
//define area for play again button collision
if (mousePressed)
{
if (
(mouseX > width/4) &&
(mouseX < width/4 +width/2) &&
(mouseY > (height/2-height/10.5)) &&
(mouseY < ((height/2-height/10.5) + height/8))
)
{
setup(); //reset game
}
}
}
}
Main
Asteroid[] asteroids; //K Level 1 starts with 6, add 2 each level, 10 levels
Ship myShip;
GameManager gameManager;
ArrayList<Bullet> bullets;
// Array help sourced from chapter 28 of 'Processing: A programming handbook
// for visual designers and asrtists' by Casey Reas and Ben Fry
int bulletIndex; // used to recycle bullets
// index sourced from https://py.processing.org/reference/list_index.html
int startNum = 6; //K begin game with 6 asteroids in the level
boolean[] keys; // boolean for storing keypressed/released
void setup() {
size(800, 800);
gameManager = new GameManager();
gameManager.newGame();
bulletIndex = 0;
bullets = new ArrayList<Bullet>();
keys = new boolean[5];
myShip = new Ship();
asteroids = new Asteroid [startNum]; //K
for (int a = 0; a < startNum; a++) { //K create asteroids in array
asteroids[a] = new Asteroid(0, 0, 1); //K
}
for (int i = 0; i < 20; i++)
{
bullets.add(new Bullet()); // create bullets
}
}
void draw() {
background(0);
collisionDetect();
gameManager.gameState = true;
myShip.updateShip(); // E
myShip.moveShip(); // E
for (int a = 0; a < asteroids.length; a++) { //K for asteroids in array
asteroids[a].moveAsteroid(); //K
asteroids[a].asteroidDraw(); //K
}
gameManager.scoreUpdate();
gameManager.lifeUpdate();
for (int i = 0; i < bullets.size(); i++)
{
bullets.get(i).drawBullet(); // drawing bullets
}
}
void keyPressed() {
if (key == CODED) {
if (keyCode == UP)
keys[0] = true;
if (keyCode == LEFT)
keys[1] = true;
if (keyCode == RIGHT)
keys[2] = true;
if (keyCode == DOWN)
keys[3] = true;
} else {
if (key == 'w')
keys[0] = true;
if (key == 'a')
keys[1] = true;
if (key == 'd')
keys[2] = true;
if (key == 's')
keys[3] = true;
if (key == ' ')
keys[4] = true;
}
}
void keyReleased() {
if (key == CODED) {
if (keyCode == UP)
keys[0] = false;
if (keyCode == LEFT)
keys[1] = false;
if (keyCode == RIGHT)
keys[2] = false;
if (keyCode == DOWN)
keys[3] = false;
} else {
if (key == 'w')
keys[0] = false;
if (key == 'a')
keys[1] = false;
if (key == 'd')
keys[2] = false;
if (key == 's')
keys[3] = false;
if (key == ' ')
keys[4] = false;
}
}
void fireBullet(PVector pos, PVector spe, float dir) {
bullets.get(bulletIndex).reset(pos, spe, dir);
// set attributes of last used bullet
// get sourced from https://processing.org/reference/get_.html
bulletIndex++; //update index
bulletIndex %= bullets.size(); //keep index in range
}
void collisionDetect(){
Asteroid testHolder;
Bullet bulletHolder;
// asteroid and bullet objects to minimize creating new objects
for(int i = 0; i < asteroids.length; i++){
testHolder = asteroids[i];
if(dist(testHolder.x, testHolder.y, myShip.shipPosition.x,
myShip.shipPosition.y) < testHolder.asteroidSize)
// collision of player and the asteroid
{gameManager.gameOver();}
for(int j = 0; j < bullets.size(); j++){
bulletHolder = bullets.get(j);
// pull and store each bullet from the list
if(bulletHolder.bulletHidden){continue;}
// don't calculate anything if it is hidden
if(dist(testHolder.x, testHolder.y, bulletHolder.bulletPosition.x,
bulletHolder.bulletPosition.y) < testHolder.asteroidSize){
testHolder.manDown();
// used to detect collision and split if collided
bulletHolder.bulletHidden = true;
// hide the bullet so it won't go 'through' the asteroids
j++;
}
}
}
}
For the problem with the smaller asteroids, you need to make the asteroidSize dependent on the level. Currently they are all the same: float asteroidSize = (width/80*12);
As the to collision issue, the first thing is that you also have to take the size to the ship/bullet hitting the asteroid into account:
if(dist(testHolder.x, testHolder.y, myShip.shipPosition.x, myShip.shipPosition.y) < (testHolder.asteroidSize + myShip.size))
For clarity: size is in both cases the radius.
Second, there will always be some area's where this basic type of collision detection does not follow the visual, because your shapes are not circles. The randomness that you use for the asteroids does not help in that respect. A way to get more control over this is to define a couple of shapes per level, and pick one of those at random when creating an asteroid. This way you can tweak the shape/radius to make a good trade off between looks and function so it looks 'believable enough'.

Array is only displaying 1 object instead of the full amount of variables

I'm new to coding (as I'm sure you might be able to tell). The program runs and generates 1 Tubble, but the additional objects don't show.
Here's my class:
class Tubble {
float x;
float y;
float diameter;
float yspeed;
float tempD = random(2,86);
Tubble() {
x = random(width);
y = height-60;
diameter = tempD;
yspeed = random(0.1, 3);
}
void ascend() {
y -= yspeed;
x = x + random(-2, 2);
}
void dis() {
stroke(0);
fill(127, 100);
ellipse(x, y, diameter, diameter);
}
void top() {
if (y < -diameter/2) {
y = height+diameter/2;
}
}
}
Class
class Particle {
float x, y;
float r;
float speed = 2.2;
int direction = 1;
PImage pbubbles;
Particle(float x_, float y_, float r_) {
x = x_;
y = y_;
r = r_;
}
void display() {
stroke(#F5D7D7);
strokeWeight(2.2);
noFill();
ellipse(x, y, r*2, r*2);
}
boolean overlaps(Particle other) {
float d = dist(x, y, other.x, other.y);
if (d < r + other.r) {
return true;
} else {
return false;
}
}
void move() { //testing
x += (speed * direction);
if ((x > (width - r)) || (x < r)) {
direction *= -1;
}
}
void updown() {
y += (speed * direction);
if ((y > (height - r)) || (y < r)) {
direction *= -1;
}
}
}
Main sketch:
Tubble[] tubbles = new Tubble [126];
PImage bubbles;
Particle p1;
Particle p2;
Particle p3;
Particle p4;
Particle p5;
float x,y;
float speed;
int total = 0;
int i;
//int direction = 1;
void setup() {
size(800, 925);
bubbles = loadImage("purple_bubbles.png");
p1 = new Particle (100, 100, 50);
p2 = new Particle (500, 200, 100);
p3 = new Particle (600, 600, 82);
p4 = new Particle (height/2, width/2, 200);
p5 = new Particle ((height/3), (width/3), 20);
for (int i = 0; i < tubbles.length; i++); {
tubbles[i] = new Tubble();
}
}
void mousePressed() {
total = total + 1;
}
void keyPressed() {
total = total - 1;
}
void draw() {
image(bubbles, 0, 0, 800, 925);
//background(0);
for (int i = 0; i < tubbles.length; i++); {
tubbles[i].ascend();
tubbles[i].dis();
tubbles[i].top();
}
if ((p2.overlaps(p1)) && (p2.overlaps(p4))) {
background(#BF55AB, 25);
}
if ((p3.overlaps(p2)) && (p3.overlaps(p4))) {
background(#506381, 80);
}
p2.x = mouseX;
p3.y = mouseY;
p1.display();
p2.display();
p3.display();
p4.display();
p5.display();
p4.move();
p5.updown();
// for (int i = 0; i < tubbles.length; i++); {
// tubbles[i].dis();
// tubbles[i].ascend();
// tubbles[i].top();
// }
}
There are extra semicolons in the lines
for (int i = 0; i < tubbles.length; i++); {
for (int i = 0; i < tubbles.length; i++); {
// for (int i = 0; i < tubbles.length; i++); {
It make the for loop do virtually nothing.
Then the block after the for loop will read the global variable i and do the action only once.
Remove the semicolons like this to put the block in the loop.
for (int i = 0; i < tubbles.length; i++) {
for (int i = 0; i < tubbles.length; i++) {
// for (int i = 0; i < tubbles.length; i++) {

Unable to run the program

I am making a game in Eclipse Mars using the Processing library. I had made the game elsewhere and it ran fine. There were no errors after I copied and pasted the files from my flash drive to the folder in Eclipse. When I tried to run it, it said "The selection cannot be launched, and there are no recent launches." There were no recent launches because I had just gotten Eclipse. My code is as follows:
Main Class:
//package dogeball;
import processing.core.PApplet;
import processing.core.PImage;
import java.awt.Color;
import processing.core.PFont;
public class Dogeball extends PApplet {
Ball ball;
Furniture butterChair;
Furniture[] bricks;
PFont dogefont;
float py;
float score;
boolean game;
int checker;
boolean mode;
PImage img = loadImage("doge.jpg");
PImage img2 = loadImage("doge2.png");
public void setup() {
checker = 0;
size(300,250);
game = false;
mode = true;
ball = new Ball(this, 100, 225, 0, 0, 10, Color.DARK_GRAY );
butterChair = new Furniture(this, 130, 238, 40, 10, Color.YELLOW);
py = butterChair.w /2;
bricks = new Furniture[56];
dogefont = loadFont("ComicSansMS-48.vlw");
for(int rowNum = 0; rowNum<8; rowNum+= 1) {
for(int colNum = 0; colNum<7; colNum += 1){
bricks[7*rowNum + colNum] = new Furniture(this, 10+40*colNum, 10+15*rowNum, 40, 15, Color.red);
score = 0;
}
}
}
public void draw() {
if(game == false) {
background(img);
fill(0,255,255);
textSize(30);
textFont(dogefont);
text("DogeBall",33, 170);
fill(255,255,0);
textSize(20);
text("Press Space", 120,190);
fill(255,0,0);
text("Such BrickBreaker", 20, 20);
fill(0,0,255);
text("Much Atari", 190, 80);
fill(0,255,0);
text("How Breakout", 150, 230);
}
if(keyPressed == true) {
if (key == ' ') {
game = true;
}
}
if(game == true) {
if(keyPressed == true) {
if (key == 'm') {
mode = !mode;
}
}
//checker = 0;
background(img);
ball.appear();
ball.hover();
butterChair.appear();
if(mode == true) {
butterChair.x = mouseX-butterChair.w/2;
}
if(mode == false) {
if(keyPressed == true) {
if (key == CODED) {
if (keyCode == LEFT){
butterChair.x -= 3;
}
}
}
if(keyPressed == true) {
if (key == CODED) {
if (keyCode == RIGHT){
butterChair.x += 3;
}
}
}
}
if(butterChair.x <= 0) {
butterChair.x = 0;
}
if(butterChair.x >= width - butterChair.w) {
butterChair.x = width - butterChair.w;
}
textFont(dogefont);
fill(255,0,255);
text("Much Doge", 12, 160);
fill(255,0,0);
textSize(20);
text("M to toggle mouse mode.", 20,200);
fill(0);
textSize(10);
text("You might have to press twice", 10,220);
fill(0,0,255);
textSize(20);
text("Press S to Start", 150, 230);
if (keyPressed == true) {
if (key == 's' || key == 'S'){
ball.vy = 2;
ball.vx = 1;
}
}
/*if(mousePressed == true) {
ball.vx = 0;
ball.vy = 0;
}*/
for(int i = 0; i<56; i+= 1) {
bricks[i].appear();
}
}
detectCollision();
if(ball.y >= height) {
checker = 0;
if(checker ==0){
background(img);
ball.vx = 0;
ball.vy = 0;
textSize(30);
fill(255,0,0);
game = false;
text("Such Sorry", 130, 160);
fill(0,255,255);
text("Much Game Over", 20, 215);
fill(255,255,0);
text("So Losing", 10, 30);
textSize(20);
text("Press P to Play Again", 20, 245);
}
if(keyPressed == true) {
if(key == 'p') {
game = true;
ball.x = 100;
ball.y = 225;
checker = 1;
for(int rowNum = 0; rowNum<8; rowNum+= 1) {
for(int colNum = 0; colNum<7; colNum += 1){
bricks[7*rowNum + colNum] = new Furniture(this, 10+40*colNum, 10+15*rowNum, 40, 15, Color.red);
score = 0;
}
}
}
}
}
}
void detectCollision() {
if(keyPressed == true) {
if(key == '-')
{
for(int cCode = 0; cCode < 56; cCode += 1) {
Furniture b = bricks[cCode];
b.x = width * 2;
b.y = height * 2;
score = 56;
}
}}
if(ball.x >= butterChair.x &&
ball.x <= butterChair.x + butterChair.w &&
ball.y + ball.s /2 > butterChair.y) {
ball.vy *= -1;
}
for(int i = 0; i<bricks.length; i+= 1) {
Furniture b = bricks[i];
if(ball.x >= b.x && ball.x <= b.x+b.w && ball.y-ball.s/2 <= b.y) {
b.y = height * 2;
b.x = width * 2;
ball.vy *= -1;
score += 1;
}
if(score == 56){
background(img);
ball.vx = 0;
ball.vy = 0;
fill(255,0,0);
textSize(20);
text("Such Winning!", 20, 20);
textSize(40);
fill(0,255,0);
text("Much Congrats!",12 ,160);
textSize(20);
fill(255,0,255);
text("Press P to Play Again", 20, 245);
if(keyPressed == true) {
if(key == 'p') {
game = true;
ball.x = 100;
ball.y = 225;
checker = 1;
for(int rowNum = 0; rowNum<8; rowNum+= 1) {
for(int colNum = 0; colNum<7; colNum += 1){
bricks[7*rowNum + colNum] = new Furniture(this, 10+40*colNum, 10+15*rowNum, 40, 15, Color.red);
score = 0;
}
}
}
}
}
}
}
static public void main(String args[]) {
PApplet.main("Dogeball");
}
}
Ball Class:
//package dogeball;
import java.awt.Color;
import processing.core.PApplet;
public class Ball extends PApplet {
float x;
float y;
float vx;
float vy;
float s;
Color c;
PApplet p;
Ball(PApplet pApp, float xLocation, float yLocation, float xSpeed, float ySpeed, float size, Color shade){
x = xLocation;
y = yLocation;
vx = xSpeed;
vy = ySpeed;
s = size;
c = shade;
p = pApp;
}
void hover() {
x += vx;
y += vy;
if(x< 0 || x> p.width) {
vx *= -1;
}
if(y< 0) {
vy *= -1;
}
}
void appear() {
p.fill(c.getRGB() );
p.ellipse(x,y,s,s);
}
}
Paddle Class:
//package dogeball;
import java.awt.Color;
import processing.core.PApplet;
public class Furniture extends PApplet {
float x;
float y;
float w;
float h;
Color c;
PApplet p;
Furniture(PApplet PApp, float locationX, float locationY, float fWidth, float fHeight, Color shade) {
x = locationX;
y = locationY;
w = fWidth;
h = fHeight;
c = shade;
p = PApp;
}
void appear() {
p.fill(c.getRGB());
p.rect(x,y,w,h);
}
}
You have probably the wrong project selected on the projects tree or the run configurations are set to another project, since you haven't run it yet.
Either way, you have to right click your projects folder on the projects tree, then find Run As > Java Applet.
Another way to do it would be adding a main function, as you already did, and run is as a Java Application. Instead of using the current main function, you can try to use the code below to see it in present mode and see if it works:
public static void main(String args[]) {
PApplet.main(new String[] { "--present", "Dogeball" });
}

Resources