Spawning Endless Object With Conditions

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
katlicia
Prole
Posts: 1
Joined: Thu Feb 15, 2024 10:03 pm

Spawning Endless Object With Conditions

Post by katlicia »

I am new to both Lua and Löve2D. Trying to learn them both by recreating Flappy Bird but got stuck on spawning pipes. I am creating the lower pipe based of on the upper pipe by adding a gap to its Y coordinate. It works good so far but I couldn't figure out a way to actually spawn them but not draw each one. (Impossible obviously.) I was trying to change the coordinates but soon realized that changing the pipes coordinates results in the change of first pipes coordinates too, so it would just glitch on the screen. (You get the idea of how a pipes spawn condition should be like in the original Flappy Bird) Here is what the base code seems like:

Code: Select all

function Pipes:load()
    self.pipeSprite = love.graphics.newImage("sprites/pipe-green.png")
    self.posY = math.random(100, love.graphics.getHeight() / 2)
    self.posX = love.graphics.getWidth()
    self.pipeGap = 80
    self.pipeVelocity = 80
end

function Pipes:update(dt)
    self.posX = self.posX - self.pipeVelocity * dt
end

function Pipes:draw()
    love.graphics.draw(self.pipeSprite, self.posX, self.posY, 0, 1, -1)
    love.graphics.draw(self.pipeSprite, self.posX, self.posY + self.pipeGap)
end
And a really quick question: If off screen objects are using memory like "setting a pipes X coordinate to -100" how could you actually destroy them once they are no longer used.
User avatar
Azzla
Prole
Posts: 43
Joined: Sun Mar 29, 2020 2:23 am

Re: Spawning Endless Object With Conditions

Post by Azzla »

What you are looking for is a soft implementation of OOP. Try the following:

Code: Select all

local Pipe = {}
Pipe.__index = Pipe

function Pipe.new(x, y, sprite, gap, velocity)
	local pipe = {
		x = x,
		y = y,
		sprite = sprite,
		gap = gap,
		velocity = velocity
	}
	return setmetatable(pipe, Pipe)
end

function Pipe:update(dt)
	self.x = self.x - self.velocity * dt
end

function Pipe:draw()
	love.graphics.draw(self.sprite, self.x, self.y, 0, 1, -1)
	love.graphics.draw(self.sprite, self.x, self.y + self.gap)
end

return Pipe
Then in your main.lua (or wherever you are instantiating pipe objects) you track all the pipes that you create in a table and update/draw them accordingly:

Code: Select all

local PipeClass = require('pipe') --wherever you put the above code
local Pipes = {}
local pipe_sprite = love.graphics.newImage('sprites/pipe_green.png')

function love.load()
	local total_pipes = 100
	for i=1,total_pipes do
		local x = love.graphics.getWidth() + (i * 50)
		local y = 0
		table.insert(Pipes, PipeClass.new(x, y, pipe_sprite, 80, 80)) --store all the created pipes in a table
	end
end

function love.update(dt)
	for _,pipe in ipairs(Pipes) do pipe:update(dt) end
end

function love.draw()
	for _,pipe in ipairs(Pipes) do pipe:draw() end
end
This code is not meant to work as-is, but it shows you the idea behind OOP and how to create multiple objects from a "class" (lua module really). You can and should change this to suit your game's needs. For example, if you want to create some pipes at init time but not draw them right away, you can use a boolean flag:

Code: Select all

function Pipe:draw()
	if self.is_visible then --this is either true or false based on some distance value from the visible screen.
		love.graphics.draw(self.sprite, self.x, self.y, 0, 1, -1)
		love.graphics.draw(self.sprite, self.x, self.y + self.gap)
	end
end
libraries: Stalkpile
electronic music stuff: https://soundcloud.com/azzlamusic
RNavega
Party member
Posts: 355
Joined: Sun Aug 16, 2020 1:28 pm

Re: Spawning Endless Object With Conditions

Post by RNavega »

katlicia wrote: Thu Feb 15, 2024 10:21 pm And a really quick question: If off screen objects are using memory like "setting a pipes X coordinate to -100" how could you actually destroy them once they are no longer used.
The Lua language standard defines a memory managed environment, and the LuaJIT interpreter used by Löve follows that.
Any objects (like tables, strings, userdata) that are not visible to any parts of your code, get garbage collected. So object deletion has to do with visibility within code.

This means that any time some object, like a table for example, goes out of scope (has all references to it lost, effectively becoming inaccessible to any parts of your code), it's automatically marked to be destroyed for you, eventually freeing its memory.
Edit: for example, you have myVariable = myTable, and at some point you have myVariable = otherTable. After that new assignment, if nobody else has a reference to myTable, then it'll automatically be destroyed.

If you keep pipe tables in some bigger "allPipes" table, then removing an item from that allPipes table should eventually let it be garbage collected, provided that there are no other tables or variables holding a reference to that pipe table of course.
But a suggestion is to not delete pipes that have moved off screen -- rather, just reuse them as needed, giving them new coordinates that make them appear as they are new pipes coming up ahead.
Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests