Medieval themed 2D strategy game

Thanks. I almost have it working. Because I’m using the Defold Input set up you made a few posts back, I’m trying to figure out how to set up the messaging. I think I may need another lua, such as onscreen, since it looks like messages only work with game objects and not guis.

Here’s how I’ve set it up.

I’m using the cursor to send a message to the gui, telling it to turn on when clicking a unit.

if message_id == cursor.PRESSED then
		print("message.id", message.id)
		if message.id == hash("/unit") then
			msg.post("/guis#panel", "unit_panel_on")
		else
		-- elseif message.id ~= hash("/unit") then
		-- 	msg.post("/guis#panel", "unit_panel_off")
		end

This works fine. I only sent messages to turn on the panel, but not off. I figured it would be best to turn off the panel from the panel GUI. If I used the cursor to disable the panel, the panel would turn off when clicking it. Also, I think it’s only possible to set up panel interactions from the gui script.

In the panel gui, I have the following.

function on_message(self, message_id, message, sender)
	if message_id == hash("unit_panel_on") then
		local unit_panel = gui.get_node("unit_panel")
		gui.set_enabled(unit_panel, true)
	end

	if message_id == cursor.PRESSED then
		print("panel message.id", message.id)
	end
end

function on_input(self, action_id, action)
	if action_id == hash("touch") and action.pressed then
		local unit_panel = gui.get_node("unit_panel")
		local move = gui.get_node("move")
		if gui.pick_node(unit_panel, action.x, action.y) then -- <5>
			print("clicked panel")
		elseif gui.pick_node(move, action.x, action.y) then
			print("clicked move")
		end
	end	
end

However, this isn’t working as intended. Not only am I getting message nil from my cursor script, which I want to ignore, I’m not getting a response when clicking the button. I’m able to detect when I click the panel, but nothing else.

In addition to the above, I can still click the panel and move button even when it’s disabled. Need to figure out why that’s happening.

EDIT 1: Maybe the answer is to have the GUI placed outside of the bounds of screen and have it moved in/out when enabled/disabled.

EDIT 2: Yes, that seemed to do the trick. I will set and reset the position when enabled/disabled, so it’s not interactable when disabled.

1 Like

This will require some state handling on your part. You need to track which part of the game that needs to get inout. You can release the input focus or in other ways prevent input from propagating between components in the input stack. More info here (and in the following sections): https://defold.com/manuals/input/#input-focus

1 Like

That almost has it working. The problem is if when I release focus from the cursor, either by using return true or script messaging, I’m unable register the button clicks on the panel. It seems like having a GUI acquire focus means it takes it for the entire screen, not just the GUI elements.

For example, here I am able to determine which has focus – the panel or the game world.

However when I remove focus from the cursor, I cannot seem to interact with the GUI.

EDIT1: I think it was because I was removing focus from the cursor and not the game world in the main script. Back to trying to get it working…

EDIT2: I think using return true somehow may be the way to go.

I think I have it working with the following code. Needs a few tweaks because I have to figure out how to set up what happens when the panel is turned off.

function on_message(self, message_id, message, sender)
	if message_id == hash("unit_panel_on") then
		local unit_panel = gui.get_node("unit_panel")
		local is_unit_panel_enabled = gui.is_enabled(unit_panel)
		local unit_panel_position = gui.get_position(unit_panel)
		gui.set_enabled(unit_panel, true)
		gui.set_position(unit_panel, vmath.vector3(480, 0, 0))
		msg.post(".", "acquire_input_focus")
	end
end

function on_input(self, action_id, action)

	if action_id == hash("touch") and action.pressed then
		local unit_panel = gui.get_node("unit_panel")
		if gui.pick_node(unit_panel, action.x, action.y) then
			print("panel pressed")
			local move = gui.get_node("move")
			if gui.pick_node(move, action.x, action.y) then
				print("move button pressed")
			end
			-- msg.post(".", "release_input_focus")
		end
	end

I’m out of time for today.

Trying to stay positive. It’s difficult when you spend an entire day figuring out something that should, in theory, be simple. I tell myself this will pay off one day.

1 Like

I just read this whole thread and wish you luck man. I’ve spent the last week downloading/trying out engines: Phaser, Unity, LibGDX, Godot.

Even though I am brand new to LUA and only have some skill in Java, let’s do this. I’ve spent 12 hours just today (day off from day job) doing defold tutorials. You’ve made a lot of progress and would love to see an RTS game.

So, please keep positing, and you can do it !

2 Likes

Yeah, I’m not giving up!

It’s just that if this where a “how it started, how it’s going” meme, the how it started side would have me and my imagination — thinking of all the cool ideas I want to implement.

Then, on the how it’s going side, there’s be me working all day trying to get a “move” button working…

1 Like

I believe I have it working, for now. This is the code I’m using from the cursor — it’s set to show the panel when clicking a unit; later, I want to make the panel appear for buildings and other objects too, but for now, this is just to set things up. If the message is nil, the panel closes.

I may end up creating a background collider so I can use that instead of nil. I could be wrong, but I believe I read somewhere that nil should be avoided when possible.

if message_id == cursor.PRESSED then
		print("message.id", message.id)
		if message.id == hash("/unit") then
			msg.post("/guis#panel", "unit_panel_on")
		else
			msg.post("/guis#panel", "unit_panel_off")
		end
end

Next, I have my panel GUI set up like this:

function on_message(self, message_id, message, sender)
	if message_id == hash("unit_panel_on") then
		local unit_panel = gui.get_node("unit_panel")
		local unit_panel_position = gui.get_position(unit_panel)
		gui.set_enabled(unit_panel, true)
		gui.set_position(unit_panel, vmath.vector3(480, 0, 0))
		msg.post(".", "acquire_input_focus")
	end
	if message_id == hash("unit_panel_off") then
		local unit_panel = gui.get_node("unit_panel")
		local unit_panel_position = gui.get_position(unit_panel)
		gui.set_enabled(unit_panel, false)
		gui.set_position(unit_panel, vmath.vector3(480, -50, 0))
		msg.post(".", "release_camera_focus")
	end
end

function on_input(self, action_id, action)

	if action_id == hash("touch") and action.pressed then
		local unit_panel = gui.get_node("unit_panel")
		if gui.pick_node(unit_panel, action.x, action.y) then
			print("panel pressed")
			local move = gui.get_node("move")
			if gui.pick_node(move, action.x, action.y) then
				print("move button pressed")
			end
			return true 
		end
	end
	-- Consume all input. Anything below us on the input stack
	-- will never see input until we release input focus.
	-- return true
end

The panel turns on/off based on messages received and releases focus accordingly. The trick party was deciding where to put “return true” — it had to be where it was shown in the code in order to keep the cursor active on the game world while taking priority when over the panel.

EDIT1: One small bug with this setup is once the panel has acquired focus, it continues to receive input — even when focus is released. I’ve added “print(“action_id”, action_id)” to the on_input and it doesn’t print until the panel has acquired focus. However, once focus is released, it continues to accept actions and print. This is either an error or my part or the game.

EDIT2: Just saw that I was using camera focus instead of input! Oh boy…

I got my unit to move around, but it’s done in a sloppy way. It’s still however progress because I found out how to send the destination of a mouse click to a unit.

Right now the unit moves whenever I click a destination, but the goal is to only allow movement after the move button is pressed — AND — only for the unit that has activated the panel.

Kind of offtopic but it would be nice to read your opinion (on another thread) about all those other engines, the reasons why you decided not to use them, and what you think defold does better (or worse) than the others.

Good luck with the project Raymond, slowly but steady you seem to keep making progress.

2 Likes

I think I found a solution for interacting between the GUI and world — enabling/disabling a GUI node around the game objects that I want to have as destinations, similar to what’s seen here: http://britzl.github.io/publicexamples/gui_follows_go/index.html

Yeah, the input handling is a lot simpler than you think. It doesn’t filter anything. Inputs happen (button presses, key presses, mouse movement, joystick, etc.), if they are bound in your input-bindings file, they get sent to each object in the input stack. That’s it. When you “acquire_input_focus” on an object, it doesn’t “take” input from other things, it just means, “send all inputs to this object too”.

What I usually do is:

  1. Make sure that your gui_script gets input first, and then your “game world” afterwards (using the input stack or some other method).
  2. For mouse events, the gui_script uses gui.pick_node to check if the cursor is over any interactible gui node. If so, it does its thing and returns true to prevent the game world from getting the input.
    2.2. Likewise for key inputs: if the gui uses the input, consume it, if not, ignore it.
  3. Then a script in your game world uses input as usual. It simply won’t receive any input that it shouldn’t be using.

As a general note, this is why people recommend you start with Pong or Space Invaders. You’re trying to climb Mount Everest with one shoe and a ham sandwich. You can do it, go for it(!), but keep in mind you’re biting off something huge, so it’s going to be tough.

There will always be times when things you thought would be trivial will take days longer than you thought. Those times will get less frequent as you learn, but probably never stop completely.

In my experience, GUI stuff tends to be a lot of work. You might consider putting that on hold for now to focus on getting units moving around in the world and some simple but meaningful interactions. You can do everything with hotkeys instead of GUI. Just a thought.

3 Likes

There’s nothing wrong with nil!

2 Likes

Haha, I love it! And it’s true. It doesn’t matter what engine you choose. You will struggle in the beginning, but it gets gradually easier.

2 Likes

@britzl Haha. I wish I could take credit for that one! Someone coined it on an art critique forum years ago, but the site’s gone now so I couldn’t find the reference.

1 Like

Well. I got pretty far with my project with Phaser. I mean, I learned how to set up a localhost server thingie, and got a crude little animation to play on a scrolling background, but it took a LONG way to get there. But then I was like, Phaser is just HTML5 and cant do anything else? It seemed limited to me. I looked at all the examples and they were all these crappy little webgames that no one plays. Like, honestly, how many short, pointless platformers can there be? I guess I’m just more of a PC gamer at heart…I like something with meat, and I couldn’t find any examples of that on Phaser.

Unity for some reason just leaves a bad taste in my mouth. The game company I worked for used unity, and I played around with it back then, and it’s all to slick. Too much marketing. Downloading their launcher had this video playing of all these nerds talking about how crappy their first games were - super zoomed in on their faces. It made me gag. I hate that style of tech-industry feel good corporate shit. You know exactly what I’m talking about. I got VS code and did some basic tutorials with C#, but again, I just felt meh. Maybe it’s the hipster in me refusing to do the thing that is the most popular.

I actually started with Godot - and maybe it was my fault, but I swear I would do the tutorials and the thing just wouldn’t work. I couldn’t understand why it wouldn’t work. I checked everything 100 times. So I quit that one out of frustration.

I could be wrong but I think Defold is a way to make little games that are cool - which I got that vibe from Phaser - but I also do want to make money with it, and it seemed there was money making stuff built in to Defold, and when I saw they were associated with King, I was like…oh yeah.

Then my game idea actually came from my dicking around with phaser. I made a little animation of a knight turning back and forth in like a battle-ready stance with a repeating background passing by. And I was like, you know what would be hilarious? A mobile game where your character moves automatically through a level and is attacked by hordes of skeletons and all you have to do is tap or swipe to kill them. But, I wanted to fill it with as much extra crap as possible. Like an overly-dramatic story with cutscenes, maybe a path of exile type, ridiculously large skill tree, items you can buy in the shop, and perhaps an overworld map Candy Crush style. All with 32 bit graphics. That just seems so funny to me.

Anyway - that’s the game I want to make, and Defold seems like the engine I should use.

I understand this advice; but for me, making Pong isn’t satisfying. It’s extremely more challenging the way I’m doing it, but it’s also more gratifying when I get results.

That’s a possible idea. The thing is, the movement is a key part of the game and I want to tackle it first.

At the moment, I’m figuring out how to use the GUI to send commands to a game object. Defold handles each differently and making them communicate with each other is not so simple, especially when there is a screen and world view to consider.

The goal is to:

  1. Click a unit
  2. Select move from a panel of options (GUI)
  3. Select a destination on the screen to move to (destinations will be buildings (game objects))
  4. Move the unit

I was thinking of having a separate GUI node appear when clicking “move”, but that makes the node appear on the screen — not on the actual game object. So while it creates the effect, it’s not practical.

Here’s a video of where I’m at currently. Notice I can move the units from mouse clicks, but that is not ideal since there will be multiple units. I have the panel working, but I need to use the GUI to select a destination (I think), since that’s what has input originally.

Perhaps I could release focus after clicking move… and then temporarily enable a collision object that responds to movements.

The video also shows how I can create a GUI over a game object, but it doesn’t stay on the game object when the screen is moved.

File size limit for videos on the forums seems to have changed. Having to use YouTube now.

Well, feel free to keep us updated on your progress and particularly any feedback worth mentioning about the experience of learning Defold, but on a different thread haha this one “belongs” to Raymond XD.

If I were you Raymond I would try to find easier alternative solutions to your issues, and by that I mean from a pure game design perspective, not regarding code. Maybe there are other ways to implement similar mechanisms without the game suffering (or maybe even improving!).

Many famous games could only be finished because their creators sacrificed some parts that were problematic. Into the Breach for example, usually regarded as one of the best tactics games from last decade, (google it if you haven’t tried it), had a difficult development and the designers were struggling with several elements from the genre, including map and camera scrolling, fog of war, long term campaign progress… Eventually they decided to cut all those features which allowed them to focus on the things that really mattered, and as a result ended up with an incredible game.

You’re right. I’ve been thinking today about a new and better approach to movement.