Files
eceg431/09/Snake/Snake.jack
2025-11-14 15:23:07 -05:00

188 lines
5.2 KiB
Plaintext

// Manages snake body segments and movement mechanics
// Handles growth, collision detection, and rendering
class Snake {
field Array body;
field int length;
field int maxLength;
field int direction;
field int size;
field Point head;
// create snake with initial length at center screen
constructor Snake new() {
let maxLength = 200;
let length = 3;
let size = 8;
let direction = 4; // right
let body = Array.new(maxLength);
// initialize head at screen center (adjusted for header area)
let head = Point.new(256, 144);
let body[0] = head;
// create initial body segments
let body[1] = Point.new(248, 144);
let body[2] = Point.new(240, 144);
do draw();
return this;
}
// free memory
method void dispose() {
var int i;
var Point segment;
let i = 0;
while (i < length) {
let segment = body[i];
do segment.dispose();
let i = i + 1;
}
do body.dispose();
do Memory.deAlloc(this);
return;
}
// draw entire snake as solid squares
method void draw() {
var int i;
var Point segment;
do Screen.setColor(true);
let i = 0;
while (i < length) {
let segment = body[i];
do Screen.drawRectangle(segment.getX(), segment.getY(),
segment.getX() + size - 1, segment.getY() + size - 1);
let i = i + 1;
}
return;
}
// erase tail segment
method void eraseTail() {
var Point tail;
let tail = body[length - 1];
do Screen.setColor(false);
do Screen.drawRectangle(tail.getX(), tail.getY(),
tail.getX() + size, tail.getY() + size);
return;
}
// move snake one step forward with optional growth
method void move(boolean grow) {
var int i;
var Point newHead;
var Point oldTail;
var int newX, newY;
// calculate new head position based on direction
let newX = head.getX();
let newY = head.getY();
if (direction = 1) { let newY = newY - 8; } // up
if (direction = 2) { let newY = newY + 8; } // down
if (direction = 3) { let newX = newX - 8; } // left
if (direction = 4) { let newX = newX + 8; } // right
// create new head first
let newHead = Point.new(newX, newY);
if (grow) {
// growing: shift everything back and add new head
let i = length;
while (i > 0) {
let body[i] = body[i - 1];
let i = i - 1;
}
let body[0] = newHead;
let head = newHead;
let length = length + 1;
// draw new head only
do Screen.setColor(true);
do Screen.drawRectangle(head.getX(), head.getY(),
head.getX() + size - 1, head.getY() + size - 1);
} else {
// not growing: move tail to front as new head
let oldTail = body[length - 1];
// erase old tail first
do Screen.setColor(false);
do Screen.drawRectangle(oldTail.getX(), oldTail.getY(),
oldTail.getX() + size - 1, oldTail.getY() + size - 1);
// shift body segments back
let i = length - 1;
while (i > 0) {
let body[i] = body[i - 1];
let i = i - 1;
}
// dispose old tail and use new head
do oldTail.dispose();
let body[0] = newHead;
let head = newHead;
// draw new head
do Screen.setColor(true);
do Screen.drawRectangle(head.getX(), head.getY(),
head.getX() + size - 1, head.getY() + size - 1);
}
return;
}
// change direction (prevent reverse moves)
method void setDirection(int newDirection) {
// prevent moving directly backwards
if (((direction = 1) & (newDirection = 2)) | // up -> down
((direction = 2) & (newDirection = 1)) | // down -> up
((direction = 3) & (newDirection = 4)) | // left -> right
((direction = 4) & (newDirection = 3))) { // right -> left
return;
}
let direction = newDirection;
return;
}
// check wall collision (adjusted for header area)
method boolean hitWall() {
return (head.getX() < 8) | (head.getX() > 496) |
(head.getY() < 33) | (head.getY() > 240);
}
// check self collision
method boolean hitSelf() {
var int i;
var Point segment;
let i = 1; // skip head (index 0)
while (i < length) {
let segment = body[i];
if (head.equals(segment)) {
return true;
}
let i = i + 1;
}
return false;
}
// get head position
method Point getHead() {
return head;
}
// get current length
method int getLength() {
return length;
}
// get current direction
method int getDirection() {
return direction;
}
}