Help needed. I have programmed almost a year and more then half of the time i have done in C# (programs), for school project i am doing HTML, CSS & JavaScript (mainly) Snake game. Where i need to add different objects to eat to get different values. I have transparent pictures for these berries (raspberry, blackberry, gooseberry that i need to add in game instead of colored tiles (is it possible?).
Main game itself is fully ready and working when eating Food i get +1 for snake (that value i can change how i wish). Now i need to add new berries (raspberry, blackberry, gooseberry). When eating RASPBERRY it should make my snake smaller by 5 units or up to the head (ex: if snake is only 3 grids long and i eat raspberry then i cannot go to -2 but instead going to 1 aka the head of snake. But when snake is 20 grids long and You eat raspberry you lose 5 grids and then your snake will be 15 grids long. With berry random re-spawn delay 20 seconds after eating). Blackberry and gooseberry both of them are for speed. Normal snake speed is 2 moves per second. Eating blackberry will increase speed to 5 moves per second that last for 30 second and re-spawn of blackberry is 1 minute. Eating gooseberry will decrease speed 4x (snake speed should be 0,5 moves per second) and last 1,5 minute, re-spawn of gooseberry 3 minutes. Also for the code there must be spawn location so that it won't spawn on snake or any of the food/berries (in below code there is function so that food won't spawn on top of snake).
As i have already learned programming almost a year, i know that there is for/while loop needed for berry actions, but i am not so good programmer (jet) to write it my own. I have looked for that info whole day but cannot find solution for the for loop.
Is there any nice person who could help me with this for loop request? I am using type=modul for JavaScript. Also every element have it's own JS file (game.js, input.js (arrowkeys), grid.js, snake.js, food.js as well as future codes raspberry.js, blackberry.js, gooseberry.js). Also each berry would need it's own JS file. My food.js code for the game.
food.js
import { onSnake, expandSnake } from './snake.js'
import { randomGridPosition } from './grid.js'
let food = getRandomFoodPosition() //food location, must be grid numbers, and in CSS always starts from 1, not 0! Use { x: umber, y: number } if you want specific location food to come
const EXPANSION_RATE = 1 //how much snake grows after eating food
export function update()
{ //checking if snake is over the food
if (onSnake(food))
{
expandSnake(EXPANSION_RATE)
food = getRandomFoodPosition() //this is new food spawn with random location, but not on top of snake
}
}
export function draw(gameBoard)
{ //draw(gameBoard) means it will draw food on gameboard
const foodElement = document.createElement('div')
foodElement.style.gridRowStart = food.y //vertical location
foodElement.style.gridColumnStart = food.x //horizontal location
foodElement.classList.add('food')
gameBoard.appendChild(foodElement)
}
//randomizing food location and not on top of snake
function getRandomFoodPosition()
{
let newFoodPosition
while (newFoodPosition == null || onSnake(newFoodPosition))
{
newFoodPosition = randomGridPosition()
}
return newFoodPosition
}
EDIT: i added raspberry.js and also snake.js below
raspberry.js
import { onSnake, decreaseSnake } from './snake.js'
import { randomGridPosition } from './grid.js'
let raspberry = getRandomRaspberryPosition() //food location, must be grid numbers, and in CSS always starts from 1, not 0! Use { x: umber, y: number } if you want specific location food to come
const DECREASING_RATE = 1 //how much snake decreases after eating food
export function update()
{ //checking if snake is over the food
if (onSnake(raspberry))
{
decreaseSnake(DECREASING_RATE)
raspberry = getRandomRaspberryPosition() //this is new food spawn with random location, but not on top of snake
}
}
export function draw(gameBoard)
{ //draw(gameBoard) means it will draw food on gameboard
const raspberryElement = document.createElement('div')
raspberryElement.style.gridRowStart = raspberry.y //vertical location
raspberryElement.style.gridColumnStart = raspberry.x //horizontal location
raspberryElement.classList.add('raspberry')
gameBoard.appendChild(raspberryElement)
}
//randomizing food location and not on top of snake
function getRandomRaspberryPosition()
{
let newRaspberryPosition
while (newRaspberryPosition == null || onSnake(newRaspberryPosition))
{
newRaspberryPosition = randomGridPosition()
}
return newRaspberryPosition
}
snake.js
// all the codes for snake goes in this JS file
import { getInputDirection } from "./input.js"
export const SNAKE_SPEED = 5 //snake speed. Moves per second
const snakeBody = [{ x: 13, y: 13 }] //snake location when starting game on grid (current grid size is 25 x 25)
let newSegments = 0
let negSegments = 0
export function update()
{
addSegments(), removeSegments()
const inputDirection = getInputDirection()
for (let i = snakeBody.length - 2; i >= 0; i--)
{
snakeBody[i + 1] = { ...snakeBody[i] }
}
snakeBody[0].x += inputDirection.x
snakeBody[0].y += inputDirection.y
}
export function draw(gameBoard)
{ //gameboard for draw means it will draw snake on gameboard
snakeBody.forEach(segment =>
{ //drawing snake inside gameboard
const snakeElement = document.createElement('div')
snakeElement.style.gridRowStart = segment.y
snakeElement.style.gridColumnStart = segment.x
snakeElement.classList.add('snake')
gameBoard.appendChild(snakeElement)
})
}
export function expandSnake(amount)
{
newSegments += amount
}
export function decreaseSnake(amount)
{
negSegments -= amount
}
export function onSnake(position, { ignoreHead = false } = {})
{
return snakeBody.some((segment, index) =>
{
if (ignoreHead && index === 0) return false
return equalPositions(segment, position)
})
}
export function getSnakeHead()
{
return snakeBody[0]
}
export function snakeIntersection()
{
return onSnake(snakeBody[0], { ignoreHead: true })
}
function equalPositions(pos1, pos2)
{
return pos1.x === pos2.x && pos1.y === pos2.y
}
function addSegments()
{
for (let i = 0; i < newSegments; i++) {
snakeBody.push({ ...snakeBody[snakeBody.length - 1] })
}
newSegments = 0 //stops adding new elements on snake otherwise it will grow nonstop from the first eaten food
}
function removeSegments()
{
for (let i = 0; i < negSegments; i++) { //reversed < and ++
snakeBody.pop({ ...snakeBody[snakeBody.length - 1] }) //reversed push to pop in this line atm
}
negSegments = 0
}