SimpleSnake

advertisement
The Art and Science of
ERIC S. ROBERTS
CHAPTER 11
Java
An Introduction
to Computer Science
Arrays and ArrayLists
Little boxes, on a hillside, little boxes made of ticky-tacky
Little boxes, little boxes, little boxes, all the same
There’s a green one and a pink one and a blue one and a yellow one
And they're all made out of ticky-tacky and they all look just the same
—Malvina Reynolds, “Little Boxes,” 1962
Lecture Slides, Part III
CS101 @ Özyeğin University
Slides are adapted from the originals available at
http://www-cs-faculty.stanford.edu/~eroberts/books/ArtAndScienceOfJava/
Chapter 11—Arrays and ArrayLists
1
Example: SimpleSnake
• In this problem we will implement a simple version of the
snake game in which a snake bounces from the walls of the
screen.
2
SimpleSnake
• Each part of the snake body will have a size of
BODY_PART_WIDTH.
• There are SNAKE_LENGTH many body parts.
• Each body part is a GOval object. All the body parts are kept
in a GOval array.
private GOval[] snakeBody = new GOval[SNAKE_LENGTH];
• Corresponding to each body part, we keep the velocity in the
x direction and in the y direction.
private double[] xVelocities = new double[SNAKE_LENGTH];
private double[] yVelocities = new double[SNAKE_LENGTH];
• Food for thought: Why don’t we keep a single velocity value?
3
SimpleSnake
public void run() {
initializeSnakeBody();
initializeVelocities();
while(true) {
moveSnake();
checkBounds();
pause(20);
}
}
4
SimpleSnake
(initializing body parts)
BODY_PART_WIDTH / sqrt(2)
BODY_PART_WIDTH
5
SimpleSnake
public void initializeSnakeBody() {
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
for(int i = 0; i < snakeBody.length; i++) {
snakeBody[i] = createSnakeBodyPartCenteredAt(xCenter, yCenter);
xCenter -= (BODY_PART_WIDTH/Math.sqrt(2));
yCenter -= (BODY_PART_WIDTH/Math.sqrt(2));
add(snakeBody[i]);
}
}
public GOval createSnakeBodyPartCenteredAt(int xCenter, int yCenter) {
GOval circle = new GOval(xCenter - BODY_PART_WIDTH/2,
yCenter - BODY_PART_WIDTH/2,
BODY_PART_WIDTH, BODY_PART_WIDTH);
circle.setFilled(true);
circle.setFillColor(Color.BLUE);
return circle;
}
6
public void initializeVelocities() {
for(int i = 0; i < xVelocities.length; i++) {
xVelocities[i] = 3;
}
for(int i = 0; i < yVelocities.length; i++) {
yVelocities[i] = 3;
}
}
SimpleSnake
public void moveSnake() {
for(int i = 0; i < snakeBody.length; i++) {
snakeBody[i].move(xVelocities[i], yVelocities[i]);
}
}
public void checkBounds() {
for(int i = 0; i < snakeBody.length; i++) {
double x = snakeBody[i].getX();
double y = snakeBody[i].getY();
if(x < 0 || x > getWidth() - BODY_PART_WIDTH) {
xVelocities[i] *= -1;
}
if(y < 0 || y > getHeight() - BODY_PART_WIDTH) {
yVelocities[i] *= -1;
}
}
}
7
SimpleSnake v.2
• In this problem we will implement yet another simple version
of the snake game.
• P.S. You may need to click on the window to request focus so
8
that key events will be captured.
SimpleSnake v.2
• In this version, there is a single, constant SPEED value. The
head of the snake has a direction, which can be one of
NORTH, EAST, SOUTH, WEST.
• After each move, a body part replaces the part in the front.
snake
direction
9
SimpleSnake v.2
• In this version, there is a single, constant SPEED value. The
head of the snake has a direction, which can be one of
NORTH, EAST, SOUTH, WEST.
• After each move, a body part replaces the part in the front.
snake
direction
10
SimpleSnake v.2
• Moving the snake parts:
• Each part element gets the location of the element in front
of it.
• Head element is moved according to its direction.
0
1
2
3
4
5
6
7
11
public class SimpleSnakeV2 extends GraphicsProgram {
private final int BODY_PART_WIDTH = 20;
private final int SNAKE_LENGTH = 12;
private final int SPEED = BODY_PART_WIDTH;
SimpleSnake
private GOval[] snakeBody = new GOval[SNAKE_LENGTH];
private final int NORTH = 1;
private final int EAST = 2;
private final int SOUTH = 3;
private final int WEST = 4;
// Direction of the head is one of {N, W, S, E}
private int direction = EAST;
// Cont’d on the next slide
// . . .
12
public void run() {
addGrid();
initializeSnakeBody();
while(true) {
moveSnake();
pause(200);
}
}
public void addGrid() {
for(int i = 0; i < getWidth(); i += BODY_PART_WIDTH) {
add(new GLine(i, 0, i, getHeight()));
}
for(int i = 0; i < getHeight(); i += BODY_PART_WIDTH) {
add(new GLine(0, i, getWidth(), i));
}
}
13
public void initializeSnakeBody() {
int x = SNAKE_LENGTH * BODY_PART_WIDTH;
int y = getHeight() / 2;
for(int i = 0; i < snakeBody.length; i++) {
snakeBody[i] = createSnakeBodyAt(x, y);
x -= BODY_PART_WIDTH;
add(snakeBody[i]);
}
}
public GOval createSnakeBodyAt(int x, int y) {
GOval circle = new GOval(x, y,
BODY_PART_WIDTH, BODY_PART_WIDTH);
circle.setFilled(true);
circle.setFillColor(Color.BLUE);
return circle;
}
14
public void moveSnake() {
// Each body part replaces the one in front of it
for(int i = snakeBody.length - 1; i >= 1; i--) {
GOval prevPart = snakeBody[i-1];
snakeBody[i].setLocation(prevPart.getX(), prevPart.getY());
}
// Move the head
if(direction == EAST) {
snakeBody[0].move(SPEED, 0);
} else if(direction == WEST) {
snakeBody[0].move(-SPEED, 0);
} else if(direction == NORTH) {
snakeBody[0].move(0, -SPEED);
} else if(direction == SOUTH) {
snakeBody[0].move(0, SPEED);
}
}
15
// The method below is invoked whenever the user presses a key
// You do not need to spend too much time understanding this part
public void keyPressed(KeyEvent keyEvent) {
// VK_UP: key code for up arrow key
// VK_RIGHT: key code for right arrow key
// VK_DOWN: key code for down arrow key
// VK_LEFT: key code for left arrow key
if(keyEvent.getKeyCode() == KeyEvent.VK_UP) {
direction = NORTH;
} else if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
direction = EAST;
} else if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
direction = SOUTH;
} else if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
direction = WEST;
}
}
public void init() {
setSize(600, 400);
addKeyListeners(); // required for key interaction
}
}
16
Download