Support Me on Patreon

Showing posts with label godot. Show all posts
Showing posts with label godot. Show all posts

Monday, May 11, 2020

And everything changes again.

I LIVE!

A week after the Covid-19 lockdown my laptop's HDD died, and swapping it out was a pain. A few other problems arose and my three-year-old HP laptop dies completely. I was able to cobble together a desktop without internet access (no service where I live). My cousin's phone gets crap reception in my room (but it gets reception); a dongle and tether later I'm able to access the IRS webpage.

Let me spell it out.

Due to my heart condition\s, and the Covid-19 crisis, I'm unable to have gainful employment. I'm also not disabled enough for any kind of help (major vital organ, really?).
My heart is good, just has some electrical problem due to a previous surgery from birth, and other developing problems (my left arm is a bit numb).

I have a lot of aggression. I'd consider it "anger issues" if I didn't have control (I'm being reminded that laziness isn't control). Sterilize-the-planet levels of wrath. This aggression is great for my focus, not so great for my health or control. After the loss of my laptop (and most of my data) I'm livid.

The government stimulated me, so I have a new laptop. I'll spare the details, it's last year's model so I could keep some money. I've meds to buy and plans to lay.

Now where was I?

Little One may have had some files corrupted, I need to re-assemble the project from backups (Always keep multiple backups). I've got some ideas for Adventures' EDGE (I didn't plan well enough for that) and ideas for future projects.

For now I'm just going to try putting all my focus into my projects, and hoping it doesn't hurt me too much. My focus and aggression can cause chest pains, but I'm not sure the precise trigger. Time for some pomodoro rushes.

Pomodoro rush:
The use of several pomodoro intervals (four or more), each focusing on a different task (two or more) in rotation. Breaks optional, but suggested.

So now, my plans:

Little One need to be brought back up and finished, need to ease into that.
Adventures' EDGE might be going 2D. It'll probably get a turn-based battle system as well.
Resources (2D & 3D) might be created and uploaded to OGA.





Friday, April 17, 2020

Eclipse

This post will contain gamedev tips, some concerning Godot, after my depressing rant. I'll pound the area around the rant with some octothorpes.


###   ###   ###   ###
Shortly after the corona virus restrictions went into place, my laptop died. First the HD, after I replaced that the wireless and memory failed. In the end my HP laptop fully failed and I lost most of my files. Thankfully, I had backed up the most important files.

I pieced together a desktop running windows 7 for now. I don't have the money to get internet access where I live, and last I checked I don't get service here anyway. I live in a dead zone and have to choose specific phones and services to even get a small signal. After using my phone at a WI-fi hot spot in town to gather drivers and service packs, I was able to run the godot engine and play some games. During some gameplay on my cousin's Xbone, we discovered his phone gets signal in my room, in a very specific area. I'm now connected to a hot spot that isn't much better than dial up.

I'm going to gather my files and try working on games again soon, but with my more limited resources, I'll have some difficulties uploading updates until I can either get better internet or a laptop. It doesn't help that my focus seems to cause delayed chest pains. Since I have no idea how to avoid that, I must fight my own coping methods, ignore the pain, and push myself. While not the best idea, I haven't many other options.


Aggression is great for forward momentum. More dangerous and stimulating than coffee.

###   ###   ###   ###

Since I'm slightly depressed I guess, not feeling myself, I'm going to take a break from Little One and fiddle around with Godot some. I'm interested in procedurally generated maps, mostly 2D tile maps. There are great tutorials on using noise to make these maps, mostly.

I found using the help search in the script section of the editor rather useful. Mainly I just generated a flat map that sets either dirt or stone based on the height. This is slightly randomized and doesn't use noise, but noise could be used. I've got a function that makes noise for the caves and removes tiles based on the value when I get the 2d noise of an area. It has seriously reduced the amount of code I need and the map looks better.

For ores I'll be using different noise, choosing an area, and setting ores by height. Overlapping the ore heights will make things look more natural. I'll mostly be replacing solid blocks in chosen areas, with numerous areas randomly sampled or sampled through another method. Once I have the noise modified the way I want, I'll use different noise to shape the hills.

The map will be in three layers; land, fluids, and backgrounds. Fluids will be randomly placed and filled, but will also rely on the land map for placement and flow. Trees and plants might be on the BG area. I'm not concerned with good-looking details, and much of the gameplay will be a mix of minecraft (water,trees), starbound (mining, tools) and terraria (combat, weapons) with some mechanics from interesting mods and myself thrown in (tool modifiers, bombs).

For falling blocks (sand, gravel) I'll most likely remove the tile and add a kinematic object that becomes a tile again once it stops falling. Liquids will be handled as closely to minecraft as possible. Block placing will remove liquids and infinite pools will be planned. Mostly this is because I'm lazy and I don't think godot has fluid dynamics.


There are ideas and plans for this project, but for now it's just me tinkering. Now for some tips.

The noise seed can either be randomized, or you can use a specific world seed.

Write different noise functions to generate noise for different parts of map generation.

Creating functions to generate noise based on parameters will allow easy modification.

Tile Maps can use kinematic physics, or the parent  node's physics. This should allow an area to be used for the liquids.

A tile map's tile set can be changed or modified during game play.
 Swap a tile and nobody cares, swap a sprite in the tile set and the whole map updates.

"invx128y32" Use similar keys in a dictionary of inventories to keep track of chests at almost any position. I just hope some player doesn't try filling the world with chests. X & Y should correspond with the chest's position.

If the map is modified by the player (mining, bombs) write a function to check surrounding tiles for any actions they need to take (flowing, falling).

Liquids should try flowing down first, then sideways. I'll most likely place iquid tiles below and flow tiles to the side

Create dictionaries and lookup tables to keep track of tiles and what can affect them.


And finally:

Map generation can take some time with all the loops and actions. Rendering the map as it is generated can cause even more lag and freezes.

Set the tile map's visibility to false before generating the map, then back to true after. The map generates far faster with no visuals.






Thursday, January 30, 2020

Naughty Plot

This post will cover ideas and tips for the more mature game types, however I'll be avoiding vulgar or descriptive bits. Not like I'll ever make one and most of these tips can be used for virtual pet games.

Rub-a-dub:

Touching, poking, or petting is relatively straightforward. Either an invisible collider or area is attached to a bone and may have metadata attached. This attachment is usually set to detect mouse or touch inputs. Using signals connected to a script can turn that input into variable values to change a character's mood. This is usually the easiest mechanic to make, but the longest to perfect.


Designer "pet":

Character creation systems are nothing new, but how they are handled relies on numerous factors. Doing them in 3D is easiest, but layering sprites or using 2D animation skeletons allow customization in 2D games as well.

You'll first want one or more protoform characters without hair, skin color, or defining features. Their looks can be altered easily with textures and extra items (accessories). Shape keys (vetex animations) can be used to define other body features (nose, hands, etc.). Using clothing textures can be faster than 3D clothing, but can have a few restrictions. 3D clothing can allow inside objects to clip outside. With just a few characters, textured clothing offers few benefits, and combining both can be useful. If there are more than ten animated characters, clothing textures can help with lag if you have it.

This mechanic has many parts to it, don't become discouraged if things don't always work as intended.

Pose this way:

Custom poses can be done in most game engines. There are several ways to do it, even if the engine doesn't allow direct access to the skeleton, blending animations can be useful. Godot allows skeletal access and bone manipulation via script and allows animation blending. Creating a pose can be done by making a dictionary, using the bone names as keys, and adding the bone vectors to it.

Poses are nice for a screenshot, but what if you want the player to make their own animations? Godot allows full access to the animation data via scripting, and should be able to create and save an animation. Of course, building and saving the animation(s) would involve even more work, so providing plenty of animations yourself is a good idea.

If an engine does not allow access to animation data, consider hacking your own in with dictionaries or json files. The mark of a good developer is how obstacles are handled, not avoided.


Make the camera dizzy:

Camera controls can range from great to abysmal, which is why I like first-person cameras. For any "pet" game, it is best to center the rotation nodes on the character themselves. Have two spatial nodes for 3D rotation (and rotating them on individual axes) gives the easiest control. Remember to add a camera reset button to reset the camera position and node rotations (in case the player messes up the camera).

Camera zoom can be done either through movement, or changing the FOV. Checking the camera's distance from a specific point (one of the axis or gimbal nodes) allows you to set limits to how far the camera can go.

This is relatively easy to implement.

Mods mods mods:

Creating or adding mods to the game is usually *technically* possible. Since any engine *should* be able to read their own data formats even after compiling. I'm not entirely sure how to go about it in godot, but there is a way to load, modify, and save almost anything within run. The main problem is making sure resource scenes have everything they need and are organized. While I'm not sure how Godot feels about zip files, a json file in a mod folder could help.

Here are a few ideas:

Putting the mod and associated files in a folder with a json file. The json file would tell the game about the mod, resources needed, and type of mod (character, object, prop, scene).

Having a zip file, with a json file. It's really the above tip, but zipped.

Using  self-contained scene file and putting these files in the appropriate mod folder.

Using a scene compiled to a pck file by the engine, however I'm not sure how this could work. This could make mods easier to load.


###   ###   ###

Warning: inhibitor 34 unstable


Tuesday, December 17, 2019

Yadda Bla Bla Bla Bla







Dialog systems tend to be as complex and as varied as inventories. Once you've created one, others are easier to make. Giving the player choices, branching dialog, or changing variables from the dialog system all make it more complicated. Little One's dialog system is just going to be a direct info dump. There will be text, and a done button when you are finished reading.

Godot has two of my favorite nodes ever, EVER!. The resource preloader contains assets for later use so you don't have to write all the paths out. The rich text label is a force unto itself. With BBCode, word wrap, scroll bars, and metadata links, you only need this node for dialog output. Text can be set as a meta-link that can pass a value via a connected signal. You can then do various things depending on the meta value passed.

My main dialog output setup consists of a panel with the rich text label as the child. The panel has the script, but the rich text label does all the work. I usually set a custom font since Godot only has one tiny, terrible font. The meta link is underlined by default, but I add BBCode color and center it to make it more visible. Several meta links can be added to the dialog and consist of the data passed and each attaches to the next text or BBCode string added.

The worst part of a dialog system is actually creating the dialogs. I'll be using a preload script with dictionaries and functions to randomly select text strings. Day zero will mostly consist of hints and tips for the game. Just make sure that if you pause the scene, you don't pause the dialog output.

I usually connect a signal from the player to the NPCs and from the NPCs to the player. If you have limited NPCs and everything is grouped correctly, this can be done at the start of the level/game. If the NPCs are numerous or randomized, this can be done when you interact with the NPC. Just remember to check if the signal is connected, godot doesn't like reconnecting existing signals.

With this basic setup I signal the NPC (and pass a value so only that NPC answers) to talk. The NPC then gets the text and signals the player with the required information. Now the player passes the data to the dialog system to format and output the text. I've started just calling a function from the dialog system in the player's script. Since I've learned that you can just call the functions from a node's script I might connect and use signals far less.

Direct-calling functions might replace generated signals, but it cannot replace all signals.





Friday, December 13, 2019

Player: ReLoaded

Finally got the player model imported with animations. At first, I just added the animation setup to the player scene, but I knew I'd need to refactor the player. Starting with a copy of the animation setup, I copied the script and test room then started working. Referencing the original player, I added all the accessories and gave them the groups and signals needed. Since so much had changed, minor edits were required for the script's copy.

Initial tests went well. Objects fired at near-lethal velocities, so I had to scale back their speed. Vacucel aiming was a bit off, so I adapted it. Items were collected slightly better and faster. All the buildings and menus thus far work.

The major problem came from the water pools. Water was being spawned, but it kept falling into the pool before collection. Most times it wouldn't seem to appear. After some debugging (print statements) the problem was located. For some reason, the water was spawning too low. I just added an extra unit to the spawn's Y axis for a quick fix.

I'm not looking forward to adding the dialog system, but that may come next.

Tutorial, How to Debug Code:

Most times when there is a syntax error, you either get a warning or a crash. Most script editors take you somewhere close to the offending line so you can find the problem. With godot, the error is usually above the line indicated. Most flaws are within a few lines of the line indicated, if not the line itself. Remember, these editors are making a best guess, so they can be a little off.

However, sometimes something doesn't work for any number of reasons. Sometimes you cannot see the error because it's logical (and that skill may need a few levels). If a specific mechanic isn't working in a game, your first option is to check the area of code for that mechanic. Usually, this is contained in a function for ease of use. Often, just looking will reveal the problem.

If not, I like to add print() statements in the code and output different strings or values. hen the statement at the top of a function doesn't print, then the function isn't being called. More code to check, but you could have forgotten to call the function. This is also useful to check if statements in a similar way. When the requirements of an if statement are not met, it won't activate.

Printing variables can help determine if they have the correct values, or that they are being used. An errant or empty value can cause much mayhem. Bad incoming variables are also problematic, so check them if you have them.

If all else fails, get a rubber duck and read the code's lines to it. Then kick yourself smartly when the solution is obvious. The solution is almost always obvious.







Tuesday, November 26, 2019

Grain Drain

I added a save function to Little One. Most of the data was just easy to write to the file, but the buildings had to be formatted. Writing the dictionary for the buildings didn't take long, but I've had to add values throughout. A dictionary for the wild plants was also needed. Then I had to make sure the build platforms saved their own values while the buildings saved their values.


The fields seemed like a good start, both wild and domestic. They mostly went off without a hitch, but I had some bugs when I programmed out an exploit. Storage was next, and I gave it little thought before moving to the critter pens. Those pens had a few bugs, but the critters were missing. I had to modify the re-parenting function so they'd work, but the critters never seemed to load. Turns out, they did load, but kinematics and rigid bodies don't like each other and critters got flung.

Last night I checked to make sure everything was working, and the storage buildings were not. I was trying to get values from an empty dictionary within a dictionary. Putting the storage cell generator in the global dictionary worked, but I had to modify a few things. Today I added a few new grain plants just for something new. Most of the plants are modeled, but I need to tweak them.

After all that, I'm going to rest before I add more content. This whole project has taught me valuable lessons I'll carry into the next project.

Thursday, November 21, 2019

Saving Games

Godot Engine already has a tutorial about saving games here, but it may not be for everyone. Basically, it grabs all the nodes in the “Persist” group and writes them to a file. It does this line-by-line, but you might just want to dump a dictionary to a file and grab it again.

I'm assuming you are using a singleton (preload) scrip that holds the game data. Singletons are scripts that load before any others and can hold persistent data for the game. Dictionaries are a complex datatype that can keep things organized. Since dictionaries are passed by reference, they are easy to keep updated.

func save_world():
    var saveFile = File.new()
    saveFile.open("user://savegame.save", File.WRITE)
    saveDat["Cells"] = cells
    saveDat["VacDat"] = vacDat
    saveDat["PlayDat"] = playerDat
    saveDat["Storage"] = storeDat
    saveDat["MatDat"] = matDat
    saveDat["BuildDat"] = buildDat
    saveDat["RingDat"] = ringDat
    saveDat["WorldDat"] = worldDat
    saveFile.store_var(saveDat)
    saveFile.close()
   
    pass



 Everyone will tell you that you don't need the "pass" keyword. They are correct, "pass" is used to skip empty functions and does no harm at the bottom of a function. I usually start two or more functions at once and use pass so I don't get errors or red lines as I work on individual functions.

First I created the "saveFile" variable and created a new file. Then I opened a file I intended to save to. The file does not need to exist if you are writing it, godot will automatically create a new file. It is best to use the "user://" location as this is a location that the game is allowed to write to. Now I assign the different variables I want to save to a single variable I initialized at the top of the script. Then the variable is stored in the file and it is closed. Remember to close the file to avoid memory leaks.

func load_world():
    var saveFile = File.new()
    if not saveFile.file_exists("user://savegame.save"):
        print("error, no save file")
    else:
        saveFile.open("user://savegame.save", File.READ)
        saveDat = saveFile.get_var()
        cells = saveDat["Cells"]
        vacDat = saveDat["VacDat"]
        playerDat = saveDat["PlayDat"]
        storeDat = saveDat["Storage"]
        matDat = saveDat["MatDat"]
        buildDat = saveDat["BuildDat"]
        ringDat = saveDat["RingDat"]
        worldDat = saveDat["WorldDat"]
    saveFile.close()
   
    pass


Now to load the data back. First we need to create a variable and open a new file. Variables initialized in a function can only be used by that function. Next, check to make sure the file actually exists, since we are getting data from it. I don't check to see if the file has any data since it should be in there.

Open the file and assign the data to another variable, the one initialized at the top of the scrip should work. Now we just apply the different key values to their respective variables. I'm not sure if different keys are passed by reference, but I think it depends on the variable's type. Finally, close the file to prevent memory leaks.

Feel free to reference godot's save tutorial if you want to try different ways of saving data.











Tuesday, November 19, 2019

The Rain in the Game Falls Mainly on Nothing?!

There are many ways to do rain and other weather effects. Some games use particles, which can clip through objects. A few just add/remove objects, but the physics needed and constant object flow causes lag. In 2D it can just be a screen effect. A few use shaders or have dedicated weather systems. For newer developers, that don't have the resources or experience, rain systems can seem awkward.

Either you have particles or objects, but those either clip through objects, or cause lag. I've found another way. First, a little advice and an example. Everyone seems to think the rain needs to fall, preposterous. Take two coins, fairly new ones, and stack them between your thumb and pointer finger. Now rub the coins together, slowly getting faster. If done correctly, three coins should be visible. It's an optical illusion, the same as an after-image that some anime characters can create.

How does this help us create a rain system? By taking several rain meshes and shuffling them around the player, we can cause an illusion of rain. I'll walk you through the steps.

First, make two rain objects, a drop and a splash. We'll add them to a parent object/node as meshes with a basic water or blue texture, no colliders or transparency needed, just meshes. I like to add each to a different group or have some other way to grab them from code. Don't try to grab them directly or through paths, we're going to copy them. The scene should be a parent node with a few dozen drop/splash children.

Make a few dozen copies of the drops and splashes. Add the scene to a scene, preferably as a child of something positioned at (0,0,0). Now let's create a new scene with any positional node. Since I'm doing 3D I'll use a spatial node. This can also work in 2D with minor adjustments. Add a raycast and make sure it is casting down (-y) by about 300.  Move it up to +y 200/250, make sure it is active as well. Create copies and change their x/z to whatever you feel like. Keep them relatively close to the center, but not on the center.

About 12-32 raycasts should be good. Add a script to the top (parent) node. The scene should be a parent node with a few dozen raycast children. On ready you should get the splashes and drops from the scene tree using groups. If you've added the raycast scene to the same parent you added the drops scene to, you can just get the parent and then the drops scene's children. Either way is good.

Get the raycasts as well, you can just add the children to a variable. Get the player node/character as well. You should have two main functions, shuffle_rain and unshuffle_rain. The unshuffle_rain function should just get all the drops/splashes and place them somewhere hidden. I suggest changing their translation to (0,-200,0).

The shuffle_rain function is a bit more complex. Grab a random raycast, drop, and splash. Check that the raycast is colliding and get the collision position. Place the splash at the collision position, and the drop at a higher position. You can add a random number to the position's Y axis.  You would do this several times a frame, feel free to experiment.

The final things to do is to get the raycast parent to rotate and change it's X/Z translation to that of the player. Randomizing the Y rotation can help make the rain move more randomly. Now all you need is signals/Boolean to start/stop the rain.

No odd clipping, no lag, no physics, easily editable. It's a good rain system if you want something easy to implement.















Monday, November 4, 2019

A Small Matter

It always seems like two steps forward, one step back when you are a singular gamedev. I'm having problems with the textures/materials in Little One and there is still so much to do. Sometimes I wish these problems didn't happen, but I enjoy solving problems. Once the material problem has been corrected, and I know a good way to correct it, I'll start adding and testing the final mechanics.

The dialog system is in another project and needs to be modified for Little one. Player and NPC models are mostly done, just need textures, animations, and a few minor accessories. Critters need some more programming and they'll give way to beasts within the game. Building upgrades need to be modeled, textured. and fully implemented. There needs to be a way to dispense materials from destructible objects. Many of the parts and player upgrades need to be coded and implemented. Opening and ending scenes need to be done along with success/fail conditions. World data and save/load systems need to be finished.

I should do some planning on the final parts needed. Most of the player upgrades are partly implemented. There is a collection on open game art that has resources for Little One, as well as what I'm making now.

Speaking of planning, I'll be planning a project a bit this month. If I finish Little One this month (November 2019) I can work on another project in December. Little One will have taken about five or six months at the end of November 2019.

I wonder if I can make a bigger game in two months if I planned it well.

Monday, September 30, 2019

Node of Command

So I told the build menu, to tell the build system, to tell the building; to upgrade. This all while the game was "paused". Any node with a script is able to get another node to run functions within their script. Something like node.function() where node is the node that has the function, and function is the function. Clear as mud until you try it.

This is great in situations where signals may be too troublesome to set-up. I'm not talking about default signals, but custom connections. It is also helpful where you can get or pass a node with w function you want to run. Not sure if you can run a node's functions on another node, but if I can I'd probably crash the engine every day. Might try it just to check.

The game is never truly "paused". Pausing the scene tree in godot just pauses processing functions (process, input, physics). Signals and calling other nodes' functions from an active node still works. (Running the _process function on a node from an un-paused menu node might crash godot) This means I can cause NPC expressions, object building, and general mischief while the game is paused just from a single active node. Cascading function calls anyone? (How to mess with the player, 101)

Arrays (really?) and dictionaries are passed by reference, not copied. This means that if a node's script sets a dictionary as equal to another dictionary, changes are synced across all instances of this dictionary. So my silos will grab the parent's exported dictionary which will be referenced from a global building dictionary (or even a nested dictionary). So updating the silos when you add/remove items will update the master dictionary.

And there are still tricks to find.

Thursday, September 26, 2019

It's a cube, it's a sphere, it's a placeholder!

Added a build system to Little One. I'm currently using placeholders for the upgrades and a couple of buildings. So far it is going good, but there are only upgrades for one building. The upgrades are hidden below the building and moved up once activated.


As you can see, the buildings can be created, deleted, and one can have upgrades. The final version will require materials to create the buildings and upgrades. After the upgrade placeholders are done, I'll add the actual upgrad objects and material requirements.