Mega

Last Login:
January 30, 2015
Warn:

Rank:
Member



User Profile
Comments
Follow

Hits: 113,533
Joined August 08, 2010
Games (11)

Game Music Player
October 10, 2011
Exile
August 01, 2012
In a word
August 10, 2010
Trace
October 07, 2010
Flood the mines Demo
November 12, 2010
Tetris
January 24, 2011
Velocite R
April 12, 2011
Shinsetsu Ninja
February 18, 2013
Walk of Darkness Demo
November 15, 2013
Project Phoenix
April 30, 2014
Frosty RPG WIP
December 23, 2014
Examples (1)
Favorite Users


Engineering Logs - VFS
Posted on January 13, 2015 at 06:57

It's a quiet day at work and I feel like doing something with my time.
So here's the second in a potentially long-lived series of blogs about what I'm doing with my engine.

Just a note, before I start:
These may or may not be the 'best' ways of doing things, but I really don't give a damn. I'll do things as I please, since I'm the one who has to work with the end product.
Everybody is welcome to work in whatever way they think is best. This is my way of working.

VFS


In Exile I used a static class called AssetManager that handled all the resources used by the game. This included textures, fonts, music, sound and levels.

The AssetManager class loaded an asset list on startup, which was a file that looked something like this:
Code

# Asset File
TEXTURE ./res/tiles/tex_brick.png BRICK_001
TEXTURE ./res/crosshair.png CROSSHAIR

SOUND ./sfx/enm_hit.wav ENM_HIT

MAP ./maps/E1L1.grv E1L1


This uses a simple parser to read in first a type identifier, then a relative path, and finally an internal identifier that was used in-code to reference the assets.
These are stored in separate lists for each type of asset, and come with associated Getters (GetTexture, GetTexturePAK, GetTextureIndex, etc).

The system worked, but became really difficult to deal with every time I needed to add a new type to the manager.

I did a bit of thinking and decided to implement a simple VFS, or "Virtual File System".

What I wanted was a very simple abstraction that worked with a class called File, of which there were subtypes (TextureFile, SoundFile, and so on).
The VFS manager must maintain a list of all paths from its root, and allow for both a lazy-loading system and for a preload system, with hooks for loading screens if necessary.

With that, I started out with what I believed to be the closest 'skeleton' representation of the VFS class and its methods. VFS is a Singleton, but I'm ignoring the specifics below.

Code

class GSVFS {
    public:
        void stageFile(std::string path);
        void preloadFiles(std::function<void ()> loaderCallback);
        
        GFile& getFile(std::string path); // Will load if not loaded, but its
                                         // best to preload if possible.
    private:
        std::string root_path = ".";
        const std::string exclusions = "exe;dll;pak";
        
        std::map<std::string, GFile> files;
        std::vector<std::string> preload_list;

        void enumuratePaths(); // Recursively scan folders for files.    
                               
};


This is just a simple representation of what I have. The ability to stage
files for preloading is very useful when you're loading a lot of resources, even small ones.
My actual implementation has quite a few extra management methods (For clearing staged files, unloading loaded files, mostly).

It's quite a simple system, really. The only 'complicated' bit is the enumuratePaths() method. And that isn't really complicated at all. It uses the C library header dirent.h to operate on the directory.
Certain filetypes are excluded (Via the exclusions string).

In addition to handling files on the actual HDD, the VFS class can also manage PAK files. It treats PAK files in a slightly different manner, in that it adds one extra layer to the root path that matches the internal name of the PAK.
This has the interesting side-effect of allowing 'patches' to existing assets.

As an example, if the original release of Exile had utilized this system and I wanted to fix those holes in the maps without having to build and release the entire game again, I'd just release a "patch1.pak" that overwrites the faulty maps.

Additionally, the VFS class also handles general file IO. So writing new files or reading from text/binary files is managed at a relatively low level via this class.

The GFile class


Well, time to discuss the data the VFS actually deals with.
The GFile class is pretty much a wrapped ifstream with a virtual Get method that returns the file contents.

In the case of the plain GFile, it returns a reference to the opened ifstream.
Other variants I use so far are GTextFile (Returns a block of text), GTextureFile (Returns an sf::Texture) and GSoundFile (Returns a pointer to the beginning of a Sound for SFML).

The implementation for each is black-boxed so that the caller doesn't have to worry about how it gets the data, just that it'll get it (Or an exception if the file isn't the correct type).
The VFS class manages instantiating the correct types via a table of lambda functions mapped to extensions.
If an extension isn't covered, the default GFile handler is used.

Well, that's enough of that. I'm going to go find something to do. Work is slow today...




Engineering Logs - Singletons
Posted on January 12, 2015 at 14:40

I'm feeling the need, to write blogs people won't read.

EDIT: Link to Part 2

Over the last year or two, I've been spending a lot of my time working on my ideas as quietly as possible. I have a 'major' game I'm slowly piecing together, bit by little bit.

One of the things that always slows me down is the engine I use for my games. I'm always torn between using an engine like GM, or creating my own.
I always want to create my own for the added benefit of being able to implement things that are unwieldy in GM, or even in Unity.
But as I've been noticing over the course of the last few competitions, I've always started out in C++ and ended up using GM (Or Unity in the case of Project Phoenix).

My work flow tends to involve drawing some initial artwork, and beginning work on the framework I'll be using. What usually happens not long after drawing the artwork is that I start to get anxious with regards to testing mechanical concepts, and seeing my animations in-context.
So I invariably end up just choosing the GM route for a quick game; at least with my competition entries.

In this case, especially with my long-term project (Called Fallen Keep), I've been sticking with C++ for the long haul.
My main reason for this is that it's far easier to express certain pieces of game logic in C++ than it is to fudge it out in GML.

Anyway, I've been working on the latest iteration of "my engine" for quite a long time now. About 18 months ago was when I started working on this game, and the new framework with it.

The engine that powers Exile was my original choice, but I realized shortly that the engine was very much locked in to creating 3D games; 2D games were too unwieldy. Much of the code was modified to fit into what I needed for the game.
If you ever want to see mangled code, give a programmer with nothing better to do a month and a simple 2D game engine, then tell him to make a Hexen clone.

Fallen Keep is 2D, and relies on the Core OpenGL profile for various effects. Exile primarily used Fixed Function OpenGL, and later mixed GL3.2+ features to add the lighting model I used for Abyss.
As a result, the render code is pretty much screwy. Rewriting in this case was the sane choice.

Anyway, enough rambling. I've learned a lot over the past year with regards to quickly implementing a game engine from scratch. A lot of experimentation has gone into this, and I decided to start writing a few pieces on some of the patterns and ideas I've been using for it.

Take everything with a pinch of salt. No doubt some of you will have an alternative, or 'better', way of doing things; that's fine. Discuss it, I'm always interested. :P

Singleton Pattern


This is a mildly polarizing design pattern; some people swear that you should use the things "wherever possible", whereas others insist they be treated as something akin to goto.

My opinion is that they fit the bill perfectly for their intended purpose: To provide the programmer an instance of a class, and only ever that one instance of that class.

Originally, I used to create purely static classes for things like this. The AssetManager class from Exile is an example.
There are downsides along with advantages to static classes, but in the end it boils down to aesthetic for me. I hate using the :: accessor outside of the only context I believe it fits: Namespaces.

Anyway, on to the actual definition of a Singleton.
The Singleton Pattern is a specific manner of coding a class in such a way that you can only ever instantiate a single instance of that class at any given time.

This might sound stupid to some, and in many cases it is. You wouldn't make, say, a GameEntity class a Singleton.

But for some things it provides an elegant solution to the problem of access.
A lot of 'tutorials' I've seen on GameDev and other sites that involve creating game engines tend to either make liberal use of global variables, or pass certain objects as parameters.
Something like this:

Code

// Using some basic SFML code.
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>

void update(const sf::RenderWindow& window);
void draw(const sf::RenderWindow& window);

int main(int argc, char** argv) {
    sf::RenderWindow *renderWindow = new sf::RenderWindow(sf::VideoMode(640,480));

    sf::Event event;
    while(renderWindow->isOpen()) {
        while(renderWindow->pollEvent(event)) {
            if(event.type == sf::Event::Closed) { renderWindow->close(); }
        }

        update(*window);
        draw(*window);
    }
}

void update(const sf::RenderWindow& window) {
    // Do stuff, update view, etc
}

void draw(const sf::RenderWindow& window) {
    window.clear();
    // Render game objects
    window.display();
}


This is a 'flat' example, just here to show the concept I'm talking about. I've seen quite a few "C++" engines that depend heavily on coupling like this (The function definition requires another object to exist, instead of being able to exist on its own).
Decoupling is fairly important to building stable programs, in any given situation.
Some classes and functions are designed to work with each other, but in some cases you're passing references out like candy. Break or change the thing being passed, and you start getting potential cascades of breakages.

The point with the renderWindow variable above is that it's something that will need to be accessed by a large number of classes.
If I was using SFML's built in draw functions, every Drawable object would need a reference to the render window.
And things will get messy very quickly this way.

Static classes alleviate the problem somewhat, but in my opinion are somewhat messy to handle.

So I'll skip those and dive right into the same program segment above, reworked to use a Singleton class.

Code

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>

#define INSTANCE(singleton) singleton::getInstance() 

class GSWindow { 
    public:
        static GSWindow& getInstance() {
            static GSWindow window;
            return window;
        }

        sf::RenderWindow& getRenderWindow() { return *this->renderWindow; }
    private:
        GSWindow(){
            this->renderWindow = new sf::RenderWindow(640,480);
        }

        ~GSWindow() {
            delete renderWindow;
        }

        sf::RenderWindow* renderWindow;
};

void update();
void draw();

int main(int argc, char** argv) {
    sf::Event event;
    while(INSTANCE(GSWindow).getRenderWindow().isOpen()) {
        while(INSTANCE(GSWindow).getRenderWindow().pollEvent(event) {
            // ...   
        }    

        update();
        draw();
    }
}

void update() {
    
}

void draw() { 
    INSTANCE(GSWindow).getRenderWindow().clear();
    INSTANCE(GSWindow).getRenderWindow().display();
}


Longer winded, perhaps, but neater... at least to my eye. :P
And yes, I'm using simple Macro expansion. I could also just call GSWindow::getInstance(), but I prefer the INSTANCE macro to be 'first'; makes it easy to read that I'm using one of the Singleton classes.

The 'creation' of a singleton can be automated somewhat with templates, but I prefer to hand craft them to a degree.

A way of creating something like "INSTANCE()" without using the pre-processor is to create a static method that operates on anything of the Singleton 'type', but I consider it too much work and extra processing to be bothered for the scarce few Singletons I use.

Anyway, back to the subject at hand.
This setup allows for a few things. First of all, clarity. Reading this code in my engine I see immediately that I am using one of the few Singletons I have.
Secondly, I can access everything with a guarantee that everything is initialized and ready to be used.
Thirdly, and class method or function can access and use the instance of GSWindow as long as it 'sees' the class declaration (Normally I'd split that GSWindow class into separate .h .cpp files).

So, a few notes. I only have three major Singletons in my engine, each of which are natural fits for the pattern.
These three Singleton classes are :
GSWindow - Wraps the sf::RenderWindow and associated window functions.
GSVFS - Virtual File System for game resources.
GSTasker - Task management system


The "GS" prefix stands for "Game" and "Singleton".
I had a GSInput class for a while, but decided that it was a poor idea if I ever felt like implementing multi-source input (for local multiplayer), or for input streaming (for demo playback, AI control, or even network play).

A little quirk you'll notice if you stare at the code hard enough is the way I implement getInstance(). I'm specifically taking advantage of the static keywork, initializing an instance of the class (Possibly on the Stack, depending on compiler and what the optimizer feels like doing, so don't get too carefree with them).
When the program ends, this instance falls out of scope and will automatically delete itself. Nifty, as it allows you to 'black box' the details of creating the instance.

Anyway, that's enough rambling for now. Next time I'll write about my VFS system, why I'm using it instead of my old AssetManager system, and maybe some other stuff.
Feel free to argue inefficiencies below; don't get too hard-assed about doing things 'right' though - there isn't any such thing as far as I care. If it allows me to make games, it's right for me.




F4D Progress Blog
Posted on December 19, 2014 at 16:19

I'll post micro-updates here.

I'm making a mini-RPG thingy, because that's what I feel like making.
So far, I've created a character template, and started on an icy dungeon/castle tileset. I'm trying to go for a somewhat SNES/GBA style of art this time round.

Here's what I have so far:


I also have some basic music I've started to hammer out. You can hear it here if you have an NSF player: https://dl.dropboxusercontent.com/u/11942397/Frosty2014.nsf

Not doing much more tonight; I have work in the morning. :P




Bees.
Posted on December 08, 2014 at 15:36

I had a somewhat amusing day at work. I arrived this morning just before 9AM, and noticed something out of the corner of my eye.
There, on our store-front window, was a swarm of bees clustered together, about the size of a grapefruit.

I hate bees, and being stung. Fortunately, these bees were not interested in me in the slightest.
Still, as a precaution, we kept the doors closed for most of the day and put a sign up "CAUTION: Door closed due to bees" with an arrow pointing to the swarm.
Most people thought it was a joke, until they looked. Some of them jumped pretty far.

We don't know why they were hanging there, but they stayed that way all day while we waited for some beekeeper or other to show up. He didn't, and my boss was getting tired of waiting. The bees were hurting (literally in some cases) our business.
So she grabbed a can of Doom (Insecticide), sprayed some quickly and dashed back inside.
The bees didn't die, but they did start to fall apart. One of the last 'pieces' of the swarm that fell off had the queen in it, surrounded by a ball of other bees. Reminded me of Katamari...

The funny thing is, there wasn't anything there for the bees to make a hive in. They were literally gripping onto a tiny bit of dried paint that had formed a small bump in the paintwork, on the underside of the window lintel (Concrete and metal construction).

That was certainly the last thing I imagined happening today; would've taken a photo, but I kinda forgot. :P

Ludum Dare
I kinda flunked this. Not intentionally, nor because I didn't have time. The whole country has been going through rolling blackouts, and they were particularly bad on the weekend. I lost quite a bit of work to the first one, and had a lot of trouble getting back on track after that.

I didn't upload my 'final' product, but here's what I had at the end:


The theme for this LD was "The entire game on one screen". I decided to make something arcade-like. Waves of enemies would be beamed in by that contraption in the middle, and you'd have to survive for as long as possible, collect randomized powerups and possibly have a second player join in.

Somewhat low-key for me, but that's because of what I coded this in. What I do have, I made entirely from scratch in C++. I was originally planning to use one of my existing frameworks to accelerate the workflow, but decided to test the difficulty of doing something like this from scratch.

Turns out, not too long.

All I really have here is animation, running and jumping (And collision, of course). I had started on an enemy, projectile and health system when the power went out. And of course I hadn't saved.

I did stream a bit. Potato quality if you want to take a look: http://www.twitch.tv/64mega/profile/past_broadcasts

Uhh... Impulse post mortem, I guess?

Overall 'engine' design
I decided to use a system that was a hybrid of my old Exile system, and a newer one I have been working on.
In Exile, all GameObjects are spawned into a single list. Every frame, this list is traversed, dead objects are culled and the update() method for each object is called.
This is great, when you're dealing with a small number of objects.
It's also great when you don't need any information about the type of object.

Oh, and it becomes a bloody mess when you need to do collision detection/object interaction. Loops within loops within loops...
Exile worked though. :3

My 'new' system uses a few different techniques. Here's the base game object class:
Code

class GObject {
public:
    static GRegistry registry;

    std::string id = "object";
    GSprite* sprite = nullptr;
    float x = 0.0F, y = 0.0F;
    bool dead = false;

    GObject();
    virtual ~GObject();

    virtual void update();
};


It's very similar to what I used for Exile. It has a 'dead' flag, it has a position (I could decouple that into a separate object, but I was rushing), and it has the update method.
The magic here is in the static GRegistry object.

A GRegistry is nothing more than a list of objects. Which isn't a big deal. Here's the definition:
Code
class GRegistry {
public:
    void add(GObject* obj);
    void cull();
    void iterateOver(std::function<bool(GObject&)> func);
    void update();
    void cullAll();
private:
    std::vector<GObject*> objects;
};


The only mildly unusual thing is the iterateOver() method; it may be alien to C++ developers who haven't yet begun poking into the newer C++11 features.
An std::function is basically a 'safe' function pointer. Much cleaner than the old syntax.

In GObject's constructor, only one statement is called:
Code
registry.add(this);


This basically means that any GObject is automatically added to the list.
The 'trick' here only comes into play when I start adding new classes to the game.

The first one I added was a "block" type, for level pieces.
Code
class EBlock : public GObject
{
public:
    static GRegistry registry;
    EBlock(int tx = 0, int ty = 0);
    virtual ~EBlock();

    virtual void update();
};


Note that it also declares a static GRegistry member. This overrides registry for the EBlock object, but leaves GObject's registry intact. This has a nifty use, as can be seen a bit later.

The EBlock constructor is basically this:
Code
EBlock::EBlock(int tx, int ty) :
GObject()
{
    this->registry.add(this);
}


This explicitly places a pointer to the newly instanced EBlock into EBlock::registry, but also calls the base constructor, which will add a pointer to the instance to GObject::registry.

Later, in the Player object, I need to check for collision with any EBlocks. But I only want to check EBlocks, I don't want to loop through every single GObject like Exile used to do. Especially not for level tiles (Exile actually separated level collisions completely, adding another layer of collision detection. It was complicated).

But because of this system, I can use a very nice representation to interact with specific classes of object. Like so:
Code

EBlock::registry.iterateOver([&](GObject& object) {
    EBlock* block = (EBlock*) &object;
    // Do collision stuff with block
});


I treat the cast as implicitly safe due to knowing that the objects EBlock::registry should contain are all of type EBlock. This is something that would be a lot uglier to implement if it weren't for lambdas; I'd have to define a separate method, and pass a pointer to that method into the iterateOver() method.

Of course, even with this narrowing of search data, I'd still rather move away from using GObject's for level collisions anyway. Generally I create a tile-table, and check against those directly (It's easy to determine what point in a grid the player will be in by the end of a frame, making the entire thing a single simple check as opposed to potentially hundreds of little checks).
Unfortunately, I ran out of time (Though I may finish this little project at some point).

This entire system makes working with classes of objects a lot easier. In Exile, I had a string called "id" (Which is present here for reasons discussed below) that I would check to find out if I was dealing with an object I wanted to deal with.
With this system, I know what type I'm dealing with, and can avoid a lot of conditional tests I'd otherwise be using.

The id member is there more as a tagging system now. Kind of like a packed data system that can be used for anything I want.
I could set the string to "cd" and have the following in my player code:
Code

if(object->id.find_first_of("c") != string::npos) {
    // Collide with this object
}
if(object->id.find_first_of("d") != string::npos) {
   // Get damaged by this object
}


Though with the way my design is moving, I probably won't use it like that. I'm using a Component system more often at the moment, and my Object class will change to reflect that.
To avoid extensive checking, I'd probably implement the system somewhat like this:
Code

// Partial class definition
class GObject {
    private:
        Damage *damage = nullptr; 
        Collider *collider = nullptr;
   public:
       void DoCollision(std::function<void(GObject&)> func);
       void DoDamage(std::function<void(GObject&)> func);
};

// Will use like this:
void Player::update()
{
    Player *self = this;
    EEnemyProjectile::iterateOver([&](GObject& obj) {

        // Check if colliding and perform following
        obj.DoDamage([&](GObject& obj) {
            TDamage* damage = (TDamage*) &obj;
            self->hp -= damage->value;
        });
    }); 
}


The implementation for DoCollision and the like will basically only execute the function if it actually has a pointer to a TCollider, and likewise for DoDamage.

On that note, I haven't actually tested internal lambda capture rules yet. The [&] I passed to the lambda mean to 'capture' all variables in the scope the lambda was defined in. I'm not 100% sure if the nested lambda will capture the entire scope, including the one passed from the outer lambda.
My logic says it should, but the compiler may say otherwise.

...

I rambled more than I meant to. I'll stop now. :P




Android Tablet and LD plans
Posted on December 03, 2014 at 15:47

Last weekend I saw an ad for a tablet that was on promotion at our local Walmart.
(Called Game here, to confuse people living in the UK. :P)
I was talking to my parents about wanting one for a while, but something clicked in my head at that point and I decided to buy the thing... at a cost.
That cost being that I'm going to be eating very simple packed lunches for the next week or two... but that's OK; I needed to break my Soda habit... and Dorito habit...

Anyway... I got the tablet on Monday. It's a Telefunken TEL7JD. I'd seen a few (mostly negative) reviews about its predecessor, the TEL7J, and was expecting a really low-end tablet. But that was fine by me; I really only wanted it for one thing: Reading.
I have a tonne of digital books on my PC, from iTunes and otherwise.
Speaking of iTunes... it's kinda stupid that it doesn't let you read books on your PC. It's just in epub format...

Well, the tablet I received was better than I expected, outdoing what the store catalog said in the item description. It's got a dual core 1.0Ghz ARM processor, 512mb RAM, a 7" display with a crisp resolution (Telefunken know their screens, I'd say), has Wi-fi (No 3G, but that's fine by me. I hate mobile carriers...), and has Android 4.4 installed.
Only 2GB internal storage, but I can get large SD cards on the cheap, and already have a 4GB one installed.

The thing is a little powerhouse. I've installed a collection of emulators on the system, including PPSSPP on a whim... and yeah. Playing Super Robot Wars is now my favorite time-killer at work.
Back to the 'powerhouse' thing... I can play Monster Hunter Freedom Unite via PPSSPP without slowdown. That seriously surprised me, all things considered.
The available DS emulators do a crappy job by comparison; slow as heck.

So yeah... great little device. Got it for the equivalent of $80, which is less than I bought my DS Lite for. Very happy with it, and I may even try harder to develop stuff for Android platforms now that I have a device to play around with.

Ludum Dare plans
So yeah... found out about LD yesterday, and decided to enter again. Mostly because I have this severe urge to make something that isn't related to my job.
Of course, I tend to feel pretty burnt out on weekends. But I'm planning on taking things slowly. I'll shoot lower than usual; make a 1-screen game or something like that, but do it as well as I can.
I intend to use C++; I've been practicing a bunch of rapid (And messy) development techniques using the new C++11 features. Lambdas and auto make for an easy method of passing game logic around dynamically.

Oh, and something about Pokemon ORAS
No, I haven't played it. I don't even have a 3DS. Wouldn't mind getting one though, because I especially want to play this game (Sapphire was the second Pokemon game I ever played, and one I still have good memories of, despite the naysayers).

The other day, a friend of mine introduced me to this:


That friend and I were talking about how this theme sounds somewhat metal for a Pokemon game; sounds more like something out of Super Robot Wars, Street Fighter... that kinda thing.
I jokingly said I'd have to make a Mega Gallade Mecha mockup... and actually started work on that:


Well, that's enough out of me. Got work tomorrow, so I need my rest.




Slow Saturday.
Posted on November 22, 2014 at 03:57

I'm sitting at the PC shop; I usually don't bother opening on Saturday, but I had a minor backlog (Which has been cleared).

I stumbled upon some very amusing and gratifying articles by one David Thorne; I now have the urge to employ weapons-grade sarcasm against some of my more annoying customers.

http://27bslash6.com/p2p2.html
http://27bslash6.com/missy.html




A little blog.
Posted on November 20, 2014 at 16:39

It's been over a month since I've written a blog. And I have some excuses for that. Ranging from laziness to business and everything in-between...

So yeah... I regret not being able to finish my game for S4D. I haven't even opened the project since three weeks ago, nor have I even given game design much thought for that time either.

The main reason for this is that my job is becoming busier. A lot busier. My range of responsibilities has increased, the number of customers we get on a daily basis has increased... and this is all great. It means I have a modicum of job security to look forward to; we're starting to get people from the next town over come to our shop for our prices and service! (And they have three franchise stores there).

And, with encouragement from my boss, I've been using the spare time I have at work to develop my programming skills further, specifically tackling areas I'm not comfortable with.
Things like GUI programming, design patterns, networking, inter-process communication, Unix/Linux specific stuff... and it's been great so far.

Within the space of three weeks I've become proficient enough with wxWidgets to create a simple GUI off the top of my head. It's dead simple once you get your head around the way it presents itself.

More C++/wxWidgets/Linux stuff
Linux. The more I use it, the more I love it. I've reached the "convince customers that Linux is a more-than-capable and free Windows upgrade" point. I've installed Lubuntu on three machines over the past couple of weeks; and the customers are satisfied.

But what I really love about Linux? Programming for it. It's so ridiculously easy to pull off what would otherwise be a hair-pulling exercise in Windows. Case in point being the existence of the Posix threads library.
Sockets are suddenly straightforward and easy to use. Child processes are relatively easy to manage... Yeah. It's been a fun time.

For the first time ever, I've been piecing together a "real world" application. A Point of Sales program, with an Inventory Tracker (Compacted to "POSIT").
After reading a few books on design patterns, I spent the time designing a decoupled system in which the core logic doesn't need to know about the data, and neither of those need to know interface internals, and so on.

wxWidgets allows for dynamic binding of event handlers during runtime, and I've been using that to my advantage. For data, I've been using a custom key-record system that defines the fields and types of the record as well as the content.
Each 'system' provides basic interfaces to the outside world, but I could just as easily use the Core and Data systems from a CLI implementation (And do, for testing), or create a socket based interface that can use a Node front-end. It's fascinating to piece together such a system.

The Inventory manager has been pretty fun to write; the fun began when I essentially noted that the "real" inventory classes more or less mirrored "game" inventories (In that the inventory contains a finite or zero number of items that have "effects" and cost/value associated with them).

The interface is designed in wxFormBuilder, and because of the way I detached event logic from the UI classes, updating the design is a breeze; even after deciding I had to redesign the entire interface using SplitWindows (For resizable panels), the existing logic worked just as it did before.

I'll try remember to snag a screenshot of the interface tomorrow. I'm rather pleased with how easy it is to piece these things together, and I'm already planning a new editor for my engine.

In other news, I've begun to use lambdas a lot more in C++. They're great; just enough functional programming without making the language a complete headache!
Also, I've begun to see proposals coming out involving the addition of modules to the language as a replacement for the old #include directive.
I think this could potentially alleviate a lot of headaches we tend to face when dealing with circular dependencies and such.

One feature I'm waiting for is for somebody to add the ability to replace :: with . when dealing with namespaces and static methods/members... because :: is ugly.

Shop stuff
Stupid stuff still happens on a daily basis at my workplace. It's usually quite frustrating while I'm dealing with it, but it's funny in hindsight.
Some new samples of the local flavor:
- Being told to "make" a PCI-E card fit an AGP slot because "it's your job".
- Having to deal with and attempt repairs on a laptop in which the HDD was taken out of the bay rather violently, and the SATA connectors were literally ripped off the board. The solution involved copious amounts of fuming, an SD card, external HDD bay, and RAM-loaded Linux.
- People buying a cheap second-hand machine from us. I tell them it won't play games. They still come back a few days later accusing me of selling them faulty hardware.
- One of my 'competitors' coming into the shop with his own PC. The problem? He didn't know where to plug the front-panel cables in on the motherboard (Even though it was clearly labeled). Took me all of 10 seconds...
- Being told that Minecraft, Borderlands 2, Far Cry 2 and several other games are "Free games, the ones at the shop are illegal".
- Being asked to send faxes. CRACKS ME UP EVERY FUCKING TIME SOMEBODY COMES INTO THE SHOP WITH A 100 PAGE FAX.
- Again, faxes. And when I ask for the fax number, they hand me an email address. Explanations and hilarity ensue.
- Also, emails. When I ask for the email address, I get a fax number. Involuntary spasms may occur.
- Having to explain that Windows 7 or 8 (Or Sevenorate as some of the locals are calling an imaginary combination between the two...) will not slow your piece of shit laptop up by any stretch of the imagination.
- Ditto for desktop PCs.
- Same, but this time with fans being the preferred 'upgrade'.
- Getting paid in R200 notes for a R2 printout. I tend to point-blank deny these, though, much to the annoyance of the "valued" customer. Spend more money and I'll assign more value to you.
- Having people stop outside the shop, read the sign that clearly says "Friendz Computers", and still asking us "is this a computer shop?". This behavior has convinced me that the people in this town can't read, as they tend to ignore our other signs too (Back in 15 minutes, Away on Callout, etc).
- "I took this box out of my computer, it was making a noise. Why isn't my computer working?" - confused customer pointing at HDD.

I'm starting to really enjoy the work a lot more though. It's really satisfying to repair a machine quickly and get thanked by customers for efficient service.

I actually received a tip from one of my customers a few days ago. An Irish couple on holiday visiting a relative. They wanted me to pull the photos off this relative's computer and put them on a USB drive; the old man didn't want the PC anymore.
Not only did they give me a large tip afterwards (Precisely the same as the service fee), they donated the PC to the shop!

Well, it's back to work tomorrow. This week has felt really hectic; I felt like yesterday should have been Friday with how dragged out everything felt... and I'm only facing Friday tomorrow.

Gaming
I still find an hour or so after work to play a few games. For the most part, that's been nothing but Risk of Rain for the last week; it's addictive as heck.
Just beat it for the first time last night.

I've also got my copy of the Witcher 2. Even better, it's the Enhanced Edition, which is very nice of GOG. I'm just waiting for it to download.

And on a final note... Dark Souls is extremely close to updating.
But here's a little twist... it seems that the update isn't merely a patch to remove GFWL...
SteamDB has a few interesting nuggets of information on what's going on behind the scenes.

One of the first things I noticed is that the new Depot size is 7.4GB, up from 4.06GB. This indicates strongly that there are some potential content additions and fixes.
Secondly, the depot branches. There are two major new branches of interest.
The first is "steambuild", with the description NOG4WL. Obvious what this one is.
But a new one popped up the other day. "hybrid", with the description "G4wl + Patch".

So yeah, it's pretty obvious that something is being patched, and it's probable that something has been added to the game. 3.0+GB of content is a bit much for a mere migration to Steamworks :P

Show


I'll love From if they release the patch tomorrow, just in time for a weekend of invading. :3

Well, that's enough blog from me. I need to get to sleep.




GOG.com giving away a few freebies
Posted on November 13, 2014 at 06:11

Just a heads up. The first is Mount & Blade (The original game).
Scroll somewhat down the page for it.

http://www.gog.com/

And the second? The Witcher 2 + The Gamers: Director's Cut.
For that one you have to check in every day to 'claim a sticker' (Which just involves clicking a box), and you'll get it at the end of the week.




Shop Talk
Posted on October 16, 2014 at 14:39

Caution: This blog contains traces of stupid. Read at own risk

I work at a PC shop. That's a bit of a vague term, and possibly an incorrect one.
To best describe the business, I'd have to call it a "Repair/Retail/Internet Cafè/Scapegoat/Printer/Contractor/Graphic Design/Web Design/Help my internet broke" Shop or Call Center.

I work the typical 9 to 5 shift, and man the shop on my own for 90% of the day.
My boss is on callout for part of the day, and working her other job for another good portion of it.

So yeah... it's a nice little shop. We stock a lot decent retail goods; things like flash drives, keyboards, webcams, speakers, ink, etc...
And of course we do repairs. That's officially my job, though I do everything else too.

Naturally, some of the repairs/requests that customers bring to me are absolutely ludicrous; stressful, but funny when looking back. Here's a couple of anecdotes.

A+ 101: Lubricating your Hard Drive


So, one day this guy walks into the shop and tells me that one of his HDDs stopped working suddenly.
I asked him what happened prior to the failure. He described to me that he thought it was making too much noise (You know the noise those slightly older IDE drives make when they're reading/writing data), and that he tried to fix it.

Yeah... I asked him how he fixed it.

He "fixed" it... by drilling a hole in the motor casing and putting boat engine grease into the hole.
What I wonder is... why did he even have to ask...

Multi-core processing on the cheap


Let's keep this short...
Did you know that apparently 1 out of every 2 people in this town cannot legitimately understand why soldering a bunch of processors on top of each other won't work? (And didn't work, in one guy's case).

Bucket Computer


This one was from today. Around 5 hours ago, to be precise. A guy walks towards the shop with a plastic window-washer's bucket. All I could see in it was a damp looking rag, and I thought he was... well... a window washer, coming to ask if our window needed cleaning (We get a lot of hawkers and such).

Then I saw the power cables coiled on top. That was his 'machine'. The rag was soaked in cooking oil (There's a common myth floating around that submerging or otherwise subjecting your PC to cooking oil will cool it down. It works, but will leave your PC smelling rancid after a while, will leave a slimy residue... and has the potential to build up more heat than you normally would).

Anyway, yeah. Bucket PC. No, it wasn't working. No, he wasn't here to have us repair it... he wanted to sell it to us...

Grease makes things go faster, right?


Is your computer feeling sluggish? CPU slowing down? Never fear! Just apply a generous coating of engine grease to your RAM, CPU and GPU, and never worry about your computer being slow again!

This is another one I've seen relatively often. Vaseline is another lubricant of choice, and some of them have a spritz bottle of cooking oil they use.

Pro Overclocking


This one guy... decided that the best way to speed his PC up was to replace each capacitor on the motherboard with the same high-voltage ones found in PSUs.
According to him, this was 'overclocking'.

Oh, I should probably mention that in all of these encounters, the customer proudly explains their methodology (And shattered logic), then ask "So why isn't it working?".

This is why I'm on anti-anxiety medication...

"I made it fit, so why doesn't it work?"


I encounter, and replace, several varieties of RAM chips, the most common being the DDR2 variety.
But what happens when somebody decides that DDR/SIMM/Whatever ought to fit in <insert slot here>.
One sharp/abrasive implement and a trip to Your Friendly Computer shop later, and I'm again hearing the "So why isn't it working?" line...

This also happens on occasion with AGP/PCI-E graphics cards, and processors.

Well that's enough of that for now


Writing these is both funny and depressing. Depressing because I'm actually having to deal with this on a near-daily basis.
But hey, at least I get paid for it. :P

In other work-related news...
I have an old Pentium sitting around, fully intact. In fact, the inside of the case is the cleanest PC I've ever seen. Slight layer of dust, but the board (A 1996 Intel board), is still shiny and clean.

Naturally, the machine is, for all practical purposes, pretty useless. That's no deterrent to me. My boss has approved a long term project wherein we install DOS or Win98 on the thing, buy some joysticks and a coin box from a company in Cape Town, and build an Arcade Cabinet; Old versions of MAME run pretty well on old hardware :P

We're also planning on moving two of our machines near the front of the shop, on a long bench-table. These particular machines have a few free games installed (Red Eclipse, for instance), and a few classics (Doom, Quake, Quake 2, Unreal Tournament).
Not many people stop by to use our internet services... but we're literally right next to a school/high-school, and hordes of the undead little buggers walk past our doors every day.
We plan on setting up a few LAN tournaments with small prizes; those machines are our 'base' machines, and they can bring their own.

If that gets big enough, we might plan a bigger tournament at the town hall; my boss is a trained event planner/coordinator, and we could potentially make a pretty big deal out of it :P

On a completely different tangent...
Objects of interesting lying around our shop:
> An old Yamaha XG sound card. In working condition.
> An ancient scanner. It's the size of a big office printer, though flatter, yet it can only scan A4 pages (At around 80DPI).
> Mount Oki. For some reason, we have a pile of discarded OKI printers in the back of the shop.
> 22 3 1/2 inch floppy drives. Am tempted to make a robot out of them.
> 8 CRT monitors, some of them are huge. Am planning on using one of them in conjunction with one of our crappy webcams to make a monitoring system of sorts.

Well, that's enough outta me. I'll probably have tons more stories in a few weeks. Things get pretty crazy at work, with great regularity...




I've now seen everything...
Posted on October 09, 2014 at 02:53

Minecraft 1.8. Have you guys seen what's possible with Armor stands?



Gotta run to work, but take a look at this :P



Prev Page | Next Page

Recent Activity
 
Active Users (0)