OSU eCampus CS475 Parallel Programming review & recap

This post is part of an ongoing series recapping my experience in Oregon State University’s eCampus (online) post-baccalaureate Computer Science degree program. You can learn more about the program here.

Six-word summary: A well-designed and satisfying course

I feel like I sometimes write these recap articles to complain and warn other students of landmines, but CS475 was what every OSU online CS course should be: organized, succinct, and educational. I learned so much and enjoyed the course from start to finish.

CS475 Review

It only runs in the Spring quarters, but it’s worth holding out for! You’ll learn a lot, the material is interesting, the course is well-paced, and the exams felt fair.

I picked this class because parallel programming was something I thought sounded intimidating and was unlikely to be something I would attempt on my own. I’m very glad I chose it! It was way less intimidating than I feared, and now I feel entry-level competent in a subject I formerly knew nothing about.

Class structure

  • 10 weeks
  • 8 programming assignments where you code, run the code, and then write an analysis of it
  • I spent about 7-10 hours on this class each week, making it one of the lighter workloads in the program
  • Proctored midterm, proctored final
  • Weekly quizzes in Canvas (usually 5 questions with a full hour to answer them)
  • About 1-1.5 hours of video lectures each week (sadly they are without captions, but they are very high quality otherwise)
  • Some code is provided for you to use, saving time for focusing on what the class is really about
  • Instructor attends office hours! He’s really approachable, you should go even if you don’t have a specific question!

The instructor is SUPER active! You can get on a video chat with him – he’s just sitting there at pre-announced times, waiting for people to show up to his video chat room! He’ll look at your code! He’ll talk to you 1:1 about topics! I’ve never had such a productive “office hours” experience as I did in this class, and I didn’t even show up with any questions.

Contrast this with how most classes in this program hand you a problem and set you loose on figuring it yourself (via Google, Stack Overflow, old projects posted to GitHub, etc). There’s a time and a place for that, sure, but for $2000 in tuition I’m happiest when the class makes me feel like I learned something from the person teaching it. I want an experience I can’t get from Google and an independent project. I want an intelligent, skilled person to say “here’s what I know, and here’s how I think about it” and that’s how Professor Bailey ran this class.

Prof. Bailey also sends out an anonymous survey at the end of the course asking for feedback on each and every assignment as well as time spent. He genuinely cares about the class.

CS475 Project Structure

Unlike most classes, CS475 hands you some “starter code” for every assignment. You still have to put it in the right place, call it at the right time with the right data, and format and analyze the output yourself, but being provided this “starter code” was great for a few reasons:

  • Less time spent on things that aren’t the point of the assignment
  • No super fancy math skills needed (the bezier volume calculation formula is given to you, for example)
  • Less likely that you’ll go off into the weeds and do something ridiculously wrong and miss the point of the assignment
  • Less time needed overall for each assignment

This class has you throw nearly 100% of your efforts towards parallel programming related coding and analysis. For those of us with a finite number of hours in a week it was so good to just focus on the subject of the class and skip some of the boilerplate project setup. This class would pair well with another less-time consuming class, if you need (or prefer) to double up.

Most of this class’s projects go something like this: start a new C project, bring in the starter code, refactor/add to it to make it do what you need, write a bash script (or whatever you prefer) to run a loop and pass different parameters to the program each run, get all of the output in your Terminal (some people write it to a file), dump the output into a spreadsheet (I used Google Sheets), create graphs and write your analysis (in response to prompts).

Typical project output – here’s my output from Project 2

Bring these into your favorite spreadsheet software and create a pivot table. Then, generate the needed graphs for your analysis.

Somehow I made it this far in life without ever needing a pivot table. In this class, pivot tables made graphs a cinch.

And that’s pretty much how the assignments go.

I was a bit intimidated by this class before I took it. People say it’s dry and the subject has a reputation for being challenging, so I wanted to show other prospective students what’s actually involved and how approachable it really is.

Tips for CS475

NVIDIA CUDA support is limited on some versions of Mac computers. (For example, Apple just doesn’t support it for OS 10.14 at the time of this writing). If you’re on a Mac, I suggest using the school-provided rabbit server for your CUDA assignments and not wasting hours like I did trying to get it all working on a Mac.

Go to the office hours! Seriously, I went on a whim near the end of the quarter and was surprised to find myself alone in a video chat with the professor. I was just going to lurk but it ended up being a great chance to discuss a bunch of class topics one on one. Another student showed up and he stepped through her previous assignment code with her. You can’t beat the value of having an expert review your code with you!

The exams are straightforward. Some classes in this program use exams as an opportunity to test your speediness and your ability to keep track of registers through multiple iterations of multiple loops, but this class kept it fair and simple: watch the lectures, take notes, study those notes and you’ll do fine! He even gives a generous amount of time for the exams.

Overall, it’s just a high quality course. The lectures were freshly recorded, well-paced, on-topic, and relevant to the assignments and tests. The weekly assignments always looked challenging at first but were ultimately quite doable and enjoyable.

I’ve got just 4 classes left to complete my degree. I’ll be back in the fall quarter for Intro to Networks! See you all then!

OSU eCampus CS344 Operating Systems review & recap

This post is part of an ongoing series recapping my experience in Oregon State University’s eCampus (online) post-baccalaureate Computer Science degree program. You can learn more about the program here.

Six-word summary: Four final projects in a row

CS344 is your chance to work on four large, back-to-back projects that cover a breadth of topics. They feel a bit contrived (ie: more like schoolwork than real-world problems) at times and their application to real problems might be hard to see at first, but there’s no denying it: doing four big projects in a row will level up your skills a whole bunch.

CS344 Review

This course picks up where other C courses left off and introduces some new and exciting features, such as bash scripting and mutual exclusion locks.

The projects are utterly massive – any one of them could’ve been CS162’s notoriously huge final project – and the course comes off as feeling more like an advanced C course than an operating systems course because of it. You do a lot of project setup and boilerplate in this class (but you do touch on a long list of OS topics as well). Sometimes the new thing (whatever the actual point of the assignment was) only takes minutes to add, like a little cherry on top of a 5-tier wedding cake of a C project.

Class structure

  • 10 weeks
  • 4 programming projects with about 2 weeks each
  • Bash and C programming language
  • No midterm, open-book (but timed) final
  • Due dates are kinda all over the place, best to triple-check them (they don’t follow a pattern)

Grading script FTW

CS344’s best feature is the clarity of its expectations. Unlike many of the courses that came before it in this program, this one is VERY CLEAR about what’s expected and how you’ll be graded on it. They hand you a grading script that runs your program code and spits out a list of results (pass/fail) or something for you to interpret. When it all passes, so do you. It’s that simple.

Overall, this class is fair and straightforward. It’s one of those classes you just gotta be disciplined and hardworking in, and it’ll reward you by introducing you (in a fairly friendly way) to topics such as sockets, locking threads, writing bash script, making your own shell, and more. I’m not sure I would have pushed myself through some of this stuff on my own – the project where we wrote our own shell was definitely intimidating at first – but I’m glad the program included this class and these opportunities. I think I learned a lot in CS344!

Tips for CS344

You don’t have to code on the school server. The class will tell you up and down and over and over to code in VIM on the school server. You don’t have to. I did the whole class on my MacBook in SublimeText and I transferred the files to the school server for testing using FileZilla. It’s just bash and C code, there’s no reason to isolate it the way the class tells you to.

I think this whole “only work on the school server” stuff is bad advice. The programs in this class are large enough to justify a text editor and working locally makes it easy to use version control (which you should absolutely be using – at least one person in my class lost their work by compiling over their .c files on accident :( ).

I kinda wish I’d taken it alone or with a less time-consuming class. I paired it with CS340 (Databases) and the two classes just took turns being hellishly time-consuming. It’s like right on the fence of being a “better off alone” class. By itself it might’ve felt light, but paired with anything I was constantly strapped for time. YMMV.

Tutorial: Making a variety of 2D particle effects in Godot 3.1

In this tutorial: a step-by-step guide to making a few different particle effects in Godot 3.1. This guide assumes some familiarity with the Godot game engine.

I recently started adding particle effects to my hobby game project but I found that while the Godot docs offer a pretty good introduction to particles, I was still a bit lost when it came to some of the more advanced features like color ramps, stacking particle effects, and controlling them through code.

Note: the illustrative gifs I made for this guide run at 8 fps. They look a lot smoother in-engine and on target.

Godot 2d particle tutorial #1: floaty sparkles from a cauldron

I have a giant pink cauldron and I want it to “emit” pink sparkles that fade to white and disappear.

A sparkling pot of sparkles (the jump is just the gif looping, it runs smoothly in-game)

All of these begin as a scene (their own scenes, for the sake of organization) with a Particles2D node as the root.

The little yellow warning triangle tells us we need to assign a material to this particle effect, so in the Inspector scroll down to Process Material, roll out the bar and click where it says [empty].

Choose New ParticlesMaterial.

You should now have a steady stream of white dots in your viewport. These little white dots are just the placeholders for sprites you’ll attach to the effect later.

Click on ParticlesMaterials to roll out all the tweakable properties. (There are many and this guide covers some of them in more detail.)

Flipping gravity

First thing I did was reverse gravity from 98 (heavy!) to -30 (floaty!) so that the little particle dots emit upwards.

A negative Y value makes particles appear to travel up instead of down.

Changing the emission shape

Next, I changed the Emission Shape to a box and gave it a height and a width. This area represents the space in which new particles can spawn.

A short, wide rectangular box

Hey, it’s starting to look like bubbles floating up from a cauldron!

Adding a sprite texture

The next step is to add a sprite texture. I have an 8×8 simple “plus” graphic to serve as my sparkle for now.

Grab that sprite graphic and drag it over to the Textures > Texture field in Inspector tab like so:

Voila – the white dots are now white plusses.

Adding randomized rotation to each sparkle

Back in the ProcessMaterials section of the Inspector, open up the Angle property. If you just type a rotation value for Angle, all particles will emit at that angle. Increase Angle Random to 1 to generate every particle at a random angle.

Setting Angle to 45 and Angle Random to 1

Now we have randomized sparkle rotations.

(This gif is a lot choppier than how it looks in-engine.)

Adding a color ramp

I want my particles to start one color and fade to a different color as they reach the end of their lifespans. That’s easy to do with a Color Ramp. In the Color section, find Color Ramp and click on [empty]. Add a New Gradient Texture.

Click on the new GradientTexture to add a Gradient Map.

Click on that new Gradient to access the actual color gradient.

Here’s where things got unintuitive for me. The biggest hurdle was realizing the box to the right of the gradient is a button! I also didn’t notice the vertical adjustment boxes, since they start out at the extents of the gradient and are easy to overlook until you know they are there.

This gif attempts to demonstrate the color gradient UI.

How to use Godot’s gradient editor.
  • Slide the vertical boxes left/right to adjust how much of the gradient is dedicated to a particular color
  • Click on the vertical boxes to open a color picker (it’s easy to accidentally dismiss the color picker, as I do in this gif at least once)
  • Click anywhere in the gradient to add another color
  • (Right click on a box to remove it – not shown in gif)
  • With the color picker open, slide the “A” slider to adjust opacity.

Here’s what I went with for my pink-to-white cauldron sparkles:

Now you can see the sparkles starting out pink and turning white as they reach the end of their lifespan.

I saved this particle effect as its own scene, then place it (via drag and drop) into the scene where I want to use these particles.

From here, I continued to fine-tune their properties: I made their spawn box wider to better fit the width of the cauldron and I changed their gravity to -10 so they would float slower. I think there’s always going to be a bit of try-and-see-then-tweak-again when it comes to making particle effects, or at least that’s the case for me.

Godot 2d particle tutorial #2: ghostly glow on defeated heroes

From here on out I’m going to skip the setup steps covered in tutorial #1 and just show you some of the effects I was able to make and what parameters I used to achieve them.

Here, I wanted a ghostly “cloud” to surround defeated heroes.

I wanted the “ghost glow” to follow them around as they walk, so I made it a child of the hero node.

However, I control its appearance through script like so:

func ghost_mode(ghostMode):
if (ghostMode):
print("ghost mode on")
$body.modulate = Color(0.8, 0.7, 1)
$particles_ghost.set_emitting(true)
$particles_ghost.show()
else:
$body.modulate = Color(1, 1, 1)
$particles_ghost.set_emitting(false)
$particles_ghost.hide()

Parameters used to achieve this effect:

  • Amount: 9
  • Lifetime: 4
  • Preprocess: 3 (this makes it behave like it’s already been running for 3 seconds we don’t see the effect “start up” when we enter a scene where this effect is playing)
  • Emission shape: box (5x5x5)
  • Velocity: 10
  • Scale: 0.55 (because the puff png is too big otherwise)
  • Color ramp starts transparent and ends transparent, with purple in between
  • Material: CanvasItemMaterial
    • Blend mode: Add (so it makes things underneath the effect look bright and more ghostly-er)
    • Light mode: normal

Godot 2d particle tutorial #3: Boom! spawn-in animation

For this last one I wanted to achieve a “spawn in” effect for my game’s enemies. I wanted it to be big enough to cover the enemies popping in and I wanted to try layering at least two effects so that it looked like both clouds and sparkles happening at the same time.

Here’s what I ended up with after a bit of playing around:

Incoming! :D

This is two separate particles but they spawn at the same time.

Effect #1: purple puff clouds

They puff cloud is just a chunky Photoshop scribble with some randomization applied. Here’s the puff cloud by itself:

This is the .png used to make it. It’s just a fat brush stroke from Photoshop.

smoke.png

Parameters used to make this animation:

  • Amount: 6
  • Lifetime: 5
  • Preprocess: 0.25
  • Speed scale: 3.8
  • Explosiveness: 1
  • Spread: 180
  • Gravity: -4 on Y
  • Angle: 160
  • Angle random: 1
  • Scale: 0.55
  • Scale random: 0.03
  • Scale curve: Curve texture
Curve Texture is useful for fine-tune control over the scale of the particles through their lifespan. Here they start small, get bigger, then shrink again as they reach the end of their lifespan.
  • Color ramp is a gradient that starts and ends transparent with a solid section of purple in the middle

Effect #2: bright sparkle ring

This ring effect plays over the puff clouds.

Parameters used to make this animation:

  • Amount: 20
  • Lifetime: 1.6
  • Preprocess: 0.25
  • Speed scale: 1.5
  • Explosiveness: 1
  • Spread: 180
  • Initial velocity: 40
  • Angular velocity: 28
  • Linear accel: 1
  • Damping: 22
  • Angle: 45
  • Angle random: 1
  • Color ramp:

Spawning the two effects simultaneously

For the sake of completion, here’s the entire method that spawns my game’s mobs. I bolded the parts that spawn the particles. I add them as a child to the mobScene and show the mob sprites themselves after a brief pause so that the spawn-in animation starts slightly before the mobs are actually visible to the player.

func populate_mobs(mobs):
for i in mobs.size():
var mobScene = preload("res://baseEntity.tscn").instance()
mobScene.hide()
mobScene.set_script(load("res://mob.gd"))
mobScene.set_instance_data(mobs[i])
var p_spawnCloud = load("res://particles/particles_spawnCloud.tscn").instance()
var p_boomRing = load("res://particles/particles_boomRing.tscn").instance()

p_spawnCloud.set_emitting(true)
p_boomRing.set_emitting(true)
mobScene.add_child(p_spawnCloud)
mobScene.add_child(p_boomRing)

mobScene.set_position(Vector2(mobPositions[str(i)]["x"], mobPositions[str(i)]["y"]))
mobScene.set_display_params(false, true) #no walking, show name
mobScene.add_to_group("mobs")
add_child(mobScene)

yield(get_tree().create_timer(0.5), "timeout")
get_tree().call_group("mobs", "show")
get_tree().call_group("mobs", "_draw_sprites")

Parting thoughts (and links to more readings)

OSU eCampus CS340 Intro to Databases review & recap

This post is part of an ongoing series recapping my experience in Oregon State University’s eCampus (online) post-baccalaureate Computer Science degree program. You can learn more about the program here.

Six-word summary: Surprise, it’s a web development class!

You’ll glance at some database topics in CS340, but you’ll put most of your effort into building a big full-stack website.

CS340 Review

Get ready to sharpen your web skills! You’ll work with a partner the entire quarter (try to pick a good one!) to design and implement a website that interfaces with a database. This class is very heavy on web development. You’ll make tables to display data that comes in from the db, forms that can create, update, and delete data, and you’ll need it all up and running on the school’s servers by end of quarter. Course pacing is uneven and the numbering of assignments, projects steps, and assignments is borderline illogical.

I HIGHLY recommend finishing 290 before you take 340 so that you can use your last 290 project as starter code for 340’s. It’s criminal that people say you should take 290 and 340 simultaneously. Don’t do it. One of the last projects of 290 is a node.js website that interfaces with a database, and if you have this project complete, you have a fantastic head start on 340’s website project.

Class structure

  • 10 weeks
  • No midterm, no final
  • Pick your partner in the first week
  • Each week you make progress towards a completed website project with your partner
  • Some weeks require “peer review” in which people from outside your group look at what you turned in and critique it (and you, in turn, review others’ work)
  • Hits hard in the last few weeks of the quarter when you have to put the entire site together. Start early.

The first week is slow: you’ll pick a partner and you’ll import a database dump into the database tool of your choosing. You’ll sit on your hands after this ~30 minutes of work is complete.

This is a good time to figure out what you want your site to be. My partner and I did a museum ticketing system and found it easy to hit all the requirements. Don’t reinvent the wheel here.

Each week you’ll work on an ever-growing document outlining your plans. No one will read it, but you’ll submit it every week nonetheless. There is absolutely no TA feedback at any point in this class. I finished this class without so much as a “Looks good!” from a TA.

About midway through the quarter they’ll give you an assignment to build the HTML portion of your site. If this is all you do this week you’ll probably fall behind, because each week after this has a much higher workload. You should immediately look at your projects from 290 to get started with the routing and db queries once you’re happy with the HTML.

There are no exams and no quizzes.

CS340: Too light on database-specific stuff

For a database class, this class is (sadly) rather light on hands-on query writing. It tries to teach database design, which is appreciated, but I think it spends too long belaboring minutia relating to the design diagrams (we must’ve done three iterations of ours before the precise requirements finally became clear on Piazza). It also spends weeks on the diagrams – one would’ve been enough.

The two places CS340 has you get your hands dirty is on Mimir for a few query-writing assignments and in your quarter-long website project. This is where the class shines: where it’s actually teaching (or forcing you to figure out on your own) how to interact with a database to do something useful.

CS340’s Mimir assignments

Rather than write SQL queries in any kind of industry-standard tool, CS340’s query writing is done in a browser-based tool called Mimir. Deadlines are generous and the work takes maybe 2-5 hours to get through (per assignment). Mimir is slow and the feedback it gives is not as robust as what you might get in a better tool. CS340 does give you the db dump, so you can go play around in a better environment (I used MySQL Workbench) but sometimes syntax that works locally does not work in Mimir.

Nonetheless, the Mimir-based parts of the course are some of the best parts. Experience writing queries is a skill you can take to an interview and job. I just wish there had been more of it.

CS340 group work

“What one engineer can do in one week, two engineers can do in two weeks.” The adage holds up in CS340. My partner was great, but I think I would’ve moved faster through the project without having to coordinate with someone else. There’s a lot of overhead in keeping someone else in the loop, not duplicating work, waiting for input before continuing, etc.

A few weeks into the quarter, everyone gets assigned a random group of 5. This is your “peer review” group. (Your partner will be in his/her own peer review group). Since 340 doesn’t seem to feature any TA feedback, this is what the class gives you instead: feedback from other students who probably know the same or less than you do about what you’re working on.

The real kicker? You have to bring their feedback into your document and either act on it or explain why you chose not to. The feedback we got was generally useless: at best it was people pointing out UI bugs we already knew about, at worst it was a hot take dashed out 2 minutes before the feedback was due that suggested little to no reading comprehension on the reviewer’s part. At least we didn’t have to all meet at the same time like we did in 361.

Our CS340 project

We made a museum ticketing system. This project was a bit large for the time given but I enjoyed working on it.

In our app, you can add museums, add exhibits to museums, “sell” tickets to guests with a variety of exhibit entitlements, create new guests, add orders to existing guests, search for tickets by ID, date or transaction, view transactions, refund exhibit entitlements from tickets, and refund tickets themselves. You can also rename exhibits and museums, and update guest info.

We used Bootstrap on a node.js/Express/MySQL stack. (I’d have preferred to use an actual front-end framework but my partner was much newer to all this so we went with a nice big bowl of JQuery spaghetti instead.)

Here’s a few screenshots from our completed web app:

Our app’s default page – you can change which museum to view tickets and exhibits for.
Here’s the “sell tickets” flow, where the user chooses which guest types to create tickets for as well as a visit date.
The user can manage which extra exhibits each guest ticket should have access to.
Review your order before proceeding…
Enter guest info and complete the purchase! The ticket info is added to the database.
The Transactions page shows all pages and provides links to individual tickets.
In the Museums page the user views all museums and can choose to rename them.

Here’s one of the queries from the project that I wrote:

app.get('/get-transactions', function(request, response) {
var context = {};
var queryStr = "SELECT tr.transaction_id, tr.trans_date, tr.trans_time, g.fname, g.lname, tr.pymt_type, GROUP_CONCAT(ti.ticket_id) AS ticket_ids, GROUP_CONCAT(ti.admission_type) AS guest_types "+
"FROM transactions tr "+
"JOIN guests g ON tr.guest_id = g.guest_id "+
"JOIN tickets ti ON tr.transaction_id = ti.transaction_id "+
"WHERE tr.museum_id = ? "+
"GROUP BY tr.transaction_id;";
pool.query(queryStr, [request.query.id], function(err, result, fields) {
if (err) {
console.log(err);
return;
}

context.transactions = result;
response.json(context);
});
});

GROUP_CONCAT is a neat trick we used to get a string of ticket IDs and admissions types back from the db (which you can then parse on the front-end).

My favorite parts of this class were when I got to do something new and exciting in SQL.

CS340: What’s missing?

I wish the class had covered any (or all) of these topics:

  • Non-relational databases
  • Input sanitization
  • Security
  • Stored procedures
  • Thread locks
  • Transactions
  • Advanced SQL (this class never goes further than a SELECT within a SELECT)
  • Best practices

And this is just “what I know I don’t know”.

If I were to redesign this course, I would give students a defined project (“Make a theme park ride ticketing system”) and provide a functioning front-end so the class can super deep dive into database-specific topics instead. I know databases don’t exist in isolation, but the sheer amount of front-end work it required to interact meaningfully with our data greatly overshadowed the database work.

A few final tips for CS340

The course is disorganized and the assignments never fall into a predictable “rhythm”, so double-check everything. Every week it’s something different: this week you turn in a PDF, the next week a .zip. Sometimes you turn it into Canvas, sometimes you post it to your “peer review” discussion group. Does it count for you and your partner or just you? It varies week to week. Is there a quiz that opened last week due this week? These aren’t difficult things to figure out, but they add a lot of “overhead” and I saw more than a few people going “OMG I thought that submission counted for both of us!!” in the Slack chat.

Take 290 first. Easily the best thing you can do for yourself to ensure success in CS340. The last 290 assignment will have you make routes for interacting with a database. You can use that work as boilerplate for your CS340 project and save yourself a ton of grief. Can you imagine taking 290 and 340 at the same time and being stuck on the same problem for both classes? Take 290 first! It should be a hard pre-req for 340.

Skip the lectures. They’re a mess. I mean, I won’t tell you how to live your life, but the lectures in this class are worthless. They won’t help you build your site, they’re thin on examples, and sometimes the topic they introduce was actually needed for the homework due last week so… yeah. I’m a diehard “watch the lectures no matter what” person and I gave up on them. It’s like they’re from a previous version of the course or something.

Don’t reinvent the wheel. Use Bootstrap (or similar) to make your front-end look nice, choose a project idea that lends itself to lots of pairings (customers to orders, people to tickets, etc).

Overall, I was disappointed by CS340. I’ve weathered other not-so-great courses and found the good in them, but this one was just a whole lotta making a bigger website than we made in 290 and writing a few SQL queries on the side. My database/SQL skills didn’t grow much in this course and I’m bummed that it didn’t live up to my expectations. My partner was awesome, though, so there was that. :)

Simple program to shuffle an array of strings in C

Here’s a quick and simple program for shuffling an array of strings in C. There are many ways to do this, but I needed something much simpler and more beginner-friendly (ie: complete) than the examples I was finding online.

Enjoy!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define CITY_NAMES_COUNT 10

const char* cityNames[] = {
    "Seattle",
    "Chicago",
    "San Diego",
    "Orlando",
    "Anahiem",
    "Tampa",
    "Indianapolis",
    "Portland",
    "Chelan",
    "Sandusky"
};

void shuffleCities()
{
    int size = CITY_NAMES_COUNT;
    if (size > 1)
    {
        int i;
        //step through each index of the city name array
        for (i = 0; i < size - 1; i++)
        {
        //pick a random index (j) to swap it with
        //okay to pick same value as i
        int j = rand() % CITY_NAMES_COUNT; //random between 0 and 10
        const char* temp = cityNames[j];
        cityNames[j] = cityNames[i];
        cityNames[i] = temp;
        }
    }
}

int main(int argc, char* argv[])
{
    srand (time(NULL));
    shuffleCities();

    printf("SHUFFLED CITY NAME ARRAY\n");
    int p;
    for (p = 0; p < CITY_NAMES_COUNT; p++) {
        printf("%i: %s\n", p, cityNames[p]);
    }
}

To compile:

 gcc -o shuffleCities shuffleCities.c

To run:

./shuffleCities

Expected output:

SHUFFLED CITY NAME ARRAY
0: Portland
1: Tampa
2: Sandusky
3: Seattle
4: Chelan
5: San Diego
6: Anahiem
7: Chicago
8: Indianapolis
9: Orlando

Godot 3.0: Exporting game data from Google Sheets into a staticData .gd file using node.js

If you’re making a Godot game with a bunch of “static data” such as items with stats and effects, quests, characters with stats, enemies, loot tables, spawn tables, etc. – then you might be wondering where to put your game’s data (and how to format it) in a Godot project.

When I first set out to do this I couldn’t find a great guide so I decided to figure it out and make one. My way probably isn’t perfect, but it gets the job done. 

My goals (and what I ultimately built):

  • Organize my game’s data into separate tabs in a Google Sheets spreadsheet.  Advantages: I would get to use Sheets’s validation features, I can access/edit my data from any computer anywhere, working in Sheets is easy and familiar to me and anyone who has used Excel.
  • Export from Sheets into something I can process into Godot objects. I went with JSON. (More on this later)
  • Turn the exported JSON into a game data file, which would be “globally” available for my game’s code to use
  • Easily access items, mobs, etc. by ID from within the game’s code. I want to do something like this: var sword = allItems[“Rusty Sword”].duplicate()

Setting up the game data in Google Sheets

If you’re doing something similar feel free to build your data however you like. I liked rows, with the thing’s id in the first column. 

This first example is the items sheet. These are all the swords, robes, armor pieces, crafting items, quest items, etc. in the game. Every item has a name, a “slot” it goes into, class restrictions, and stat bonuses. Typical RPG stuff. This sheet is very large, but it’s easy to search and I color coded by slot to help make it easier to find things. 

The next example is my game’s enemy (mob) data. Enemies (mobs) in my game just have a few stats, but you can see how the data could be built out to support much more complex monsters.

You might have noticed that the mobs have loot tables. Loot tables are yet another tab in the data sheet.

Google Sheets lets you set up “validation” so that some cells can only contain data from another sheet. (You can type the loot table name or pick it out of the dropdown that Google Sheets generates when you use validation.)

Adding a simple validation here helps cut down on typos and errors that result from things getting renamed. 

There are more data sheets for my game, but this should be enough to give you an idea of how to put your game data in a spreadsheet. Next up, exporting.

Exporting the game data as .json

I picked .json for a few simple reasons:

  • It’s easy to find Google Sheets to JSON exporters
  • I’m already familiar with JSON and it’s fairly human readable
  • Godot has some built-in capabilities for parsing JSON

For the export itself, I used the free “Export Sheet Data” Google Sheets add-on (link). Just install it and find it in the Add-ons dropdown.

There are a bunch of settings in here to play with depending how you want your data formatted.

I wanted mine to be an array of objects, so the settings I checked are:

Checked settings: JSON format, current sheet only, Replace existing file(s), Export cell arrays, Export contents as array.

The exported data looks like this. (This is a super truncated version of what the items tab gets exported as.)

[
  {
    "name": "Novice's Blade",
    "icon": "sword1.png",
    "bodySprite": "sword1.png",
    "itemType": "sword",
    "consumable": false,
    "prestige": 0,
    "slot": "mainHand",
    "rarity": "common",
    "classRestriction1": "warrior",
    "classRestriction2": "",
    "classRestriction3": "",
    "classRestriction4": "",
    "classRestriction5": "",
    "hpRaw": 0,
    "manaRaw": 0,
    "dps": 2,
    "armor": 0,
    "strength": 0,
    "defense": 0,
    "intelligence": 0,
    "noDrop": false
  },
  {
    "name": "Rusty Mace",
    "icon": "mace1.png",
    "bodySprite": "mace1.png",
    "itemType": "mace",
    "consumable": false,
    "prestige": 0,
    "slot": "mainHand",
    "rarity": "common",
    "classRestriction1": "cleric",
    "classRestriction2": "paladin",
    "classRestriction3": "",
    "classRestriction4": "",
    "classRestriction5": "",
    "hpRaw": 0,
    "manaRaw": 0,
    "dps": 2,
    "armor": 0,
    "strength": 0,
    "defense": 0,
    "intelligence": 0,
    "noDrop": false
  }
]

Turning the exported .json into a .gd file for Godot 

Here’s what we need to do:

  • Open the .json file(s) (remember there’s one .json for every tab in the spreadsheet)
  • Parse it line by line and make any formatting changes necessary
  • Write the parsed and modified data to a .gd file that contains all of the game’s “static” data
  • Access the static data in the .gd file from the game’s code 

There are practically infinite number of ways to accomplish these steps (it’s just some file i/o and text parsing), but I went with what I already knew – Javascript. My quick-n-dirty parser (named “Parsely”) is far from beautiful code but it gets the job done.

You can see it in its entirety here: Parsely.js gist.

Parsely’s code is written specifically for my project, but one thing I want to point out is the way it transforms my objects. 

An object comes out of the Google Sheets exporter like this simplified example:

[
  {
    "name": "Novice's Blade",
    "icon": "sword1.png"
  },
  {
    "name": "Awesome Weapon",
    "icon": "sword2.png"
  }
]

But what I really need is this:

{
  "Novice's Blade": {
    "name": "Novice's Blade",
    "icon": "sword1.png"
  },
  "Awesome Weapon": {
    "name": "Awesome Weapon",
    "icon": "sword2.png"
  },
}

Notice the array has become one giant object, and each object is a property within that object. I want to grab my item by its name, ie: “Novice’s Blade”, and get the associated object data. I also want all this stuff to be in one giant object so I can grab objects directly without having to iterate through it (as I would have to if it were an array). 

So that’s what Parsely is doing when it does this:

for (var value of fromJSON) {
  var key = "";
  if (file == "items.json") {
    key = value["name"];
    formatted[key] = value;
  } ...
... 

It’s getting the name and making that the key, and it’s getting the whole object and making that the value. Now I have a giant object full of smaller objects, where each smaller object is a unique item in the game (like the second JSON example above).

Also, sometimes I wanted to add more parameters to an item at runtime, such as a unique ID or a boolean representing whether it was an enhanced item or not. Those things don’t exist in my spreadsheet, they’re just slapped on when this script is run. 

Here’s an example from parsely.js of three new params (“itemID”, “improved”, and “improvement”) being added to each item as it is processed.

For the sake of keeping everything related to my project in one place, I placed parsely.js and the .json files it processes in my Godot project folder like so:

When I export from Google Sheets, I download the .json file it generates and place the .json file in the appropriate folder (names, staticData, or timedNodeData). Parsely handles files from different source folders slightly differently, ie: files from names get built into arrays, files from timedNodeData get some “inProgress”, “readyToCollect” booleans attached, etc.

Finally, we can run it! I open a Terminal window and navigate to the Parsely folder. To run, I type:

node parsely.js

It then grabs those json files, processes them, and places them in res://gameData (which is where I want them to go).

Inside each of these .gd files is an object or an array formatted as one long line.

This is staticData.gd:

Here’s our data, organized into separate objects.

Using the data in my Godot project

Finally, make the staticData.gd file global by adding it in Project Settings > Auto Load. Now it’s accessible everywhere in the project. 

Now, throughout the project items, mobs, loot tables, etc. are all accessed from staticData like in these examples:

var newItem = staticData.items[itemNameStr].duplicate()

var loadout = staticData.loadouts[loadoutIDStr]

And that’s it! Now my game has all of its items, spawn tables, loot tables, quests, crafting recipes, and more pre-loaded as data objects and universally available anywhere in the game’s code.

Godot 3.0 Tutorial: Building a simple character creation menu screen

In this tutorial: structuring and scripting a simple RPG-style character creation screen using Godot’s built-in containers and Godot script

What we’re building

I recently added a menu to my game that lets the player create their own custom character for the game. In the context of my game, that means getting to name the character, choose the character’s head sprite, and choose the character’s class. It sounds simple but this work managed to touch on a lot of things, so I thought I’d share my work here in hopes that it’ll help someone else. I’ve been working in Godot on a hobby project for about 5 months now and I think the engine is great but could use a few more tutorials and “here’s how I did it” type stuff, so here we go. 

Some of the things covered in this guide include:

  • Godot’s container system (VBoxContainer, HBoxContainer, etc)
  • Building a simple menu out of Godot nodes
  • Hooking that menu up to the rest of the game
  • Changing scenes
  • Altering aspects of a “hero” scene, such as its name and head sprite
  • Lots of Godot script examples

PS: The project I’m using for this guide already exists (in some capacity), so there are references to things that are already built prior to this guide. Hopefully this “slice” of the game’s development is still helpful to someone, even if it doesn’t start from scratch. 

Structuring the scene: Godot container types explained

The first thing I did was make a new scene and add a Node2D to serve as the parent node and a VBoxContainer as its child to hold all of the major elements of this menu. The first child of the VBoxContainer is a label.

My new scene is called createHero.tscn

Let’s talk about structuring a menu in Godot.

For a menu with many “sections” or “elements” that read top-to-bottom, use a VBoxContainer. The VBox stacks its children elements vertically (one on top of the other) which saves you from having to position each one individually and from having to worry about overlapping elements. You can also control the VBox’s width and the spacing between its child elements.

Each element in the stack can be something simple, such as a label or a button, and it will occupy as much vertical space as it is tall. Nothing will overlap it. Or, each element could be something more complex, such as an HBox (which would let you create a row of buttons, labels, or similar).

This system takes a little practice to get used to, but hopefully this diagram made of children’s blocks helps clarify the general concepts.

This stack represents a VBox with child elements. Each “row” is a container, element (such as a label or a button), or an HBox with child elements of its own.

For the sake of brevity I’ve skipped ahead to my assembled scene. This builds on the concepts already explained.

My scene now contains a VBox parent with three children: a label, an HBox, and another HBox.

For now, it’s just made out of unskinned/unstyled Godot nodes.

Some things of note:

  • There’s an open space below the “Create Hero” label that I will use to display the hero art later on
  • “container_spacer” is a generic Container node. I set its minimum width to 420 so that the other thing in the HBoxContainer2, the “Rename” button, gets pushed to the right side of the screen.
  • The hero class (Cleric, Druid, Ranger, etc.) buttons are in an HBox that manages their left-to-right spacing 

Getting to this new scene

I made a little button on the main screen of my game to access createHero.tscn.

This is just temporary so that I can access the new menu for testing.

Eventually, this “Create a character” screen will be the first thing the player sees when starting a new game, but I don’t want to clutter the new game startup flow with an unfinished (possibly broken) menu yet. 

Here’s the button on my main game scene:

I hooked up its button press signal (I just go with the default function name Godot suggests):

And the code:

If you’re following along at home, all you need is the last line, the one that begins get_tree()… as the other two lines are specific to my game.

With that button hooked up, I can now run my game and click the temporary button to get into my new menu. 

Here it is in-game. No, it’s not beautiful. but we gotta start somewhere!

Creating a script file for this menu

For this menu to actually do anything I’m going to need a script file for this menu (or this scene, to use Godot’s parlance). To create a script file for the scene I click on Node2D and go into the Inspector tab. I selected New Script and let Godot create a new script for me.

With Node2D selected, go down to Script and selected New Script.
I just take the defaults most of the time in Godot. This stuff is all fine as-is. I click “Create” and let it make the new script file for me.

Adding an instance of the Hero scene to the Create Hero menu

Usually with a character creator you want to show a preview of the character being created. For the game I’m working on, that means making an instance of the Hero scene and attaching it to the menu so the player can see their character preview.

(The Hero scene already exists in my project. I won’t cover it in this tutorial, but you can see the code that makes up a Hero scene and the hero generator by viewing these gists I made for the sake of this guide: hero.gd, baseHero.gd, heroGenerator.gd. You don’t need to look at or understand these files to follow this guide, but you may find them helpful if you are trying to build something similar.)

Here’s how hero.tscn looks in my project, structurally speaking:

Back in createHero.gd, we have to add some code in order to see the hero scene in the menu. The project already has a heroGenerator file that I use to make random heroes for the player’s guild. Here, the heroGenerator file is used to make a single hero and present it to the user in this menu. The general idea here is to generate a random hero, show it to the player, and then let the player customize it to their liking (just like how “create a new character” works in a lot of MMO type games).

Code for generating a hero, adding it to the guild roster, creating a scene instance for that hero, and adding the instance to the menu scene. View this code as a gist.

Here’s how it looks in-game:

Ta-dah: a hero character instance now exists in the menu.

Making the “Rename” popup and functionality

There are a few things we have to do to get the rename popup working:

  • Add the popup node itself (a ConfirmDialog node)
  • Give the popup a TextEdit field so the player can enter a name
  • Make the popup appear when the user taps the Rename button
  • Write the script that accepts the new hero name
  • Update the hero’s data to keep the new name
  • Add a random name generator button
  • Name validation (not part of this tutorial but for a real game you’d probably want this)

First, the popup.

Godot has some dialogs (popups) built in. The “Rename” popup is going to be a ConfirmDialog with a child LineEdit. The LineEdit is a field for the user to type in. This guide’s game is imagined as an Android/iOS game, and LineEdit conveniently brings up the keyboard on those devices.

I made this confirmation dialog into its own scene since the rename functionality will be used elsewhere in the game. (To do that, right click the ConfirmDialog in the Scene tree, click Save Branch As Tree, and save it as its own scene.)

If you don’t make a ConfirmDialog its own scene, its Ok button script can just go in your parent scene’s .gd file.

If you do make ConfirmDialog its own scene, its Ok script will be in its own file.

Either way works, I just like to make anything used in more than one place into a scene so I don’t have to maintain code in two places.

Hooking up the Rename button to open the popup

Now that we have the confirm popup scene made, let’s make it so the “Rename” button actually opens the ConfirmDialog (which I’ve named confirm_rename_dialog). Godot makes this really simple.

Select the Rename button and navigate to its pressed() signal.

Select the “Rename” button and navigate to its Node signals. Highlight pressed() and click the Connect… button in the lower right.
I’m happy with the method name Godot suggests, so I click Connect and let it create the method.
Here’s the empty method Godot created.
And here’s all the code it needs to open the dialog.
get_node(“confirm_rename_dialog”).popup()

If we tried it in-game now, we would be able to open the popup and type a name but not actually save our new hero name. 

Saving the user’s input to the hero

To make the “OK” button actually do something, we have to go into the confirm_rename_dialog scene and attach a script file to the scene. I made a new script file for this ConfirmationDialog.

In the Node signals panel, the confirmed() entry is what is triggered when the user presses OK. I connected it to an empty function.

Click confirmed() and then click Connect to generate a function in the popup’s script file.

Godot makes it realy easy to grab the user’s input from the LineEdit. Just write:

var newName = $LineEdit.text

and then do something with newName. In my case, that meant updating the selected hero’s heroName to be the value of newName. 

(Note there’s no attempt at validation in this example, so the user can enter anything they want right now. For a real game, you’d probably want to keep names under a certain length and filter out numbers, special characters, symbols, emoji, and possibly dictionary words and profanities.)

But what’s this signal business? Well, the popup is a separate scene from createHero, so it has to communicate with its parent scene. Godot does that with signals.

Declare the signal (line 3) and then emit it (line 12). It’ll be caught by the code up in createHero.gd.

Back in createHero.gd I’ve had to make a few changes. There’s now a draw_hero_scene() method because I think we need to clear and redraw the hero scene from at least two places in the code, so I took it out of _ready and made it its own function.

I also attached the redrawHeroName signal to the confirm_rename_dialog instance, so that it can “listen” for the signal and call “update_hero_name” when the signal is “heard”. All update_hero_name() does is free the existing hero scene (clear it from the stage) and make a new one. This draws a new hero instance with the new name.

I’ll probably rename update_hero_name() to something more generic once I give the user the ability to modify the hero’s appearance and class.

Let’s try it out in game before moving on:

User types anything they want (seriously there’s no validation yet)
Success! And it doesn’t even flicker. I was afraid it would flicker.

Making the “hero class” buttons (radio buttons)

Next up: changing this hero’s class.

A hero can only be one of the available classes (ie: she can be a Wizard, or a Warrior, or a Cleric, but not more than one of those options). When the player picks a choice, the others are “deselected”. 

This is a lot like how “radio buttons” on the web work. Pick one choice, the others are “un-picked”. Godot actually has something for this: a button group! A button group is somewhat convoluted to set up.

First, select one of the buttons we want to add to the (not-yet-created) button group. In the inspector tab, scroll down to Group. Click where it says <null> and then choose New ButtonGroup. 

Click on New ButtonGroup to view its inspector pane. Go to Save As… to save it as a .tres.

Saving it lets us load it onto all the other buttons.

Select all of the remaining buttons and click the field next to Group. Choose Load and then choose the saved .tres file. Now all of the buttons are in the createHero_classButtonGroup.

Let’s try it in-game.

Here we have Cleric selected.
…and here we have Druid selected. (The faint blue border indicates which one is selected.)

Making these buttons mutually exclusive will help with styling later on and allows us to quickly “deselect” the user’s previous choice and highlight the new current choice. (The highlight on these default Godot buttons is a thin blue border that might be difficult to spot at first.)

Changing the hero’s class (in data)

This step is going to require some refactoring. Currently, there is no mechanism in the game to change a hero’s class. A hero is given a class and a matching gear loadout by the heroGenerator.gd file and that’s it. 

Our refactor will need to:

  • Change the hero’s class
  • Change the hero’s starting gear to match that class
  • Change the hero’s starting stats
  • Do not change the hero’s name or head (these might already be set by the player, but if we just generate a new hero they will also be re-generated)

I had to do some refactoring here…

So this next part is kind of a tangent and really specific to my project, but I wanted to include it and not just hand-wave it in case it’s valuable to someone who reads this (hello, future me, probably).

Currently, the hero’s starting gear is handed out in heroGenerator. A hero already has a “give_new_item” method that accepts a string (must match an item in the game’s static data) to create an instance of the item and assign it to the hero’s equipment object. Here, giving a character its starting gear is done with multiple calls to give_new_item on the hero class.

The old way of giving gear was done line-by-line.
Hero.gd has this method to find the item (by its name as a string) in staticData.items and stick it on the hero in the correct equipment slot.

The problem with how this is currently done is that this “gear assignment” step happens when the hero is generated for the first time, and then does not (or cannot) happen again. But if you change a brand-new character from a warrior to a wizard, you need to wipe the warrior gear and replace it with wizard gear. I could probably do this out of methods that already exist on the hero for giving and taking equipment, but I have an idea for something cleaner: a “gear loadout” system, whereby gear sets exist in staticData and are assigned to a hero in one fell swoop.

Here’s a quick look at the changes I did during this refactor. I won’t cover every last step, just a high level of how this stuff works in my game.

Added a new data sheet: In my game data Google Sheet, I made a new tab and set up some gear loadouts like so. (The fields are restricted to just items that actually exist in the Items tab of the game data workbook.)

This gets exported as a json:

And then I go over to the tool I wrote to process individual JSON files into my Godot project’s staticData.gd file. (This deserves its own tutorial, but for now you can check it out as a gist here if you like.)

Parsely (a tool I wrote for this project to turn .json data into objects in a .gd file) now handles this new loadouts.json file
And now var loadouts is an object in staticData.gd.

And now var loadouts = {…} exists in staticData.gd. Since staticData.gd is an AutoLoaded file, this means that my game’s code can retrieve a specific loadout by id like so, from anywhere in the project:

var gearSet = staticData.loadouts[“clericNew”]

Updating hero.gd Now that we have the concept of gear loadouts, it’s time to update the hero class with the ability to use them.

Now you can call hero.give_loadout(“clericNew”) and get all the gear associated with that loadout.

For now, the give_loadout() method is also going to delete any armor already on the hero, since this feature is only used during the creation of a new hero and we don’t want to keep all the gear generated by changing class. I don’t think give_loadout() will be used outside of character creation and testing purposes so for now this is fine.

Writing the change_class() method in hero.gd

Finally, I have everything needed to write change_class(). Now we can write hero.change_class(“Cleric” and that hero will become a cleric, complete with the default newbie cleric gear. 

One last thing to do before calling this refactor complete: update the heroGenerator.gd code to use loadouts instead of one-by-one gear gifting like we saw earlier in this guide.

heroGenerator.gd now uses give_gear_loadout() to assign gear sets to newbies. Remember, the gear loadouts themselves are stored in the spreadsheet data now, so there’s even some validation (in the Google Sheet) that the user picked a gear item that actually exists. Win-win all around.

Okay, NOW we can finish what we came here to do: clicking the class buttons should change the new hero’s class and change all of its starting gear to match.

Back in createHero.gd, we hook up each hero class button to a bit of code that calls change_class on the selected hero (the one we are viewing). I’m sure there’s some more efficient way to do this but for a small set of buttons this makes it pretty clear what’s going on. Remember how I thought we might change “update_hero_name()” to something more generic? Well now it’s “update_hero_preview()” because we also call it after changing the hero’s class.

Let’s try it out in game. Here our new hero is a Wizard.

And now she’s a Warrior, with the right gear and without losing the head graphic or name the user picked for her.

Phew – the refactoring detour is done. Yay! 

There’s just one thing I want to do before calling this particular piece of work (and this little guide) done, and that’s give the user the ability to change the hero’s head. 

Selecting a head sprite and saving that choice

There’s lots of head sprites in the game already. Currently, the only “race” (in the fantasy sense) you can play as is humans.

The game already has a concept of “male” and “female” head sprites. The lists of those sprite filenames are kept in two separate arrays, like so:

The heads are already in two arrays for the sake of the random hero generator, but the player gets to pick from all possible heads.

There’s no gameplay concept of gender, and separating heads into two arrays was just something I did to help the random hero generator pair the more masculine-looking (bearded, balding) heads with the more masculine names, and vice versa with the more feminine-looking heads and names.

This is important because when the player makes their own character the player gets to pick from ALL the heads, not just a subset of heads. So I’m going to have to combine them into one array for the sake of cycling through them in the create hero menu, while still keeping them as two separate arrays for the hero generator.

Originally, the head arrays were in heroGenerator.gd. That wouldn’t work going forward, though, since I now needed to access them from createHero.gd (the create hero menu scene) and by the time we’re in createHero, the generator is done doing its thing and we don’t want to go back “into” it and access some arrays in it.

I realize that sounds confusing: the goal is to make the head arrays exist on the hero so they can be accessed from both createHero and heroGenerator.

I moved the head arrays to baseHero.gd, which is where I keep all the base hero stats data (hero.gd extends baseHero.gd and inherits everything in it).

baseHero.gd now contains all the head sprite data

I had to make a minor update to heroGenerator.gd, telling it to look on the hero itself for the head sprite arrays instead of at a variable local to itself. Now that the arrays are on the hero, though, they can be grabbed by either heroGenerator or createHero.gd.

heroGenerator.gd before
heroGenerator.gd after – the humanMaleHeads and humanFemaleHeads are now on newHero

Over in createHero.gd, I added two new vars: allHumanHeads = [] and headIndex = -1.

I added code in _ready() to build a new array, allHumanHeads, out of the two separate male and female head arrays. It also figures out which index the hero’s starting head is at, so we can use that head as the starting point in the array when we press the “Previous Head” and “Next Head” buttons.

Adding the buttons

This part should look familiar – in the createHero scene I added another HBox (HBoxContainer3 in the screenshot) and centered two buttons inside it.

These buttons have to cycle through all the possible heads. Still in createHero.gd, I attached the “Prev Head” and “Next Head” buttons to two new functions:

I also added some logic to handle the “wrap around” effect that should occur if the user clicks “prev” or “next” enough to reach the end of the head array.

Finally, in hero.gd I added a very short method called change_head. All it does is take the string of the new head sprite (such as “female_head_01.png” and update headSprite on that hero.

Pass in a string representing the filename of the new head sprite and this method updates the hero instance to use that new head sprite.

End result: changeable heads!

This menu could be prettier, but styling it is a topic in and of itself and this guide is already huge.

Final steps: testing the results of the character creator

The very last step is to hook up the “Create hero!” button at the bottom of the menu. Technically, the hero was already created. All we did was modify that already-created hero’s class, head, and name. This button just has to take the player to the main scene. 

I hooked up the Create hero! button to this script in createHero.gd…

I customized a hero… (she was originally a warrior with a different name and head)

And confirmed she is now part of my guild. Here she is with the group:

There she is!

Checking in the Guild Management screen…

And checking her hero page (to ensure she has the correct stats):

Looks good!

I wanted to make a guide showing some of the work I’ve done in Godot, mostly just to help support what I think is a great game engine for indies and hobbyists. If you found this helpful, let me know in the comments!

Godot 3: How to disable a button and tint its sprite icon a darker color

In this tutorial: disabling buttons and tinting their icons (sprites) a darker color to indicate that they cannot be interacted with by the player.

What we’re making

Here’s my game’s item vault. It displays a grid of buttons, each one representing an inventory “slot” and each button can be used to display an item the player actually owns. There’s an icon and a slot label to help the player understand what each item is (ie: a sword, a robe, a pair of boots, etc.)

This is great for viewing all the items, but sometimes the player wants to fill a specific slot on their character. Here’s what the character page looks like:

When the player goes to select, for example, a “jewelry” item for their character to wear, I want to make it easy to spot which items in the inventory vault are actually jewelry.

To do this, I will write script that figures out which items are not jewelry, disable their buttons, and tint their icons a darker color. The end result should look something like this:

(I could have just hidden all the non-jewelry items, but I think having items “move around” on the player would be confusing. Tinting the non-jewelry items seemed, to me, anyway, like the better user experience.)

Setting it up in script

The initial creation of the inventory button instances takes place in my game’s “vault” scene. Below is a simplified version of my game’s code that (hopefully) demonstrates how the grid of buttons is created and populated with icons and labels. (PS: I have a separate tutorial specific to making a grid of buttons just like this.)

Thematically, the vault represents a shared inventory across all of the player’s characters in my RPG-style game. The shared inventory is represented as an array named global.guildItems.

Each inventory “slot” is represented as an itemButton instance (itemButton is a scene I created, we’ll look at it more closely in a bit).

The first method, _position_vault_buttons(), creates the blank buttons and places them in a grid, the second method, _draw_vault_items(), “populates” them with actual items from the inventory.

This way, we always get X number of buttons, where X is the total capacity of the player’s inventory, and only some of them are used to “hold” the items the player actually owns.

(A lengthier explanation of how I know which item slot to filter by is outside the scope of this tutorial, but it’s done with a global flag set by the heroPage and you can see evidence of it in this code sample below about 6 lines from the end. It’s the one that goes “if (global.guildItems[i].slot != global.browsingForSlot):”)

#vault.gd

func _ready():
  #display inventory size and capacity
  _position_vault_buttons()

func _position_vault_buttons():
  #this method handles the STRUCTURE of the buttons
  #it places the empty buttons in the grid
  #use _draw_vault_items() to put icons and data into buttons
  for i in range(global.vaultSpace):
    var itemButton = preload("res://menus/itemButton.tscn").instance()
    itemButton._set_vault_index(i)
    itemButton.connect("updateSourceButtonArt", self, "_draw_vault_items")
    $centerContainer/grid.add_child(itemButton)
    buttonArray.append(itemButton)
    _draw_vault_items()

func _draw_vault_items():
  #now we pair each physical button with data from global.guildItems array 
  #grab each button from buttonArray and "decorate" it 
  var currentButton = null
  for i in range(buttonArray.size()):
    currentButton = buttonArray[i]
    if (global.guildItems[i]):
      currentButton._set_label(global.guildItems[i].slot)
      currentButton._set_icon(global.guildItems[i].icon)
      currentButton._set_data(global.guildItems[i])
      if (global.currentMenu == "vaultViaHeroPage"):
        if (global.guildItems[i].slot != global.browsingForSlot):
          currentButton._set_disabled() #script I wrote in itemButton.gd 
        else:
          currentButton._clear_label()
          currentButton._clear_icon()
          currentButton._clear_data()

About 4 lines up from the bottom is this line of code:

currentButton._set_disabled()

That _set_disabled() method is a method I wrote on the itemButton’s script, it’s not something built into Godot.

Let’s take a look at the itemButton scene and see how it works.

itemButton scene and script

An itemButton, in my game, is made up of a Button node along with a couple labels and a sprite.

Here is the scene’s structure:

Here is the script that disables the button and dims the sprite over the button:

func _set_disabled():
  $Button.disabled = true
  $Button.modulate = Color(0.5,0.5,0.5,1)
  $Button/sprite_itemIcon.modulate = Color(0.25,0.25,0.25)

The tricky part here, for me, was figuring out how modulate works. The Godot docs are thin on examples and it took some Googling just to figure out that the key word here was “modulate”, not “tint” or “color” or other terms I was initially guessing.

Some things to note about “modulate”:

  • Modulate is a property, so you can set it using “dot” notation.
  • It uses Color, which is built into Godot.
  • set_modulate and get_modulate are the old way of working with modulate (if you see reference to them the guide you’re reading/watching was probably made prior to Godot 3)

There’s a bunch of ways to work with Color, my example is just one of them. Mine is Color(R, G, B, alpha). Here are some more examples of working with Color in Godot.

This method could be expanded to a near-infinite number of uses, my example is just one tiny, specific use case.

References and more reading:

Godot 3: Centering a grid of evenly-spaced buttons on screen

In this tutorial: The scene structure and settings I used in the Godot 3 engine to achieve this amazing centered grid of evenly-spaced buttons. The buttons themselves are all instances of the same scene and are placed in the grid programmatically.

This is my “finished” result (pardon the placeholder assets). It’s a simple hero inventory page for an RPG. The buttons that make up the hero inventory are evenly spaced in a grid, and that grid is centered horizontally on the screen:

This guide will show you the code and the scene structure used to achieve this centered-grid-of-centered-buttons, but it assumes some familiarity with the Godot engine and will skip over some of the basics.

Scene hierarchy and container settings

This “Hero Page” is its own scene. This scene is named heroPage.tscn (and its script is in heroPage.gd). We’ll come back to its script at the end of the tutorial.  For now, we’re working in the scene’s hierarchy.

The parent-most node is a Node2D, and the important bits here for the centered grid of inventory items are:

  • a CenterContainer (which I renamed to centerContainer)
  • a GridContainer (which I renamed to grid)

(You could make this stuff programatically if you prefer but I like to see a certain amount of my UI in the viewport – at least the outlines of containers, where possible.)

I positioned my CenterContainer where I wanted it on the Y axis and gave it a width equal to that of my screen and left the rest alone.

Doesn’t look like much in the viewport yet – just a thin horizontal line.

That’s okay – the buttons themselves will bulk it out.

The next step is to adjust the grid’s settings. I changed the number of columns to 4 and under Custom Constants, I changed Vseparation and Hseparation to 24 (to put some space between each of the buttons).

The button instances

The square buttons are all instances of the same “itemButton” scene (that I made myself). That scene looks like this in the 2D viewport and scene hierarchy:

Unlike the grid or center container, I gave the button’s Control parent a size and a minimum size.

Generating the buttons with script

Finally, the code that adds the buttons to the grid is in the heroPage.gd file itself. This code goes in the _ready() method.

for i in range(heroEquipmentSlots.size()):
   slot = heroEquipmentSlots[i]

   var inventoryBtn = preload("res://menus/itemButton.tscn").instance()
   inventoryBtn._set_label(heroEquipmentSlotNames[i])
  
   #only set icon if the hero actually has an item in this slot
   #otherwise leave it empty
   if (global.selectedHero["equipment"][slot] != null):
      inventoryBtn._set_data(global.selectedHero["equipment"][slot])

   $centerContainer/grid.add_child(inventoryBtn)

I simplified some of the above code from my actual project for readability. The important parts are where it generates an instance of each inventory button and pushes the label and data into that instance, then adds the button to the grid.

The end result

The hero’s eight inventory slots are now in a grid and neatly centered. (I can’t say the same for the rest of the elements on this page yet, but it’s a start!)

OSU eCampus CS290 Web Development review & recap

This post is part of an ongoing series recapping my experience in Oregon State University’s eCampus (online) post-baccalaureate Computer Science degree program. You can learn more about the program here.

Six-word summary:  :(  :(  :(  :(  :(  :( 

Web dev is, for some reason, this really polarizing thing in tech. I’ve certainly heard a lot of devs go “Ewww, JavaScript!” (both in my real life job and from my classmates). That’s too bad, because I think the web is really cool and it’s where a lot of people spend a lot of their time these days! I like building web apps, but I can see why some people don’t – it’s prone to “flavor of the week” syndrome, the tooling isn’t great, JavaScript does some things “weird”, etc.

I went into this class curious to see what aspects of web would be taught, since it’s such a broad topic to stuff into just 8 (or 11) weeks. Here’s some of what we covered in CS 290:

Git

This is the first OSU class I’ve had that covers git in any capacity (I’m halfway through the program). This is awesome – hooray, CS290, for introducing git!

I wish the OSU program covered it sooner. It has been frustrating to group with people in my previous classes who have never used it before and would rather use things like email (!!!) to share files because they don’t know git.

Unfortunately, 290 didn’t go very in-depth with git. We pushed two files to a Github repo in the first week and called it good. We literally never used git again. I think this was a huge missed opportunity: the class could easily include a group project of some sort that focuses on collaborating in a git repo, or require us to post incremental work on a project to our github repos, or something.

Quirks of JavaScript

The first three weeks of CS290 focused heavily on “this weird thing JavaScript does”. The usual suspects are here: lack of strict typing, hoisting, closures. It’s not that these things aren’t important, it’s that they aren’t what makes web development compelling or useful. Starting the class out by spending three weeks on these topics just seemed to make JavaScript look weird and annoying, when in practice, these things aren’t that big a deal.

I think it’d have been cooler if they set us to actually making things and learning the tools of the trade in those first three weeks. In the accelerated schedule, week 4 is when it got interesting: we made an HTML website with JavaScript methods to navigate around in a table and mark cells yellow. 

Week 4 homework: a bare-bones interactive “website”. This is the first step in building the kind of stuff that makes the web compelling!

Installing npm packages on a server

They had us do this in week 1 – OSU provides some server space, and everyone was tasked with claiming a port and setting up a little server on it.

We never came back to it. I don’t know why we did this so early in the class. Node and its (infinite) packages is an interesting topic and it’s weird to just install it and never come back to it. It was like a story that someone started telling and never finished. 

Some light database stuff and routing with Express

This part was fun – make routes (like “/get”) and make them return data from a class-provided database. This work will be extremely useful as starter code when you take CS340 (Databases) so keep it somewhere safe. 

The biggest, most complex project of this class is the one where you develop backend routes for database interaction. You’ll spend a lot of time on form validation and making rows in a table switch between a read-only state and an editable state. This is also the project I thought was the most interesting of all of them, since it was the most like a real site. 

What CS290 didn’t cover

Sadly, there was no mention of Chrome’s various debugging tools, running node locally, front-end frameworks like React, the difference between running JavaScript on the front end and the backend, the staggering quantity of problems that have already been solved with neat existing NPM packages, unit testing, integration testing, and deployment.

Somewhat irritatingly, some of the assignments had what I would consider poor coding practices. The second assignment (sorting automobiles) in particular irked me because it makes unnecessary copies of an array:

/*This function sorts arrays using an arbitrary comparator. You pass it a comparator and an array of objects
appropriate for that comparator and it will return a new array which is sorted with the largest object in index 0
and the smallest in the last index*/
function sortArr( comparator, array ){
//returning a new array to satisfy assignment requirements; we could have run sort on array itself (it's passed by reference)
var sortedArr = array.sort(comparator, array);
return sortedArr;
}

Arrays are passed by reference; there was no need to create a new one and return the new one. In fact, we could have run .sort() in place instead of calling a completely separate method for it. Maybe I’m just cranky, though.

The workload in weeks 1, 2, 3, and 4 is very low, but then things pick up after that. 

CS290 final exam

Whoever wrote this exam does not know what is important in web development.

I’ve used JavaScript (both as a hobbyist and a professional) for over half a decade, and I got one of the lowest scores I’ve ever gotten on a test here. I don’t know what to say – expect a ton of oddly-worded bullshit questions about tricky trivia that have no relevance to how JavaScript is used or real life web development practices. 

CS290 parting thoughts

I can only guess what this class is like for someone who is new to web development. It’s probably a disjointed pastiche of topics that get introduced in a vacuum and then quickly abandoned. I’m sure this class isn’t helping anyone become enthusiastic about web development, which is too bad. 

For a better introduction to modern web development consider building your own site. I think that’s how a lot of us got started – we wanted a website for some reason or another and set one up. There’s plenty of project starters (known as ‘boilerplate’) out there to pick from. Here’s what I would recommend…

  • Buy some $5/month shared hosting and make your own portfolio site out of HTML and your own CSS. Once you’ve got that…
  • Start up a node server on your own computer and get it to serve your own project
  • Build a simple one-page app that does a simple job using a front-end framework such as Angular or React (here are some ideas: a text capitalizer, a shipping price calculator, an anagram solver)
  • Use a popular front-end styling framework, such as Bootstrap
  • Realize what you made is garbage and start over
  • Repeat a bunch of times
  • Keep Googling any time you get stuck
  • If you build something decent, deploy it somewhere like Heroku and show it off!