I'm making a multi-player chopper clone in Processing. Here's my code:
ArrayList<Heli> helis = new ArrayList<Heli>();
ArrayList<Heli> permaHelis = new ArrayList<Heli>();
ArrayList<Wall> walls = new ArrayList<Wall>();
IntDict keys = new IntDict();
float speed = 3;
float loop = 0;
float distance = 20;
float place = 100;
int numDead;
PFont f;
void setup() {
size(1000, 500);
f = createFont("Trebuchet MS", 25);
textFont(f);
permaHelis.add(new Heli(place, height/2, 20, 0.1, "w", color(255, 100, 100), "Dr.Swerve"));
//permaHelis.add(new Heli(place+150, height/2, 20, 0.1, str(UP), color(255, 255, 0), "Grebbles"));
for (int i = 0; i<=permaHelis.size()-1;i++) {
helis.add(permaHelis.get(i));
}
}
void draw() {
noStroke();
background(200);
if (loop == distance) {
walls.add(new Wall(width+100, random(height), random(25, 100), speed, color(0, 255, 0)));
loop=0;
}
for (int i = 0; i<helis.size();i++) {
for (int j = 0; j<walls.size();j++) {
walls.get(j).iterate();
walls.get(j).display();
if (walls.get(j).x+walls.get(j).size<=0) {
walls.remove(i);
}
if (dist(helis.get(i).x, helis.get(i).y, walls.get(j).x, walls.get(j).y)<helis.get(i).size/2+walls.get(j).size/2||helis.get(i).y<0||helis.get(i).y+helis.get(i).size>height) {
helis.get(i).explode=true;
helis.get(i).run = false;
}
}
helis.get(i).iterate();
helis.get(i).display();
}
for (int i = 0; i < helis.size();i++) {
if (helis.get(i).run==false&&helis.get(i).dead == false) {
helis.get(i).dead = true;
numDead++;
}
}
And here's the faulty bit.
if (numDead==helis.size()) {
fill(0);
text("Restart? (Press R)", width/2, height/2);
if (keyPressed&&key=='r') {
walls = new ArrayList<Wall>();
helis = new ArrayList<Heli>();
for (int i = 0; i<=permaHelis.size()-1;i++) {
helis.add(permaHelis.get(i));
}
numDead = 0;
}
}
loop++;
}
And a little key-checker at the bottom.
void keyEvent(int pressed) {
if (key==CODED) {
keys.set(str(keyCode), pressed);
}
else {
keys.set(str(key), pressed);
}
}
void keyPressed() {
keyEvent(1);
}
void keyReleased() {
keyEvent(0);
}
So when I press R to restart, the heli scores stay, unchanging, at the top of the screen, but the helis themselves don't display. Also, the walls restart fine. The array empties and new walls come in from the right of the screen. What am I doing wrong?
Some notes:
Where you do this:
for (int i = 0; i<=permaHelis.size()-1;i++) {
helis.add(permaHelis.get(i));
}
You can instead use this:
helis.addAll(permaHelis);
In this snippet, you redisplay every wall for each heli, which isn't good (because if you have ten helis, each wall is getting displayed ten times per frame!). You could have a separate loop just for the walls list to display it.
for (int i = 0; i<helis.size();i++) {
for (int j = 0; j<walls.size();j++) {
walls.get(j).iterate();
walls.get(j).display();
I think you had a typo here. Should it be walls.remove(j);?
if (walls.get(j).x+walls.get(j).size<=0) {
walls.remove(i);
}
Finally, on to your question. I can't say for sure without the code for the classes, but what I think is happening is this. You create your permaHeli, fine. You add it to the list of normal helis, fine, but it doesn't copy the object, it only adds a reference to it. So, when you do things like helis.get(i).dead = true;, you're actually changing the original permaHeli, too! Then, when you hit R and reset it, it's clearing the list and adding an already dead heli into it. Try putting println(helis.get(i).dead); in a for loop somewhere to see if this is true. If it is, all you need to do is create a new heli instead of re-using the permaHelis list (but maybe then the permaHelis aren't useful anymore).
Related
I am trying to fill some particular circle areas on a square grid in Proceesing. However, I am facing some weird filling after I run my code. I used the "atan2" function to get the angle of points in the grid and apply some if conditions to limit the area. But it doesn't work. Actually, it works some way but not exactly what I want.This is the result I run the code-> enter image description here, but it should be like -> enter image description here Can someone help me to solve this, please?
(Additionally, I seized this page to detect which points are in the area I specified enter link description here.
Cell [][] cells;
int res = 10;
PVector circleCenter ;
float rad=290;
void setup() {
size(1200, 800);
cells = new Cell[width/res ][height/res];
for (int i=0; i<cells.length; i++) {
for (int j = 0; j<cells[0].length; j++) {
cells[i][j] = new Cell();
}
}
}
void draw() {
background(255);
circleCenter = new PVector(mouseX, mouseY);
display();
pushStyle();
ellipse(circleCenter.x, circleCenter.y, 20, 20);
popStyle();
//println(frameRate);
}
void display() {
for (int i=0; i<cells.length; i++) {
for (int j = 0; j<cells[0].length; j++) {
if (sq(i*res-width/2) + sq(j*res-height/2) <=sq(rad/2)) {
float angleInRad = atan2(j*res-height/2, i*res-width/2);
///
if (angleInRad<radians(-10) && angleInRad>radians(-60)) {
fill(0, 255, 0); // degrees(atan2(j*res-circleCenter.y, i*res-circleCenter.x))
}
} else {
noFill();
}
rect(i*res, j*res, res, res);
}}
class Cell {
boolean blackness=false;
Cell() {
}
}
You have not specified input data for your task. I assume we have center coordinates cx, cx, radius r, starting and ending angle sa, ea of the sector (in code -10, -60).
There is an approach to check whether vector direction lies in sector, it's robust to potential troubles with periodicity, negative values etc. At first normalize range ends, then find middle angle and half-angle
half = (ea - sa) / 2
mid = (ea + sa) / 2
coshalf = Cos(half)
Now compare that difference of angle and middle one is lower then half-angle
if Cos(angle - mid) >= coshalf then
angle lies in range sa..ea
I've built this L-System in Processing using toxiclib and I want to connect each point which is specified to each intersection in the branching of the tree. I've written a separate sketch in which I'm trying to create a triangle mesh by connecting the three closest points, I've been able to connect three points but I want it to be able to go through all the Vertices in an arraylist and then connect three closest points until I have a mesh out of all the vertices in the array. I also need to be able to convert this whole sketch into a function where by I can feed it into my L-System and then it will return the whole system with all the points connected in order to create a mesh. Essentially this is so I can then texture and maybe possibly apply Shaders to it if possible. I think that I might be attempting a harder way of approaching this for I believe toxiclibs or HEMESH libraries could do all of this for me, but I've been unable to figure it out. Any help would be much appreciated.
Here's the code for the sketch I wrote to try and connect all the points into a mesh.
import peasy.*;
float min = 1000;
ArrayList <PVector> loc = new ArrayList <PVector> ();
ArrayList <PVector> locSort = new ArrayList <PVector> ();
float [] minDists;
int [] minIdxs;
PeasyCam cam;
void setup() {
size(600, 600, OPENGL);
cam = new PeasyCam(this, 100);
for (int i=0; i<50; i++) {
loc.add(new PVector(random(-50, 50), random(-50, 50), random(-50, 50)));
}
minDists = new float[3];
minIdxs = new int[3];
for (int i = 0; i < 3; i ++)minDists[i] = 1000;
for (int i=0; i<loc.size(); i++) {
for (int j=0; j<loc.size (); j++) {
PVector vi= loc.get(i);
// loc.remove(i);
PVector vj= loc.get(j);
// loc.remove(j);
float c = vi.dist(vj);
for (int k = 0; k < 3; k++) {
if (c < minDists[k] && c > 0) {
if (k == 0) {
minDists[2] = minDists[1];
minDists[1] = minDists[0];
} else if (k == 1) {
minDists[2] = minDists[1];
}
println(k, c);
minDists[k] = c;
minIdxs[k] = j;
break;
}
}
}
}
}
void draw() {
background(255);
for (PVector v : loc) {
pushMatrix();
translate(v.x, v.y, v.z);
fill(0);
noStroke();
sphere(1);
popMatrix();
}
for (int i = 0; i < 3; i ++) {
PVector p1 = loc.get(minIdxs[i]);
PVector p2 = loc.get(minIdxs[(i+1)%3]);
stroke(255, 0, 0);
line(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);
}
}
Also the L-System was created by following this tutorial: https://www.youtube.com/watch?v=qF8LGLVrwfo
So I followed a free manual instructing how to write Asteroids in Java, and it runs great. I would like to add it into a program so I can call it, run it for a time, and then have it return an int. The program I'm making is an application, and I've been searching for a while trying and failing, figuring out how to make make it run as an application. The stuff I've read here says I should do this:
public class Main extends JFrame {
public static void main(String[] args) {
AsteroidsGame game = new AsteroidsGame();
JFrame frame = new JFrame();
frame.setLayout(new GridLayout (1,1));
frame.add(game);
frame.setSize(500,500);
game.init();
game.start();
frame.setVisible(true);
}
}
But then I get an error
Exception in thread "main" java.lang.NullPointerException
at AsteroidsGame.init(AsteroidsGame.java:49)
at Main.main(Main.java:15)
which points me to the below for line 49, and my game.init() for line 15.
g = img.getGraphics();
Here's the code for the AsteroidsGame, I'm too tired to think anymore. I just need to get it to run as an application, any other code changes are irrelevant at this point. I know it's a lot of code but I'm hoping it's a simple something I've missed. Any help is greatly appreciated. Thank you!
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class AsteroidsGame extends Applet implements Runnable, KeyListener {
Thread thread;
Dimension dim;
Image img;
Graphics g;
long endTime, startTime, framePeriod;
Ship ship;
boolean paused; // True if the game is paused. Enter is the pause key
Shot[] shots;
int numShots;
boolean shooting;
Asteroid[] asteroids; // the array of asteroids
int numAsteroids; // the number of asteroids currently in the array
double astRadius, minAstVel, maxAstVel; // values used to create
// asteroids
int astNumHits, astNumSplit;
int level; // the current level number
int money;
double fuel;
Random rand = new Random();
public void init() {
resize(500, 500);
shots = new Shot[41]; // 41 is a shot's life period plus one.
// since at most one shot can be fired per frame,
// there will never be more than 41 shots if each one only
// lives for 40 frames.
numAsteroids = 0;
level = rand.nextInt(25)+1; // will be incremented to 1 when first level is set up
astRadius = 10; // values used to create the asteroids
minAstVel = 2;
maxAstVel = 8;
astNumHits = 3;
astNumSplit = 2;
money = 0;
fuel = 100;
endTime = 0;
startTime = 0;
framePeriod = 25;
addKeyListener(this); // tell it to listen for KeyEvents
dim = getSize();
img = createImage(dim.width, dim.height);
g = img.getGraphics();
thread = new Thread(this);
thread.start();
}
public void setUpNextLevel() { // start new level with one more asteroid
level++;
// create a new, inactive ship centered on the screen
// I like .35 for acceleration, .98 for velocityDecay, and
// .1 for rotationalSpeed. They give the controls a nice feel.
ship = new Ship(250, 250, 0, .35, .98, .1, 12);
numShots = 0; // no shots on the screen at beginning of level
paused = false;
shooting = false;
// create an array large enough to hold the biggest number
// of asteroids possible on this level (plus one because
// the split asteroids are created first, then the original
// one is deleted). The level number is equal to the
// number of asteroids at it's start.
asteroids = new Asteroid[level
* (int) Math.pow(astNumSplit, astNumHits - 1) + 1];
numAsteroids = level;
// create asteroids in random spots on the screen
for (int i = 0; i < numAsteroids; i++)
asteroids[i] = new Asteroid(Math.random() * dim.width,
Math.random() * dim.height, astRadius, minAstVel,
maxAstVel, astNumHits, astNumSplit);
}
public void paint(Graphics gfx) {
g.setColor(Color.black);
g.fillRect(0, 0, 500, 500);
for (int i = 0; i < numShots; i++)
// draw all the shots on the screen
shots[i].draw(g);
for (int i = 0; i < numAsteroids; i++)
asteroids[i].draw(g);
ship.draw(g); // draw the ship
g.setColor(Color.cyan); // Display level number in top left corner
g.drawString("Level " + level, 20, 20);
g.drawString("Money " + money, 80, 20);
g.drawString("Fuel " + fuel, 20, 50);
gfx.drawImage(img, 0, 0, this);
}
public void update(Graphics gfx) {
paint(gfx);
}
public void run() {
for (;;) {
startTime = System.currentTimeMillis();
// start next level when all asteroids are destroyed
if (numAsteroids <= 0)
setUpNextLevel();
if (!paused) {
ship.move(dim.width, dim.height); // move the ship
// move shots and remove dead shots
for (int i = 0; i < numShots; i++) {
shots[i].move(dim.width, dim.height);
// removes shot if it has gone for too long
// without hitting anything
if (shots[i].getLifeLeft() <= 0) {
// shifts all the next shots up one
// space in the array
deleteShot(i);
i--; // move the outer loop back one so
// the shot shifted up is not skipped
}
}
if(ship.accelerating && fuel>0){
fuel -= 1.5;
}
if(ship.accelerating && fuel == 0)
{
ship.accelerating = false;
}
// move asteroids and check for collisions
updateAsteroids();
if (shooting && ship.canShoot()) {
// add a shot on to the array
shots[numShots] = ship.shoot();
numShots++;
}
}
repaint();
try {
endTime = System.currentTimeMillis();
if (framePeriod - (endTime - startTime) > 0)
Thread.sleep(framePeriod - (endTime - startTime));
} catch (InterruptedException e) {
}
}
}
private void deleteShot(int index) {
// delete shot and move all shots after it up in the array
numShots--;
for (int i = index; i < numShots; i++)
shots[i] = shots[i + 1];
shots[numShots] = null;
}
private void deleteAsteroid(int index) {
// delete asteroid and shift ones after it up in the array
numAsteroids--;
for (int i = index; i < numAsteroids; i++)
asteroids[i] = asteroids[i + 1];
asteroids[numAsteroids] = null;
}
private void addAsteroid(Asteroid ast) {
// adds the asteroid passed in to the end of the array
asteroids[numAsteroids] = ast;
numAsteroids++;
}
private void updateAsteroids() {
for (int i = 0; i < numAsteroids; i++) {
// move each asteroid
asteroids[i].move(dim.width, dim.height);
// check for collisions with the ship, restart the
// level if the ship gets hit
if (asteroids[i].shipCollision(ship)) {
money+= Math.random()*1000;
deleteAsteroid(i);
//level--; // restart this level
//numAsteroids = 0;
return;
}
// check for collisions with any of the shots
for (int j = 0; j < numShots; j++) {
if (asteroids[i].shotCollision(shots[j])) {
// if the shot hit an asteroid, delete the shot
deleteShot(j);
// split the asteroid up if needed
if (asteroids[i].getHitsLeft() > 1) {
for (int k = 0; k < asteroids[i].getNumSplit(); k++)
addAsteroid(asteroids[i].createSplitAsteroid(
minAstVel, maxAstVel));
}
// delete the original asteroid
deleteAsteroid(i);
j = numShots; // break out of inner loop - it has
// already been hit, don't need to check
// for collision with other shots
i--; // don't skip asteroid shifted back into
// the deleted asteroid's position
}
}
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
// These first two lines allow the asteroids to move
// while the player chooses when to enter the game.
// This happens when the player is starting a new life.
if (!ship.isActive() && !paused)
ship.setActive(true);
else {
paused = !paused; // enter is the pause button
if (paused) // grays out the ship if paused
ship.setActive(false);
else
ship.setActive(true);
}
} else if (paused || !ship.isActive()) // if the game is
return; // paused or ship is inactive, do not respond
// to the controls except for enter to unpause
else if (e.getKeyCode() == KeyEvent.VK_UP)
{if(fuel>0){
ship.setAccelerating(true);
//fuel -= 1.5;
}
else{
fuel = 0;
}
}
else if (e.getKeyCode() == KeyEvent.VK_LEFT)
{
ship.setTurningLeft(true);
}
else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
ship.setTurningRight(true);
//else if (e.getKeyCode() == KeyEvent.VK_CONTROL)
//shooting = true; // Start shooting if ctrl is pushed
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP)
ship.setAccelerating(false);
else if (e.getKeyCode() == KeyEvent.VK_LEFT)
ship.setTurningLeft(false);
else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
ship.setTurningRight(false);
//else if (e.getKeyCode() == KeyEvent.VK_CONTROL)
//shooting = false;
}
public void keyTyped(KeyEvent e) {
}
}
I believe that createImage() is going to return null until the component is actually on-screen, wihch i believe is after the thread has started.
Instead of this:
img = createImage(dim.width, dim.height);
g = img.getGraphics();
thread = new Thread(this);
thread.start();
try:
new Thread(new Runnable() {
public void run() {
do {
try {
Thread.sleep(25);
} catch(InterruptedException e) {
System.out.println("wait interrupted");
break;
}
} while(!isDisplayable());
// Now it should be safe to make these calls.
img= createImage(dim.width, dim.height);
g = img.getGraphics();
start();
}
}).start();
I am trying to create an array of objects, more specifically buttons or "rectangles", but when I initialize the elements using a for loop it appears that when I assign the object to an index it they are all stored in index 0 of the array.
This is the class that I am working in:
and this is the class I am trying to create an object of:
!
import java.util.Arrays;
class ButtonPanel {
Internet i;
Button b;
Button[] buttons;
ButtonPanel() {
i = new Internet();
stroke(28, 215, 234);
noFill();
rect(width, 0, -i.getX(), height);
buttons = new Button[3];
}
void drawButtons() {
rectMode(CORNER);
fill(255);
translate(1040, -105);
for (int i = 0; i < buttons.length; i++) {
buttons[i]= new Button(0, i*90, -width/2, 90);
// work out proper calculations
// work out how to manipulate individual indexes
buttons[0].addColor(color(0));
}
//for (int j = 0; j < switches.length; j++) {
//switches[0] = new Button(j*-width/6, -90, -width/6, 90);
//}
}
void addPanel() {
drawButtons();
}
}
What makes you suspect everything is stored on index 0?
This loop should work, since i is starting at 0 and increases until it reaches buttons.length (which should be 2), and you're assigning the new Buttons to buttons[i]. Concluding from this, your loop should run twice, assigning unique Button objects to buttons[0] and buttons[1].
I think you should not create the buttons in draw method, do so in the constructor. Each thing should do only one thing :)
Same thing in Buttons, don't draw in the constructor, make a display() method. If you call addColor() it won't work cause the rects are already drew.
the structure might look some thing like this:
ButtonPanel bp =new ButtonPanel();
void setup() {
size(300, 200);
bp.drawButtons();
}
class ButtonPanel {
Button[] buttons;
ButtonPanel() {
buttons = new Button[3];
for (int i = 0; i < buttons.length; i++) {
buttons[i]= new Button(100+i*35, 100, 30, 30);
}
}
void drawButtons() {
stroke(28, 215, 234);
noFill();
rect(90, 90, 120, 50);
for (int i = 0; i < buttons.length; i++) {
buttons[i].addColor(color(random(255), random(255), random(100)));
buttons[i].display();
}
}
}
class Button {
int x, y, w, h;
color c;
Button(int _x, int _y, int _w, int _h) {
x = _x;
y = _y;
w = _w;
h = _h;
c = color(100, 100, 100);
}
void display() {
fill(c);
stroke(255);
rect(x, y, w, h);
}
void addColor(color newC) {
c = newC;
}
}
I have a processing game i am designing that is supposed to display a game over screen when the game is lost. Unfortuinately, the game over screen never comes up. Here is the function i have it narrowed down to:
if (lives < 1) {
background(0);
textSize(100);
text("You Lost",10,10);
delay(1000);
lives = 10;
x = (int)random(width);
y = (int)random(height / 2);
velocity = new PVector(1,random(-1.4,-0.6));
score = 0;
}
When the amount of lives goes to zero, it pauses for a second and then restarts the game.
I have tried everything i can think of, but still no luck.
So my best guess, having gotten to know the processing language 2 minutes ago is the following:
Because you set the background to black (0) the text can't be seen because it is black as well, maybe try changing the text's color to something else with the fill() method to see if that's causing the issue.
if (lives < 1) {
background(0);
textSize(100);
fill(255, 255, 255); // White text
text("You Lost",10,10);
delay(1000);
lives = 10;
...
Figured it out:
i added a piece of code at the start of my loop:
if (dflag) {
delay(2000);
dflag = false;
}
and then, i put the regular update code in an else statement after it check weather you die:
if (lives < 1) {
// for(int df = 0; df < 1000; df++) {
background(0);
textSize(100);
text("You Lost",100,100);
dflag = true;
//redraw();
lives = 10;
x = (int)random(width);
y = (int)random(height / 2);
velocity = new PVector(1,random(-1.4,-0.6));
score = 0;
} else {
textSize(13);
background(0);
stroke(255);
text(score,10,10);
String l = "";
for (int q = 0; q < lives; q++) { l += "%"; }
text(l,50,10);
strokeWeight(balld);
point(x,y);
strokeWeight(8);
line(paddlex,height - 30,paddlex + paddlew,height-30);
}