Weird Snake behavior
Posted: Mon Jun 18, 2018 5:43 pm
Hi, its me again. This time I have some problems with game logic. Its a snake-type game, when you move, you paint floor with blue-ish color.
The problem is that when snake direction is "top" or "left" everything is ok, painting is smooth. But when snake is facing "right" or "down" firstly head of the snake moves to desired destination and only then floor is painted. It causes some breaks in snake body. I do not know how to fix it. I tried many solutions but they were no right solutions at all.
Function that is responsible for this logic is Game:update(dt). snake.realX and snake.realY are real pixel coordinates. snake.newX and snake.newY are grid based coordinates. snake.x and snake.y are coordinates from last snake position. Im checking if snake[1].newX or snake[1].newY is different from old coordinates. If it is Im creating snake object at old coordinates and setting old coordinates to new coordinates. But unfortunately it is not working. And I dont see where is the logic error.
If you can tell me how to make floor painting smooth in every direction I would very appreciate it.
main.lua
snake.lua
game.lua
tile.lua (probably not needed here, but whatever)
Project is using classic.lua library and it is attached to the post. Thank you in advance :>
The problem is that when snake direction is "top" or "left" everything is ok, painting is smooth. But when snake is facing "right" or "down" firstly head of the snake moves to desired destination and only then floor is painted. It causes some breaks in snake body. I do not know how to fix it. I tried many solutions but they were no right solutions at all.
Function that is responsible for this logic is Game:update(dt). snake.realX and snake.realY are real pixel coordinates. snake.newX and snake.newY are grid based coordinates. snake.x and snake.y are coordinates from last snake position. Im checking if snake[1].newX or snake[1].newY is different from old coordinates. If it is Im creating snake object at old coordinates and setting old coordinates to new coordinates. But unfortunately it is not working. And I dont see where is the logic error.
If you can tell me how to make floor painting smooth in every direction I would very appreciate it.
main.lua
Code: Select all
Object = require "classic"
require "game"
WINDOW_WIDTH = 960
WINDOW_HEIGHT = 640
function love.load()
-- window
love.window.setMode(WINDOW_WIDTH, WINDOW_HEIGHT, {vsync = true, resizable = false, fullscreen = false})
love.window.setTitle("Snake Expansion")
love.graphics.setDefaultFilter('nearest', 'nearest')
-- sounds
winSound = love.audio.newSource("win.wav", "static")
menuSound = love.audio.newSource("menu.wav", "static")
moveSound = love.audio.newSource("move.wav", "static")
itemSound = love.audio.newSource("item.wav", "static")
collisionSound = love.audio.newSource("collision.wav", "static")
-- graphics
background = love.graphics.newImage("background.png")
ring = love.graphics.newImage("ring.png")
smallFont = love.graphics.newFont("liquid.ttf", 30)
normalFont = love.graphics.newFont("liquid.ttf", 40)
bigFont = love.graphics.newFont("liquid.ttf", 50)
wallTile = love.graphics.newImage("wall.png")
floorTile = love.graphics.newImage("floor.png")
-- varibles
angle = 0
gameState = "start"
titleVisible = 0
end
function love.update(dt)
angle = angle + (2 * dt)
if gameState == "start" then
titleVisible = math.min(255, titleVisible + (100 * dt))
end
if titleVisible >= 255 and gameState == "start" then
gameState = "menu"
end
if gameState == "play" then
game:update(dt)
end
end
function love.mousepressed(mouseX, mouseY, button, isTouch)
if button == 1 and gameState == "menu" then
if mouseX > WINDOW_WIDTH/2 - 100 and mouseX < WINDOW_WIDTH/2 + 100 and mouseY > WINDOW_HEIGHT/2 and mouseY < WINDOW_HEIGHT/2 + 50 then
print("Play clicked")
game = Game(1)
gameState = "play"
end
if mouseX > WINDOW_WIDTH/2 - 100 and mouseX < WINDOW_WIDTH/2 + 100 and mouseY > WINDOW_HEIGHT/2 + 100 and mouseY < WINDOW_HEIGHT/2 + 150 then
print("Options clicked")
gameState = "options"
end
if mouseX > WINDOW_WIDTH/2 - 100 and mouseX < WINDOW_WIDTH/2 + 100 and mouseY > WINDOW_HEIGHT/2 + 200 and mouseY < WINDOW_HEIGHT/2 + 250 then
print("Exit clicked")
love.event.quit()
end
end
end
function love.draw()
love.graphics.setColor(255,255,255,255)
love.graphics.draw(background, 0, 0)
love.graphics.setColor(255,255,255,100)
love.graphics.setBlendMode("add")
love.graphics.draw(ring, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, angle, 1, 1, 100, 100)
love.graphics.setBlendMode("alpha")
if gameState == "start" or gameState == "menu" then
love.graphics.setFont(bigFont)
love.graphics.setColor(255,0,255,titleVisible)
love.graphics.printf("Snake Expansion", 0, WINDOW_HEIGHT/4, WINDOW_WIDTH, "center")
love.graphics.setFont(normalFont)
love.graphics.printf("Play", 0, WINDOW_HEIGHT/2, WINDOW_WIDTH, "center")
love.graphics.printf("Options", 0, WINDOW_HEIGHT/2 + 100, WINDOW_WIDTH, "center")
love.graphics.printf("Exit", 0, WINDOW_HEIGHT/2 + 200, WINDOW_WIDTH, "center")
end
love.graphics.setColor(255, 255, 255, 255)
if gameState == "play" then
game:draw()
end
end
Code: Select all
Snake = Object:extend()
segmentsCount = 0
dir = 2
function Snake:new(x, y, speed)
self.speed = speed or 0
segmentsCount = segmentsCount + 1
self.x = x
self.y = y
self.width = 32
self.height = 32
self.realX = self.x * 32
self.realY = self.y * 32
end
function Snake:collision(object)
if self.x > object.x and self.x + self.width < object.x and self.y > object.y and self.y + self.height < object.y then
return true
else
return false
end
end
function Snake:update(dt)
if self.speed ~= 0 then
if dir == 1 then
self.realY = self.realY - self.speed * dt
elseif dir == 2 then
self.realX = self.realX + self.speed * dt
elseif dir == 3 then
self.realY = self.realY + self.speed * dt
elseif dir == 4 then
self.realX = self.realX - self.speed * dt
end
end
end
function Snake:draw()
love.graphics.rectangle("fill", self.realX, self.realY, self.width, self.height)
end
Code: Select all
require "snake"
require "tile"
Game = Object:extend()
map = {}
objects = {}
snake = {}
direction = 2
local canMove = true
function Game:new(level)
self.level = level
snake = {}
self.loadMap(self)
self.visible = 0
end
function Game:loadMap()
-- loading level from file
for line in love.filesystem.lines("level" .. tostring(self.level) .. ".lst") do
table.insert(map, line)
end
-- instantiate objects on map
for index, str in ipairs(map) do
for i = 1, #str do
local letter = str:sub(i, i)
if letter == "X" then
table.insert(objects, Tile(i, index, "wall"))
elseif letter == "S" then
table.insert(objects, Tile(i, index, "floor"))
snake[1] = Snake(i, index, 10)
elseif letter == "_" then
table.insert(objects, Tile(i, index, "floor"))
end
end
end
end
function Game:update(dt)
self.visible = math.min(255, self.visible + 100 * dt)
if canMove == false and math.floor(snake[1].realX) % 32 == 0 and math.floor(snake[1].realY) % 32 == 0 then
dir = direction
canMove = true
end
snake[1]:update(dt)
snake[1].newX = math.floor(math.floor(snake[1].realX)/32)
snake[1].newY = math.floor(math.floor(snake[1].realY)/32)
if snake[1].newX ~= snake[1].x or snake[1].newY ~= snake[1].y then
table.insert(snake, 2, Snake(snake[1].x, snake[1].y))
snake[1].x = snake[1].newX
snake[1].y = snake[1].newY
end
end
function love.keypressed(key)
-- adding change direction to the queqe
if key == "left" and canMove == true then
if direction == 1 then
direction = 4
else
direction = direction - 1
end
canMove = false
elseif key == "right" and canMove == true then
if direction == 4 then
direction = 1
else
direction = direction + 1
end
canMove = false
end
end
function Game:draw()
love.graphics.setColor(255,255,255,255)
for i, v in ipairs(objects) do
v:draw()
end
colorChange = 255/#snake * 0.5
for i = #snake, 1, -1 do
love.graphics.setColor(colorChange * (i - 1), colorChange * (i - 1), 255, 255)
snake[i]:draw()
end
love.graphics.setColor(255,0,255,self.visible)
love.graphics.setFont(normalFont)
love.graphics.printf("Level: " .. self.level, 0, 50, WINDOW_WIDTH, "center")
love.graphics.setColor(255,255,255,255)
--print("Snake newx: " .. snake[1].newX)
--print("Snake newy: " .. snake[1].newY)
--print("Snake x: " .. snake[1].x)
--print("Snake y: " .. snake[1].y)
end
Code: Select all
Tile = Object:extend()
function Tile:new(x, y, typeof)
self.x = x
self.y = y
self.tileType = typeof
end
function Tile:update(dt)
end
function Tile:draw()
if self.tileType == "wall" then
love.graphics.draw(wallTile, self.x * 32, self.y * 32)
elseif self.tileType == "floor" then
love.graphics.draw(floorTile, self.x * 32, self.y * 32)
end
end