Reputation: 11
I am new to programming and am stuck on a particular part involving the change in direction for the snake. This game is the same as the one for the old Nokia phone. It is classic.
Currently, the snake moves 1 square/20 pixels each time I press the W, A, S, or D key. The problem is that I would like this motion to be continuous and ALERT to other keys pressed. For example, when I press the 'S' key, the snake will move down (until it hits the wall) unless I press W, A, or D. In which case, the snake should change its movement to the corresponding direction. I have a slight idea that I will have to use a loop to keep moving the snake (this loop I THINK would be located inside a branch(if/else) of the method: movement).
Here is the current source code I have developed. This code works with no problem on "Ready to Program" for Java. It would also be helpful (but not necessary) if instead of writing "System.out.println();", you write "c.println()". This is because I am using the C console.
I have imported KeyAdapter and KeyEvent. This is all in a public class called SnakeGame. keyPressed is present as I tried to figure this out earlier. I believe it can still be useful.
// STORAGE ---- Setting up the variables
public static int life = 1; // Sets how many lives the snake has: 1
public static int appleX; // The X coordinate of the apple
public static int appleY; // The Y coordinate of the apple
public static int[] jointPosX = new int[400]; // X coordinates of the snake's joints. Stores as an array
public static int[] jointPosY = new int[400]; // Y coordinates of the snake's joints. Stores as an array
public static int jointNum = 3; // How many joints the snake starts out with: 3
public static int key;
public static boolean goLeft;
public static boolean goRight;
public static boolean goUp;
public static boolean goDown;
public static char moveInput; // The character (w, a, s, d) pressed for direction of movement
public static void board() // The game board
{
c.setColor(Color.black);
c.drawRect(19, 19, 401, 401); // These 3 lines make the border thick
c.drawRect(18, 18, 403, 403);
c.drawRect(17, 17, 405, 405);
c.setColor(new Color(72, 232, 75)); // Color: Medium - Dark Green
c.fillRect(20, 20, 400, 400); // The actual area where the snake moves
c.setColor(Color.black);
for (int y = 20; y < 420; y+=20) // Moving the position of the square across the Y axis
{
for (int x = 20; x < 420; x+=20) // Moving the position of the square across the X axis
{
c.drawRect(x, y, 20, 20); // Drawing the individual squares of the grid
}
}
}
public static void apple() // Where the apple will spawn
{
Random generator = new Random(); // Setting up the randum number generator
appleX = generator.nextInt(380 - 0 + 1) + 1; // X coordinate for apple (0 - 380)
if (appleX % 20 == 0) // Divisible perfectly by 20. Each square is 20 pixels wide
{
appleX = appleX; // The number is perfect
}
else
{
int rem = appleX % 20; // The remainder is assigned a variable
appleX = appleX - rem; // The X coordinate is now divisible by 20 (Subtracts the remainder from the indivisible X coordinate)
}
appleX = appleX + 21; // Adds 21 since board starts 21 pixels to the right
appleY = generator.nextInt(380 - 0 + 1) + 1; // Y coordinate for apple (0 - 380)
if (appleY % 20 == 0) // Divisible perfectly by 20. Each square is 20 pixels tall
{
appleY = appleY; // The number is perfect
}
else
{
int rem = appleY % 20; // The remainder is assigned a variable
appleY = appleY - rem; // The Y coordinate is now divisible by 20 (Subtracts the remainder from the indivisible Y coordinate)
}
appleY = appleY + 21; // Adds 21 since board starts 21 pixels downwards
}
public void keyPressed(KeyEvent e)
{
key = e.getKeyCode();
if (key == KeyEvent.VK_W)
{
goLeft = false;
goRight = false;
goUp = true;
goDown = false;
}
if (key == KeyEvent.VK_A)
{
goLeft = true;
goRight = false;
goUp = false;
goDown = false;
}
if (key == KeyEvent.VK_S)
{
goLeft = false;
goRight = false;
goUp = false;
goDown = true;
}
if (key == KeyEvent.VK_D)
{
goLeft = false;
goRight = true;
goUp = false;
goDown = false;
}
}
public static void selfDeath() // If the snake hits itself
{
for (int i = jointNum - 1; i > 0; i--) // Variable i stands for index number
{
if (jointPosX[0] == jointPosX[i] && jointPosY[0] == jointPosY[i]) // Checks if X and Y coordinates of head of snake matches any other part of snake
{
life--; // Loses a life
}
}
}
public static void wallDeath() // If the snake hits the wall
{
if (jointPosX[0] < 20 || jointPosX[0] > 420 || jointPosY[0] < 20 || jointPosY[0] > 420) // Checks if X and Y coordinates of head of snake is outside border coordinates
{
life--; // Loses a life
}
}
public static void movement() // How the snake moves
{
c.setColor(new Color(23, 156, 26)); // Color: Dark green
c.fillRect(jointPosX[0], jointPosY[0], 19, 19); // Initial point of snake
while(life == 1) {
moveInput = c.getChar(); // Getting W, A, S, or D from user
board(); // Redrawing the board
c.setColor(Color.red); // Color: Red
c.fillOval(appleX, appleY, 19, 19); // Drawing the apple
if (moveInput == 'w')
{
for (int i = jointNum - 1; i > 0; i--) { // Variable i stands for index number
jointPosY[i] = jointPosY[i - 1]; // Changing the Y coordinates of the joints to follow
jointPosX[i] = jointPosX[i - 1]; // Changing the X ooordinates of the joints to follow
}
jointPosY[0] = jointPosY[0] - 20; // Changing the vertical position of snake head (User pressed W)
c.setColor(new Color(23, 156, 26));
for (int z = 0; z < jointNum; z++) { // Moving along the index numbers
c.fillRect(jointPosX[z], jointPosY[z], 19, 19); // Drawing each joint
}
}
if (moveInput == 'a')
{
for (int i = jointNum - 1; i > 0; i--) { // Variable i stands for index number
jointPosX[i] = jointPosX[i - 1]; // Changing the X ooordinates of the joints to follow
jointPosY[i] = jointPosY[i - 1]; // Changing the Y coordinates of the joints to follow
}
jointPosX[0] = jointPosX[0] - 20; // Changing the horizontal position of snake head (User pressed S)
c.setColor(new Color(23, 156, 26));
for (int z = 0; z < jointNum; z++) { // Moving along the index numbers
c.fillRect(jointPosX[z], jointPosY[z], 19, 19); // Drawing each joint
}
}
if (moveInput == 's')
{
for (int i = jointNum - 1; i > 0; i--) { // Variable i stands for index number
jointPosY[i] = jointPosY[i - 1]; // Changing the Y coordinates of the joints to follow
jointPosX[i] = jointPosX[i - 1]; // Changing the X ooordinates of the joints to follow
}
jointPosY[0] = jointPosY[0] + 20; // Changing the vertical position of snake head (User pressed A)
c.setColor(new Color(23, 156, 26));
for (int z = 0; z < jointNum; z++) { // Moving along the index numbers
c.fillRect(jointPosX[z], jointPosY[z], 19, 19); // Drawing each joint
}
}
if (moveInput == 'd')
{
for (int i = jointNum - 1; i > 0; i--) { // Variable i stands for index number
jointPosX[i] = jointPosX[i - 1]; // Changing the X ooordinates of the joints to follow
jointPosY[i] = jointPosY[i - 1]; // Changing the Y coordinates of the joints to follow
}
jointPosX[0] = jointPosX[0] + 20; // Changing the horizontal position of snake head (User pressed D)
c.setColor(new Color(23, 156, 26));
for (int z = 0; z < jointNum; z++) { // Moving along the index numbers
c.fillRect(jointPosX[z], jointPosY[z], 19, 19); // Drawing each joint
}
}
addJoint();
selfDeath();
wallDeath();
}
}
public static void addJoint() // Checks to add a joint to the snake
{
if (jointPosX[0] == appleX && jointPosY[0] == appleY) // If X and Y coordinates of head of snake match X and Y coordinates of apple
{
jointNum++; // Adds a joint
apple(); // Adds another place for the apple to spawn
}
}
public static void main(String[] args)
{
c = new Console(25, 75);
jointPosX[0] = 101;
jointPosY[0] = 101;
jointPosX[1] = 101;
jointPosY[1] = 101;
jointPosX[2] = 101;
jointPosY[2] = 101;
board();
apple();
movement();
}
}
Upvotes: 0
Views: 1716
Reputation: 2861
Well, first things first, you want to have it move a bit in the correct direction each time the frame is redrawn, not just when the user presses an arrow key.
When the user does press a key, that is not the time to tell it to move, but rather the time to modify a variable that stores the current direction of the head node. The real trick is in preserving the shape of your snake, and in order to achieve that, you do not want every node moving in the same direction, but rather that each node moves to the location of the previous one.
For example if this is your snake (1 is the head that you start with, 7 is the tail from wha you ate last)
1)The game is in the current Position
xxxxxxxxxxxxxxxxxx
x x 2) User presses the Right Arrow (=>)
x 76 x
x 543 x 3) Direction is adjusted
x 2 x Var Direction_X = 1
x 1 x Var Direction_Y = 0
x x
xxxxxxxxxxxxxxxxxx
4) Head node moves per Direction_X and Direction_Y
xxxxxxxxxxxxxxxxxx
x x
x 76 x
x 543 x
x 2 x
x 1 x
x x
xxxxxxxxxxxxxxxxxx
5) Node 2 moves to where node 1 was
xxxxxxxxxxxxxxxxxx
x x
x 76 x
x 543 x
x x
x 21 x
x x
xxxxxxxxxxxxxxxxxx
6) Node 3 moves to where node 2 was
xxxxxxxxxxxxxxxxxx
x x
x 76 x
x 54 x
x 3 x
x 21 x
x x
xxxxxxxxxxxxxxxxxx
7) Nodes 4 to 7 follow the same pattern
xxxxxxxxxxxxxxxxxx
x x
x 7 x
x 654 x
x 3 x
x 21 x
x x
xxxxxxxxxxxxxxxxxx
8) The frame is repainted with everything in the new position.
A Note on implementation:
The diagram above was the best way I could think of showing it to make the intention of the algorithm clear, but when actually coding it, you may want to start from the back instead, when replacing nodes (place 7 at 6, 6 at 5, 5 at 4, ... , 2 at 1, move 1 per the current direction variables). This is because the next position will already be stored in your list.
Upvotes: 1