wxWidgets for a Blob Game Editor

A blob game is something like Loco Roco or Gish where there are characters and objects in the game that can compress and squeeze and roll around. Using the physics system I have been working on this semester I wanted to replicate that and create a game with the following in mind:

  • Must contain a character that can roll around
  • Must contain a level editor for placing composite objects
  • Must display features of a mass aggregate system

For me, creating the game would not be hard, but I wanted to be able to pay special attention to the editor I was going to make for the game. I wanted to create my level editor so that it was styled similar to that of Grey: The Lost Technology, and by that I mean a separate control panel so that I do not have to create a rendering loop for the active, drawable game space within a window. I knew that you could use Windows Forms with C++ so I tried setting that up. The problem with this idea is that the C++ implementation of Windows Forms is managed. This immediately created problems because my current game implementation is written in unmanaged code. After some fiddling around with Windows Forms, I eventually gave up. The primary reason I wanted to use was that I could use the visual designer, so it was primarily the speed of quickly mocking up a UI that I wanted.

I started looking at other C++ UI libraries and I found a few, such as Qt and wxWidgets. Both are really powerful UI libraries that offer all the functionality that Windows Forms offers, but cross-platform. I had done my research and found that Qt is easier to use, but wxWidgets was meant to be the most natural looking for the given system it runs on. It’s meant to look as close to system dialogs as possible. I had also looked at wxWidgets before and had already read their documentation because I saw that a company that I like was using it for their tools development. The decision was made… already having some prior knowledge of the library, I chose wxWidgets.

wxWidgets turned out to be a really easy platform to implement into my existing codebase. I usually have a lot of trouble linking a new library into my existing code, but not with this. The documentation is very clear, and I didn’t even have to compile my own version of the source code! The setup instructions for getting wx into your Visual Studio can be found here. After that, you can grab any of the “Hello World” scripts or samples from the wx documentation page.

 Code

Here is my minor implementation of a small control panel for my editor:

//CompositeCPanel.h
#pragma once

#include <wx/wx.h>
#include "CompositeEditor.h"

class CompositeCPanel : public wxFrame
{
public:
	CompositeCPanel(const wxString& title, CompositeEditor* editor);
	
	void OnUpdate(wxCommandEvent & event);
	void OnSave(wxCommandEvent & event);
	void OnComboBoxSelected(wxCommandEvent & event);

	wxTextCtrl * entryX;
	wxTextCtrl * entryY;
	wxTextCtrl * entryZ;
	wxTextCtrl * radius;

private:
	wxTextCtrl* mName;
	wxComboBox* mCombo;

	CompositeEditor* mEditor;
};

//CompositeCPanel.cpp
#include "CompositeCPanel.h"

CompositeCPanel::CompositeCPanel(const wxString& title, CompositeEditor* editor)
	: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 350))
	, mEditor(editor)
{
	wxPanel *panel = new wxPanel(this, wxID_ANY);

	wxStaticText* xText = new wxStaticText(panel, wxID_ANY, "X:", wxPoint(5, 20), wxDefaultSize, 0L, wxStaticTextNameStr);
	entryX = new wxTextCtrl(panel, wxID_ANY, "", wxPoint(20, 20), wxDefaultSize, 0L, wxDefaultValidator, wxTextCtrlNameStr);
	wxStaticText* yText = new wxStaticText(panel, wxID_ANY, "Y:", wxPoint(5, 45), wxDefaultSize, 0L, wxStaticTextNameStr);
	entryY = new wxTextCtrl(panel, wxID_ANY, "", wxPoint(20, 45), wxDefaultSize, 0L, wxDefaultValidator, wxTextCtrlNameStr);
	wxStaticText* zText = new wxStaticText(panel, wxID_ANY, "Z:", wxPoint(5, 70), wxDefaultSize, 0L, wxStaticTextNameStr);
	entryZ = new wxTextCtrl(panel, wxID_ANY, "", wxPoint(20, 70), wxDefaultSize, 0L, wxDefaultValidator, wxTextCtrlNameStr);

	wxStaticText* radiusText = new wxStaticText(panel, wxID_ANY, "Radius:", wxPoint(5, 95), wxDefaultSize, 0L, wxStaticTextNameStr);
	radius = new wxTextCtrl(panel, wxID_ANY, "", wxPoint(50, 95), wxDefaultSize, 0L, wxDefaultValidator, wxTextCtrlNameStr);

	wxButton *button = new wxButton(panel, wxID_EXIT, wxT("Update"), wxPoint(20, 120));
	Connect(wxID_EXIT, wxEVT_COMMAND_BUTTON_CLICKED, 
		wxCommandEventHandler(CompositeCPanel::OnUpdate));

	wxStaticText* nameText = new wxStaticText(panel, wxID_ANY, "Name:", wxPoint(5, 195), wxDefaultSize, 0L, wxStaticTextNameStr);
	mName = new wxTextCtrl(panel, wxID_ANY, "", wxPoint(50, 195), wxDefaultSize, 0L, wxDefaultValidator, wxTextCtrlNameStr);

	wxButton *buttonSave = new wxButton(panel, wxID_SAVE, wxT("Save"), wxPoint(20, 220));
	Connect(wxID_SAVE, wxEVT_COMMAND_BUTTON_CLICKED, 
		wxCommandEventHandler(CompositeCPanel::OnSave));

	wxString items[] = {"rod", "spring"};

	wxStaticText* typeT = new wxStaticText(panel, wxID_ANY, "Link Type: ", wxPoint(5, 170), wxDefaultSize, 0L, wxStaticTextNameStr);
	mCombo = new wxComboBox(panel, wxID_OK, wxEmptyString, wxPoint(70, 170), wxDefaultSize, WXSIZEOF(items), items);
	Connect(wxID_OK, wxEVT_COMMAND_COMBOBOX_SELECTED, 
		wxCommandEventHandler(CompositeCPanel::OnComboBoxSelected));
	mCombo->SetSelection(0);
	mEditor->NotifySelectedItem(mCombo->GetValue().ToStdString());

	button->SetFocus();

	mEditor->mFrame = this;
}

void CompositeCPanel::OnComboBoxSelected(wxCommandEvent & event)
{
	mEditor->NotifySelectedItem(mCombo->GetValue().ToStdString());
}

void CompositeCPanel::OnUpdate(wxCommandEvent & WXUNUSED(event))
{
	// update the game.
	mEditor->ReceiveStrings(
		entryX->GetValue().ToStdString(),
		entryY->GetValue().ToStdString(), 
		entryZ->GetValue().ToStdString(),
		radius->GetValue().ToStdString());
}

void CompositeCPanel::OnSave( wxCommandEvent & event )
{
	mEditor->SaveObject(mName->GetValue().ToStdString());
}

One of the problems I faced with using wxWidgets was that I did not fully understand how their event system worked and thus I was not able to take full advantage of their feature set. To achieve the goal that I wanted, I passed a reference to the class that this Dialog was linked to. While it’s probably not the best solution, it is a solution, and until I find out a better way this will be the way it stays for now.

Videos

Senior Production: Game Over Feedback

Believe it or not, we never implemented an in-game way of showing which team won when the game is over. This has created some confusion at the QA labs because when the game finishes, nothing happens. You can imagine that people get confused when it appears there are no more enemies left, but they can still run around.

I have spent this week working on getting a win/lose screen to show up when the game is over. To accomplish this we need to:

  1. Check to see if there are lives remaining on only 1 team
  2. Check to see if there are existing players
  3. Ensure that the remaining players are all on the same team.

It’s pretty easy doing the first step, I send an RPC to the server, and the server checks the remaining lives array. Checking the players is not easy though. When the server creates a player we store the data in a structure that holds a players team color, and the players NetworkPlayer. This last part is key for us because we can then do a search for all game objects that are networked players and see if their NetworkView has this stored player. We can filter for the team because the structure contains the team color.

Having this information on hand, I was able to check for all existing players and if they were found, update a counter for each team to count all the players on the screen for each team. I then checked these final counts, and if there is only one that has a count greater than zero, then that team wins.

To each NetworkView connected to the server, I send out the team that won, and each client then handles which image to show on the screen.

Win Screen
Win Screen
Lose Screen. See that Pun?
Lose Screen. See that Pun?

I did encounter a problem with tracking the players. I check if the game is done every time a player is supposed to be removed from the game (because they died, or were vacuumed up). This is achieved by sending an RPC to the server that tells it a player died and it should check for gameover. The problem is that the RPC gets sent before the player is actually removed. To counter this problem, I create a co-routine with a delay of 2 seconds before sending the RPC this way I can ensure that the player is removed before the server checks for gameover.

Senior Production: A Lobby Full of Problems

Hi everyone,

I started reworking the lobby system for VacuuLab. This sounds like a simple task, but as it turns out it’s really not. I wanted to create a lobby system that has a similar menu flow as many other games, where from the menu you can choose to Join a game, or Host a game. By choosing the options it would take you to a scene with more specific options.

Halo Matchmaking Lobby
Halo Matchmaking Lobby

From the Join game scene you would be presented with all the current games, and be able to change game types that you want to play in, and in the Host game scene you would configure the game you want to play and create it.

Simple? Nope.

I can create the game just fine with all the different options I want, but the problem I am facing now is that when I go to list all the games available on the server, nothing shows up. I’m not sure if it’s because I am doing this all across different scenes, or because a configuration option may be messed up, but it’s not working.

I have decided to put the new lobby on the back burner because our current primitive game lobby works, and while it would be cool to get this new lobby in the game, if I have to spend another 8 hours debugging it, then it might not be worth it for now.

Senior Production: Gooey Weaponry

Hi Everyone,

This week has been interesting! I’ve been working hard to get a gooey metaball effect for the bullets that come from the gun to make it look like an awesome goo effect. After many hours of work and research I have implemented the effect into the game. I won’t go into much detail into how I did it, I’m going to save that for another blog post.

This week has been filled with understanding and learning the Unity3D graphics pipeline. The biggest problem that I had with implementing this feature was that I didn’t not know how I would actually go about doing this in Unity. I know how I would do it in another language from scratch, but when it came down to the implementation and using separate rendertargets within unity, I was lost. I began using a sample from the Unity Asset Store, Shader Replacement, to assist me in getting familiar with what I wanted to do. I was having a problem where when I rendered my metaballs layer they would show up as white squares rather than the faded gradient I was hoping for. This is where I began to research everything about Unity shaders and what options were available to me get it working. It turns out that properties used in certain shaders (such as _Color, and _MainTex) are available in the same frame in other shaders that operate the same (by use of Tags, like RenderType=”Opaque”). After finding this diamond (in the rough) I was able to pull the feature together.

Check it out:

finalgoogun

Simulating the Solar System in C++

Hey everyone,

Recently I’ve been working on simulating our solar system and it has been a difficult endeavor. There are a few big problems that I faced in this project:

  • Float Point Imprecision
  • Conversion from actual (metric) values to something smaller

Let’s evaluate each of these items.

Floating Point Imprecision

A float is a 32-bit data type in many languages that allow you to hold decimal data. You may have heard of floats referred to as Singles, this is because floats have a bigger brother known as a double. They are called doubles because it is a 64 bit data type. This allows a double to hold a much larger number, but you have the overhead of using a lot more memory. Due to this, there is a tradeoff in the manipulation of the data. Further, floats are use in many existing libraries and utilities, so now there is build in imprecision. What is imprecision? Imagine working with some really small numbers, something like 1.0 x 10-10 then dividing this number by say 1000. After these operations, the values will be getting so small that you are bound to lose some digits simply because the data type cannot hold numbers of that size. Imprecision is basically a limit on decimal digits, resulting in “unintended” rounding.

Actual Value Conversion

Because of the previous point having been stated about imprecision, using the real solar values is not preferrable because after all of our calculations, much of the data will be cut off. I found this part very difficult because finding a suitable size was nearly impossible. However, in the end I was able to make a decision and for distances, I decided to go with Astronomical Units and for weight, Earth Masses. Getting these values was easy because all I had to do was perform a simple Google search and I could find the AU’s a given planet was from the sun, and their weight in Earths.

Formula

To perform this simulation, I am using the Newtonian Universal Gravitation Equation

universal gravitation equation

Because of the units that I chose to use to scale the actual values (AUs and Earth Masses), it was extremely difficult to convert Big G to a number that accurately represents Earth Masses and AU’s. For this I used the good old, Guess and Check method. I just tried values that I thought might work really well for what I was doing. Ultimately I was able to find a value that fit well with my solar system.

Notes

This project is programmed in C++ using OpenGL (Libraries: GLFW3, Glut, Glew, and GLM).

Video

Check out the video below to get a better idea of what the project is like

 

Senior Production: Smooth Moves

Hey everyone,

I finished the new lobby system for the game, it works as you would expect any game lobby to work.  The typical start a game, pick a side, and ready up situation. When a player hosts a game, they choose their team and can technically join a game alone, but usually a user joins and prevents them from starting until the new user is ready to play. The new player follows the same procedure that the host follows, they pick their team and then can choose to ready up. While waiting, a user can change their team color at any given time and then ready up. Once all users are ready, the host can start the game.

Another thing I worked on was getting the team lives to work correctly. The focus of the Team lives is that each team has a given amount of lives in a shared pool. When you spawn your team life counter goes down, and when the team lives are at zero, you can’t spawn again. At this point if you die, then you’re dead. This is now how it’s implemented, previously I implemented it so that the team lives were decremented when you died, this created a problem of the team lives showing negative values.

Finally, the last thing that I did was implement network smoothing. The smoothing is an integral part of any networked game, and having this is essential for our game. Before the smoothing the game looked really choppy and ruined the flow of the game when everything around you looks like it’s jittering. The smoothing was implemented simply by tracking the last received rotation and position then using linear interpolation to smoothly transition between the actual position of the character and where the newest position is. This alleviated the jittering and made the game a lot more fun, according to our most recent QA testing results.

I am planning on working a cool metaballs effect for the guns to really help play up the “gooey” feel of the game, stay posted!

Metaballs GIF, Source: http://thedailytask.tumblr.com/post/66796683746/131112

That is all for now!

Tom

Senior Production: Changing Back to the Old System

Hey,

After much deliberation this week, Dan and I have come to the conclusion that it is not worth continuing work on the authoritative server. We originally wanted to use the Authoritative server as a method for control, anti-cheating, and data capture features. We also believed that it would send significantly less data than the old system that I had programmed last semester. However, while implementing the bullets across the network, we realized that with all the work and time spent:

  • We have not made it very far in 3 weeks
  • Many features still need to be implemented
  • We are using basically the same data as previous

The last point was discovered after a quick check between normal gameplay in the existing system. Once we realized this, we sat down and began to list the pros and cons of each existing system. Ultimately, the fact that we understand the older codebase, and that it worked were the main factors is us scrapping our last 3 weeks of work. I do not regret it and I’m glad that we switched back. I do enjoy the fun of prototyping and working new methods, but given the time frame it doesn’t make sense to continue with the authoritative server.

Moving on with the new system, I began to implement a true lobby system that lets you choose and change your team, and set your ready status. The game host will then be able to start. Dan began reworking the shooting system with some new firing modes, like a continuous stream, burst fire, and a goo stream. I also began setting the framework for the planned game modes, such as capture the flag, and king of the hill.

For next week, I would like to begin implementing more  feedback into the game mechanisms so that the players feel more immersed and don’t have to guess whether or not their bullets are hurting the enemy.

Tom

Senior Production: Unity Authoritative Server

Hi everyone,

Dan and I have been working on the authoritative server and porting everything over. We really want to make this switch so that we can collect more metrics on the game. We also think it would be really cool to have a replay system for the game where anybody can watch a previous game that has been played. This is good for both the players and the us, the developers. This will let the designers be able to analyze the game and see specific game moments and understand common play tactics to be able to fine tune the game play. We will also be able to implement heat maps with it. So far we have only implemented the movement, shooting, visually showing the vacuuming, and jumping.

The thing with implementing the authoritative server is that we have to implement everything on both ends. This means that we send the input to the server, the server parses the input, and then sends the new positions and players back to all clients so that everything is synced. The best way to think about the authoritative server is that you are watching a video and seeing how your inputs can modify subjective properties of “characters”

That is all for this week.

Tom

Senior Production: Initialization

Hey everyone,

My final semester at Champlain College has begun, and I am once again required to write about my experiences in the last half of my capstone class.

This last week was about reworking the networking for the game. Our new programmer, Dan, and I were working together to remedy some of the hacky solutions I came up with while rapidly developing VacuuLab. We decided it would be best to create an authoritative server set up to ease the implementation of game features and be able to monitor the game closely. Having a dedicated server would allow us to control the games and be able to make better decisions for level design and etc.

As far as the development, we have implemented smoothing and simple game play.

That is all for now.

Tom

Senior Capstone: The Wrap-up

These past few weeks have been wild… In terms of development the game is ever evolving and ever flowing. Like water… or goo?

To update you on things that have happened previously… the goo vacuum game has been named! VacuuLab! We finally settled on a name. It works, and rolls off the tongue… Or slides, or slimes, or glops off.. Regardless. With all this networking under my belt I feel as though I am a Networking Ninja Master Code Guru.

All this work, and my neglect to work on a networked game has come together into a harmonious experience that has blossomed into a beautiful flower. In a technical sense there is a lot going on and it’s pleasing to see my work pay off.

We are now on the downward slope for the semester working into the tweaking and the polishing that the game needs. My effort in working towards an easy and smoothly flowing environment starts with refactoring the code. As with all game development, the code that creates the prototype is never pretty. When we started my code was very bad. I’m not saying that now it’s good, it’s probably mediocre at best, but now with the refactor it is manageable. This is one truth about all programmatic development: There will be bad code in a large game. Not all features in the game will have the most defined and planned code. It’s just how rapid development works. While these rapidly developed features may not be the most readable as long as they are functional, you must carry on.

With VacuuLab, this is the case for some mechanics and features. I’m not bothered by it, I don’t necessarily have the time to refactor my code to such a manageable degree… When I am implementing features on features into a very large game I don’t have the time to dedicate to fixing my code and making it look pretty.

Ultimately we will be adding and adjusting features for the game over the next few weeks.