I'm currently working on a basic snake game in java. I've got it all pretty much done, save for one problem.
The way my snake works is as follows: the "head" of the snake is the first snakeNode in line, and the next segment of its body is pointed to by the head. The second segment points to the third, etc. When you get to the end, the last segment points to null, and that's how you know that you're at the end of the snake. When the snake eats a pellet, a segment is simply added on at the front and the bottom is not updated.
As for collision detection, i use a 2d array to determine whether the snake has hit its own body parts or the walls.
Here's my problem:
As my snake starts to grow larger, it starts to leave spots behind it where it is still marked as an occupied square. I've looked all around for the problem, but there seems to be no pattern as to why it leaves behind these spots. In the code, I color any spaces that the snake is considered to be "occupying" as green, so as to make identifying these spots easier.
Here's the code:
snakeMain.java
package snake;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.*;
@SuppressWarnings("serial")
public class snakeMain extends JFrame{
Image DBImage;
Graphics dbg;
ImageIcon bg;
int screenWidth = 805;
int screenHeight = 598;
int keyPressed = 0;
static int direction = 2;
static int lastDirection = 2;
static int nextDirection = 2;
static snakeNode firstNode;
static snakeNode curNode;
static snakeNode checkNode;
static int snakeLength = 100;
static boolean needNewPellet = true;
static int pelletX = 1000;
static int pelletY = 1000;
static int[][] board = new int[80][59];
static boolean gameOver = false;
Dimension screenDimension = new Dimension(screenWidth,screenHeight);
public snakeMain(){
this.setTitle("Snake");
this.setSize(screenDimension);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.addKeyListener(new keyListener());
firstNode = new snakeNode(2,24,0,0);
for(int i = 0; i < board.length; i++){
for(int j = 0; j < board[i].length; j++){
board[i][j] = 0;
}
}
}
public static void main(String[] args){
@SuppressWarnings("unused")
snakeMain main = new snakeMain();
Random r = new Random();
//game loop
while(!gameOver){
if(direction == 1){
if(firstNode.getArrY() == 0){
//gameOver = true;
}else if(board[firstNode.getArrX()][firstNode.getArrY()-1] == 1){
gameOver = true;
}else{
firstNode = new snakeNode(firstNode.getX(),
firstNode.getY()-10,
firstNode.getArrX(),
firstNode.getArrY()-1,
firstNode);
board[firstNode.getArrX()][firstNode.getArrY()] = 1;
lastDirection = 1;
}
}else if(direction == 2){
if(firstNode.getX() >= 792){
// gameOver = true;
}else if(board[firstNode.getArrX()+1][firstNode.getArrY()] == 1){
gameOver = true;
}else{
firstNode = new snakeNode(firstNode.getX() + 10,
firstNode.getY(),
firstNode.getArrX()+1,
firstNode.getArrY(),
firstNode);
board[firstNode.getArrX()][firstNode.getArrY()] = 1;
lastDirection = 2;
}
}else if(direction == 3){
if(firstNode.getY() >= 575){
//gameOver = true;
}else if(board[firstNode.getArrX()][firstNode.getArrY()+1] == 1){
gameOver = true;
}else{
firstNode = new snakeNode(firstNode.getX(),
firstNode.getY()+10,
firstNode.getArrX(),
firstNode.getArrY()+1,
firstNode);
board[firstNode.getArrX()][firstNode.getArrY()] = 1;
lastDirection = 3;
}
}else if(direction == 4){
if(firstNode.getX() <= 11){
//gameOver = true;
}else if(board[firstNode.getArrX()-1][firstNode.getArrY()] == 1){
gameOver = true;
}else{
firstNode = new snakeNode(firstNode.getX()-10,
firstNode.getY(),
firstNode.getArrX()-1,
firstNode.getArrY(),
firstNode);
board[firstNode.getArrX()][firstNode.getArrY()] = 1;
lastDirection = 4;
}
}
int count = 1;
curNode = firstNode;
while(count < snakeLength){
if(curNode.getNext() != null){
curNode = curNode.getNext();
}
count++;
}
checkNode = curNode.getNext();
if(snakeLength > 2){
board[checkNode.getArrX()][checkNode.getArrY()] = 0;
}
curNode.setNext(null);
direction = nextDirection;
nextDirection = direction;
while(needNewPellet){
pelletX = 0;
int xPos = 0;
int yPos = 0;
while(pelletX % 10 % 10 != 2 || pelletX <= 11){
pelletX = r.nextInt(793);
xPos = (pelletX-2)/10;
}
pelletY = 0;
while(pelletY % 10 % 10 != 4 || pelletY <= 33){
pelletY = r.nextInt(575);
yPos = (pelletY-4)/10;
}
if(board[xPos][yPos] == 1){
needNewPellet = true;
}else{
needNewPellet = false;
}
}
if(firstNode.getX() == pelletX && firstNode.getY() == pelletY){
snakeLength++;
needNewPellet = true;
}
try{
Thread.sleep(25);
}catch(Exception e){}
}
}
public void paint(Graphics g){
DBImage = createImage(getWidth(), getHeight());
dbg = DBImage.getGraphics();
draw(dbg);
g.drawImage(DBImage, 0, 0, this);
}
public void draw(Graphics g){
g.setColor(Color.GREEN);
for(int i = 0; i < board.length; i++){
for(int j = 0; j < board[i].length; j++){
if(board[i][j] == 1){
g.fillRect((i*10)+2, (j*10)+24, 10, 10);
}
}
}
g.setColor(Color.BLACK);
int count = 0;
curNode = firstNode;
while(count < snakeLength){
g.fillOval(curNode.getX(), curNode.getY(), 10, 10);
if(curNode.getNext() != null){
curNode = curNode.getNext();
}
count++;
}
g.setColor(Color.RED);
g.fillOval(pelletX,pelletY,10,10);
repaint();
}
class keyListener extends KeyAdapter{
public void keyPressed(KeyEvent e){
keyPressed = e.getKeyCode();
if(keyPressed == e.VK_UP){
if(direction == 3){
}else if(lastDirection == 3){
nextDirection = 1;
}else{
nextDirection = 1;
}
}else if(keyPressed == e.VK_RIGHT){
if(direction == 4){}
else if(lastDirection == 4){
nextDirection = 2;
}else{
nextDirection = 2;
}
}else if(keyPressed == e.VK_DOWN){
if(direction == 1){}
else if(lastDirection == 1){
nextDirection = 3;
}else{
nextDirection = 3;
}
}else if(keyPressed == e.VK_LEFT){
if(direction == 2){}
else if(lastDirection == 2){
nextDirection = 4;
}else{
nextDirection = 4;
}
}
repaint();
}
public void keyReleased(KeyEvent e){
}
}
}
snakeNode.java:
package snake;
public class snakeNode {
int snakeX;
int snakeY;
snakeNode nextNode;
int arrX;
int arrY;
public snakeNode(int snakeX, int snakeY, int arrX, int arrY, snakeNode nextNode){
this.snakeX = snakeX;
this.snakeY = snakeY;
this.nextNode = nextNode;
this.arrX = arrX;
this.arrY = arrY;
}
public snakeNode(int snakeX, int snakeY, int arrX, int arrY){
this.snakeX = snakeX;
this.snakeY = snakeY;
nextNode = null;
this.arrX = arrX;
this.arrY = arrY;
}
public boolean equals(snakeNode node){
if(this.getX() == node.getX() && this.getY() == node.getY()){
return true;
}else{
return false;
}
}
public snakeNode clone(){
return new snakeNode(getX(), getY(), getArrX(), getArrY());
}
public int getArrX(){
return arrX;
}
public int getArrY(){
return arrY;
}
public void setArrX(int arrX){
this.arrX = arrX;
}
public void setArrY(int arrY){
this.arrY = arrY;
}
public int getX() {
return snakeX;
}
public void setX(int snakeX) {
this.snakeX = snakeX;
}
public int getY() {
return snakeY;
}
public void setY(int snakeY) {
this.snakeY = snakeY;
}
public snakeNode getNext() {
return nextNode;
}
public void setNext(snakeNode nextNode) {
this.nextNode = nextNode;
}
}
Any ideas or suggestions are greatly appreciated. Also, I'm wondering, is this the most efficient way of doing this?
As my snake begins to grow larger, the game starts to flicker. I suspect it's because my drawing algorithm is very
inefficient.
Thanks in advance,
-jc-

New Topic/Question
Reply




MultiQuote




|