patchyparrot
patchyparrot
Patchy Parrot
7 posts
Don't wanna be here? Send us removal request.
patchyparrot · 2 months ago
Text
One little Game Jam
Woah, was it a saturated month! Or two months? So many things happened, and I had a pretty valid reason to not come here for so long. First, I had a vacation and was out of the country, then I fell ill. Then immediately ill again. And then ill! Again! And then we had a Game Jam at my job. And that's what I want to talk about. It gonna be just as long as my absence.
Now, this Game Jam was hosted by a mobile game company, who was hungry for fresh ideas - preferably match-3 or hidden object ones. They wanted these ideas in a form of a power point presentation, and no one was looking for new mechanics. You could make a prototype, but it won't influence your chances. So as you might imagine, this was a quite boring jam! But the boring jam had a cash prize, and the task sounded like something suitable for my skill level. So I decided to try anyway. Two colleagues joined me and agreed to do arts and stuff.
While we were waiting for jam's requirements to be announced, I made some preparations in advance. I made a test...err...gaaaame? to see if I truly understand how to do hidden objects. I downloaded a plugin which should have turned a PSD file into a scene in godot, and tested it. It worked perfectly, although I had to contact the plugin's creator for some instructions. I also wanted to make randomized placing of objects in the scene, so each time someone plays the game, they will look for different things. I would have had a scene with all possible objects placed on it but hidden (keke). The list of these objects would have been an array, from which you take five random things, place then into a new array called "the task", and then unhide in the scene - alongside with several distractions. The player would click on objects, the program would compare objects to the list and then tell the player if they were correct. I haven't finished that, however, because there was not enough time. The jam started, and with it came the hustle.
First obstacle raised up immediately. Upon reading requirements for the presentation it became clear that I have to join my colleagues in arts and stuff too, or we won't make it in time. The time was suuuuper limited - only two days. And at first I felt pretty discouraged. My whole point to take part was to challenge myself in programming, not writing or talking to AI-generators. However we chewed through the problem surprisingly fast, and at least I could dedicate the second day to what I truly wanted. Which, as you would imagine, gave a whole new level of complexity!
Then the second obstacle came. The psd import plugin, tested and working, now refused to do shit! It just ignored me. No complaints. No errors. Just gfy. Ugh, umh... happily I kinda felt that things will go south, and looked up for workarounds beforehand. There is a way to export layers from PSD file so they would keep the original dimensions, so they would be automatically placed where I need them in godot if imported in a batch.
Tumblr media
Third obstacle was lack of time to make the array thing. Even the routine things like bashing together Dialogic nodes took surprisingly much time. Or rather, they took very little time, but there was a lot of them. I needed to recall how arrays work, to test my idea, to make sure I did not break something in the process. I needed some kind of a workaround. And the workaround I found was somehow the most programmer thing I did, but also the most embarrassing thing I did.
Tumblr media
Without a better idea I just wrote the same script to each and every object the player will be looking for, only changing the signal name. Should they all be a class or something? Of course. Should they have only one shared signal and only one shared function? Absolutely! But I am an idiot with roughly six hours left.
I wrote some dialogue without thinking, and it worked. Placed characters, made them the proper size and position - all in Dialogic. Tried to change the design of dialogue windows and buttons; windows changed, buttons didn't. Made a menu, somehow even recalled how to make it nice-looking; it worked.
Placed the scene and objects together, and then came the third obstacle - I had no idea how to tell the player that he is good and found all the stuff. Ideally it should be some region on the screen where the objects are listed and then the words grey out or disappear. So probably it should be some container with text labels, maybe....how do you make the text in a label grey?... or strikethrough? Time was growing shorter and shorter, I couldn't google it immediately and had to invent something once again. I had a psd file left after I explained to colleagues how I see the field. And I knew how to change sprites. So I took the buttons from the psd file, made grey and strikethrough versions of it and saved it as plain .pngs, with normal buttons being 0, and grey one - 1. So, on a click on the respective object the sprite would change and the object would disappear. A win!
But that's not the end. Because the end should be defined. How do I tell the program that the player found everything? If I had an array, I would check if its empty. I do not have an array. But I only have 6 objects.
Stay strong, it gonna hurt.
I made a variable with just a number - 6 - and added a string to every object function to subtract 1 and check if the variable is 0 yet. And if it is 0, it calls the "you win" function.
Just look at this abomination. I have six of them:
Tumblr media
Horrible as it was, it was most of the game done. I had to connect it to two dialogues I had written, which somehow worked first try, which was fantastic because I had like 15 minutes left.
Original plan included the Reward sticking to the player's cursor so they could place it where they want in the final location. It would have included an invisible grid and an inventory-like system. But there was no time left and I used in-program animation tools to just whack the Reward on the table and be done. Which was quite the accomplishment for me because I did not even know godot can animate before.
So tested it, exported as an .exe, tested the .exe, and happily uploaded the perfectly working hunchback of a program I created. The next step - the presentation itself - should have been done by one of my colleagues, while my job here was done.
On the day of the presentation the said colleague tested the file on her enormous monitor and found a horrible bug! On each and every screen size but mine the layout was messed up HORRIBLY. It was so bad it sometimes did not even work! I immediately knew what happened. In the hurry I forgot to change window scaling in the preferences, not a big deal. Asked the orgs if I can replace a file, they allowed. I open the project, press "yes" to something it asked me about, repack it and throw into our google disk. Voila! Adventure for one minute.
Except during this time I installed godot 4.4, which had one important change since 4.3. And what it asked me about, was if I want to refresh file paths and use UIDs. Everything seemed to be working, except for Dialogic, which did not get the joke and lost all the dialogues alongside with all the characters. And I only noticed it when the same colleague asked "Patchy, what did you do? You made it worse!" I mean, it worked for me! So now it's less than an hour before the presentation, my prototype doesn't work, I do not have a backup, I have no idea how to fix it, and it's a middle of the week and I have a job to do. I uploaded the old file in hopes that people will just take a brief look and won't try to resize the window.
We didn't win.
---------
Later I returned to this weird new bug. Turned out, it wasn't my fault, it should have worked anyway but had a minor incompatibility with the plugin which is now fixed, and all you need is to install the newest version. It's stunning how the simplest solutions may elude you when you're under stress and in a hurry.
Anyway. It was quite the experience and I understand why people recommend new devs to take part in game jams. I had to mobilize all my elusive knowledge and use the limited tools I have in order to fulfill a goal. Those stupid workarounds there are the result of this determination, and a point into a skill to throw away perfect but unknown and unpredictable solutions and leave the ones working here and now. It makes you evaluate yourself and your knowledge.
I'd love to take part in another jam when I am rested. Now it's time to fill the holes this one uncovered.
0 notes
patchyparrot · 5 months ago
Text
Setting up signals and mouse detection
The title sounds almost professional, lol
Today got to godot again, although nothing particularly interesting. Usually if I have several ideas for something, I leap from one to another, and this is the case. I temporarily moved away from the platformer tutorial, instead trying to figure out what I may need for a tiny escape room game. It's not much actually. What's a point and click game is, when broken down to its simplest components? Basically the following:
Display sprites and UI
Detect clicks on specific areas on the screen
Run some code (mostly change sprites to other sprites and change variables)
Show a cutscene when solved the puzzle
If the first one is super-duper easy and I've done that before, the second one gave me some moments of shame. I've expected it to be two clicks, not a big deal, wheeesh-and-whoosh! But it did not work! Would you imagine?! On the first attempt I connected appropriate signals but placed them in func _ready(), the result was... expectedly bad. For some reason I thought we should check mouse position every frame. Another mistake was to actually call signal-related functions, so instead of checking if mouse is over one of the test shapes it would execute them straight away.
Tumblr media Tumblr media
Oh, and function names are not similar to outputs because at first I drew two shapes via polygon2D, which it turned out does not simply scale. People online said you have to adjust anchor points position instead. So godot logo it is! This setup finally allowed me to detect mouse cursor and scale test images as intended (just noticed the cursor did not make it into the screenshot; its on the purple logo):
Tumblr media Tumblr media
The code which worked:
func _on_triangle_mouse_entered() -> void: print('This is the purple one') $Purple/CollisionShape2D.set_scale(Vector2(1.25, 1.25)) $Purple/Icon.set_scale(Vector2(1.25, 1.25))
func _on_purple_mouse_exited() -> void: $Purple/CollisionShape2D.set_scale(Vector2(1, 1)) $Purple/Icon.set_scale(Vector2(1, 1))
func _on_rectangle_mouse_entered() -> void: print('This is the green one') $Green/CollisionShape2D.set_scale(Vector2(1.25, 1.25)) $Green/Icon.set_scale(Vector2(1.25, 1.25))
func _on_green_mouse_exited() -> void: $Green/CollisionShape2D.set_scale(Vector2(1, 1)) $Green/Icon.set_scale(Vector2(1, 1))
(jee, there must me a better way to paste code into tumblr)
Area2D refused to scale at once too, throwing its children all other the canvas, so I had to scale the children separately. No idea why is that and if there is a better way. But it works.
And lastly the code for checking for a mouse click, so my holey memory did not lose it.
func _on_purple_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void: if event.is_action_pressed("click"): print("something")
I did not even open the input map before (however I have a shadow of a memory of a tutorial where you have to), and it was a pleasant surprise how easy it was to set custom inputs. Basically similar to changing key bindings. It allowed to count as a click touchpad click and phone tap at the same time.
I can now get to drawing first sprites! You know it's so funny how happy all this is making me. I realize how basic this knowledge is, and how infinitely far away I am from being an actual developer. And yet there is a bit of a pride. This may be how people feel when their toddler makes his first steps, clumsy, silly and immediately falling. But through this falling he will one day run.
0 notes
patchyparrot · 5 months ago
Text
I made it! it now properly shows health in pics!
Tumblr media
(It's not dynamic atm as I haven't figured out yet which part of the script is the best for calling the function, but I'll invent something later)
The tutorial I mentioned before was not exactly what I needed, but it pushed me in a right direction. It handles damage and HP as a separate script (mine is divided, health is within the player, on-screen UI is within the level function; should do something about it in the future), thus the Damage function calls the HP-Drawing function. I'd love to have a dedicated script for such things as damage and Player-related UIs, only thing left here is to find a way to have one Damage function for ALL enemies. I.e. damage and stuff are different for different types, but all enemies are doing the same, basically - detect and hurt the player. Right now, though, I had to somehow connect different scenes and scripts to make it work with what I have.
Another thing had to be changed is what's inside the box container which is going to handle the picture. In the tutorial the author puts texture rectangles into the container beforehand, and then checks whether they should be visible or not. Not all games have a static amount oh max HP, and I would like it to change sometimes. Why not make the program put them there for me, using data from a dedicated variable?
I made a microscene with a sprite inside, and instantiated it. But oops, it kept appearing in one spot for some reason. Turned out box container does not fully understand non-control nodes and ignores their size, stacking them. So I switched type of the root node to control with a texture rect inside. It was better, I could see all hearts (or rather their left halves). During tests, I put texture rects inside of the container manually, so it was wrong, obviously, and parent control node probably was excessive. I removed it, and voila!
Of course there are better ways to do all that, maybe without a separated scene, or...some other way? But it's the future problem. For tonight, I am a happy and accomplished person.
1 note · View note
patchyparrot · 6 months ago
Text
A dev...log??
Did some more learning today. Figured out partially how does theme editor works (pretty easy in fact; reading their docs was sufficient). You can even pick 9patchrect for your buttons! It may be a very common function, but I have no idea if it is since I'm super new here. I've also set fonts and colors here and there.
It's a little bit non-intuitive to set margins in a margin container. If I forget about it, it's in the dropdown menu to the immediate right from the theme editor. You can also pick there other unpickable sections, like panel for example.
Tumblr media
After setting up buttons, colors, margins and sizes, this is how my test menu looked like. Still clumsy but hey, it's only the start.
Tumblr media
After that, I returned to the freecodecamp tutorial. I've done everything before script polishing and collectibles, and then got distracted by questions popping into my head. Like, the author mentions death animation, but does not actually get to it. How do I do that? He also mentioned animation tree, but again, skips that. What is that? What is it for? He makes lives count as a number, which is the most easy way possible. But it's not too pretty. How do I set them as a sprite, or a bar? I have some cute pixel bars, would love to use those. I made a list on trello of all the things I would like to make.
There are bugs already! I've set some ledges and platforms and placed enemies on them to see how they act if I am underneath. Expectation: they chase the player, still. Reality: They chase the player. But there is a catch. The catch:
There is also another bug(?). As you jump on the enemy, it dies, and plays death animation. So at some point closer to the end of said animation the player is standing on air. I do not understand what to do with it yet, how to turn off collisions for this short moment. Maybe replace the enemy completely with some animated sprite? This may actually be good, since many enemies may share the same animation.
Watched some other tutorials. At this point I start to notice how many people write really weird code. Some delete default movement functions and replace them with their own code, changing just a couple of parameters. Hopefully it's to show it to newbies and explain what does what, but...I have my doubts. People with unnecessary if statements where signals do the job just alright. People doing UIs through a Node2D with static Sprite2Ds inside. Idk, I do not see any sense in those. Even the tutorial mentioned above placed damage function into the enemy scene, not the player scene. I can see some future problems with that. What if we have dozens of enemies? They all do the same - deal damage. Writing the same func again and again would be obscure. Obviously there should be a better solution. Placing it into the Player scene, and define enemies by a class or boolean? Here is one more question to find an answer to.
For the lives as sprites I found this video:
youtube
It's not 100% what I am looking for, but very close to.
As a wrap-up, some plans I have for this tutorial project. In the files you download for the tutorial, there is A LOT of stuff. It's huge! There are swamps, mountains, different forests, winter and smaller "unfinished" sets like lava or castle. I just want to turn it all into something actually playable. Even if the game will be small and clumsy.
Some things are missing though. Like there is no good transition between the grass tile and the earth tile; border between the two is way too sharp and obvious. There is no tall grass and only one crooked tree. Some enemies only have one move. I'll have to draw some of them.
4 notes · View notes
patchyparrot · 6 months ago
Text
I was following this tutorial some time ago. It's good but lacks some important things, like player death animation. Which I decided to add myself - to test what I've learned.
Apparently I've learned not much, because it immediately did not work. I could either have the animation changed to death animation, or do queue_free and other stuff. But not together. It would just show first frame of the intended animation and then nothing. Then I've added some print()s so I could see where does it break, but it marginally helped - all I've got was the very first log, but, oh, was it in IN QUANTITY! Dozens of "animation starts" notes. This kept me awake at nights for a month which is a lot, but not so if you work and attend lessons, barely scraping time for anything else.
Today I may or may not have a breakthrough. Dozens of messages may have been the result of this code being in the _physics_process function, which is called every frame. So my code was called every frame, too, starting the animation again and again and again. I've also forgot to remove the "loop" flag from the said animation, which was like a broken nail during a tornado of course, but it's not good either. Quick googling revealed an easy and popular solution - to make a boolean variable which will become false at the end of the required function, thus preventing it from being called again. It worked the most smooth when I applied this variable to the _physics function itself, only going to the death function if normal flaw of thing is broken (i.e. player health is zero).
And it worked now! ...uh... mostly. It would change animation and count the timer, and then quit the game. But once the timer is replaced with what's supposed to be the animation end signal, it just plays said animation indefinitely. So, I got signals all wrong it seems. Did more googling on the matter. People suggest many various solutions, but each and every one starts with "why won't you use the state machine bro?"
Well... At least I know my next stop.
1 note · View note
patchyparrot · 6 months ago
Text
About me
As a first post here and a starting point - a little bit about me and what I have in mind.
Call me Patch. My whole life I loved computer games and played them a lot - first when I visited my friend, then - on my own computer. It started with platformers (Lion king, Aladdin, Frogger 2: Swampy's revenge, Jazz Jackrabbit 2, Captain Claw, Woody Woodpecker) and point and click games (Patt-patt, Freddy Fish, Pink Panther, etc). As I grew older and smarter I learned to enjoy strategies, with HOMM3 and Warcraft 3 becoming a thing. And then came borderline obsession with RPGs, especially with Dragon Age: Origins, which felt like a whole other life to live. Such things as NWN and TES did not come unnoticed, too. After I left my university (which is eternity away from anything gamedev related) I learned to appreciate action and stealth games like Dishonored or Half-Life. And then it all make a full circle with Ori and the Blind Forest and Hollow Knight.
Now I work in a game development company as an artist and find myself more and more often thinking about making a game of my own. Nothing professional, though. Because if you make your hobby your job, you lose a hobby.
It all starts small, and at the moment I am trying to figure out how do you do a sidescroller platformer or a visual novel. At first I tried GDevelop, and it was nice, but it quickly became too small for my idea. It didn't work with Unity either and I ended up with GoDot.
0 notes
patchyparrot · 6 months ago
Text
Hello World?
Okay, so I'd like to have a place to keep track of my gamedev attempts as it now seems to become my hobby. Here I'll post my learning progress as well as tips, links and lifehacks I found online.
0 notes