Template for using Löve as if it were not event-oriented

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
pgimeno
Party member
Posts: 2211
Joined: Sun Oct 18, 2015 2:58 pm

Template for using Löve as if it were not event-oriented

Post by pgimeno » Sat Sep 21, 2019 10:11 am

Inspired by this question from forum user neku: https://love2d.org/forums/viewtopic.php ... 84#p220884 I've written a template that allows using Löve for, e.g., visualizing algorithms without needing to interrupt them. It is based on hump.timer's timer.script function, which internally uses a coroutine. Grab the timer module from the hump suite here: https://github.com/vrld/hump

The program will run without displaying anything until you use the sleep() global function. If you want to update the display without pausing, use sleep(0).

The code to run can be placed in a file called mycode.lua, or passed as an argument in the command line. The files you need from this project are main.lua and conf.lua.

This makes your code work in a similar fashion to that of PyGame and similar. It uses 255 for colour values because that way, it is compatible with all versions of LÖVE starting with 0.9, without losing compatibility with 11.0+.

The code is now in a NotABug repository: https://notabug.org/pgimeno/alg-visualizer. It is public domain. Full documentation is in README.md. The examples are also in the repository.

Update March 31, 2020: Basically rewritten to cover all events instead of just keys and a timer. Backward compatibility is not kept; the ESC key no longer terminates the program by default. waitkey() is now gone - use wait.keypressed() instead. sleep() now only waits; there is a new function called pause(), similar to sleep() but it also resumes on a key or mouse button, and if the key is ESC, terminates the program.
Last edited by pgimeno on Tue Mar 31, 2020 9:07 pm, edited 8 times in total.

User avatar
pgimeno
Party member
Posts: 2211
Joined: Sun Oct 18, 2015 2:58 pm

Template for using Löve as if it were not event-oriented

Post by pgimeno » Sat Sep 21, 2019 10:12 am

(deleted - see repository for demos)
Last edited by pgimeno on Tue Mar 31, 2020 9:07 pm, edited 1 time in total.

User avatar
ivan
Party member
Posts: 1564
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Template for using Löve as if it were not event-oriented

Post by ivan » Sat Sep 21, 2019 11:03 am

Pretty cool. I have though about doing algorithm visualizations but it's hard to generalize that sort of thing and there's not much use for it apart from looking cool.
Nice result although the nested "for" loops are atrocious. :)

neku
Prole
Posts: 12
Joined: Thu May 17, 2018 3:07 pm

Re: Template for using Löve as if it were not event-oriented

Post by neku » Sat Sep 21, 2019 8:18 pm

That's great!
and atrocious nested "for" loops?
well - who can do it better?
;)
Thank you very much.

User avatar
Roland Chastain
Prole
Posts: 29
Joined: Sat Feb 07, 2015 2:30 pm
Location: France
Contact:

Re: Template for using Löve as if it were not event-oriented

Post by Roland Chastain » Mon Sep 23, 2019 7:04 am

Very interesting. Thank you for sharing.

neku
Prole
Posts: 12
Joined: Thu May 17, 2018 3:07 pm

Re: Template for using Löve as if it were not event-oriented

Post by neku » Thu Sep 26, 2019 1:50 pm

It's any time a go..
after I have (due to carelessness in the zerobrane) overwrited an already functioning version of the "knigt's tour" (with some test) I was so frustrated that I switched to corona sdk. well, the other (maybe the first) reason was "delay". I managed not (even with HUMP not) to slow down the jump animation.
I succeeded in corona (and knigt's tour) quickly so I stayed with corona. in my next project (maze generator & solver) I walked (at the way back from end to start) in a problem and sought help. I found that by pedro gimeno: technically competent and human a gigant. for me a not everyday experience.
Thanks a lot Pedro.

maze main-code:

Code: Select all

-------------------------------------------------------------------------
-- main.lua  	v.5f	(after: pgimeno)
-------------------------------------------------------------------------
--[[
 concept of:
 Python maze generator program (using PyGame for animation)
 Davis MT
 Python 3.4
 10.02.2018
 video with explanations of the original py program:
 https://www.youtube.com/watch?v=Xthh4SEMA2o
 ]]
-- ----------------------------------------------------------------------

this can be combined with the program "queens" mentioned above (by pgimeno).
(I have to search first how I can attach the zip ..)
-- globals:
w = 17					-- field side (17 is ok for: iPhone5 640 x 1136
						-- others are questionable in corona sdk).
x, y = w, w				-- grid startposition

-- tables:
mgrid 		= {}
--visited	= {}		-- in carve
--stack		= {}		-- in carve
solution 	= {} 		-- as dictionary

-- *****************  helper functions:  *****************

-- if 2D-table contains Value		-- important
local function contains( table, x, y )
   for i=1,#table do
      if table[i][1] == x and table[i][2] == y then
         return true
      end
   end
   return false
end
 
-- randomizer kick on for maze construction & way back
math.randomseed(os.time())

-- ****************** -- pgm functions: *********************

-- build the maze matrix
local function build_grid( x, y, w )	
	love.graphics.setLineStyle("rough")
	for i = 1, w do             -- col
		x=w                     -- set koord. to start pos.
		y=y+w         		   	-- start a new row
		for j = 1, w do         -- row 
			love.graphics.setColor(255, 255, 255)
			love.graphics.rectangle("line", x+0.5, y+0.5, w, w)			
			table.insert( mgrid, {x, y} ) 	--append cell to grid: OK
			x = x+w							-- move to new position
		end
	end
end --func

-- ********************  pgm grafics: *********************

local function newRect(x, y, w, h)
  love.graphics.rectangle("fill", x, y, w, h)
end

function push_up(x, y)		--draw a rectangle twice the width of the cell
	love.graphics.setColor( 0, 0, 255 ) 		-- blau  / blue
	newRect( x+1, y-w+1, w-1, 2*w-1 )
end
--
function push_down(x, y) 
	love.graphics.setColor( 0, 0, 255 ) 		--blau
	newRect( x+1, y+1, w-1, 2*w-1 )  
end
--
function push_left(x, y)	
	love.graphics.setColor( 0, 0, 255 ) 		--blau
	newRect( x-w+1, y+1, 2*w-1, w-1 )
end
--
function push_right(x, y)
	love.graphics.setColor( 0, 0, 255 ) 		--blau
	newRect( x+1, y+1, 2*w-1, w-1 )
end
--
function single_cell(x, y)		-- draw a single width cell  
	love.graphics.setColor( 0, 255, 0 ) 		--gruen / green
	love.graphics.rectangle("fill", x+2, y+2, w-3, w-3 )
end
--
function backtracking_cell(x, y)	--used to re-colour the path after 
	love.graphics.setColor( 0, 0, 255 ) --blau single_cell has visited cell
	newRect( x+2, y+2, w-3, w-3 )
end
--
function solution_cell(x, y)		-- used to show the solution
	love.graphics.setColor(255, 255, 0) 	-- gelb / yellow
	newRect( x+w/2-1, y+w/2-1, 3, 3 )
end
-- ---------------------------------------------------------------
-- 	      **************  main function:  **************
-- ---------------------------------------------------------------
function carve_out_maze(x, y, w)
	visited		= {}
	stack		= {}
	single_cell(x, y)				-- starting positing of maze
	-- append stack & visited (at end of table) 
	table.insert(stack, {x, y})		-- place starting cell into stack   
	table.insert(visited, {x, y})	-- add starting cell to visited list
	while #stack > 0 do				-- loop until stack is empty (done)
		cell = {} 					-- create new empty table 
		-- check availability - Right,Left,Down,Up
		-- right cell available?  (NOT in visited BUT in grid)		
		if not contains(visited, x+w, y) and contains(mgrid, x+w, y) then
			table.insert( cell, "right" )	--if yes add to cell list
		end
		if not contains(visited, x-w, y) and contains(mgrid, x-w, y) then
			table.insert( cell, "left" )
		end
		if not contains(visited, x, y+w) and contains(mgrid, x, y+w) then
			table.insert( cell, "down" )
		end
		if not contains(visited, x, y-w) and contains(mgrid, x, y-w) then
			table.insert( cell, "up" )
		end		

			if #cell >0 then					--check if cell list is empty
				math.random(); math.random()	-- really necessary?
				cell_chosen = cell[math.random(1, #cell)] -- chose random cell-item			
				-- cell_chosen:
				if cell_chosen == "right" then	-- if cell is has been chosen
					push_right(x, y)			-- cell push_right function					
					solution[x+w..","..y] = {x,y}					
					x = x+w						-- make this cell the current cell
					table.insert(visited, {x, y} )
					table.insert(stack, {x, y} )
				elseif cell_chosen == "left" then		
					push_left(x, y)	
					solution[x-w..","..y] = {x,y}
					x = x-w
					table.insert(visited, {x, y} )	-- add to visited list
					table.insert(stack, {x, y} )	-- place current on to stack
				elseif cell_chosen == "down" then
					push_down(x, y)	
					solution[x..","..y+w] = {x,y}
					y = y+w
					table.insert(visited, {x, y} )
					table.insert(stack, {x, y} )				
				elseif cell_chosen == "up" then
					push_up(x, y)
					solution[x..","..y-w] = {x,y}
					y = y-w
					table.insert(visited, {x, y} )
					table.insert(stack, {x, y} )
				end	--end-if
				sleep(0.1)						-- pause
			else		
				-- if no cells are available pop one from the stack
				x, y = stack[#stack][1], stack[#stack][2]
				table.remove(stack)				-- stack pop (the last)
				-- use single_cell func. to show backtracking image
				single_cell(x, y)	
				sleep(0.1)						-- pause
				-- change colour to identify the backtracking path
				backtracking_cell(x, y)	
			end --if #cell
	end --while
end --carve_out_maze

-- visualize the way back to the start point  
function plot_route_back(x, y)	
	-- start b. retour: x: 289  y: 289 (ziel: 17 / 17
	solution_cell( x, y )		--[[ solution list contains all the  
									 coordinates to route back to start.]]		
	while x ~= w or y ~= w do	-- loop until cell pos == start pos. better but??
		-- "keys" now becomes the new values	 
		local xy = x..","..y	-- important!
		x = solution[xy][1]		-- because otherwise error:
		y = solution[xy][2]		-- <--<<<   nil value   
		
		solution_cell(x, y)				-- animate route back (grafics)
		table.remove(solution)			-- pop the last value
		sleep(0.1)						-- pause
	end --while
end --func plot_route_back

-- 		***********************  main:  ************************

-- 1st argument = x value, 2nd arg. = y value, 3rd arg. = width of cell
build_grid(2*w, 0, w)		-- build labyrinth
carve_out_maze(x, y, w)		-- call build the maze  function
plot_route_back(w*w, w*w)  	-- call the plot solution function

-- 	  ***********************  the end   ************************


neku
Prole
Posts: 12
Joined: Thu May 17, 2018 3:07 pm

Re: Template for using Löve as if it were not event-oriented

Post by neku » Thu Sep 26, 2019 2:03 pm

Here's a complete zip-file with the maze (generator&solver) project:
Attachments
NestorMazeSolverPGim.zip
love2d project maze: generator&solver
(6.02 KiB) Downloaded 96 times
Dank an Pedro-2-18_09.png
way back to the start.
Dank an Pedro-2-18_09.png (4.1 KiB) Viewed 3916 times

User avatar
YoungNeer
Party member
Posts: 118
Joined: Wed May 15, 2019 7:49 am

Re: Template for using Löve as if it were not event-oriented

Post by YoungNeer » Fri Sep 27, 2019 4:06 pm

pgimeno wrote:
Sat Sep 21, 2019 10:12 am
(sorry for the double post, the forum has problems when trying to attach more than one file):
Is that your secret? Like how you made those "unbelievable" 1700+ posts! :rofl:
My Github- your contribution is highly appreciated

monolifed
Party member
Posts: 127
Joined: Sat Feb 06, 2016 9:42 pm

Re: Template for using Löve as if it were not event-oriented

Post by monolifed » Fri Sep 27, 2019 5:05 pm

From the image, it looks like it also optimizes the path

neku
Prole
Posts: 12
Joined: Thu May 17, 2018 3:07 pm

Re: Template for using Löve as if it were not event-oriented

Post by neku » Fri Sep 27, 2019 8:05 pm

ingsoc451 wrote:
Fri Sep 27, 2019 5:05 pm
From the image, it looks like it also optimizes the path
maybe I'm not right, but I do not see any other way there. only this one.
look at the code. :monocle:

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests