made new snake and index and liberary improvements
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
function preload() {
|
||||
img1 = loadImage('../assets/wallpaper/dear.png');
|
||||
img2 = loadImage('../assets/wallpaper/elphantJap.jpg');
|
||||
}
|
||||
let img1, img2;
|
||||
|
||||
function setup() {
|
||||
async function setup() {
|
||||
try {
|
||||
img1 = await loadImage('assets/wallpaper/dear.png');
|
||||
img2 = await loadImage('assets/wallpaper/elphantJap.jpg');
|
||||
} catch (err) {
|
||||
console.error('Image load failed', err);
|
||||
return;
|
||||
}
|
||||
createCanvas(img1.width, img1.height);
|
||||
background(255, 255, 255)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ let cleanedText = "";
|
||||
let wordToIndex = {};
|
||||
|
||||
async function setup() {
|
||||
trainingText = await loadStrings('assets/text/TheSubspaceEmissaryWorldConquest.txt');
|
||||
trainingText = await loadStrings('assets/text/50shades.txt');
|
||||
createCanvas(windowWidth, windowHeight);
|
||||
background(255, 255, 230);
|
||||
|
||||
@@ -53,9 +53,9 @@ async function setup() {
|
||||
}
|
||||
}
|
||||
|
||||
textSize(19);
|
||||
textSize(windowHeight / 18);
|
||||
console.log(finalText);
|
||||
text(finalText, width / 2-400, height / 2, 800, height);
|
||||
text(finalText, 10, 10, windowWidth-20, windowHeight-20);
|
||||
}
|
||||
|
||||
function splitText(text) {
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
function preload() {
|
||||
img1 = loadImage('assets/wallpaper/dear.png');
|
||||
img2 = loadImage('assets/wallpaper/elphantJap.jpg');
|
||||
}
|
||||
async function setup() {
|
||||
try {
|
||||
img1 = await loadImage('assets/wallpaper/dear.png');
|
||||
console.log('img1 loaded');
|
||||
} catch (err) {
|
||||
console.error('Failed to load dear.png', err);
|
||||
}
|
||||
|
||||
try {
|
||||
img2 = await loadImage('assets/wallpaper/elphantJap.jpg');
|
||||
console.log('img2 loaded');
|
||||
} catch (err) {
|
||||
console.error('Failed to load elphantJap.jpg', err);
|
||||
}
|
||||
|
||||
function setup() {
|
||||
createCanvas(img1.width, img1.height);
|
||||
background(255, 255, 255)
|
||||
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
function preload() {
|
||||
img1 = loadImage('assets/wallpaper/Space-Nebula.png');
|
||||
}
|
||||
|
||||
function setup() {
|
||||
async function setup() {
|
||||
img1 = await new Promise(resolve => loadImage('assets/wallpaper/lagrugru.jpg', resolve));
|
||||
createCanvas(img1.width, img1.height);
|
||||
background(255, 255, 55)
|
||||
// performance enhancmend (from LLM)
|
||||
img1.loadPixels();
|
||||
for (let y = 0; y < img1.height; y++) {
|
||||
for (let x = 0; x < img1.width; x++) {
|
||||
let idx = (x + y * img1.width) * 4;
|
||||
let r = img1.pixels[idx];
|
||||
let g = img1.pixels[idx+1];
|
||||
let b = img1.pixels[idx+2];
|
||||
let sum = r + g + b;
|
||||
let threshold = random(0, 255) * 3;
|
||||
set(x, y, sum < threshold ? color(0) : color(255));
|
||||
}
|
||||
}
|
||||
updatePixels();
|
||||
|
||||
//image(img1, 0, 0);
|
||||
|
||||
//original code (works to but somettimes not good for bigger images)
|
||||
/*
|
||||
for (let col = 0; col < img1.width; col += 1) {
|
||||
for (let row = 0; row < img1.height; row += 1) {
|
||||
let c = img1.get(col, row);
|
||||
@@ -26,6 +37,8 @@ function setup() {
|
||||
point(col, row);
|
||||
}
|
||||
}
|
||||
console.log('finished');
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -98,21 +98,21 @@ function buttonUpgradeAIPressed(){
|
||||
break;
|
||||
|
||||
case "wallDetection":
|
||||
AItype = "nearApple";
|
||||
AItype = "snakeDetection";
|
||||
UpgradeAIPrice = 12;
|
||||
break;
|
||||
|
||||
case "snakeDetection":
|
||||
AItype = "nearApple";
|
||||
UpgradeAIPrice = 25;
|
||||
break;
|
||||
|
||||
case "nearApple":
|
||||
AItype = "appleBias";
|
||||
UpgradeAIPrice = 25;
|
||||
break;
|
||||
|
||||
case "appleBias":
|
||||
AItype = "snakeDetection";
|
||||
UpgradeAIPrice = 50;
|
||||
break;
|
||||
|
||||
case "snakeDetection":
|
||||
case "appleBias":
|
||||
AItype = "smart";
|
||||
UpgradeAIPrice = 120;
|
||||
break;
|
||||
@@ -121,6 +121,11 @@ function buttonUpgradeAIPressed(){
|
||||
AItype = "survival";
|
||||
UpgradeAIPrice = 300;
|
||||
break;
|
||||
|
||||
case "survival":
|
||||
AItype = "perfect";
|
||||
UpgradeAIPrice = 1000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,6 +240,18 @@ function runSnake(){
|
||||
summonApple();
|
||||
eatenApples++;
|
||||
}
|
||||
if (
|
||||
snake.length >=
|
||||
(gridColumns * gridRows) - appleAmount
|
||||
){
|
||||
|
||||
if (AItype == "perfect"){
|
||||
rewardPerfectAI();
|
||||
}
|
||||
|
||||
restartGame();
|
||||
return;
|
||||
}
|
||||
drawSnakeOnGrid();
|
||||
}
|
||||
|
||||
@@ -349,6 +366,10 @@ function snakeAI(){
|
||||
snakeAIwallDetection();
|
||||
break;
|
||||
|
||||
case "snakeDetection":
|
||||
snakeAIsnakeDetection();
|
||||
break;
|
||||
|
||||
case "nearApple":
|
||||
snakeAInearApple();
|
||||
break;
|
||||
@@ -357,10 +378,6 @@ function snakeAI(){
|
||||
snakeAIappleBias();
|
||||
break;
|
||||
|
||||
case "snakeDetection":
|
||||
snakeAIsnakeDetection();
|
||||
break;
|
||||
|
||||
case "smart":
|
||||
snakeAIsmart();
|
||||
break;
|
||||
@@ -368,6 +385,10 @@ function snakeAI(){
|
||||
case "survival":
|
||||
snakeAIsurvival();
|
||||
break;
|
||||
|
||||
case "perfect":
|
||||
snakeAIperfect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,6 +502,43 @@ function countFreeNeighbors(x, y){
|
||||
return count;
|
||||
}
|
||||
|
||||
// got this inspiration by an LLM AI
|
||||
function getHamiltonianDirection(){
|
||||
|
||||
let x = snake[0][0];
|
||||
let y = snake[0][1];
|
||||
|
||||
// snake-like scan pattern
|
||||
|
||||
if (y % 2 == 0){
|
||||
|
||||
// move right
|
||||
if (x < gridColumns - 1){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// move down
|
||||
if (y < gridRows - 1){
|
||||
return 1;
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
// move left
|
||||
if (x > 0){
|
||||
return 2;
|
||||
}
|
||||
|
||||
// move down
|
||||
if (y < gridRows - 1){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// top fallback
|
||||
return 3;
|
||||
}
|
||||
|
||||
function snakeAIrandom() {
|
||||
snakeDirection = floor(random(0, 4));
|
||||
}
|
||||
@@ -712,4 +770,75 @@ function snakeAIsurvival(){
|
||||
}
|
||||
|
||||
snakeDirection = bestDirection;
|
||||
}
|
||||
|
||||
// instpired by an LLM AI
|
||||
function snakeAIperfect(){
|
||||
|
||||
let apple = getClosestApple();
|
||||
|
||||
// try smart movement first
|
||||
if (apple != null){
|
||||
|
||||
let bestDirection = -1;
|
||||
let bestDistance = Infinity;
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
|
||||
if (!isDirectionSafe(i)){
|
||||
continue;
|
||||
}
|
||||
|
||||
let vec = directionToVector(i);
|
||||
|
||||
let newX = snake[0][0] + vec[0];
|
||||
let newY = snake[0][1] + vec[1];
|
||||
|
||||
let distance =
|
||||
abs(newX - apple[0]) +
|
||||
abs(newY - apple[1]);
|
||||
|
||||
let freeNeighbors =
|
||||
countFreeNeighbors(newX, newY);
|
||||
|
||||
// avoid traps
|
||||
if (
|
||||
freeNeighbors <= 1 &&
|
||||
snake.length < (gridColumns * gridRows) - 5
|
||||
){
|
||||
continue;
|
||||
}
|
||||
|
||||
if (distance < bestDistance){
|
||||
bestDistance = distance;
|
||||
bestDirection = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestDirection != -1){
|
||||
snakeDirection = bestDirection;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to Hamiltonian path
|
||||
let direction = getHamiltonianDirection();
|
||||
|
||||
if (isDirectionSafe(direction)){
|
||||
snakeDirection = direction;
|
||||
return;
|
||||
}
|
||||
|
||||
// fallback survival
|
||||
snakeAIsurvival();
|
||||
}
|
||||
|
||||
function rewardPerfectAI(){
|
||||
|
||||
let reward =
|
||||
floor(
|
||||
(gridColumns * gridRows) * 0.75
|
||||
);
|
||||
|
||||
eatenApples += reward;
|
||||
}
|
||||
671
sketches/snakeAIEvolution.js
Normal file
671
sketches/snakeAIEvolution.js
Normal file
@@ -0,0 +1,671 @@
|
||||
let grid = [];
|
||||
let snake = [];
|
||||
let alive = true;
|
||||
let snakeDirection = 0;
|
||||
let AItype = "random";
|
||||
let gridSize = 20;
|
||||
let gridColumns = 10;
|
||||
let gridRows = 10;
|
||||
let eatenApples = 0;
|
||||
let _textSize = 16;
|
||||
let appleAmount = 1;
|
||||
let gameSpeed = 10;
|
||||
let buttonAddColoums = null;
|
||||
let buttonAddRows = null;
|
||||
let buttonUpgradeAI = null;
|
||||
let buttonAddMoreApples = null;
|
||||
let buttonSpeedUpgrade = null;
|
||||
let SpeedUpgradePrice = 5;
|
||||
let AddMoreApplesPrice = 1;
|
||||
let AddColoumsPrice = 1;
|
||||
let AddRowsPrice = 1;
|
||||
let UpgradeAIPrice = 1;
|
||||
let buttonSnifferUP = null;
|
||||
let buttonSnifferDown = null;
|
||||
let sniffingDistance = 1;
|
||||
let buttonEyeUp = null;
|
||||
let buttonEyeDown = null;
|
||||
let eyeDistance = 1;
|
||||
let snifferUpgradePrice = 1;
|
||||
let eyeUpgradePrice = 1;
|
||||
let snifferLevel = 1;
|
||||
let eyeLevel = 1;
|
||||
let sniffingIncrement = 1;
|
||||
let eyeIncrement = 2;
|
||||
let sniffingPriceIncrement = 2;
|
||||
let eyePriceIncrement = 2;
|
||||
let moulthOpenDistance = 2;
|
||||
|
||||
|
||||
function setup() {
|
||||
buttonAddColoums = createButton("Add coloums");
|
||||
buttonAddRows = createButton("Add rows");
|
||||
buttonAddMoreApples = createButton("Add more apples");
|
||||
buttonSpeedUpgrade = createButton("Increase speed");
|
||||
buttonSnifferUP = createButton("SnifferUp");
|
||||
buttonSnifferDown = createButton("SnifferDown");
|
||||
buttonEyeUp = createButton("EyeUp");
|
||||
buttonEyeDown = createButton("EyeDown");
|
||||
createCanvas(windowWidth, windowHeight);
|
||||
background(255, 255, 255);
|
||||
for (let i = 0; i < gridColumns; i++) {
|
||||
grid[i] = [];
|
||||
for (let j = 0; j < gridRows; j++) {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
buttonAddColoums.mousePressed(buttonAddColoumsPressed);
|
||||
buttonAddRows.mousePressed(buttonAddRowsPressed);
|
||||
buttonAddMoreApples.mousePressed(buttonAddMoreApplesPressed);
|
||||
buttonSpeedUpgrade.mousePressed(buttonSpeedUpgradePressed);
|
||||
buttonSnifferUP.mousePressed(buttonSnifferUPPressed);
|
||||
buttonSnifferDown.mousePressed(buttonSnifferDownPressed);
|
||||
buttonEyeUp.mousePressed(buttonEyeUpPressed);
|
||||
buttonEyeDown.mousePressed(buttonEyeDownPressed);
|
||||
frameRate(gameSpeed);
|
||||
summonSnake();
|
||||
summonApple();
|
||||
drawGrid();
|
||||
}
|
||||
|
||||
|
||||
function buttonSnifferUPPressed(){
|
||||
if (sniffingDistance > gridRows) {
|
||||
return;
|
||||
}
|
||||
if (snifferUpgradePrice > eatenApples) {
|
||||
return;
|
||||
}
|
||||
if (!(snifferLevel * sniffingIncrement > sniffingDistance)) {
|
||||
eatenApples -= snifferUpgradePrice;
|
||||
snifferUpgradePrice += sniffingPriceIncrement;
|
||||
snifferLevel ++;
|
||||
}
|
||||
|
||||
sniffingDistance += sniffingIncrement;
|
||||
}
|
||||
function buttonSnifferDownPressed(){
|
||||
if (sniffingDistance < 1) {
|
||||
return;
|
||||
}
|
||||
sniffingDistance -= sniffingIncrement;
|
||||
}
|
||||
|
||||
function buttonSpeedUpgradePressed(){
|
||||
|
||||
if (eatenApples < SpeedUpgradePrice) {
|
||||
return;
|
||||
}
|
||||
|
||||
eatenApples -= SpeedUpgradePrice;
|
||||
|
||||
gameSpeed += 2;
|
||||
|
||||
frameRate(gameSpeed);
|
||||
|
||||
SpeedUpgradePrice += 5;
|
||||
}
|
||||
|
||||
function buttonEyeUpPressed(){
|
||||
if (eyeDistance > gridColumns) {
|
||||
return;
|
||||
}
|
||||
if (!(eyeLevel * eyeIncrement + 1 >= eyeDistance) && eyeUpgradePrice <= eatenApples) {
|
||||
eatenApples -= eyeUpgradePrice;
|
||||
eyeUpgradePrice += eyePriceIncrement;
|
||||
eyeLevel ++;
|
||||
}else if(eyeUpgradePrice > eatenApples){
|
||||
return;
|
||||
}
|
||||
|
||||
eyeDistance += eyeIncrement;
|
||||
}
|
||||
function buttonEyeDownPressed(){
|
||||
if (eyeDistance < 1) {
|
||||
return;
|
||||
}
|
||||
eyeDistance -= eyeIncrement;
|
||||
}
|
||||
|
||||
function buttonAddColoumsPressed(){
|
||||
if (eatenApples < AddColoumsPrice) {
|
||||
return;
|
||||
}
|
||||
eatenApples -= AddColoumsPrice;
|
||||
gridColumns++;
|
||||
grid.push([]);
|
||||
for (let i = 0; i < gridRows; i++) {
|
||||
grid[grid.length - 1][i] = 0;
|
||||
}
|
||||
}
|
||||
function buttonAddRowsPressed(){
|
||||
if (eatenApples < AddRowsPrice) {
|
||||
return;
|
||||
}
|
||||
eatenApples -= AddRowsPrice;
|
||||
gridRows++;
|
||||
for (let i = 0; i < gridColumns; i++) {
|
||||
grid[i].push(0);
|
||||
}
|
||||
}
|
||||
|
||||
function buttonAddMoreApplesPressed(){
|
||||
if (eatenApples < AddMoreApplesPrice) {
|
||||
return;
|
||||
}
|
||||
eatenApples -= AddMoreApplesPrice;
|
||||
if (appleAmount < 5){
|
||||
AddMoreApplesPrice += 1;
|
||||
}else if (appleAmount < 10){
|
||||
AddMoreApplesPrice += 2;
|
||||
}else if (appleAmount < 20){
|
||||
AddMoreApplesPrice += 3;
|
||||
}else if (appleAmount < 50){
|
||||
AddMoreApplesPrice += 4;
|
||||
}else{
|
||||
AddMoreApplesPrice += ceil(AddMoreApplesPrice*0.15);
|
||||
}
|
||||
summonApple();
|
||||
appleAmount++;
|
||||
}
|
||||
|
||||
function summonApple(){
|
||||
if (appleAmount >= gridColumns * gridRows - snake.length ) {
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
if (grid[i][j] == 2) {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
let x = grid.length - floor(random(1, grid.length +1));
|
||||
let y = grid[0].length - floor(random(1, grid[0].length +1));
|
||||
if(grid[x][y] == 2 || grid[x][y] == 1){
|
||||
summonApple();//best practice coding right here
|
||||
return;
|
||||
}
|
||||
grid[x][y] = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function dontMoveBackwards(lastSnakeX, lastSnakeY, currentSnakeX, currentSnakeY, direction){
|
||||
if (direction == 0) {
|
||||
return lastSnakeX < currentSnakeX;
|
||||
}else if (direction == 1) {
|
||||
return lastSnakeY < currentSnakeY;
|
||||
}else if (direction == 2) {
|
||||
return lastSnakeX > currentSnakeX;
|
||||
}else if (direction == 3) {
|
||||
return lastSnakeY > currentSnakeY;
|
||||
}
|
||||
}
|
||||
|
||||
function restartGame(){
|
||||
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
|
||||
if (grid[i][j] == 2 || grid[i][j] == 1) {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snake = [];
|
||||
|
||||
summonSnake();
|
||||
|
||||
for (let i = 0; i < appleAmount; i++) {
|
||||
summonApple();
|
||||
}
|
||||
|
||||
alive = true;
|
||||
}
|
||||
|
||||
function runSnake(){
|
||||
let x = snake[0][0];
|
||||
let y = snake[0][1];
|
||||
for (let i = snake.length - 1; i > 0; i--) {
|
||||
snake[i][0] = snake[i - 1][0];
|
||||
snake[i][1] = snake[i - 1][1];
|
||||
}
|
||||
snakeAI();
|
||||
let lastSnakeX = snake[1][0]
|
||||
let lastSnakeY = snake[1][1];
|
||||
if (dontMoveBackwards(lastSnakeX, lastSnakeY, x, y, snakeDirection)) {
|
||||
snakeDirection = (snakeDirection + 2) % 4;
|
||||
}
|
||||
if (snakeDirection == 0) {
|
||||
snake[0][0] += 1;
|
||||
}else if (snakeDirection == 1) {
|
||||
snake[0][1] += 1;
|
||||
}else if (snakeDirection == 2) {
|
||||
snake[0][0] -= 1;
|
||||
}else if (snakeDirection == 3) {
|
||||
snake[0][1] -= 1;
|
||||
}
|
||||
if (snake[0][1] >= grid[0].length || snake[0][1] < 0 || snake[0][0] >= grid.length || snake[0][0] < 0) {
|
||||
alive = false;
|
||||
return;
|
||||
}
|
||||
if (grid[snake[0][0]][snake[0][1]] == 2) {
|
||||
alive = false;
|
||||
return;
|
||||
}
|
||||
if (grid[snake[0][0]][snake[0][1]] == 1) {
|
||||
snake.push([snake[snake.length - 1][0], snake[snake.length - 1][1]]);
|
||||
summonApple();
|
||||
eatenApples++;
|
||||
}
|
||||
if (
|
||||
snake.length >=
|
||||
(gridColumns * gridRows) - appleAmount
|
||||
){
|
||||
restartGame();
|
||||
return;
|
||||
}
|
||||
drawSnakeOnGrid();
|
||||
}
|
||||
|
||||
function summonSnake(){
|
||||
let x = grid.length - floor(random(1, grid.length));
|
||||
let y = grid[0].length - floor(random(1, grid[0].length));
|
||||
snake.push([x, y]);
|
||||
snake.push([x - 1, y]);
|
||||
snake.push([x - 2, y]);
|
||||
drawSnakeOnGrid();
|
||||
}
|
||||
|
||||
function drawSnakeOnGrid(){
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
if (grid[i][j] == 2) {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < snake.length; i++) {
|
||||
|
||||
let x = snake[i][0];
|
||||
let y = snake[i][1];
|
||||
|
||||
// prevent crash
|
||||
if (
|
||||
x < 0 ||
|
||||
y < 0 ||
|
||||
x >= grid.length ||
|
||||
y >= grid[0].length
|
||||
){
|
||||
alive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
grid[x][y] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
function drawGrid() {
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
switch (grid[i][j]) {
|
||||
case 1:
|
||||
strokeWeight(0)
|
||||
fill(255, 0, 0);
|
||||
circle(i*gridSize+gridSize/2, j*gridSize+gridSize/2, gridSize-2);
|
||||
break;
|
||||
case 2:
|
||||
if (i == snake[0][0] && j == snake[0][1]) {
|
||||
strokeWeight(0)
|
||||
fill(0, 233, 0);
|
||||
rect(i * gridSize, j * gridSize, gridSize, gridSize);
|
||||
fill(100, 255, 100);
|
||||
circle(i*gridSize+gridSize/2, j*gridSize+gridSize/2, gridSize-2);
|
||||
switch (snakeDirection) {
|
||||
case 0://right
|
||||
makeEye(i*gridSize+gridSize/4, j*gridSize+gridSize/4);
|
||||
makeEye(i*gridSize+gridSize/4, j*gridSize+gridSize/4*3);
|
||||
break;
|
||||
case 1://down
|
||||
makeEye(i*gridSize+gridSize/4, j*gridSize+gridSize/4);
|
||||
makeEye(i*gridSize+gridSize/4*3, j*gridSize+gridSize/4);
|
||||
break;
|
||||
case 2://left
|
||||
makeEye(i*gridSize+gridSize/4*3, j*gridSize+gridSize/4);
|
||||
makeEye(i*gridSize+gridSize/4*3, j*gridSize+gridSize/4*3);
|
||||
break;
|
||||
case 3://up
|
||||
makeEye(i*gridSize+gridSize/4, j*gridSize+gridSize/4*3);
|
||||
makeEye(i*gridSize+gridSize/4*3, j*gridSize+gridSize/4*3);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid snakeDirection: " + snakeDirection);
|
||||
break;
|
||||
}
|
||||
makeMoulth(snakeDirection,i,j);
|
||||
}else{
|
||||
const snakeIndex = getSnakePartIndex(i, j);
|
||||
if (snakeIndex == -1) {
|
||||
console.error("Snake part not found: " + i + ", " + j);
|
||||
}
|
||||
let SnakeGreen = 255-snakeIndex*10;
|
||||
let SnakeBlue = 0;
|
||||
let SnakeRed = 0;
|
||||
if (SnakeGreen < 0) {
|
||||
SnakeBlue = abs(SnakeGreen);
|
||||
}
|
||||
if (SnakeBlue > 255) {
|
||||
SnakeRed = SnakeBlue-255;
|
||||
}
|
||||
|
||||
strokeWeight(0)
|
||||
fill(SnakeRed, SnakeGreen, SnakeBlue);
|
||||
rect(i * gridSize, j * gridSize, gridSize, gridSize);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
strokeWeight(0.3)
|
||||
fill(255, 255, 255);
|
||||
rect(i * gridSize, j * gridSize, gridSize, gridSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeEye(x,y){
|
||||
if (countFreeNeighbors(snake[0][0], snake[0][1]) == 0) {
|
||||
//make dead eyes
|
||||
fill(0, 0, 0);
|
||||
strokeWeight(2);
|
||||
line(x-gridSize/16, y-gridSize/16, x+gridSize/16, y+gridSize/16);
|
||||
line(x-gridSize/16, y+gridSize/16, x+gridSize/16, y-gridSize/16);
|
||||
return;
|
||||
}
|
||||
fill(255, 255, 255);
|
||||
circle(x, y, gridSize/4);
|
||||
fill(25, 255, 25);
|
||||
circle(x, y, gridSize/8);
|
||||
fill(0, 0, 0);
|
||||
circle(x, y, gridSize/16);
|
||||
}
|
||||
function makeMoulth(direction,i,j){
|
||||
let x, y, w, h;
|
||||
fill(0, 0, 0);
|
||||
if (moulthOpenDistance >= getClosestAppleDistanceToSnake()) {
|
||||
switch (direction) {
|
||||
case 0://right
|
||||
x = gridSize*i+gridSize/16*11;
|
||||
y = gridSize*j+gridSize/2;
|
||||
w = gridSize/8*5;
|
||||
h = gridSize/4*3;
|
||||
break;
|
||||
case 1://down
|
||||
x = gridSize*i+gridSize/2;
|
||||
y = gridSize*j+gridSize/16*11;
|
||||
w = gridSize/4*3;
|
||||
h = gridSize/8*5;
|
||||
break;
|
||||
case 2://left
|
||||
x = gridSize*i+gridSize/16*5;
|
||||
y = gridSize*j+gridSize/2;
|
||||
w = gridSize/8*5;
|
||||
h = gridSize/4*3;
|
||||
break;
|
||||
case 3://up
|
||||
x = gridSize*i+gridSize/2;
|
||||
y = gridSize*j+gridSize/16*5;
|
||||
w = gridSize/4*3;
|
||||
h = gridSize/8*5;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid direction SnakeDirection: " + snakeDirection);
|
||||
break;
|
||||
|
||||
}
|
||||
ellipse(x, y, w, h)
|
||||
}else{
|
||||
switch (direction) {
|
||||
case 0://right
|
||||
x = gridSize*i+gridSize/16*13;
|
||||
y = gridSize*j+gridSize/2;
|
||||
w = gridSize/16;
|
||||
h = gridSize/4*3;
|
||||
break;
|
||||
case 1://down
|
||||
x = gridSize*i+gridSize/2;
|
||||
y = gridSize*j+gridSize/16*13;
|
||||
w = gridSize/4*3;
|
||||
h = gridSize/16;
|
||||
break;
|
||||
case 2://left
|
||||
x = gridSize*i+gridSize/16;
|
||||
y = gridSize*j+gridSize/2;
|
||||
w = gridSize/16;
|
||||
h = gridSize/4*3;
|
||||
break;
|
||||
case 3://up
|
||||
x = gridSize*i+gridSize/2;
|
||||
y = gridSize*j+gridSize/16;
|
||||
w = gridSize/4*3;
|
||||
h = gridSize/16;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid direction SnakeDirection: " + snakeDirection);
|
||||
break;
|
||||
}
|
||||
ellipse(x, y, w, h)
|
||||
}
|
||||
}
|
||||
|
||||
function getSnakePartIndex(x, y){
|
||||
for (let i = 0; i < snake.length; i++) {
|
||||
if (snake[i][0] == x && snake[i][1] == y) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
|
||||
if (alive == false){
|
||||
restartGame();
|
||||
}
|
||||
|
||||
background(255);
|
||||
|
||||
runSnake();
|
||||
drawGrid();
|
||||
|
||||
fill(0, 0, 0);
|
||||
textSize(_textSize);
|
||||
|
||||
text("₴ " + eatenApples, gridColumns * gridSize + gridSize + _textSize*3, _textSize * 1);
|
||||
text("More apples: " + appleAmount, gridColumns * gridSize + gridSize, _textSize * 2);
|
||||
|
||||
buttonAddMoreApples.html("Add more apples ₴ " + AddMoreApplesPrice);
|
||||
buttonAddMoreApples.position(gridColumns * gridSize + gridSize + _textSize*7, _textSize * 1.1);
|
||||
|
||||
text("AI Upgrades ", gridColumns * gridSize + gridSize, _textSize * 3);
|
||||
text("Better Eyes: " + eyeLevel, gridColumns * gridSize + gridSize, _textSize * 4);
|
||||
|
||||
buttonEyeUp.html("Upgrade Eyes ₴ " + eyeUpgradePrice);
|
||||
buttonEyeUp.position(gridColumns * gridSize + gridSize + _textSize*7, _textSize * 3.1);
|
||||
buttonEyeDown.html("Downgrade Eyes");
|
||||
buttonEyeDown.position(gridColumns * gridSize + gridSize + _textSize*13, _textSize * 3.1);
|
||||
|
||||
text("Better Sniffer: " + snifferLevel, gridColumns * gridSize + gridSize, _textSize * 5);
|
||||
|
||||
buttonSnifferUP.mousePressed(buttonSnifferUPPressed);
|
||||
buttonSnifferUP.html("Upgrade Sniffer ₴ " + snifferUpgradePrice);
|
||||
buttonSnifferUP.position(gridColumns * gridSize + gridSize + _textSize*8, _textSize * 4.1);
|
||||
buttonSnifferDown.html("Downgrade Sniffer");
|
||||
buttonSnifferDown.position(gridColumns * gridSize + gridSize + _textSize*14, _textSize * 4.1);
|
||||
}
|
||||
function mousePressed() {
|
||||
}
|
||||
|
||||
function snakeAI(){
|
||||
direction = floor(random(0, 4));
|
||||
count = 0;
|
||||
while (!isDirectionSafe(direction)) {
|
||||
count++;
|
||||
if (count > 20) {
|
||||
snakeDirection =0;
|
||||
return;
|
||||
}
|
||||
direction = floor(random(0, 4));
|
||||
if (sniffingDistance >= getClosestAppleDistanceToSnake()) {
|
||||
console.log("sniffing apple");
|
||||
direction = pathSnakeToPoint(getClosestApple()[0], getClosestApple()[1]);
|
||||
|
||||
}
|
||||
if (isAppleInView(snakeDirection, eyeDistance)) {
|
||||
console.log("apple in view");
|
||||
direction = snakeDirection;
|
||||
}
|
||||
}
|
||||
snakeDirection = direction;
|
||||
}
|
||||
|
||||
function directionToVector(direction){
|
||||
|
||||
switch(direction){
|
||||
case 0:
|
||||
return [1, 0];
|
||||
|
||||
case 1:
|
||||
return [0, 1];
|
||||
|
||||
case 2:
|
||||
return [-1, 0];
|
||||
|
||||
case 3:
|
||||
return [0, -1];
|
||||
}
|
||||
}
|
||||
|
||||
function pathSnakeToPoint(x,y){
|
||||
let vec = [x - snake[0][0], y - snake[0][1]];
|
||||
|
||||
if (vec[0] > 0){
|
||||
return 0;
|
||||
}else if (vec[0] < 0){
|
||||
return 2;
|
||||
}else if (vec[1] > 0){
|
||||
return 1;
|
||||
}else if (vec[1] < 0){
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
function isDirectionSafe(direction){
|
||||
|
||||
let vec = directionToVector(direction);
|
||||
|
||||
let newX = snake[0][0] + vec[0];
|
||||
let newY = snake[0][1] + vec[1];
|
||||
|
||||
if (
|
||||
newX < 0 ||
|
||||
newY < 0 ||
|
||||
newX >= grid.length ||
|
||||
newY >= grid[0].length
|
||||
){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (grid[newX][newY] == 2){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function getClosestApple(){
|
||||
|
||||
let bestApple = null;
|
||||
let bestDistance = Infinity;
|
||||
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
|
||||
if (grid[i][j] == 1){
|
||||
|
||||
let distance =
|
||||
abs(snake[0][0] - i) +
|
||||
abs(snake[0][1] - j);
|
||||
|
||||
if (distance < bestDistance){
|
||||
bestDistance = distance;
|
||||
bestApple = [i, j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestApple;
|
||||
}
|
||||
|
||||
function getClosestAppleDistanceToPoint(x, y){
|
||||
let apple = getClosestApple();
|
||||
if (apple == null){
|
||||
return Infinity;
|
||||
}
|
||||
return abs(x - apple[0]) + abs(y - apple[1]);
|
||||
}
|
||||
|
||||
function getClosestAppleDistanceToSnake(){
|
||||
return getClosestAppleDistanceToPoint(snake[0][0], snake[0][1]);
|
||||
}
|
||||
|
||||
function isAppleInView(snakeDirection, viewDistance){
|
||||
|
||||
let vec = directionToVector(snakeDirection);
|
||||
|
||||
for (let i = 0; i < viewDistance; i++) {
|
||||
if (i >= grid.length || i >= grid[0].length|| snake[0][0]+(vec[0] *i) >= grid.length || snake[0][0]+(vec[0] *i) < 0 || snake[0][1]+(vec[1] *i) >= grid[0].length || snake[0][1]+(vec[1] *i) < 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (grid[snake[0][0] + (vec[0] * i)][snake[0][1] + (vec[1] * i)] == 1){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function countFreeNeighbors(x, y){
|
||||
|
||||
let count = 0;
|
||||
|
||||
let dirs = [
|
||||
[1,0],
|
||||
[0,1],
|
||||
[-1,0],
|
||||
[0,-1]
|
||||
];
|
||||
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
|
||||
let nx = x + dirs[i][0];
|
||||
let ny = y + dirs[i][1];
|
||||
|
||||
if (
|
||||
nx >= 0 &&
|
||||
ny >= 0 &&
|
||||
nx < grid.length &&
|
||||
ny < grid[0].length &&
|
||||
grid[nx][ny] != 2
|
||||
){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
Reference in New Issue
Block a user