anything i do seems to break down my code into unusable rubbish. Note that it is also a mess... but at least it does work almost properly.
Here are some details:
it's sort of a particle system but with images. koffer stands for bag and it has to be a sort of eplosion of rotating bags that get slightly bigger or smaller for the depth effect and they fade away in time and after leaving the screen it should be deleted.
For now i got half of the bags that explode to turn random ways and half of the bags don't do that. They all fade but don't get deleted after leaving the screen. there is no slight resize yet. But most of all i have to use an arraylist() and don't know how to implement that.
here is my code:
Main Class BagEplode:
PImage coffre;
float life = 255;
int i = 0;
Ball [] balls = new Ball [200];
void setup(){
size (600,600,P3D);
noStroke();
smooth();
coffre = loadImage("coffre.png");
for (i = 0; i < balls.length; i ++)
{
balls[i] = new Ball();
}
}
void draw()
{
clear();
life -= 2.5;
for (int i = 0; i < balls.length; i++)
{
if(i <= 4)
{
balls[i].kleur();
image(coffre, balls[i].x, balls[i].y);
tint(255, life);
balls[i].update();
}
//else
//{
//}
}
}
and i got the Class Ball:
class Ball
{
public void kleur(){
}
float x = width/2;
float y = 601;
float vX = random(1,4);
float vY = random(-9,-5);
float sizeX = 0 ;
float sizeY = 0 ;
float draaiHoek = 0;
float angle = random(-3,3);
public void update(){
x += vX ;
y += vY ;
vY += 0.125;
sizeX = 64 ;
sizeY = 64 ;
draaiHoek -=angle;
imageMode(CENTER);
pushMatrix();
translate(x,y);
rotate((radians(draaiHoek)));
image(coffre, 0, 0);
imageMode(CORNER);
popMatrix();
//if (x > width || x < 0 || y > height || y < 0)
//{
//}
}
}
Thanx for helping me in advance. I hope i really can get some pointers.
From my understanding, you need to replace balls array of type- Ball with an ArrayList of type Ball
import java.util.ArrayList;
public class Ball {
PImage coffre;
float life = 255;
int i = 0;
//Ball [] balls = new Ball [200];
ArrayList<Ball> balls= new ArrayList<Ball>();
void setup(){
size (600,600,P3D);
noStroke();
smooth();
coffre = loadImage("coffre.png");
/* for (i = 0; i < balls.length; i ++)
{
balls[i] = new Ball();
}
*/
for(int i=0;i<balls.size();i++)
{
balls.add(new Ball());
}
}
void draw()
{
clear();
life -= 2.5;
/* for (int i = 0; i < balls.length; i++)
{
if(i <= 4)
{
balls[i].kleur();
image(coffre, balls[i].x, balls[i].y);
tint(255, life);
balls[i].update();
}
*/
for (int i = 0; i < balls.size(); i++)
{
if(i <= 4)
{
balls.get(i).kleur();
image(coffre, balls.get(i).x, balls.get(i).y);
tint(255, life);
balls.get(i).update();
}
//else
//{
//}
}
}
}
Related
My game is a shooting game for school. I need help on the collision between my bullet and my enemy. I have placed the bullet class with my player but for some reason it keeps on passing through it and not disappearing. The first example below shows the weapon class which is for the bullet and the one underneath that is the main.
class Weapons{
PImage bullet;
int speed;
int imageSize = 20;
float x = 20;
float y = 20;
float m;
int damage = 5;
int[] src = new int[2];
float[] dest = new float[2];
Weapons(int x, int y){
speed = 12;
dest[0] = mouseX;
dest[1] = mouseY;
src[0] = x;
src[1] = y;
m = (dest[1]-src[1]) / (dest[0]-src[0]);
this.x = x;
this.y = y;
bullet = loadImage("bullet.png");
bullet.resize(imageSize,imageSize);
}
boolean shooting(){
image(bullet, x, y); // if attack is true then renfer the image
x += speed;
y = (m * (x - dest[0])) + dest[1];
return (x > width || y > height);
}
boolean crash(Enemy enemies) {
//// return the result of checking if the plane has crashed into the bird
return abs(this.x-enemies.x) < bullet.width && abs(this.y - enemies.y) < bullet.height;
}
}
Maincharacter MC;
Goal G;
ArrayList<Enemy> enemies = new ArrayList<>();
ArrayList<Weapons> bullets = new ArrayList<>();
final int Playing = 0;
final int Finish = 1;
int gameMode = Playing;
//Enemy[] enemies = new Enemy[10];
PImage background; // creating background
int bgX = 0;
void setup(){
size(800,500);
MC = new Maincharacter(100,3);
//E1 = new Enemy();
G = new Goal(100,20);
background = loadImage("Battleground1.png");
background.resize(width*2,height); //set image to be same size as the canvas
for(int i = 0; i<2; i++){ // i represent how many enemy I want.
enemies.add(new Enemy((int)random(200,850), (int)random(0, height- 150) ) );
}
//for(int i=0 ; i < enemies.length ; i++){
//enemies[i] = new Enemy(); }
}
void draw(){
if(gameMode == Playing){
background();
MC.display();
G.display();
for(Enemy E : enemies){
E.update();
if (MC.crash(E)){
gameMode = Finish;
}
}
for(Weapons W: bullets){
W.update();
if(enemies.crash(W)){ // doesnt exist
gameMode = Finish;
}
}
// for(int i=0 ; i < enemies.length ; i++){
//enemies[i].update(); }
}}
void keyPressed(){
// creating the movemnt for my main charcter
MC.move();
if (keyCode == RIGHT || keyCode == 68 ){
MC.x += 10;
} else if (keyCode == UP || keyCode == 87) {
MC.y -=10;
} else if (keyCode == LEFT || keyCode == 65){
MC.x -= 10;
} else if(keyCode == DOWN || keyCode == 83 ){
MC.y += 10;
} else if (keyCode == 32) { // space bar
MC.attack_function(); // call attack function to create bullet object
}// make an attack
}
void mousePressed(){ // when mouse is pressed call attack function to create bullet object
MC.attack_function();
}
void background(){
//scrolling background image
image(background, bgX, height/2); //draw image to fill the canvas
//draw image again off the right of the canvas
image(background, bgX+background.width, height/2);
bgX -= 4;
if(bgX == -background.width ) //if first image completely off the canvas
{
bgX=0; //reset back to initial value background
}
}
What I want is to have bullet colliding with the enemies and then disappearing.
You are trying to call the method enemies.crash(W) but enemies is some collection of Enemy instances. Enemy does not provide the method crash as well.
You have to loop for each of your enemies all of your weapons and call the method crash on the Weapon instance giving the current enemy, something like:
for (Enemy enemy: enemies){
enemy.update();
if (mainCharacter.crash(enemy)) {
gameMode = Finish;
}
for (Weapons weapon: bullets) {
weapon.update();
if (weapon.crash(enemy)) {
gameMode = Finish;
// TODO: are you sure that killing an enemy finishes the game?
}
}
}
(Please note that I used mainCharacter instead of MC here for better readability.)
The study project is about warping text along bezier curves(recursive polynomial form) on processing using the geomerative library to get shape from a .ttf type font file.(It needs a ttf file in the data directory to function.) currently, the sketch seems to throws errors when
fill(any color); is used at the part where the code draws the character shapes and the bezier curve's length gets shorter than a certain length. If fill(); is not used, the sketch seems to function okay without any errors.
The goal is to use the fill(); function to fill the characters without errors.
I've tried;
1) getting rid of the beginContour(); and endContour(); because I thought it hasn't been written properly.(I thought it was wrong because the contours should only be drawn when the shape is the inner side of a letter but currently, it draws contours when it's not the first or last shape) But the sketch throws errors even when the contour function was not used (fill(); was used).
2) thought it had something to do with the length of the curve, so tried to add a if statement to the part where it draws the letters. So far, I've tried using the width of the RGroup generated from the initial font size and string in void setup(){}, and the length of the bezier curve. The condition examples within the if statement was as follows;
-draw letters when the RGroup shape's width is smaller than the length of the curve
-draw letters when the "indent"(a variable to calculate the position on the curve) value is smaller than the length of the curve. (this case made the sketch to draw letters only when the letters were placed within the curve, but the error still occurred)
-draw letters when the "indent"(a variable to calculate the position on the curve) value is smaller than the width of the RGroup.
I've failed to see where exactly the problem is occurring, so I'm sharing the entire code within the sketch, but I marked the spot where I presume the error is happening with "//*******".
This study was based on the following link.
The geomerative library documentation can be seen from the following link.
//build a bezier curve using the recursive polynomial form
//number of control points(num+1 points)
int num = 4;
//arraylist to store the picked values
ArrayList<Point> pt;
float nfac;
import geomerative.*;
RFont fnt;
RGroup rg;
RPoint [][]rp;
String str = "(O_o)/ Oooh";
FloatList X;
FloatList Y;
FloatList SUM;
void setup(){
size(1000,1000,P2D);
RG.init(this);
pt = new ArrayList<Point>();
//pick a number of points with random positions and store x,y values in them
for(int i=0; i<=num; i++){
float x = random(0,width);
float y = random(0,height);
pt.add(new Point(x,y));
}
fnt = new RFont("Zapfino.ttf",100);
//RCommand.setSegmentAngle(random(0,HALF_PI));
//RCommand.setSegmentator(RCommand.ADAPTATIVE);
RCommand.setSegmentLength(3);
RCommand.setSegmentator(RCommand.UNIFORMLENGTH);
rg = fnt.toGroup(str);
rp = rg.getPointsInPaths();
X = new FloatList();
Y = new FloatList();
SUM = new FloatList();
}
void draw(){
background(255);
noFill();
strokeCap(ROUND);
strokeWeight(2);
//draw points
beginShape();
for(int i=0; i<=num; i++){
vertex(pt.get(i).x,pt.get(i).y);
}
endShape();
for(int i=0; i<=num; i++){
ellipse(pt.get(i).x,pt.get(i).y,10,10);
}
//draw curve
nfac = 1;
for(int i=0; i<num; i++){
nfac *= (i+1);
}
strokeWeight(2);
beginShape();
int Bzindex = 0;
for(float t=0; t<=1; t+=0.01){
float x = 0;
float y = 0;
Bzindex++;
for(int i=0; i<=num; i++){
float coef = 1;
float kfac = 1;
float k_nfac = 1;
for(int k=i; k>0; k--){
kfac *= k;
}
for(int k=(num-i); k>0; k--){
k_nfac *= k;
}
coef = nfac/(kfac*k_nfac);
x += coef*(pow((1-t),num-i)*pow(t,i)*pt.get(i).x);
y += coef*(pow((1-t),num-i)*pow(t,i)*pt.get(i).y);
}
vertex(x,y);
X.set(Bzindex,x);
Y.set(Bzindex,y);
}
endShape();
//get arclength by pulling points from a floatlist
int numberOfDivisions = X.size()-2;
int maxPoint = numberOfDivisions+1;
float sum = 0;
float prevPointX = X.get(0);
float prevPointY = Y.get(0);
for(int i=1; i<=maxPoint; i++){
float pointX = X.get(i);
float pointY = Y.get(i);
sum += dist(pointX,pointY,prevPointX,prevPointY);
SUM.set(i-1,sum);
prevPointX = pointX;
prevPointY = pointY;
}
//
//*******************************************************
noFill();
//creates error only when using fill();
fill(0,255,0);
stroke(0);
//noStroke();
strokeWeight(4);
float indent = SUM.get(0);
beginShape();
for(int i=0; i<rp.length; i++){
if(i>0){
beginContour();
}
for(int j=0; j<rp[i].length; j++){
float t = 0;
indent = rp[i][j].x+SUM.get(0);
//
float targetArcLength = indent;
int index = IndexOfLargestValueSmallerThan(targetArcLength);
if(SUM.get(index)==targetArcLength){
t = index/(SUM.size()-1);
}else{
float lengthBefore = SUM.get(index);
float lengthAfter = SUM.get(index+1);
float segmentLength = lengthAfter - lengthBefore;
float segmentFraction = (targetArcLength - lengthBefore)/segmentLength;
t = (index+segmentFraction)/(SUM.size()-1);
}
float x = 0;
float y = 0;
float vx = 0;
float vy = 0;
for(int l=0; l<=num; l++){
float coef = 1;
float kfac = 1;
float k_nfac = 1;
for(int k=l; k>0; k--){
kfac *= k;
}
for(int k=(num-l); k>0; k--){
k_nfac *= k;
}
coef = nfac/(kfac*k_nfac);
x += coef*(pow((1-t),num-l)*pow(t,l)*pt.get(l).x);
y += coef*(pow((1-t),num-l)*pow(t,l)*pt.get(l).y);
float v = (pow(1-t,num-l)*l*pow(t,l-1))+((num-l)*pow(1-t,num-l-1)*(-1)*pow(t,l));
vx += coef*pt.get(l).x*(v);
vy += coef*pt.get(l).y*(v);
}
PVector P = new PVector(x,rp[i][j].y+y);
PVector ldir = new PVector(P.x-x,P.y-y);
PVector dir = new PVector(vy,-vx);
//
ldir.rotate(dir.heading()+PI/2);
vertex(x+ldir.x,y+ldir.y);
}
if(i<rp.length&&i>0){
endContour();
}
}
endShape();
//**************************************************************
}
int IndexOfLargestValueSmallerThan(float _targetArcLength){
int index = 0;
for(int i=0; i<SUM.size()-1; i++){
if(SUM.get(i)<=_targetArcLength){
index = i;
}
}
return index;
}
void mouseDragged(){
int which = -1;
if((mouseX<width)&&(mouseX>0)&&(mouseY<height)&&(mouseY>0)){
for(int i=0; i<=num; i++){
if(dist(mouseX,mouseY,pt.get(i).x,pt.get(i).y)<50){
which = i;
pt.get(which).update(mouseX,mouseY);
}
}
}
}
class Point{
float x,y;
Point(float _x, float _y){
x = _x;
y = _y;
}
void update(float _newx, float _newy){
x = _newx;
y = _newy;
}
}
Sometimes the error happens when the sketch is loaded. Most of the time, it loads okay but throws an error when you drag the point around a bit. The error code sometimes refers to the point where the control points of the curve are updated by mouse position, but because error somtimes occurs when the sketch is loaded as well, I didn't think it was a problem connected to the updated positions.
The error code is as follows;
a.lang.AssertionError
at processing.opengl.PSurfaceJOGL$2.run(PSurfaceJOGL.java:412)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.AssertionError
at jogamp.opengl.glu.tessellator.Sweep.AddRightEdges(Sweep.java:358)
at jogamp.opengl.glu.tessellator.Sweep.SweepEvent(Sweep.java:1105)
at jogamp.opengl.glu.tessellator.Sweep.__gl_computeInterior(Sweep.java:1339)
at jogamp.opengl.glu.tessellator.GLUtessellatorImpl.gluTessEndPolygon(GLUtessellatorImpl.java:526)
at com.jogamp.opengl.glu.GLU.gluTessEndPolygon(GLU.java:896)
at processing.opengl.PJOGL$Tessellator.endPolygon(PJOGL.java:641)
at processing.opengl.PGraphicsOpenGL$Tessellator.tessellatePolygon(PGraphicsOpenGL.java:12621)
at processing.opengl.PGraphicsOpenGL.tessellate(PGraphicsOpenGL.java:2255)
at processing.opengl.PGraphicsOpenGL.endShape(PGraphicsOpenGL.java:1965)
at processing.core.PGraphics.endShape(PGraphics.java:1707)
at processing.core.PApplet.endShape(PApplet.java:11641)
at bezier_polynomial_recursive_text_03.draw(bezier_polynomial_recursive_text_03.java:218)
at processing.core.PApplet.handleDraw(PApplet.java:2475)
at processing.opengl.PSurfaceJOGL$DrawListener.display(PSurfaceJOGL.java:866)
at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:692)
at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:674)
RuntimeException: java.lang.AssertionError
at jogamp.opengl.GLAutoDrawableBase$2.run(GLAutoDrawableBase.java:443)
at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1293)
at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147)
at com.jogamp.newt.opengl.GLWindow.display(GLWindow.java:759)
at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81)
at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:452)
at com.jogamp.opengl.util.FPSAnimator$MainTask.run(FPSAnimator.java:178)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
I don't think this would be a direct answer to my question, but it did stop the errors from occurring while using both fill() and the P2D renderer. The main problem, as pointed out by laancelot above, indeed seems to have been connected with stack overflow. So I approached the problem in two ways written below; Conclusion: The direct reason was a poorly expressed math formula.
1) switching the RPoints inside a class.
-I don't think this was the direct reason the errors were occurring, because at the stage where only this part of rewriting the code was done, the errors were still there. But maybe it was part of the problem. I'm not sure.
2) rewriting the part where the code expresses the formula to evaluate bezier curves at a specific point.
-Previously, the formula was made by using the explicit definition of a bezier curve with degree n. And, as a result, the formula had to be calculated(more like made) for every point in the RPoint points. As is mentioned on the wikipedia page about bezier curves, this way of computing is not recommended.
-on the revised code, the formula used to warp text was expressed in the polynomial form. Thus, it was able to pre-calculate the coefficients of the polynomial before the RPoint points were iterated. This seems to have solved the problem.
I'm still not really confident about what actually caused the problem and why it has been solved, and which part of the code I should show to explain this to others, so I'll share the entire code that has been rewritten. You need processing, the geomerative library, and a ttf type font file in a data folder to test the code. I have marked the place where the revised version of the formula is implicated. (It's still really messy....)
//n number of points
int num = 4;
//arraylist to store the picked values
ArrayList<cntrlPoint> pt;
//import the geomerative library
import geomerative.*;
//string
String str = "(O_o)/ Oooh";
FloatList X;
FloatList Y;
FloatList SUM;
RClass rc;
void setup() {
size(1000, 1000, P2D);
pt = new ArrayList<cntrlPoint>();
//pick a number of points with random positions
for (int i=0; i<=num; i++) {
float x = random(0, width);
float y = random(0, height);
pt.add(new cntrlPoint(x, y));
}
RG.init(this);
rc = new RClass();
X = new FloatList();
Y = new FloatList();
SUM = new FloatList();
}
void draw() {
background(255);
noFill();
strokeWeight(2);
drwCntrlPoints();
drwCurve();
gtArcLength();
fill(0,255,0);
rc.crtPoly(pt);
rc.drwText();
}
void drwCntrlPoints() {
//draw points
beginShape();
for (int i=0; i<=num; i++) {
vertex(pt.get(i).x, pt.get(i).y);
}
endShape();
for (int i=0; i<=num; i++) {
ellipse(pt.get(i).x, pt.get(i).y, 10, 10);
}
}
void drwCurve() {
//draw curve
float curveDetail = 0.01;
float nfac = 1;
for (int i=0; i<num; i++) {
nfac *= (i+1);
}
int arcIndex = 0;
strokeWeight(2);
beginShape();
for (float t=0; t<=1; t+=curveDetail) {
float x = 0;
float y = 0;
arcIndex++;
for (int i=0; i<=num; i++) {
float coef = 1;
float kfac = 1;
float k_nfac = 1;
for (int k=i; k>0; k--) {
kfac *= k;
}
for (int k=(num-i); k>0; k--) {
k_nfac *= k;
}
coef = nfac/(kfac*k_nfac);
x += coef*(pow((1-t), num-i)*pow(t, i)*pt.get(i).x);
y += coef*(pow((1-t), num-i)*pow(t, i)*pt.get(i).y);
}
vertex(x, y);
X.set(arcIndex, x);
Y.set(arcIndex, y);
}
endShape();
}
void gtArcLength() {
//get arclength by pulling points from a floatlist
int numberOfDivisions = X.size()-2;
int maxPoint = numberOfDivisions+1;
float sum = 0;
float prevPointX = X.get(0);
float prevPointY = Y.get(0);
for (int i=1; i<=maxPoint; i++) {
float pointX = X.get(i);
float pointY = Y.get(i);
sum += dist(pointX, pointY, prevPointX, prevPointY);
SUM.set(i-1, sum);
prevPointX = pointX;
prevPointY = pointY;
}
}
//*******factorial
int fact(int fa){
if(fa==1){
return 1;
}
if(fa==0){
return 1;
}
else{
return fa*fact(fa-1);
}
}
//********************
int IndexOfLargestValueSmallerThan(float _targetArcLength) {
int index = 0;
for (int i=0; i<SUM.size()-1; i++) {
if (SUM.get(i)<=_targetArcLength) {
index = i;
}
}
return index;
}
void mouseDragged() {
int which = -1;
if ((mouseX<width)&&(mouseX>0)&&(mouseY<height)&&(mouseY>0)) {
for (int i=0; i<=num; i++) {
if (dist(mouseX, mouseY, pt.get(i).x, pt.get(i).y)<80) {
which = i;
}
}
if (which>-1) {
pt.get(which).update(mouseX, mouseY);
}
}
}
class RClass {
//get ttf file
//create rfont
RFont fnt;
//turn rfont to rgroup to get points
RGroup rg;
//going to get point in path, so that the characters in the string can be seperated
RPoint [][]rp;
//floatlist to store coefficients
FloatList Cx;
FloatList Cy;
RClass() {
fnt = new RFont("Zapfino.ttf", 100);
rg = fnt.toGroup(str);
rp = rg.getPointsInPaths();
//RCommand.setSegmentAngle(random(0,HALF_PI));
//RCommand.setSegmentator(RCommand.ADAPTATIVE);
RCommand.setSegmentLength(3);
RCommand.setSegmentator(RCommand.UNIFORMLENGTH);
Cx = new FloatList();
Cy = new FloatList();
}
//**********************************here
void crtPoly(ArrayList<cntrlPoint> _pt){
float ptsize = _pt.size();
for(int j=0; j<ptsize; j++){
float coefx = 0;
float coefy = 0;
float pi = 1;
float sigx = 0;
float sigy = 0;
for(int m=0; m<=j-1; m++){
pi *= (ptsize-1-m);
}
for(int i=0; i<=j; i++){
sigx += (pow(-1,i+j)*pt.get(i).x)/(fact(i)*fact(j-i));
sigy += (pow(-1,i+j)*pt.get(i).y)/(fact(i)*fact(j-i));
}
coefx = pi*sigx;
coefy = pi*sigy;
Cx.set(j,coefx);
Cy.set(j,coefy);
}
}
//**************************************
void drwText() {
float indent = SUM.get(0);
beginShape();
for (int i=0; i<rp.length; i++) {
if(i>0){
beginContour();
}
for (int j=0; j<rp[i].length; j++) {
float t = 0;
indent = rp[i][j].x+SUM.get(0);
float targetArcLength = indent;
int index = IndexOfLargestValueSmallerThan(targetArcLength);
if (SUM.get(index)==targetArcLength) {
t = index/(SUM.size()-1);
} else {
float lengthBefore = SUM.get(index);
float lengthAfter = SUM.get(index+1);
float segmentLength = lengthAfter - lengthBefore;
float segmentFraction = (targetArcLength - lengthBefore)/segmentLength;
t = (index+segmentFraction)/(SUM.size()-1);
}
//***************************here
float x = 0;
float y = 0;
float vx = 0;
float vy = 0;
for(int l=0; l<=num; l++){
x += Cx.get(l)*pow(t,l);
y += Cy.get(l)*pow(t,l);
}
for(int l=1; l<=num; l++){
vx += l*Cx.get(l)*pow(t,l-1);
vy += l*Cy.get(l)*pow(t,l-1);
}
//**************************************
PVector P = new PVector(x, rp[i][j].y+y);
PVector ldir = new PVector(P.x-x, P.y-y);
PVector dir = new PVector(vy, -vx);
//
ldir.rotate(dir.heading()+PI/2);
vertex(x+ldir.x, y+ldir.y);
}
if(i>0&&i<rp.length){
endContour();
}
}
endShape();
}
}
class cntrlPoint{
float x,y;
cntrlPoint(float _x, float _y){
x = _x;
y = _y;
}
void update(float _newx, float _newy){
x = _newx;
y = _newy;
}
}
I'm trying to create a Roomba program with a ball that bounces around the screen that cleans the tiles that it passes over. The program should start with all grey tiles and when the ball passes over them then the tiles turn white. Currently I have the ball that bounces around everywhere and a grid method which creates a 5x5 grid.
I have encountered two problems:
I cannot make the grid and the ball appear in the same simulation while running the program, it's either one or the other.
I'm having trouble with finding a way to analyze if the ball has passed over certain squares in the grid, perhaps I need to create an object for the grid/ball?
My code:
import edu.princeton.cs.introcs.StdDraw;
public class Roomba {
private static int windowWidth = 200;
private static int windowHeight = 200;
private static double x = 100;
private static double y = 100;
private static double vx = 2;
private static double vy = 4;
private static int radius = 5;
private static boolean inGame = true;
public static void updateLocations() {
x += vx;
y += vy;
}
public static void drawGrid() {
StdDraw.setScale(0, 5);
int[][] grid = new int[5][5];
for (int x = 0; x < grid.length; x++) {
for (int y = 0; y < grid.length; y++) {
grid[x][y] = 255;
}
}
for (int x = 0; x < grid.length; x++) {
for (int y = 0; y < grid.length; y++) {
StdDraw.square(x, y, 1);
}
}
}
public static void updateVelocities() {
if (y + radius >= windowHeight) {
vy = -vy;
} else if (y - radius <= 0) {
vy = -vy;
}
if (x >= 194 || x <= 6) {
vx = -vx;
}
}
public static void setBackground() {
StdDraw.clear(StdDraw.GRAY);
// drawGrid();
}
public static void drawBall() {
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.filledCircle(x, y, radius);
// StdDraw.setPenColor(StdDraw.RED);
// StdDraw.filledSquare(x + 3, y + 3, 1);
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.text(100, 70, "x is: " + x + " y is: " + y);
}
public static void draw() {
setBackground();
drawBall();
}
public static void main(String[] args) {
StdDraw.setCanvasSize(800, 800);
StdDraw.setXscale(0, windowWidth);
StdDraw.setYscale(0, windowHeight);
while (true) {
if (inGame) {
draw();
updateVelocities();
updateLocations();
} else {
StdDraw.text(100, 100, "Game Over");
}
// change to if all tiles have been cleaned
// if (x + radius > windowWidth || x - radius < 0) {
// inGame = false;
// }
StdDraw.show(20);
}
}
}
Maybe the background is being drawn over the ball or vice verse? Try to draw the ball first then the background? Make sure the ball is actually being rendered at the correct size and not as the entire screen. I'm not to familiar with 2D graphics but maybe there is some z fighting?
I'm working my way through Daniel Shiffman's excellent The Nature of Code book and have completed simulating gravitational attraction and repulsion between objects.
The gravitational force works well, but my objects fly right off the screen. I would like to constrain them to the drawing canvas. I am using an edge-checking function written in the previous chapter, and it is failing to keep any objects on the canvas.
I would love to know why.
The offending function is the last block of code in the Mover class.
class Mover {
PVector location;
PVector velocity;
PVector acceleration;
float mass;
float G = 0.4; //universal gravitational constant
Mover(float m, float x, float y) {
location = new PVector(x,y);
velocity = new PVector(1,0);
acceleration = new PVector(0,0);
mass = m;
}
PVector attract(Mover m) {
PVector force = PVector.sub(location,m.location);
float distance = force.mag();
distance = constrain(distance,5,25);
force.normalize();
float strength = ((G * mass * m.mass) / (distance * distance)*-1);
force.mult(strength);
return force;
}
void applyForce(PVector force) {
PVector f = PVector.div(force,mass);
acceleration.add(f);
}
void update() {
velocity.add(acceleration);
location.add(velocity);
acceleration.mult(0);
}
void display() {
stroke(0);
strokeWeight(2);
fill(0,100);
ellipse(location.x,location.y, mass*25 , mass*25);
}
void checkEdges() { // why doesn't this work?
if (location.x > width) {
location.x = width;
velocity.x *= -1;
} else if (location.x < 0) {
velocity.x *= -1;
location.x = 0;
}
if (location.y > height) {
velocity.y *= -1;
location.y = height;
} else if (location.y < 0) {
velocity.y *= -1;
location.y = 0;
}
}
}
//////////////////////////////////////////////////////////////////////
Mover [] movers = new Mover [10];
void setup() {
size(1000,1000);
for (int i = 0; i < movers.length; i++) {
movers[i] = new Mover(random(0.1,2),random(width),random(height)); //mass, loc.x, loc.y //each mover initialized randomly
}
}
void draw() {
background(255);
for(int i = 0; i < movers.length; i++){
for(int j = 0; j < movers.length; j++){
if(i != j){
PVector force = movers[j].attract(movers[i]); //Calculate attraction force
movers[i].applyForce(force); //Apply attraction force
}
}
movers[i].update();
movers[i].display();
}
}
Shouldn't you be calling checkEdges() inside Update()? If not that, then how about in your main code between
movers[i].update();
movers[I].checkEdges(); // check after the update and before the display
movers[i].display();
You're not checking whether location.y is less than zero.
Compare what you're doing for X:
if (location.x > width) {
location.x = width;
velocity.x *= -1;
} else if (location.x < 0) {
velocity.x *= -1;
location.x = 0;
}
to what you're doing for Y:
if (location.y > height) {
velocity.y *= -1;
location.y = height;
}
I am having some serious problems with my Asteroid game. I'm trying to call my Game.java run() method in my main method in Asteroid.java but I keep getting the same error:
Exception in thread "main" java.lang.NullPointerException
at asteroids.Asteroids.main(Asteroids.java:15)
Java Result: 1
Can someone help me figure out why this is happening?
here is my code:
Asteroids.java
package asteroids;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.io.IOException;
#SuppressWarnings("serial")
public class Asteroids {
Game game = null;
public static void main(String[] args){
new Asteroids ().game.run ();
}
}
//NEW Game.java//
package asteroids;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Point2D;
import java.util.ArrayList;
//#SuppressWarnings("serial")
public class Game extends Applet implements Runnable, KeyListener {
//timing variables
Thread thread;
long startTime, endTime, framePeriod;
//graphics variables
Image img;
Dimension dim;
int width, height;
Graphics g;
//text items
int level, lives, score;
SpaceShip ship;
boolean shipCollision, shipExplode;
//ArrayList to hold asteroids
ArrayList<Asteroid> asteroids = new ArrayList<>();
int numOfAsteroids = 1;
//ArrayList to hold the lasers
ArrayList<Laser> lasers = new ArrayList<>();
final double rateOfFire = 10; //limits rate of fire
double rateOfFireRemaining; //decrements rate of fire
//ArrayList to hold explosion particles
ArrayList<AsteroidExplosion> explodingLines = new ArrayList<>();
//ArrayList to hold ship explosions
ArrayList<ShipExplosion> shipExplosion = new ArrayList<>();
public void Game ()
{
init();
}
public void init() {
resize(900,700); //set size of the applet
dim = getSize(); //get dimension of the applet
width = dim.width;
height = dim.height;
framePeriod = 25; //set refresh rate
addKeyListener(this); //to get commands from keyboard
setFocusable(true);
ship = new SpaceShip(width/2, height/2, 0, .15, .5, .15, .98); //add ship to game
shipCollision = false;
shipExplode = false;
level = numOfAsteroids;
lives = 3;
addAsteroids();
img = createImage(width, height); //create an off-screen image for double-buffering
g = img.getGraphics(); //assign the off-screen image
thread = new Thread(this);
thread.start();
}
#Override
public void paint(Graphics gfx) {
Graphics2D g2d = (Graphics2D) g;
//give the graphics smooth edges
RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHints(rh);
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, width, height); //add a black background
//add text for lives, score, and level
g2d.setColor(Color.WHITE);
g2d.drawString("Level : " + level, 10, 690);
g2d.drawString("Lives : " + lives, 110, 690);
g2d.drawString("Score : " + score, 210, 690);
for(Asteroid a: asteroids) { //draw asteroids
a.draw(g2d);
}
for(Laser l : lasers) { //draw lasers
l.draw(g2d);
}
for(AsteroidExplosion e : explodingLines) {
e.draw(g2d);
}
for(ShipExplosion ex : shipExplosion)
ex.draw(g2d);
ship.draw(g2d); //draw ship
if(shipCollision) {
shipExplosion.add(new ShipExplosion(ship.getX(), ship.getY(), 10, 10));
ship.setX(width/2);
ship.setY(height/2);
shipCollision = false;
lives--;
}
gfx.drawImage(img, 0, 0, this); //draw the off-screen image (double-buffering) onto the applet
}
#Override
public void update(Graphics gfx) {
paint(gfx); //gets rid of white flickering
}
#Override
public void run(){
for( ; ; ) {
startTime = System.currentTimeMillis(); //timestamp
ship.move(width, height); //ship movement
for(Asteroid a : asteroids) { //asteroid movement
a.move(width, height);
}
for(Laser l : lasers) { //laser movement
l.move(width, height);
}
for(int i = 0 ; i<lasers.size() ; i++) { //laser removal
if(!lasers.get(i).getActive())
lasers.remove(i);
}
for(AsteroidExplosion e : explodingLines) { //asteroid explosion floating lines movement
e.move();
}
for(int i = 0 ; i<explodingLines.size(); i++) { //asteroid explosion floating lines removal
if(explodingLines.get(i).getLifeLeft() <= 0)
explodingLines.remove(i);
}
for(ShipExplosion ex : shipExplosion){ //ship explosion expansion
ex.expand();
}
for(int i = 0 ; i<shipExplosion.size() ; i++) {
if(shipExplosion.get(i).getLifeLeft() <= 0)
shipExplosion.remove(i);
}
rateOfFireRemaining--;
collisionCheck();
if(asteroids.isEmpty()) {
numOfAsteroids++;
addAsteroids();
level = numOfAsteroids;
}
repaint();
try {
endTime = System.currentTimeMillis(); //new timestamp
if(framePeriod - (endTime-startTime) > 0) //if there is time left over after repaint, then sleep
Thread.sleep(framePeriod - (endTime - startTime)); //for whatever is remaining in framePeriod
} catch(InterruptedException e) {}
}
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
//fires laser
if(key == KeyEvent.VK_SPACE) {
if(rateOfFireRemaining <= 0 ) {
lasers.add(ship.fire());
rateOfFireRemaining = rateOfFire;
}
}
if(key == KeyEvent.VK_UP)
ship.setAccelerating(true);
if(key == KeyEvent.VK_RIGHT)
ship.setTurningRight(true);
if(key == KeyEvent.VK_LEFT)
ship.setTurningLeft(true);
if(key == KeyEvent.VK_DOWN)
ship.setDecelerating(true);
}
#Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_UP)
ship.setAccelerating(false);
if(key == KeyEvent.VK_RIGHT)
ship.setTurningRight(false);
if(key == KeyEvent.VK_LEFT)
ship.setTurningLeft(false);
if(key == KeyEvent.VK_DOWN)
ship.setDecelerating(false);
}
#Override
public void keyTyped(KeyEvent e) {
}
public void addAsteroids() {
int numAsteroidsLeft = numOfAsteroids;
int size;
for(int i=0 ; i<numOfAsteroids ; i++) { //add asteroids to game
//randomize starting position
int asteroidX = (int)(Math.random() * width) + 1;
int asteroidY = (int)(Math.random() * height) + 1;
//randomize speed and direction
double xVelocity = Math.random() + 1; //horizontal velocity
double yVelocity = Math.random() + 1; //vertical velocity
//used starting direction
int xDirection = (int)(Math.random() * 2);
int yDirection = (int)(Math.random() * 2);
//randomize horizontal direction
if (xDirection == 1)
xVelocity *= (-1);
//randomize vertical direction
if (yDirection == 1)
yVelocity *= (-1);
//if there are more then four asteroids, any new ones are MEGA asteroids
if(numAsteroidsLeft > 4) {
size = 2;
} else { size = 1;
}
asteroids.add(new Asteroid(size, asteroidX, asteroidY, 0, .1, xVelocity, yVelocity));
numAsteroidsLeft--;
//Make sure that no asteroids can appear right on top of the ship
//get center of recently created asteroid and ship and check the distance between them
Point2D asteroidCenter = asteroids.get(i).getCenter();
Point2D shipCenter = ship.getCenter();
double distanceBetween = asteroidCenter.distance(shipCenter);
//if asteroid center is within 80 pixels of ship's center, remove it from the ArrayList and rebuild it
if(distanceBetween <= 80) {
asteroids.remove(i);
i--;
numAsteroidsLeft++;
}
}
}
public void collisionCheck() {
//cycle through active asteroids checking for collisions
for(int i = 0 ; i < asteroids.size() ; i++) {
Asteroid a = asteroids.get(i);
Point2D aCenter = a.getCenter();
//check for collisions between lasers and asteroids
for(int j = 0 ; j < lasers.size() ; j++) {
Laser l = lasers.get(j);
Point2D lCenter = l.getCenter();
double distanceBetween = aCenter.distance(lCenter);
if(distanceBetween <= (a.getRadius() + l.getRadius())) {
//split larger asteroids into smaller ones, remove smaller asteroids from screen
if(a.getRadius() >= 60) {
for(int k = 0 ; k < 3 ; k++)
explodingLines.add(a.explode());
split(i);
score += 200;
} else if(a.getRadius() >= 30){
for(int k = 0 ; k < 3 ; k++)
explodingLines.add(a.explode());
split(i);
score += 100;
} else {
for(int k = 0 ; k < 3 ; k++)
explodingLines.add(a.explode());
asteroids.remove(i);
score += 50;
}
lasers.remove(j); //remove laser from screen
}
}
//check for collisions between ship and asteroid
Point2D sCenter = ship.getCenter();
double distanceBetween = aCenter.distance(sCenter);
if(distanceBetween <= (a.getRadius() + ship.getRadius())) {
shipCollision = true;
shipExplode = true;
}
}
}
public void split(int i) {
Asteroid a = asteroids.get(i);
double bigAsteroidX = a.getX();
double bigAsteroidY = a.getY();
int size = (a.getSize() / 2);
asteroids.remove(i);
for(int j = 0 ; j<2 ; j++) {
//randomize speed and direction
double xVelocity = Math.random() + 1; //horizontal velocity
double yVelocity = Math.random() + 1; //vertical velocity
//used randomize starting direction
int xDirection = (int)(Math.random() * 2);
int yDirection = (int)(Math.random() * 2);
//randomize horizontal direction
if (xDirection == 1)
xVelocity *= (-1);
//randomize vertical direction
if (yDirection == 1)
yVelocity *= (-1);
asteroids.add(new Asteroid(size, bigAsteroidX, bigAsteroidY, 0, .1, xVelocity, yVelocity));
}
}
}
//Edit Update//
Okay I tried a lot of stuff and discovered that even though the game works when I debug Game.java and it doesn't work when I run it through Asteroids.java. I found that img = createIimg = createImage(width, height); and g = img.getGraphics(); are returning null and that GraphicsEnvironment.isHeadless() is returning true. How should I change my to fix this issue?
Error
Exception in thread "main" java.lang.NullPointerException
at asteroids.Game.init(Game.java:67)
at asteroids.Game.Game(Game.java:45)
at asteroids.Asteroids.main(Asteroids.java:15)
Java Result: 1
You have the var "game" null, and you tried to call the method "run" on this var (game.run); obviously if "game" is null, you can't get the method, and throws nullpointer exception.
Game game=new Game();
that's all you need. Your final code is:
Game game = new Game();//<----- here is the change
public static void main(String[] args){
new Asteroids ().game.run ();
}
This thing is null.
new Asteroids ().game
That's why you get this NullPointerException when you call run on it.
Game game = null;
public static void main(String[] args){
new Asteroids ().game.run ();
}
The prgram is running from the main method. game is null.
Maybe you should have
Game game = new Game(); // instead of null
Try it may be help
Game game = null;
public static void main(String[] args){
If( Asteroids ().game != null ){
new Asteroids ().game.run ();
}
}