Help implementing game logic from fish fillets

General discussion about LÖVE, Lua, game development, puns, and unicorns.
glitchapp
Party member
Posts: 264
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: Help implementing game logic from fish fillets

Post by glitchapp »

darkfrei wrote: Wed Feb 09, 2022 8:47 pm Here:

Code: Select all

-- this is the new code in which players move inside the grid, I am trying to insert the collisions above in this new code:
		if moves =="right" then
			self.agent.tx = self.agent.tx + dt*self.agent.vx
Why you move the agent without any checking?

Maybe the better solution:

Code: Select all

local dx, dy = 0, 0
if move = "right" then
	dx = dt*self.agent.vx -- horizontal speed
elseif move = "left" then
	dx = -dt*self.agent.vx  -- minus horizontal speed
if move = "down" then
	dy = dt*self.agent.vy -- some vertical speed
elseif move = "up" then
	dy = -dt*self.agent.vy  -- minus some (or another) vertical speed
end
local canMove, blocks = canAgentMoveAndMovedBlocks (dx, dy) -- returns boolean if agent and collinding blocks are movable and list of blocks to move
if canMove then
	dx, dy = moveAgent(dx, dy) -- move agent and change dx, dy if you need
	moveBlocks(blocks, dx, dy)
else
	-- change agent and blocks as stuck if you need
end
Hei thanks again for the help! I feel I'm very close to the solution, however when I use your code I get the following error: "Error: game/logic/push-blocks.lua:380: attempt to call global 'canAgentMoveAndMovedBlocks' (a nil value)"

I try to understand what all the variables means inside the code, but I'm struggling to see why that variable does get nil (no value). I think dy is related to vertical speed which in the pb.agent is written as "vup". I'm very confused sorry, I need time to understand and make this work.

moveAgent(dx,dy) does not exist in your library, should I make a new function? I don't understand
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Re: Help implementing game logic from fish fillets

Post by darkfrei »

glitchapp wrote: Wed Feb 09, 2022 9:36 pm I try to understand what all the variables means inside the code, but I'm struggling to see why that variable does get nil (no value). I think dy is related to vertical speed which in the pb.agent is written as "vup". I'm very confused sorry, I need time to understand and make this work.
Main structure:
Tile - the square 1x1 units, where unit is the grid size, for example 1920x1080 is a field with 48x27 tiles with size of 40 pixels. The grid size must be not used as main measure unit, but the tile.

Block - the movable (theoretically) element, that has one or more tiles.
Every block has position (tx, ty with tile units) and array of tiles as:

Code: Select all

blockForm = { -- L-block, 2 tiles wide and 3 tiles tall
	{1, 0},
	{1, 0},
	{1, 1},
}
Actually such L-block form must be parsed to the array:

Code: Select all

blockTiles = {0,0, 0,1, 0,2, 1,2} -- yes, the tile blockForm[1][1] has position 0,0

Code: Select all

-- other tiles are calles as blockForm[y][x] (y and x for rows and columns):
blockTiles = {}
tw, th = 0, 0 -- the width and height in tiles
for y, xs in ipairs (blockForm) do
	for x, value in ipairs (xs) do
		if value == 1 then
			table.insert (blockTiles , x-1) -- beware of -1
			table.insert (blockTiles , y-1)
			if tw < x then tw = x end
			if th < y then th = y end
		end
	end
end
Also this block has tw = 2 and th=3 - the width and height in tiles.

The agent is a such block too, but that has maximal velocity (as tiles per second), also it's maximal velocity can be defined separately for each direction (but no necessary). For example vx is horizontal speed and vdown and vup for positive and negative vertical speeds. Or you can just set it as vmax and use just it.
The current velocity respects the dt (delta time of this step of movement) and corresponding maximal velocity of this agent.
Normally the movement is just

Code: Select all

x, y = x+dx, y+dy
where the dx is horizontal movement and dy is a vertical movement in this delta of time:

Code: Select all

 -- if vx and vy are same as vmax
dx = (move == "right") and (dt*vmax) or (move == "left") and (-dt*vmax) or 0
dy = (move == "down") and (dt*vmax) or (move == "up") and (-dt*vmax) or 0
or

Code: Select all

-- if vertical speeds are same:
dx = (move == "right") and (dt*vx) or (move == "left") and (-dt*vx) or 0
dy = (move == "down") and (dt*vy) or (move == "up") and (-dt*vy) or 0
or

Code: Select all

-- if positive and negative vertical speeds are not same:
dx = (move == "right") and (dt*vx) or (move == "left") and (-dt*vx) or 0
dy = (move == "down") and (dt*vdown) or (move == "up") and (-dt*vup ) or 0
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
glitchapp
Party member
Posts: 264
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: Help implementing game logic from fish fillets

Post by glitchapp »

Hei, thanks again! you are helping me solve the hardest problem of my game: collisions
The actual code for the blocks is this:

Code: Select all

function pb:drawBlocks ()
	love.graphics.setLineWidth(2)
	
	local tileSize = self.grigSize
	for i, block in ipairs (self.blocks) do
		local btx = block.tx
		local bty = block.ty 
		love.graphics.setColor(block.color)
		for ty, txs in ipairs (block.form) do
			for tx, value in ipairs (txs) do
				if value == 1 then
					love.graphics.rectangle ('fill', (btx+tx)*tileSize, (bty+ty)*tileSize, tileSize, tileSize)
			
				end
			end
		end
	end
end
This the actual table with its parameters for a chair:

Code: Select all

pb.blocks = {
	{	
		tx = 6,  -- position horizontal position in tiles
		ty = 16,
		name = 'chair1',
		form = {
			--{1,1,1}, -- y=1
			--{0,1,0}, -- y=2
			--{0,1,0}, -- y=3
			{1,0,0,0},
			{1,0,0,0},
			{1,1,1,1},
			{1,0,0,1},
			{1,0,0,1},
		},
		sizeX = 4,
		sizeY = 5,
		w = 4,
		h = 5,
		movable = true,
		color = yellow,
	},
This is the agent:

Code: Select all

pb.agent = {
	tx = 19, -- position horizontal position in tiles
	ty = 13,
	x = 19*pb.grigSize, -- smooth position
	y = 13*pb.grigSize, -- smooth position
	vx = 8, -- horizontal speed, tiles per second
	vup = 8,
	vdown = 8,
	form = {
		{1,1,1},
		{1,1,1},
	},
	w = 3,
	h = 2,
}
I don't want to make an answer so long but I need to know the actual name of the variables, so now that I have the actual name of the variables I can try to implement your code, I will do something like this:
local dx, dy = 0, 0

if up and not (down or right or left) then
moves = "up"
targetY = self.agent.ty - 1

elseif down and not (up or right or left) then
moves = "down"
targetY = self.agent.ty + 1

elseif right and not (up or down or left) then
moves = "right"
targetX = self.agent.tx + 1

elseif left and not (up or down or right) then
moves = "left"
targetX = self.agent.tx - 1
end
end
I want that the agent keeps staying inside the grid, therefore I keep using targetX and targetY. I tried all of this:

Code: Select all

dx, dy = moveAgent(dx, dy) -- move agent and change dx, dy if you need
dx, dy = moveAgent(targetX, targetY)
targetX, targetY = moveAgent(targetX, targetY)
error: game/logic/push-blocks.lua:427: attempt to call global "moveAgent" (a nil value)

I realize moveAgent does not exist as a function. Should I create a new function for that or use a function inside your code which have another name?

Sorry, it may be obvious to someone else, but I'm really bad at reading the code of others specially if there are so many functions and variables. If someone understands what I actually need to do please let me know! And thank you darkfree for all this help! I'm really bad at coding game logic and I could not solve such complex problems without your collisions code!

Just in case someone new read this thread: what we are trying to accomplish is making collisions work as it did with the old code but at the same time making the player move just one cell at a time. I managed to solve both problems but I can't make them work simultaneously. The original collisions code from darkfrei let the agent move freely and that breaks the puzzle because is a sokoban game and I don't want the pieces of the puzzle to stay between cells.
Attachments
luasok.love
(444.48 KiB) Downloaded 147 times
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Re: Help implementing game logic from fish fillets

Post by darkfrei »

Yes, I need to write where is the actual code and where is the placeholder code.

We can make the game like in the first version of FF. All movements are ultra fast, the fish jumps to the next cell without any between positions, such movement is much easier.

Placeholder code (calling not existing functions that we are need to make):

Code: Select all

function love.keypressed( key, scancode, isrepeat )
	local dx, dy = 0, 0
	if scancode == "d" then -- move right
		dx = 1
	elseif scancode == "a" then -- move left
 		dx = -1
	elseif scancode == "s" then -- move down
		dy = 1
	elseif scancode == "w" then -- move up
		dy = -1
	end
	if canMove (dx, dy) then  -- need to be some function to check if the active object has this freedom
		move (dx, dy) -- need to be some function to move the active object
	end
end
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
glitchapp
Party member
Posts: 264
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: Help implementing game logic from fish fillets

Post by glitchapp »

darkfrei wrote: Fri Feb 11, 2022 8:32 am Yes, I need to write where is the actual code and where is the placeholder code.

We can make the game like in the first version of FF. All movements are ultra fast, the fish jumps to the next cell without any between positions, such movement is much easier.

Placeholder code (calling not existing functions that we are need to make):

Code: Select all

function love.keypressed( key, scancode, isrepeat )
	local dx, dy = 0, 0
	if scancode == "d" then -- move right
		dx = 1
	elseif scancode == "a" then -- move left
 		dx = -1
	elseif scancode == "s" then -- move down
		dy = 1
	elseif scancode == "w" then -- move up
		dy = -1
	end
	if canMove (dx, dy) then  -- need to be some function to check if the active object has this freedom
		move (dx, dy) -- need to be some function to move the active object
	end
end
I agree with you, the most important thing is that the game is playable, after that it can be improved 1000 times.

I'm laughing now, this is taking me much time than I thought it should... sorry I'm like a computer, I don't understand implicit statements, not that I want you to write me the code, but that move (dx,dy) does not exist and I need to know what that function should look like. I will take a break and come back at it ok?

Thanks again for the help, I can't solve this problem alone!
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Re: Help implementing game logic from fish fillets

Post by darkfrei »

glitchapp wrote: Fri Feb 11, 2022 9:07 am I agree with you, the most important thing is that the game is playable, after that it can be improved 1000 times.

I'm laughing now, this is taking me much time than I thought it should... sorry I'm like a computer, I don't understand implicit statements, not that I want you to write me the code, but that move (dx,dy) does not exist and I need to know what that function should look like. I will take a break and come back at it ok?

Thanks again for the help, I can't solve this problem alone!
dx and dy are just delta x and delta y - the length (sign is direction) of step.

The simplest move (dx, dy) is:

Code: Select all

function move (dx, dy)
	x = x + dx -- some global x
	y = y + dy -- some global y
end
so if dx was 1, then x will be 1 higher; if dx was -1 (minus one) then x will be one less than before. Here 1 is a unit, for example one tile.


Here can be the agent.x and agent.y or block.x, block.y:

Code: Select all

function moveAgent (dx, dy) -- global defined agent
	agent.x = agent.x + dx
	agent.y = agent.y + dy
end

Code: Select all

function moveBlock (block, dx, dy) -- exactly this block
	block.x = block.x + dx
	block.y = block.y + dy
end
Last edited by darkfrei on Fri Feb 11, 2022 10:47 am, edited 2 times in total.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
glitchapp
Party member
Posts: 264
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: Help implementing game logic from fish fillets

Post by glitchapp »

Code: Select all

function moveAgent (dx, dy) -- global defined agent
	agent.x = self.agent.tx + dx
	--agent.y = self.agent.ty + dy
end

--function moveBlock (block, dx, dy) -- exactly this block
	--block.x = block.x + dx
	--block.y = block.y + dy
--end
function pb:updateAgents (dt)

if problemdebug=="1" then
	if not moves then
		local up =    love.keyboard.isScancodeDown('up')
		local down =  love.keyboard.isScancodeDown('down')
		local right =  love.keyboard.isScancodeDown('right')
		local left =  love.keyboard.isScancodeDown('left')

		local dx, dy = 0, 0
		
		if up and not (down or right or left) then
			moves = "up"
			targetY = self.agent.ty - 1
		elseif down and not (up or right or left) then
			moves = "down"
			targetY = self.agent.ty + 1
		elseif right and not (up or down or left) then
			moves = "right"
			--targetX = self.agent.tx + 1
		elseif left and not (up or down or right) then
			moves = "left"
			targetX = self.agent.tx - 1
		end
	end

	-- need to move in this tick too
		local tdx = dt*self.agent.vx -- delta X in tiles
		local tdy = - dt*self.agent.vup -- delta Y in tiles
		local canMove, block = pb:canMove (self.agent, tdx, 0)

		if moves =="right"  then
			self.agent.tx = self.agent.tx + dt*self.agent.vx
				if canMove then
						--if self.agent.tx >= targetX then
							--self.agent.tx = targetX
							moveAgent (agent.x,agent.y)
							moves = false
						--end
				elseif block and block.movable then
						if self.agent.tx >= targetX then
							self.agent.tx = targetX
							moves = false
						local tx = self.agent.tx
							--self.agent.tx = targetX
							block.tx = targetX+1
							moves = false
						end
				end
Error: game/logic/push-blocks.lua:399: attempt to index global 'agent' (a nil value)

I'm obfuscated now and I need a break, I leave the code here and attached the file and I'll be back to it later. I think that agent.x is a new variable and need to be declared first but I can't see the problem right now.
Attachments
luasok.love
(444.35 KiB) Downloaded 129 times
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Re: Help implementing game logic from fish fillets

Post by darkfrei »

glitchapp wrote: Fri Feb 11, 2022 10:03 am Error: game/logic/push-blocks.lua:399: attempt to index global 'agent' (a nil value)

I'm obfuscated now and I need a break, I leave the code here and attached the file and I'll be back to it later. I think that agent.x is a new variable and need to be declared first but I can't see the problem right now.
Please see this easy code:
Here is an agent with just 1 tile size, that cannot go where it already was.
Easy map collision detection, easy movement input.

Press WASD to move
2022-02-11T11_34_52-Untitled.png
2022-02-11T11_34_52-Untitled.png (7.09 KiB) Viewed 4354 times
Attachments
tile-moving-01.love
CC0 - Creative Commons
(811 Bytes) Downloaded 126 times
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
glitchapp
Party member
Posts: 264
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: Help implementing game logic from fish fillets

Post by glitchapp »

Code: Select all

function moveAgent (dx, dy) -- global defined agent
	local x = agent.x
	local y = agent.y
		-- real changing of the agent's position:
		agent.x = x + dx
		agent.y = y + dy
end

--function moveBlock (block, dx, dy) -- exactly this block
	--block.x = block.x + dx
	--block.y = block.y + dy
--end
	
function pb:updateAgents (dt)

if problemdebug=="1" then
	if not moves then
		local right =  love.keyboard.isScancodeDown('right')

		local dx, dy = 0, 0
		
		if right and not (up or down or left) then
			--moves = "right"
			--targetX = self.agent.tx + 1
			dx=1
		end
	end

	-- need to move in this tick too
		local tdx = dt*self.agent.vx -- delta X in tiles
		local tdy = - dt*self.agent.vup -- delta Y in tiles
		local canMove, block = pb:canMove (self.agent, tdx, 0)

		if canMove then
		moveAgent (dx, dy)
		end
Error: game/logic/push-blocks.lua:354: attempt to index global 'agent' (a nil value)

This is what is causing the error: local canMove, block = pb:canMove (self.agent, tdx, 0)
I don't know why
User avatar
dusoft
Party member
Posts: 654
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Help implementing game logic from fish fillets

Post by dusoft »

If the agent is globally defined, then there is no need to use self.agent ...
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 11 guests