I'm having so many issues with my code


#1

I have a project and I decided to remake Galaga but I have a few issues with it. The bullet doesn’t make proper contact with the boss and enemy sprites, I can’t duplicate enemies on the screen; I want at least five enemies at once on the screen but it’s not working and even when the bullet does make contact with the boss or enemy sprite, it removes the enemy or boss; which is a good thing but it also stops the bullets from appearing.

Here’s the link to the code:
Galaga Project

Any help is appreciated.


#2

The best advice I can give you is to start smaller. Instead of trying to do everything at once, try to separate your project into multiple smaller steps.

For example, can you create a separate sketch that just tests your collision detection? Just use hard-coded rectangles that change color when they’re colliding. Get that working perfectly before moving on. The collision detection tutorial might help.

Separately from that, try to get multiple shapes on screen. Don’t worry about making them enemies yet. The creating classes and ArrayList tutorials might help.

Focus on one small part, and if you’re still having trouble, post a MCVE that shows just that part and I’ll be happy to help. Good luck!


#3

Thank you for your suggestion.


#4

So I tried out what you said I should do and everything is working well but I’m having issues with the enemy. Whenever the bullet hits the enemy, the enemy doesn’t disappear properly.

Here’s the link to the code:
Galaga Prototype


#5

Please narrow your problem down to a MCVE and post that directly instead of linking to files on external download sites.


#6

What do you mean by a [mcve]? I am fairly new to programming and so I am not familiar with the term.


#7

Sorry, that was supposed to be a link: MCVE

It means that you should try to narrow your problem down to a small example instead of posting your entire project.


#8

I’m sorry if this is too much but this is as minimal as I can get.

1. ArrayList<enemy> e = new ArrayList<enemy>();
2. ArrayList<bullet> b = new ArrayList<bullet>();
3. boolean shoot = false;

4. void setup() {
5.   fullScreen();
6.   //enemy
7.   for (int i = 0; i<5; i++) {
8.     e.add(new enemy(50, 50));
9.   }
10.   //bullet
11.   for (int i = 0; i<5; i++) {
12.     b.add(new bullet(mouseX, mouseY));
13.   }
14. }

15. void draw() {

16.   background(255);

17.   for (int p = 0; p<e.size(); p++) {
18.     for (int i = 0; i<b.size(); i++) {
19.       bullet a = b.get(i);
20.       enemy o = e.get(p);
21.       if (a.update()) {
22.         b.remove(i);
23.       }
24.       if (o.col()) {
25.         b.remove(i);
26.         e.remove(i);
27.       }
28.     }
29.   }

30.   //enemy
31.   for (int i = 0; i<e.size(); i++) {
32.     enemy a = e.get(i);
33.     a.display();
34.   }
35. }
36. void mouseReleased() {
37.   shoot = true;
38.   b.add(new bullet(mouseX, mouseY));
39. }
40. class enemy {
41.   int x, y, w, h;
42.   int enemyX = int(random(width));
43.   int enemyY = int(random(200));

44.   public enemy(int tempenemyW, int tempenemyH) {
45.     int tempenemyX = enemyX;
46.     int tempenemyY = enemyY;
47.     this.x = tempenemyX;
48.     this.y = tempenemyY;
49.     this.w = tempenemyW;
50.     this.h = tempenemyH;
51.   }

52.   void display() {
53.     fill(255, 0, 0);
54.     rect(this.x, this.y, this.w, this.h);
55.   }

56.   boolean col() {
57.     for (int i = 0; i<b.size(); i++) {
58.       bullet a = b.get(i);
59.       if (a.x+a.w>this.x && a.x<this.x+this.w && a.y+a.h+a.bulletSpeed>this.y && a.y+a.bulletSpeed<this.y+this.h) {
60.         return true;
61.       }
62.     }
63.     return false;
64.   }
65. }
66. class bullet {
67.   int x, y, w, h;
68.   int bulletSpeed = 10;

69.   public bullet(int tempx, int tempy) {
70.     int tempw = 3;
71.     int temph = 20;
72.     this.x = tempx;
73.     this.y = tempy;
74.     this.w = tempw;
75.     this.h = temph;
76.   }

77.   boolean update() {
78.     this.y -= bulletSpeed;

79.     fill(0, 255, 0);
80.     rect(this.x, this.y, this.w, this.h, 100, 100, 100, 100);

81.     if (x<0 || x>width || y<0 || y>height) {
82.       return true;
83.     } else {
84.       return false;
85.     }
86.   }
87. }

#9

Ok, we need to work in a couple of points. First, you need to properly format your code in the forum. To do so, edit your post, highlight your code and then hit ctrl+shift+c so it shows like this

void setup(){}

void draw(){

}

Now for the programing part. First point. When using classes, the name of classes start with upper case. In your MCVE, enemy and bullet class should be Enemy and Bullet. Variables should start with lower letters. It is a convention that you should get used to. Related to arrayList, it is better if you defined their type when they are created. For instance:

ArrayList<Enemy> e = new ArrayList();

This change will make your provided MCVE work. Now, with a working version, we can see what the problem is. I am guessing your main problem is that when you are removing your elements in your arrayList, you are not removing it backwards, as described in the documentation here:

// If you are modifying an ArrayList during the loop,
// then you cannot use the enhanced loop syntax.
// In addition, when deleting in order to hit all elements, 
// you should loop through it backwards, as shown here:
for (int i = particles.size() - 1; i >= 0; i--) {
  Particle part = particles.get(i);
  if (part.finished()) {
    particles.remove(i);
  }
}

Now, there is another few problems with your design. I won’t solve them all but it is for you to figure what to do (part of this thing called learning…)

Consider the following code:

for (int p = 0; p<e.size(); p++) {
  for (int i = 0; i<b.size(); i++) {

    bullet a = b.get(i);
    enemy o = e.get(p);
    if (a.update()) {
      b.remove(i);

    }

    if (o.col()) {
      b.remove(i);
      e.remove(i);
    }
}

Notice you are removing the current bullet object more than once. First of all, you are calling b.remove(i) twice in your code. Although these both might not get called at the same time, it will lead to painful headaches in the future. More subtle and mandates for change, you are removing a bullet in a nested loop. You need to make sure remove gets called only once. Another subtle issue with your code is the index you are using to remove the enemy. Notice the for loop counter for the enemy array is p and not i (Check this: for (int p = 0; p<e.size(); p++) {) then your line should read something like: e.remove(p);

I would rewrite your code more like this:

for (int p = e.size()-1; p>=0; p--) {
    enemy o = e.get(p); 
    if (o.col()) {
      e.remove(p);          
    }
  }
  
  for (int i = b.size()-1; i>=0; i--) {
    bullet a = b.get(i);
    a.update();
  }

As I said, this is not the final solution but for you to consider in your design. For this code, you need to figure out when to remove the bullet in the case it hits the enemy. Don’t be shy to scratch my version and come up with your own better version that handles when the bullet leaves the sketch area or when a bullet hits and destroys an enemy. I hope this helps,

Kf


#10

Thanks @kfrajer. You explained it better than I could.

@jbingo It’s okay to post your question on multiple sites, but please link between crossposts.

This question is also being discussed on Stack Overflow:


#12

Thank you, I will make a couple of adjustments to the code. I apologize for how terrible the design is, I am fairly new to programming.


#13

Thank you, I will make sure I link both crossposts.