Code Doodles!

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
HugoBDesigner
Party member
Posts: 403
Joined: Mon Feb 24, 2014 6:54 pm
Location: Above the Pocket Dimension
Contact:

Re: Code Doodles!

Post by HugoBDesigner »

I decided to try out a random "noise" generator. I was trying to figure out if a seed-based map was possible, and seems like it is! I made it so you can type in string seeds and they'll always generate the same map if you use the same seed. I also added some controls so you can set the size of the map, the amount of "smoothness" levels and how spread the map is.

KEYS:
R: Return to menu
Enter: Toggles lines

Code: Select all

--	LÖVE Code Doodle #9
--		by HugoBDesigner

function love.load()
	seed = ""
	state = "start"
	map = {}
	mapsize = 16
	levels = 5
	spread = 1
	basicColors = {{255, 255, 0}, {255, 0, 0}}
	levels_colors = {}
	
	economicmode = true
	font = love.graphics.newFont()
	
	buttons = {}
	local txt = "Map size: "
	table.insert(buttons, newButton(100+font:getWidth(txt), 300+font:getHeight()/2+20, 10, 10, "<", "mapsize", "-", 8))
	table.insert(buttons, newButton(100+font:getWidth(txt)+10+5+font:getWidth(tostring(mapsize))+5, 300+font:getHeight()/2+20, 10, 10, ">", "mapsize", "+", 64))
	txt = "Levels: "
	table.insert(buttons, newButton(100+font:getWidth(txt), 300+font:getHeight()/2+20+30, 10, 10, "<", "levels", "-", 2))
	table.insert(buttons, newButton(100+font:getWidth(txt)+10+5+font:getWidth(tostring(levels))+5, 300+font:getHeight()/2+20+30, 10, 10, ">", "levels", "+", 8))
	txt = "Spreading level: "
	table.insert(buttons, newButton(100+font:getWidth(txt), 300+font:getHeight()/2+20+60, 10, 10, "<", "spread", "-", 1))
	table.insert(buttons, newButton(100+font:getWidth(txt)+10+5+font:getWidth(tostring(levels))+5, 300+font:getHeight()/2+20+60, 10, 10, ">", "spread", "+", 5))
end

function love.update(dt)
	
end

function love.draw()
	love.graphics.setColor(255, 255, 255, 255)
	if state == "game" then
		for x = 1, mapsize do
			for y = 1, mapsize do
				local recsize = 8
				local px = 400-mapsize/2*recsize+(x-1)*recsize
				local py = 300-mapsize/2*recsize+(y-1)*recsize
				love.graphics.setColor(levels_colors[map[x][y]])
				love.graphics.rectangle("fill", px, py, recsize, recsize)
				if not economicmode then
					local r, g, b = unpack(levels_colors[map[x][y]])
					love.graphics.setColor(r*.5, g*.5, b*.5)
					love.graphics.rectangle("line", px, py, recsize, recsize)
				end
			end
		end
	else
		love.graphics.print("Type in your seed:", 100, 300-font:getHeight()/2 - 20 - font:getHeight())
		love.graphics.setColor(155, 155, 155, 255)
		love.graphics.rectangle("fill", 100, 300-font:getHeight()/2-5, 800-100*2, font:getHeight()+5*2)
		love.graphics.setColor(0, 0, 0, 255)
		love.graphics.print(seed, 100+5, 300-font:getHeight()/2)
		love.graphics.setColor(255, 255, 255, 255)
		love.graphics.print("Map size:", 100, 300+font:getHeight()/2+20+5-font:getHeight()/2)
		love.graphics.print("Levels:", 100, 300+font:getHeight()/2+20+30+5-font:getHeight()/2)
		love.graphics.print("Spreading level:", 100, 300+font:getHeight()/2+20+60+5-font:getHeight()/2)
		love.graphics.print(tostring(mapsize), 100+font:getWidth("Map size: ")+10+5, 300+font:getHeight()/2+20+5-font:getHeight()/2)
		love.graphics.print(tostring(levels), 100+font:getWidth("Levels: ")+10+5, 300+font:getHeight()/2+20+30+5-font:getHeight()/2)
		love.graphics.print(tostring(spread), 100+font:getWidth("Spreading level: ")+10+5, 300+font:getHeight()/2+20+60+5-font:getHeight()/2)
		for i, v in ipairs(buttons) do
			love.graphics.setColor(155, 155, 155, 255)
			love.graphics.rectangle("fill", v.x, v.y, v.width, v.height)
			love.graphics.setColor(55, 55, 55, 255)
			love.graphics.rectangle("line", v.x, v.y, v.width, v.height)
			love.graphics.setColor(255, 255, 255, 255)
			love.graphics.print(v.text, v.x+v.width/2-font:getWidth(v.text)/2, v.y+v.height/2-font:getHeight()/2)
		end
	end
end

function love.keypressed(key, unicode)
	if state == "start" then
		if key == "backspace" then
			if string.len(seed) > 1 then seed = string.sub(seed, 1, string.len(seed)-1)
			else seed = "" end
		elseif key == "enter" or key == "return" or key == "kpenter" then
			if string.len(seed) >= 1 then
				state = "game"
				renderSeed(seed)
			end
		elseif string.len(seed) < 15 then --let's not let giant texts, shall we?
			able = "abcdefghijklmnopqrstuvwxyz0123456789 "
			for i = 1, string.len(able) do
				if key == string.sub(able, i, i) then
					seed = seed .. key
					break
				end
			end
		end
	else
		if key == "enter" or key == "return" or key == "kpenter" then
			economicmode = not economicmode
		elseif key == "r" then
			state = "start"
		end
	end
	
	if key == "escape" then
		love.event.quit()
	end
end

function love.mousepressed(x, y, button)
	for i, v in ipairs(buttons) do
		if inside(x, y, 0, 0, v.x, v.y, v.width, v.height) then
			buttonPressed(v)
			break
		end
	end
	buttons[2].x = 100+font:getWidth("Map size: ")+10+5+font:getWidth(tostring(mapsize))+5
	buttons[4].x = 100+font:getWidth("Levels: ")+10+5+font:getWidth(tostring(levels))+5
	buttons[6].x = 100+font:getWidth("Spreading level: ")+10+5+font:getWidth(tostring(spread))+5
end

function renderSeed(seed)
	local a = ""
	for i = 1, string.len(seed) do
		a = a .. tostring(string.byte(string.sub(seed, i, i)))
	end
	math.randomseed(tonumber(a))
	
	levels_colors = {basicColors[1]}
	for i = 2, levels-1 do
		table.insert(levels_colors, fade(i-1, levels-1, basicColors[1], basicColors[2]))
	end
	table.insert(levels_colors, basicColors[2])
	
	for x = 1, mapsize do
		map[x] = {}
		for y = 1, mapsize do
			map[x][y] = 1
		end
	end
	for x = 1, mapsize do
		for y = 1, mapsize do
			local n = math.random(levels*spread)
			if n == levels*spread then
				map[x][y] = levels
				for i = 1, levels-1 do
					local n = levels-i
					--[[ First the four sides of the tile, like so:
					-- ___#___
					-- ___#___
					-- ___#___
					-- ###@###
					-- ___#___
					-- ___#___
					-- ___#___]]
					if x-i >= 1 then
						map[x-i][y] = math.max(map[x-i][y], n)
					end
					if x+i <= mapsize then
						map[x+i][y] = math.max(map[x+i][y], n)
					end
					if y-i >= 1 then
						map[x][y-i] = math.max(map[x][y-i], n)
					end
					if y+i <= mapsize then
						map[x][y+i] = math.max(map[x][y+i], n)
					end
					
					--[[ Later the diagonals, cause they're important!
					-- _______
					-- __#_#__
					-- _##_##_
					-- ___@___
					-- _##_##_
					-- __#_#__
					-- _______]]
					
					for j = 1, i-1 do
						if y-i+j >= 1 and x-j >= 1 then
							map[x-j][y-i+j] = math.max(map[x-j][y-i+j], n)
						end
						if y-i+j >= 1 and x+j <= mapsize then
							map[x+j][y-i+j] = math.max(map[x+j][y-i+j], n)
						end
						if y+i-j <= mapsize and x-j >= 1 then
							map[x-j][y+i-j] = math.max(map[x-j][y+i-j], n)
						end
						if y+i-j <= mapsize and x+j <= mapsize then
							map[x+j][y+i-j] = math.max(map[x+j][y+i-j], n)
						end
					end
				end
			end
		end
	end
end

function newButton(x, y, w, h, t, var, f, lim)
	return {x = x, y = y, width = w, height = h, text = t, variable = var, func = f, limit = lim}
end

function buttonPressed(b)
	if b.func == "+" or b.func == "add" then
		_G[b.variable] = math.min(_G[b.variable]+1, b.limit)
	elseif b.func == "-" or b.func == "sub" then
		_G[b.variable] = math.max(_G[b.variable]-1, b.limit)
	end
end

function inside(x1, y1, w1, h1, x2, y2, w2, h2)
	if x1 >= x2 and y1 >= y2 and x1+w1 < x2+w2 and y1+h1 < y2+h2 then
		return true
	end
	return false
end

function fade(currenttime, maxtime, c1, c2)
	local tp = currenttime/maxtime
	local ret = {} --return color

	for i = 1, #c1 do
		ret[i] = c1[i]+(c2[i]-c1[i])*tp
		ret[i] = math.max(ret[i], 0)
		ret[i] = math.min(ret[i], 255)
	end

	return ret
end
GUI
GUI
Captura de tela 2014-07-07 03.17.10.png (5.87 KiB) Viewed 5525 times
Big map without spread and big smoothness
Big map without spread and big smoothness
Captura de tela 2014-07-07 03.17.50.png (8.5 KiB) Viewed 5525 times
Tiny map with big spread and tiny smoothness (and with lines)
Tiny map with big spread and tiny smoothness (and with lines)
Captura de tela 2014-07-07 03.34.55.png (3.7 KiB) Viewed 5525 times
@HugoBDesigner - Twitter
HugoBDesigner - Blog
User avatar
HugoBDesigner
Party member
Posts: 403
Joined: Mon Feb 24, 2014 6:54 pm
Location: Above the Pocket Dimension
Contact:

Re: Code Doodles!

Post by HugoBDesigner »

Made a doodle to "enlarge" pixels. It's a nice little "illusion". It doesn't only converts them in the screen but also saves the resulting image. There's an image by default, but you can add a new image on "%appdata%/LOVE/ImageConverter". It must be named "oldimage.png", and it saves the new image as, guess what? Yup, "newimage.png".

Code: Select all

--	LÖVE Code Doodle #10
--		by HugoBDesigner

function love.load()
	love.filesystem.setIdentity("ImageConverter")
	love.filesystem.write("temp.txt", "temp")
	love.filesystem.remove("temp.txt")
	newimg = false
	local oldimg = false
	if love.filesystem.exists("oldimage.png") then
		oldimg = love.image.newImageData("oldimage.png")
	else
		oldimg = love.image.newImageData("glados.png")
	end
	
	if oldimg then
		newimg = love.image.newImageData(oldimg:getWidth()*3, oldimg:getHeight()*3)
		for x = 0, oldimg:getWidth()-1 do
			for y = 0, oldimg:getHeight()-1 do
				local r, g, b, a = oldimg:getPixel(x, y)
				newimg:setPixel(x*3, y*3, r, 0, 0, a)
				newimg:setPixel(x*3, y*3+1, r, 0, 0, a)
				newimg:setPixel(x*3, y*3+2, r, 0, 0, a)
				newimg:setPixel(x*3+1, y*3, 0, g, 0, a)
				newimg:setPixel(x*3+1, y*3+1, 0, g, 0, a)
				newimg:setPixel(x*3+1, y*3+2, 0, g, 0, a)
				newimg:setPixel(x*3+2, y*3, 0, 0, b, a)
				newimg:setPixel(x*3+2, y*3+1, 0, 0, b, a)
				newimg:setPixel(x*3+2, y*3+2, 0, 0, b, a)
			end
		end
		newimg:encode("newimage.png")
		newimg = love.graphics.newImage(newimg)
		love.graphics.setMode = love.graphics.setMode or love.window.setMode
		love.graphics.setMode(newimg:getWidth(), newimg:getHeight())
	end
end

function love.draw()
	if newimg then
		love.graphics.draw(newimg, 0, 0)
	end
end
The result:
Image
Attachments
ImageConverter.love
(5.13 KiB) Downloaded 206 times
@HugoBDesigner - Twitter
HugoBDesigner - Blog
User avatar
baconhawka7x
Party member
Posts: 491
Joined: Mon Nov 21, 2011 7:05 am
Location: Oregon, USA
Contact:

Re: Code Doodles!

Post by baconhawka7x »

HugoBDesigner wrote:Made a doodle to "enlarge" pixels. It's a nice little "illusion". It doesn't only converts them in the screen but also saves the resulting image. There's an image by default, but you can add a new image on "%appdata%/LOVE/ImageConverter". It must be named "oldimage.png", and it saves the new image as, guess what? Yup, "newimage.png".

Code: Select all

--	LÖVE Code Doodle #10
--		by HugoBDesigner

function love.load()
	love.filesystem.setIdentity("ImageConverter")
	love.filesystem.write("temp.txt", "temp")
	love.filesystem.remove("temp.txt")
	newimg = false
	local oldimg = false
	if love.filesystem.exists("oldimage.png") then
		oldimg = love.image.newImageData("oldimage.png")
	else
		oldimg = love.image.newImageData("glados.png")
	end
	
	if oldimg then
		newimg = love.image.newImageData(oldimg:getWidth()*3, oldimg:getHeight()*3)
		for x = 0, oldimg:getWidth()-1 do
			for y = 0, oldimg:getHeight()-1 do
				local r, g, b, a = oldimg:getPixel(x, y)
				newimg:setPixel(x*3, y*3, r, 0, 0, a)
				newimg:setPixel(x*3, y*3+1, r, 0, 0, a)
				newimg:setPixel(x*3, y*3+2, r, 0, 0, a)
				newimg:setPixel(x*3+1, y*3, 0, g, 0, a)
				newimg:setPixel(x*3+1, y*3+1, 0, g, 0, a)
				newimg:setPixel(x*3+1, y*3+2, 0, g, 0, a)
				newimg:setPixel(x*3+2, y*3, 0, 0, b, a)
				newimg:setPixel(x*3+2, y*3+1, 0, 0, b, a)
				newimg:setPixel(x*3+2, y*3+2, 0, 0, b, a)
			end
		end
		newimg:encode("newimage.png")
		newimg = love.graphics.newImage(newimg)
		love.graphics.setMode = love.graphics.setMode or love.window.setMode
		love.graphics.setMode(newimg:getWidth(), newimg:getHeight())
	end
end

function love.draw()
	if newimg then
		love.graphics.draw(newimg, 0, 0)
	end
end
The result:
Image
This is awesome!
User avatar
HugoBDesigner
Party member
Posts: 403
Joined: Mon Feb 24, 2014 6:54 pm
Location: Above the Pocket Dimension
Contact:

Re: Code Doodles!

Post by HugoBDesigner »

Thank you very much!
@HugoBDesigner - Twitter
HugoBDesigner - Blog
User avatar
Davidobot
Party member
Posts: 1226
Joined: Sat Mar 31, 2012 5:18 am
Location: Oxford, UK
Contact:

Re: Code Doodles!

Post by Davidobot »

Demoing trajectories:

Code: Select all

--[[

	Variables for a trajectory:
		g - the gravitational acceleration
		o - angle at which the projectile is launched
		v - initial velocity of the projectile
		yO - initial height from which the projectile is fired
		d - total horizontal distance traveled by the projectile
		t - time of flight
		y - the y of the projectile at a given x

	Formulae:
		d = ( ( v * cos(o) ) / g ) * ( (v * sin(o)) + sqrt( pow(v * sin(o), 2) + (2 * g * yO) ) )
		t = d / ( v * cos(o) )
		y = screenHeight - ( yO + x * tan(o) - ( (g * pow(x, 2)) / (2 * pow(v * cos(o), 2)) ) )

	Variables for energy:
		e - energy in joules
		m - mass of the object
		v - velocity of the object

	Formulae:
		e = 0.5 * m * pow(v, 2)
		v = sqrt( (2 * e) / m )
]]--

g = 9.81
o = math.rad(45)
v = 0
yO = 0

increasing = true
angChange = 0

function love.load()
	d = ( ( v * math.cos(o) ) / g ) * ( (v * math.sin(o)) + math.sqrt( math.pow(v * math.sin(o), 2) + (2 * g * yO) ) ) 
end

function love.update(dt)
	if increasing then
		v = v + dt * 15
	elseif angChange == 0 then
		v = v - dt * 15
	end

	if v >= 80 and increasing then
		angChange = 1
		increasing = false
	elseif v < 0 and increasing == false and angChange == 0 then
		increasing = not increasing
	end

	if angChange ~= 0 then
		o = o + math.rad(5) * dt * angChange
	end

	if o >= math.rad(90) then
		angChange = -1
	end

	if angChange == -1 and o <= math.rad(45) then
		angChange = 0
	end

	d = ( ( v * math.cos(o) ) / g ) * ( (v * math.sin(o)) + math.sqrt( math.pow(v * math.sin(o), 2) + (2 * g * yO) ) ) 
end

function love.draw()
	for x = 0, d, 20 do
		love.graphics.push()

		love.graphics.setColor(255, 0, 0)
		love.graphics.translate(-4, -4)
		love.graphics.rectangle("fill", x, love.window.getHeight() - ( yO + x * math.tan(o) - ( (g * math.pow(x, 2)) / (2 * math.pow(v * math.cos(o), 2)) ) ), 8, 8)

		love.graphics.pop()
	end

	love.graphics.print("Initial velocity: "..math.ceil(v).."m/s Max distance: "..math.ceil(d).."m Angle: "..math.ceil(math.deg(o)), 0, 200)
end
Not the prettiest code.

Check it out on Love Fiddle:
http://lovefiddle.com/a6bcd0ad0d816e38f ... 7a32f48e4f
PM me on here or elsewhere if you'd like to discuss porting your game to Nintendo Switch via mazette!
personal page and a raycaster
User avatar
HugoBDesigner
Party member
Posts: 403
Joined: Mon Feb 24, 2014 6:54 pm
Location: Above the Pocket Dimension
Contact:

Re: Code Doodles!

Post by HugoBDesigner »

I wanted to make a doodle to convert maps in spheres. It ended up looking good, but not 100% accurate. This is because I didn't enlarge the maps in the equator, nor shrank it near the poles. Other than that, it works decently, at least:

Code: Select all

--	LÖVE Code Doodle #11
--		by HugoBDesigner

--	I didn't add any code to make the equator parts larger than the poles,
--	so that's why it looks "pointy". Although it would be too hard to make
--	it this way, so I'm not doing it...

function love.load()
	local files = love.filesystem.enumerate("maps")
	maps = {}
	for i, v in pairs(files) do
		local f = "maps/" .. v
		if love.filesystem.isFile(f) then
			local ext = string.sub(f, -4, -1)
			if ext == ".png" or ext == ".jpg" then
				table.insert(maps, love.graphics.newImage(f))
			end
		end
	end
	map = 1
	
	posx = 0
	rotspeed = 1
	
	love.graphics.setLineWidth(5)
end

function love.update(dt)
	if love.keyboard.isDown("a") or love.keyboard.isDown("left") then
		posx = posx-dt*rotspeed
		if posx < 0 then
			posx = posx + 1
		end
	elseif love.keyboard.isDown("d") or love.keyboard.isDown("right") then
		posx = posx+dt*rotspeed
		if posx >= 1 then
			posx = posx - 1
		end
	end
end

function love.draw()
	love.graphics.setColor(255, 255, 255, 255)
	
	local radius = math.floor(maps[map]:getHeight()/2)
	
	local forlimit = 1
	if posx+radius > maps[map]:getWidth()/2 then
		forlimit = 2
	end
	
	local function myStencil()
		love.graphics.circle("fill", 400, 300, radius, 32)
	end
	love.graphics.setStencil(myStencil)
	
	for i = 1, radius*2 do
		local an = (i-1)/(radius*2)*math.pi
		local w = (math.sin(an)*2-1)*(maps[map]:getWidth()/2)
		local extrax = (math.sin(an)*2-1)*radius
		local newy = 300 - radius
		local sc = (maps[map]:getWidth()/2+w)/(maps[map]:getWidth())
		
		local wid = maps[map]:getWidth()*sc
		local newx = 400 - wid/2 - posx*wid
		while newx+wid < 400 - wid/2 do
			newx = newx + wid
		end
		
		love.graphics.setScissor(400-radius, newy+(i-1), radius*2, 2)
		while newx+wid < 400+wid/2+wid do
			love.graphics.draw(maps[map], newx, newy, 0, sc, 1)
			newx = newx+wid
		end
		
		love.graphics.setScissor()
	end
	
	love.graphics.setStencil()
end

function love.keypressed(key, unicode)
	if key == "w" or key == "up" then
		map = map - 1
		if map < 1 then
			map = #maps
		end
		posx = 0
	elseif key == "s" or key == "down" or key == " " or key == "enter" or key == "return" or key == "kpenter" then
		map = map + 1
		if map > #maps then
			map = 1
		end
		posx = 0
	elseif key == "escape" then
		love.event.quit()
	end
end
Image

The .love file contains the maps. Anyone is free to change this code, since I couldn't make it work 100%, but I'd still like to be credited...
MapToPlanet.love
(227.27 KiB) Downloaded 215 times
EDIT: Almost forgot: left/right rotate the globe, up and down switch between maps.
@HugoBDesigner - Twitter
HugoBDesigner - Blog
Clouds
Prole
Posts: 23
Joined: Tue Nov 27, 2012 4:06 am

Re: Code Doodles!

Post by Clouds »

HugoBDesigner wrote:I wanted to make a doodle to convert maps in spheres.
Is it for LÖVE 0.8? For me, with 0.9.1, it errors on line 9: no such function "enumerate".
User avatar
DaedalusYoung
Party member
Posts: 407
Joined: Sun Jul 14, 2013 8:04 pm

Re: Code Doodles!

Post by DaedalusYoung »

It must be, yes. That function had its name changed to love.filesystem.getDirectoryItems.
User avatar
HugoBDesigner
Party member
Posts: 403
Joined: Mon Feb 24, 2014 6:54 pm
Location: Above the Pocket Dimension
Contact:

Re: Code Doodles!

Post by HugoBDesigner »

Yes, it is for LÖVE 0.8.0. I'm too used to it, so I completely forgot that people use 0.9.x much more often than me...
@HugoBDesigner - Twitter
HugoBDesigner - Blog
User avatar
Zilarrezko
Party member
Posts: 345
Joined: Mon Dec 10, 2012 5:50 am
Location: Oregon

Re: Code Doodles!

Post by Zilarrezko »

Not sure if this is a valid place to put this. But I was trying out some culling in my ghetto 3D. and I came across something interesting I though, at least feature wise.

Reverse Culling? That's what I'm calling it anyway. Just culling but opposite when you still have everything that renders behind the camera.

Take a look

Similar stuff has been utilized in the stronghold series I'm sure, where you can peer into houses and shops and castles interiors through the walls and see people work/do their stuff.

and off I go to fix the stuff rendering behind the camera!
Post Reply

Who is online

Users browsing this forum: No registered users and 214 guests