How to create random 2D maps?

Good morning, I’m developing a ‘hell bullet’ style game. But I’m having trouble creating the rooms, so that the generation of each one is random and the enemies only identify the player after entering the room


Script

I am now starting to move on defold and game creation, I apologize for the lack of programming knowledge

You need to look into procedural content creation. There are a lot of good articles on this. I’d google something like “roguelike random dungeon algorithm”.

@klaytonkowalski has a series of video tutorials on procedural content generation. Here’s one of them: YouTube

You can probably find some inspiration from my old Ludum Dare entry:

HTML5: Overrun Room 0.1
Source: GitHub - britzl/oneroom: Ludum Dare #37
Using Conway’s game of life algorithm: oneroom/conway.lua at master · britzl/oneroom · GitHub
Applied to tilemap: oneroom/level.lua at master · britzl/oneroom · GitHub

3 Likes

Thanks for the help, I had a better idea of ​​what the map would look like for my project and decided to create a continuous map instead of upgradable instances. I still have some doubts, so see you soon (^. ^ ')

1 Like

Good morning, I’m having trouble updating the face of my sprites that are in a collection.
codeSprite

And another question about how to create a shooting factory for my enemies within a collection. Thank you very much

sprite.set_hflip() is the correct function to use when you want to flip a sprite. Do you see any errors in the console? Is “#slime” the correct id of the sprite component? What if you print() something in both the if and the else? Is the conditional check evaluated properly?

Here’s a project with a player that can move and shoot:

The basic idea is that you use a factory component to spawn bullets. The bullets are moved using go.animate() and removed when a collision is detected.

1 Like

Good night, I want to thank you because the mistake of the sprites was that the GO id was different from the collection.

Already to create the factory of shots I am realizing that the error is due to the number of created instances of the object.

This is my script for the slime projectile

And here I create his factory in the slime script

note: I increased the speed and also tried to destroy the objects before they accumulated, but I didn’t understand what was wrong. If you have any suggestions I am grateful

Please share code in text mode instead of screenshots!

I noticed that the console says the sprite buffer is full. You can increase the buffer size in the Sprite section of game.project. Set it to a value that matches some kind of theoretical maximum number of bullets you want in your game.

I’m sorry, I’m still learning to work with the defold tool and the forum.

I managed to fix the code where I created several instances of the object, it looks like this

function update(self, dt)
	local pos = go.get_position()                   -- Cria a variavel 'pos' e atribui a posição atual do objeto projetil
    pos = pos + self.dir * self.speed * dt          -- A variável 'pos' recebe a soma dos eixos (x, y, z) vezes a velocidade vezes o deltaT('deltaT ajusta o fps do aparelho mobile para melhor eficiência')
    go.set_position(pos)

	self.life = self.life - dt

	if not self.collided then											-- Se objeto projetil não colidir execute o código
		local new_position = pos + self.dir * self.speed * dt
		go.set_position(new_position)										-- Atualiza posição do objeto projetil gerado

		if self.life < 0 then							-- Se o tempo do projetil for menor que 0, inicia a contagem ate tempo de vida do objeto após disparo
			self.speed = 0
			go.delete()
		end
	else
		sprite.play_flipbook('#projetil_slime_enemy', hash('atirar'), go.delete())	-- Se colidir, delete o objeto projetil
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash('contact_point_response') then					-- Se local de contato de 2 objetos
		self.collided = true												-- Colisão verdadeira
		self.target = message.other_id										-- Armazena id do objeto alvo
		self.message_collision = true
	end
end

But the projectile is still standing on top of the slime, I’m having trouble understanding the factory.create () documentation

	local direction = 0
	if distance_to_player >= self.min_follow_distance and distance_to_player <= self.max_follow_distance then
		direction = 1
	elseif distance_to_player >= self.min_retreat_distance and distance_to_player <= self.max_retreat_distance then
		direction = -1
	end

	direction = 1

	local angle = -math.atan2(playerPos.x - enemyPos.x, playerPos.y - enemyPos.y)							-- Calcula a direção angulo do jogador em relação ao inimigo
	local rot = vmath.quat_rotation_z(angle)															-- Marca como alvo a posição calculada
	go.set_position(enemyPos + self.correction + vmath.rotate(rot, NORTH) * self.speed * dt * direction)	-- Calcula a posição do slime atraves do alvo marcado e velocidade do slime

	local props = self.correction + vmath.rotate(rot, NORTH) * self.speed * dt * direction
	print('rot ------- ',rot)
	print('props --------- ',props)

	self.correction = vmath.vector3()

	if self.rate_of_fire > 0 then
		if distance_to_player >= self.min_fire_distance and distance_to_player <= self.max_fire_distance then
			self.time_until_next_bullet = self.time_until_next_bullet - dt
			if self.time_until_next_bullet <= 0 then
				self.time_until_next_bullet = 1 / self.rate_of_fire
				factory.create( '#slime_projetil', nil, rot)
				msg.post(".", "slime_projetil")
			end
		end
	end

I apologize, I am still a novice and I am very grateful for all the help

This will create the projectile but you have no code that moves it. If you look at the example I shared you notice that I use go.animate() to move the bullet after it is created:

1 Like

I interpreted it as the first script:

function update(self, dt)
	local pos = go.get_position()                   -- Cria a variavel 'pos' e atribui a posição atual do objeto projetil
    pos = pos + self.dir * self.speed * dt          -- A variável 'pos' recebe a soma dos eixos (x, y, z) vezes a velocidade vezes o deltaT('deltaT ajusta o fps do aparelho mobile para melhor eficiência')
    go.set_position(pos)

However, some things to check. Is the script attached to the gameobject?
What are the self.dir and self.speed? If any of those are 0 then it wont move.

Ah, you are right! Sorry!

Yes, check those! Also check that the collision object on the bullet isn’t dynamic. If it is dynamic it will not move unless Allow Dynamic Transforms is checked in game.project.

Dynamic objects will move if there is gravity? I guess you mean “kinematic”?
And, the “allow dynamic transforms” allows for the collision objects to be scaled with the game object (and also moving dynamic objects).

True, but if he set gravity to 0 for some reason then it would just stay in place… but more likely is that self.dir or self.speed is 0

self.dir is really 0, because if I put some value. example (0, 1, 0) shots are fixed on the y axis
This is the projectile_slime.script

go.property("dir", vmath.vector3(0, 0, 0))

function init(self)

	self.speed = 200 								-- Velocidade do projetil
	self.life = 1								-- Tempo de vida do objeto projetil em segundos
end

function update(self, dt)
	local pos = go.get_position()                   -- Cria a variavel 'pos' e atribui a posição atual do objeto projetil
    pos = pos + self.dir * self.speed * dt          -- A variável 'pos' recebe a soma dos eixos (x, y, z) vezes a velocidade vezes o deltaT('deltaT ajusta o fps do aparelho mobile para melhor eficiência')
	print('dir ---  ',self.dir)
	go.set_position(pos)

	self.life = self.life - dt

	if not self.collided then											-- Se objeto projetil não colidir execute o código
		local new_position = pos + self.dir * self.speed * dt
		go.set_position(new_position)										-- Atualiza posição do objeto projetil gerado

		if self.life < 0 then							-- Se o tempo do projetil for menor que 0, inicia a contagem ate tempo de vida do objeto após disparo
			self.speed = 0
			go.delete()
		end
	else
		sprite.play_flipbook('#projetil_slime_enemy', hash('atirar'), go.delete())	-- Se colidir, delete o objeto projetil
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash('contact_point_response') then					-- Se local de contato de 2 objetos
		self.collided = true												-- Colisão verdadeira
		self.target = message.other_id										-- Armazena id do objeto alvo
		self.message_collision = true
	end
end

This is the slime.script

go.property("health", 3)
go.property("speed", 50)
go.property("rate_of_fire", 10)
go.property("min_fire_distance", 0)
go.property("max_fire_distance", 1000)
go.property("min_follow_distance", 0)
go.property("max_follow_distance", 100)
go.property("min_retreat_distance", 0)
go.property("max_retreat_distance", 0)

local NORTH = vmath.vector3(0, 1, 0)

function init(self)
	msg.post('.', 'acquire_input_focus')
	self.correction = vmath.vector3()
	self.time_until_next_bullet  = 0
end

function update(self, dt)
	local playerPos = go.get_position('/heroi')
	local enemyPos = go.get_position()
	local distance_to_player = vmath.length(playerPos - enemyPos)

	if playerPos.x > enemyPos.x then
		sprite.set_hflip("#slime_enemy", true)
	else
		sprite.set_hflip("#slime_enemy", false)
	end

	local direction = 0
	if distance_to_player >= self.min_follow_distance and distance_to_player <= self.max_follow_distance then
		direction = 1
	elseif distance_to_player >= self.min_retreat_distance and distance_to_player <= self.max_retreat_distance then
		direction = -1
	end

	direction = 1

	local angle = -math.atan2(playerPos.x - enemyPos.x, playerPos.y - enemyPos.y)							-- Calcula a direção angulo do jogador em relação ao inimigo
	local rot = vmath.quat_rotation_z(angle)															-- Marca como alvo a posição calculada
	go.set_position(enemyPos + self.correction + vmath.rotate(rot, NORTH) * self.speed * dt * direction)	-- Calcula a posição do slime atraves do alvo marcado e velocidade do slime

	local props = self.correction + vmath.rotate(rot, NORTH) * self.speed * dt * direction
	print('rot ------- ',rot)
	print('props --------- ',props)

	self.correction = vmath.vector3()

	if self.rate_of_fire > 0 then
		if distance_to_player >= self.min_fire_distance and distance_to_player <= self.max_fire_distance then
			self.time_until_next_bullet = self.time_until_next_bullet - dt
			if self.time_until_next_bullet <= 0 then
				self.time_until_next_bullet = 1 / self.rate_of_fire
				factory.create( '#slime_projetil', props, rot)
				msg.post(".", "slime_projetil")
			end
		end
	end
end

The problem is that when I pass the player’s position (x, y), factory.create () is not updating according to the player’s position and does not shoot

erroProps

Where do you do this? And are you sure it is the correct value?

1 Like

If the direction is 0, then it just won’t go anywhere.

You should pass properties to the factory when creating the bullet.
The factory will pass it on to the gameobject.

1 Like

I apologize for the delay, I spent hours trying to resolve it and luckily it worked. Thank you very much @Mathias_Westerdahl and @britzl

This is the projectile_slime.script

go.property("health", 3)
go.property("rate_of_fire", 1)
go.property("min_follow_distance", 0)
go.property("max_follow_distance", 1000)
go.property("min_retreat_distance", 0)
go.property("max_retreat_distance", 0)

local NORTH = vmath.vector3(0, 1, 0)

function init(self)
	self.speed = 200 								-- Velocidade do projetil
	self.life = 1								-- Tempo de vida do objeto projetil em segundos
end

function update(self, dt)
	self.life = self.life - dt

	if not self.collided then											-- Se objeto projetil não colidir execute o código
		local playerPos = go.get_position('/heroi')
		local projetilPos = go.get_position()
		local distance_to_player = vmath.length(playerPos - projetilPos)

		local direction = 0
		if distance_to_player >= self.min_follow_distance and distance_to_player <= self.max_follow_distance then
			direction = 1
		elseif distance_to_player >= self.min_retreat_distance and distance_to_player <= self.max_retreat_distance then
			direction = -1
		end

		local angle = -math.atan2(playerPos.x - projetilPos.x, playerPos.y - projetilPos.y)							-- Calcula a direção angulo do jogador em relação ao inimigo
		local rot = vmath.quat_rotation_z(angle)															-- Marca como alvo a posição calculada
		go.set_position(projetilPos + vmath.rotate(rot, NORTH) * self.speed * dt * direction)	-- Calcula a posição do slime atraves do alvo marcado e velocidade do slime

		if self.life < 0 then							-- Se o tempo do projetil for menor que 0, inicia a contagem ate tempo de vida do objeto após disparo
			go.delete()
		end
	else
		sprite.play_flipbook('#projetil_slime_enemy', hash('atirar'), go.delete())	-- Se colidir, delete o objeto projetil
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash('contact_point_response') then					-- Se local de contato de 2 objetos
		self.collided = true												-- Colisão verdadeira
		self.target = message.other_id										-- Armazena id do objeto alvo
		self.message_collision = true
	end
end

this is the slime.script

go.property("health", 3)
go.property("speed", 50)
go.property("min_fire_distance", 0)
go.property("max_fire_distance", 200)

local NORTH = vmath.vector3(0, 1, 0)

function init(self)
	msg.post('.', 'acquire_input_focus')
	self.correction = vmath.vector3()
	self.time_until_next_bullet  = 0
end

function update(self, dt)
	local playerPos = go.get_position('/heroi')
	local enemyPos = go.get_position()
	local distance_to_player = vmath.length(playerPos - enemyPos)

	if playerPos.x > enemyPos.x then
		sprite.set_hflip("#slime_enemy", true)
	else
		sprite.set_hflip("#slime_enemy", false)
	end

	local angle = -math.atan2(playerPos.x - enemyPos.x, playerPos.y - enemyPos.y)							-- Calcula a direção angulo do jogador em relação ao inimigo
	local rot = vmath.quat_rotation_z(angle)																-- Marca como alvo a posição calculada
	go.set_position(enemyPos + self.correction + vmath.rotate(rot, NORTH) * self.speed * dt)				-- Calcula a posição do slime atraves do alvo marcado e velocidade do slime

	if distance_to_player >= self.min_fire_distance and distance_to_player <= self.max_fire_distance then
		self.time_until_next_bullet = self.time_until_next_bullet - dt
		if self.time_until_next_bullet <= 0 then
			factory.create( '#slime_projetil')
		end
	end
end
1 Like

I have a question, what is the difference in creating several go.property and creating self.x in the init function?

You can see the go.property()in the editor, in the properties pane, when clicking on the script component. It makes it easier for a game designer to change the initial values of a game object.

2 Likes

Note that you are starting the animation each time in the update loop.
Not only is it redundant, but if you wish to have animations with more than one frame, you will only ever see the first frame.

2 Likes