I’m trying to make snake game. Everything works fine so far but the snake doesn’t eat the food. The program yields error ArrayIndexOutOfBoundsException which I think is because of eatFood(), because when I commented out the eatFood() in the draw(), the program works normally.
//20x20
boolean kPressed = false;
boolean alive = true;
int len = 6;
Segment[] arr = new Segment[len];
Food[] fArr = new Food[1];
String popUp = "GAME OVER";
int score = len - 6;
String scoreTxt = "Score: " + score;
void keyPressed() {
kPressed = true;
}
void move() {
if (kPressed == true) {
if (keyCode == UP) {
arr[0].y -= 20;
}
if (keyCode == LEFT) {
arr[0].x -= 20;
}
if (keyCode == RIGHT) {
arr[0].x += 20;
}
if (keyCode == DOWN) {
arr[0].y += 20;
}
}
}
void eatFood() { //<------------------ tell the snake to eat
if ((arr[0].x == fArr[0].fX) & (arr[0].y == fArr[0].fY)) { //<------------------ check if snake head position is at food's position
len += 1; //<------------------ add 1 segment
fArr[0].fX = int(random(29))*20; //<------------------ replace the eaten food and add new location for the next food spawn
fArr[0].fY = int(random(29))*20;
}
}
void popScore() {
textSize(20);
textAlign(CENTER, CENTER);
text(scoreTxt, 300, 0);
}
void pop() {
alive = false;
textSize(50);
textAlign(CENTER, CENTER);
text(popUp, 300, 300);
}
void gameOver() {
for (int u = 2; u < len; u++) {
if (arr[0].x == arr[u].x & arr[0].y == arr[u].y) {
pop();
}
}
if (arr[0].x < 0 || arr[0].x + 20 > 600 || arr[0].y < 0 || arr[0].y > 600) {
pop();
}
}
void setup() {
size(600, 600);
frameRate(3);
for (int i = 0; i < len; i++) {
Segment seg = new Segment();
seg.y += i*20;
arr[i] = seg;
}
Food sF = new Food();
fArr[0] = sF;
}
void draw() {
background(45);
//starting food
fArr[0].spawnFood(); //<------------------ first display the food object from setup(), after that display the ones generated by the eatFood()
eatFood(); //<------------------ causes error
if (alive == true) {
move();
}
if (kPressed == true) {
for (int i = len-1; i >= 1; i--) {
arr[i-1].display();
arr[len-1].display();
arr[i].x = arr[i-1].x;
arr[i].y = arr[i-1].y;
}
}
else if (kPressed == false) {
for (int i = 0; i < len; i++) {
arr[i].display();
}
}
popScore();
gameOver();
}
class Segment {
int x = 300;
int y = 300;
void display() {
rect(x, y, 20, 20);
}
}
class Food {
int fX, fY;
void spawnFood() {
fX = 300;
fY = 200;
ellipse(fX+10, fY+10, 10, 10);
}
}
I have modified your code. Pay attention to the changes. Few things still to do. Notice you need rectMode as center… it is easier
Watch for & in conditionals. That is not proper, you need && instead.
Check the reference for the dist() function. I provided an example in your code.
I disabled you array length increase. As it is, you are using an array to store your object. You need to “grow”/expand your array before you add an element. You need to use a Segment object. However, as it is, your segment object can only take one x and y position during construction which is not what you want. You need to fix that. To expand the rray, check append or concat in the reference. However, you probly need another structure like ArrayList. Never mind, just this will do for now.
Check for key pressed. It should execute only if the arrow keys are pressed.
Kf
final int RAD=10;
final int SQ_LEN=2*RAD;
boolean kPressed = false;
boolean alive = true;
int len = 6;
Segment[] arr = new Segment[len];
Food[] fArr = new Food[1];
String popUp = "GAME OVER";
int score = len - 6;
String scoreTxt = "Score: " + score;
void setup() {
size(600, 600);
frameRate(15);
rectMode(CENTER);
for (int i = 0; i < len; i++) {
Segment seg = new Segment();
seg.y += i*SQ_LEN;
arr[i] = seg;
}
Food sF = new Food();
fArr[0] = sF;
}
void draw() {
background(45);
//starting food
fArr[0].spawnFood(); //<------------------ first display the food object from setup(), after that display the ones generated by the eatFood()
eatFood(); //<------------------ causes error
for (int i = 0; i < len; i++)
arr[i].display();
popScore();
gameOver();
}
class Segment {
int x = 300;
int y = 300;
void display() {
rect(x, y, SQ_LEN, SQ_LEN);
}
}
class Food {
int fX, fY;
void spawnFood() {
fX = 300;
fY = 200;
ellipse(fX, fY, RAD, RAD);
}
}
void keyPressed() {
kPressed = true;
if (keyCode == UP) {
arr[0].y -= SQ_LEN;
}
if (keyCode == LEFT) {
arr[0].x -= SQ_LEN;
}
if (keyCode == RIGHT) {
arr[0].x += SQ_LEN;
}
if (keyCode == DOWN) {
arr[0].y += SQ_LEN;
}
for (int i = len-1; i >= 1; i--) { //REMARK: Begins at 1
arr[i].x = arr[i-1].x;
arr[i].y = arr[i-1].y;
}
}
void keyReleased() {
kPressed = false;
}
void eatFood() { //<------------------ tell the snake to eat
if ((arr[0].x == fArr[0].fX) && (arr[0].y == fArr[0].fY)) { //HERE use better if(dist(arr[0].x,arr[0].y,fArr[0].fX,fArr[0].fY)>RAD) ----> true when they intercept
//len += 1; //<------------------ FIX
fArr[0].fX = int(random(29))*SQ_LEN; //<------------------ replace the eaten food and add new location for the next food spawn
fArr[0].fY = int(random(29))*SQ_LEN;
}
}
void popScore() {
textSize(20);
textAlign(CENTER, CENTER);
text(scoreTxt, 300, 0);
}
void pop() {
alive = false;
textSize(50);
textAlign(CENTER, CENTER);
text(popUp, 300, 300);
}
void gameOver() {
for (int u = 2; u < len; u++) {
if (arr[0].x == arr[u].x & arr[0].y == arr[u].y) { //<------------------ FIX This conditiona is wrong: & is not the same as &&. The latter is correct for java
pop();
}
}
if (arr[0].x < 0 || arr[0].x + 20 > 600 || arr[0].y < 0 || arr[0].y > 600) {
pop();
}
}