—    —  Home

   JLJac on March 02, 2014, 02:11:59 AM:

Hahaha yeah the hackmobile didn't even leave the garage this time XD

In Lingo, there was something called a property list. It was basically a little class that was declared on the fly. A declaration could be like this:

Code:
LevelParams = [#CornerRadius : 120, #BottomPadding : 40, #LevelName : "Magma Mayhem", #TerrainData : gigantic2Darray]

Then I could just grab anything out of that thing, like this:
Code:
levelTitle.text = LevelParams.LevelName

This was cool because it enabled me to group my data together by context. I didn't need to create a new property in the player class for every little parameter that was related to movement, I could just create a
Code:
MoveParams = [#Runspeed : 4.2, #JumpHeight : 2.1, #DefaultMode : "Running"]
and everything became a lot less cluttered.

Also, talking about tree-like structures, these things could be nested indefinitely. So I could group things, and then access them like
Code:
jmp = MoveParams.JumpParams.DoubleJump.Strength
I don't expect to be able to do this in C#, but if I was able to just group and label the data at all, even if everything in the same container needs to be the same data type, that would be awesome.

Dictionaries feel wrong, because they feel like they're used for searching gigantic databases rather than just grouping three variables together because they're related. I could create classes for all of those things, but it feels super cumbersome to have a million classes where the majority is just a container that holds two or three properties.

Is there some way to accomplish something like this, or is my approach just wrong from a purist programming point of view?





   JLJac on March 02, 2014, 02:32:05 AM:

This seems like the thing for me! Is it similar to this? Why is it hacky?  Who, Me?

I feel a bit confused, to be honest. You can create two classes inside of one class? Where does the code actually go? In the same text file, but where? What is a "namespace"? What is a "dedicated field"?





   JLJac on March 04, 2014, 01:26:32 PM:

I ended up using the dictionary approach. Just want to once again confirm how incredibly thankful I am to have you guys help me :D

The sprite stuff now looks like this - I create an array of sprite containers, and I also have a dictionary where I've named each of the positions in that array. In order to not have to fetch both of those variables from the main game class each time, I've created a little function that looks as such:
Code:
public FContainer returnFContainer(string index){
   return SpriteLayers[ spriteLayerIndex[index]];
}
Where SpriteLayers is the list of FContainers and spriteLayerIndex is the dictionary. Then I can, from the objects, super easily add a sprite to whatever layer I want like this:
Code:
tpGame.returnFContainer("BkgLayer").AddChild(spr);
It works like a charm Smiley Best thing is that if I want to add a layer in the middle of the stack, I just have to change the dictionary in one place, rather than index numbers in all the objects. As long as the strings are the same, they'll find their layers!

I should probably start a workshop thread... But now I feel like I'm ready to start working on real rain world stuff soon, this learning phase should be more or less over.

I'm doing a tiny little learning project, not because I want to waste time not working on rain world, but because I felt that it was better for me to start rain world porting with some tools in the box and some basic knowledge, so I wouldn't immediately clutter rain world with a bunch of stuff I'd implement just to learn this new environment. Now the test project is done, and the last thing I want to implement is a menu, so there's somewhere to press "restart" and I can share it with you guys for fun Smiley

This also brings me to another thing I'd like to learn - someone mentioned creating a little mini class inside a bigger class.

My main menu will have four items. All of these have a lot in common, they each hold an FLabel (futile's text sprites), they should all be selectable, they should all change color when selected, etc. A lot of behavior in common, simply.

This calls for a "MenuItem" class. But the "MenuItem" class should only be instanciated and manipulated from inside the "Menu" class. Also it's a very small class which only holds a few variables and hardly executes any code, so it feels weird to roll out the red carpet and give it an entire text file of its own. Ideally, I'd wanna create some kind of mini class that's only available from inside the "Menu" class.

After searching for "c# nested classes" I think this might be the thing, but I just wanted to check with you guys if this practice is considered halal, and if you have some tips or tricks to be considered?





   JLJac on March 05, 2014, 01:04:47 AM:

Thank you sir  Gentleman

Mini class works super well  Smiley Hand Thumbs Up Right

Stupid question #4224:

Now both the players and the menu need to take input, so I want to create a FetchInput function where you pass a player number and get the current state of axes + button for that player's input.

Now, the problem is that I want to return both a Vector2 for axes, and a bool for the fire button. Do I have to create a separate text file with an InputData class only to be able to return these two variables in one go? That feels super cumbersome. Also I know that I could bake them together into a Vector3, but that's a hacky solution that I'm not learning anything from - I want to be able to solve this problem no matter what the data types happen to be.

Is there some equivalent of
Code:
public Vector2, bool fetchInput(int playerNum){
return new Vector2(0f, 0f), false;
}
that I could use? One of my searches suggests returning a KeyValuePair, but that seems like a hack IMO...  Huh?





   JLJac on March 06, 2014, 02:13:40 AM (Last Edit: March 06, 2014, 09:44:16 AM):

I used out paramaters - they're awesome! I'm learning so much these days my brain almost can't take it  Droop Why oh why didn't I start with C# earlier?

Here's the test project I've made this last week!

The game has quite a bit of Rain World-like stuff going on in it when it comes to the physics, because I wanted to try that out. What it lacks is levels, loading and saving files, sound, and much more, so I still have stuff to learn  Shocked But those things I can probably solve as I go - the reason why I made Space Worms was that I needed something simpler to just see if I could get stuff to move on the screen before diving into the depths or RW code. Also I didn't want to have a lot of junk in there from when I didn't know very basic stuff, and I did dodge a few of those bullets - for example I wrote myVector[0] instead of myVector.x for a while, and similar stupid things. Not to say that I'm not still doing stupid things that I'll pull my hair over in a few months, but at least a few of them are out of the way.

I think I'm ready to start the porting, actually!  Hand Thumbs Up Left Epileptic Hand Thumbs Up Right

I still worry about a few things.



MonoDevelop is slow on my computer, and comes up with stupid autosuggestions once in a while. The Unity console is s**t - it's not in any way a stranger to just skip logging stuff whenever it feels like it. That could probably be circumvented by creating a custom logger that logs to a text file, maybe?

In director I could "watch" an instance and see all of its properties change in real time as the game played. Whenever the game froze because of an error, it would go to where the error occurred in the code, and show what every variable was at the time. If I had for example an array of object instances, I could expand each of them and see what its properties where at. I had a console in which I could write snippets of code and execute them, if the game was running or not. This new environment is clearly inferior when it comes to those debugging assets.

Vector graphics and bezier curves, I can do without them but it would be cool to have them. At least simple shapes like square/circle.

I haven't tried sound.

I haven't tried importing graphics (this might be a problem because Futile only takes its weird texture thingies)

I don't know if I can retrieve the color of a pixel into my code with perfect accuracy. (I save level data in the level image file encoded as colors)

Futile doesn't perfectly respect the pixels. An edge that is 2 pixels wide might end up 1 pixel wide in the game (look at the lives bar in the HUD of space worms). This isn't a super big problem for Rain World which isn't very pixel art-centric, you won't see if a perfectly white silhouette is one pixel off. But it's still very annoying, and might become a real problem with for example the level graphics.

If a graphic is shrunk substantially, it will invent edge smoothing colors despite the texture being set to "point". You can see this on the very small rocks in Space Worms. This can be avoided in all Rain World scenarios I can think of, but is still a very annoying flaw.

The game becomes HUUUGE! The code and the graphics of space worms are together less than 200 kb, still the published game occupies 147MB before compression and 15MB after compression. Whaaaat?



Maybe I should try to make Space Worms work in Monogame as well - just to see if some of the above problems are absent there? Maybe someone can cue me in on that right away?

Thanks again for helping me!





   JLJac on March 06, 2014, 01:00:21 PM:

Thank you Juan and Jonbro for sorting out some of my concerns. Perhaps I'm a little too harsh at this point considering that I've far from explored all the options.

did you, by any chance, have massive white, empty spaces in the tilesets/spritesheets/whatever?
This could very well be it. I've located the weight to a file called "resources.assets", which points towards this explanation. Why does it bake everything together in an "assets" file that's much bigger than the original image file when it could obviously load a normal png just fine before publishing? Also, there is a way to load image files on the fly right, that's going to be super crucial for Rain World level loading.

You can take a look at Hotline Miami to see how that looks, their sprites rotate and maintain the same "pixelishness" at any rotation.
Hahaha this is literally the worst in my opinion  Tongue

Vector graphics/Bezier curves is a tricky challenge, you might need to roll your own custom vector renderer thing with a limited vector graphics subset or something (I hope you don't need, like, full Illustrator graphics specs support?), but with dedication and time, programming can yield the most wondrous results. Sorry, all I have on offer here is a motivational speech, which might be somewhat demotivating Sad
This can be done? Maybe with a shader?

What is a shader, btw? Is it all in the GPU? Can I write one myself?





   JLJac on March 06, 2014, 01:35:42 PM:

Hehe I "can" also climb mount everest, but the question is, can I?





   JLJac on March 12, 2014, 01:26:50 PM:

Thanks so much again guys  Beer!

Update 218
Let's get back to some devlogging haha!

Made two maps for how Rain World c# is looking in my head at the moment. I made them both to clarify my own thoughts, and so that you guys could give me an opinion on it Smiley

First up are the classes:



Those are the most basic classes I know I'll need. Later a lot of new ones will definitely pop up, such as "level loader" etc etc, but this is just what's needed to run a basic game session.

What do you guys think? Am I using inheritance the right way?

Then, what I call the "instance tree" or "update tree":



This is the structure through which the "update" command is forwarded each frame. The general idea is this - objects own each other, and objects further down the hierarchy are dependent on their "masters". Masters are autonomous.

So for example, a lizard has four limbs. It creates them on startup and saves them in an array. The "Room" (which is the class that does most of the game engine stuff) is not aware of these limbs, it just has a reference to the lizard. Every frame, the Main Loop tells the Room to update, the Room tells the Lizard to update, and the Lizard tells each of its Limbs to update. The Room doesn't need to bother about the Limbs.

One thing that might need a special mention is the BodyChunk class. This is basically a physics object, the one that will do collision checking etc. Note that contrary to how many games would do it, the creatures are not physical objects, they have them. This is because of the exact thing that gives Rain World its animation style - that each creature has many segments which makes them soft and bendable.

This means that the creature classes (lizard, player, etc) are just coordinators of other instances, and "communication hubs" those instances can use to talk to each other. For example, a lizard will own an instance of LizardAI, and when LizardAI wants to know where the body of that lizard is, it'll go by the Lizard instance. From inside LizardAI I imagine it might look something like this:
Code:
Vector2 myPosition = parent.bodyChunks[2].pos;
where parent is a reference to the Lizard instance, bodyChunks is an array of the BodyChunk instances that Lizard has, and pos is the position of a specific BodyChunk.

Similarly I imagine the Room will be a communication hub where difference creatures and objects can find each other. Say that a LizardAI wants to loop through all the items in a room to see if one of them is a spear. Then it could look something like this:
Code:
Spear spear = null;
for (i=0; i < parent.currentRoom.objects.Count; i++)
{
   if (parent.currentRoom.objects[i] is Spear){
      spear = (parent.currentRoom.objects[i] as Spear);
      break;
   }
}
Where parent is the Lizard that owns the LizardAI we're currently in, currentRoom is a reference to the Room that Lizard is currently in, and object is an array in the Room used to keep track of all the objects.

The idea here is that when two things some way out in the branches (LizardAI and Spear) want to communicate, they have to trace their way back to the last common branch (LizardAi -> Lizard -> Room). This is my interpretation of an un-messy way to do things without using globals, and I just wanted to check if you think it looks OK.

It just struck me that in the Classes map, creatures, items and effect sprites should probably all inherit from an "updateable object" class that the rooms could hold in arrays and dish out update commands to. Please consider that changed Wink

So, what do you guys think? Does it look reasonable? Any critique super welcome  Grin





   JLJac on March 13, 2014, 06:57:45 AM:

@eigenboom: Yeah, that's a good point - object oriented programming is a tool, not an orthodox religion. For the items it might very well be better to use an in-class solution rather than messing around with a bazillion text files and classes. The limbs have very different behaviors though, the only thing they have in common is basically a "position" parameter and a "owner" parameter, so there the inheritance seems like a good fit. A quick question on that note: The limbs will all have Owners, but some of them will have Owners that are slugcats, some lizards, etc. This makes it difficult for me to decide what to declare the Owner parameter as - if I declare it as a Creature I'll have to go "(owner as Lizard)" for every single line in the lizard arm, for example, which seems unnecessary as I know that a lizard arm will only be owned by a Lizard. Any ideas for this? Should I declare the Owner variable in the child classes rather than in BodyPart? That seems weird as all of them will have an Owner.

For the items, maybe a clean solution would be state classes? Has anyone played with those in c#? I get the general idea, but I have a hard time translating the examples to c# syntax. How do you make this thing work? Do you create an instance of each state class at startup, and have a currentState variable that points to the one that's currently active? In that case, what would you declare currentState as, as all the states have different classes? If anyone has some more on this design pattern in c# I'd be happy, as I plan to use it for the different "animations" for the creatures as well Smiley

@Juan: Thanks! Looked up interfaces, and made a (somewhat messy, but working) implementation in Space Worms. It's very useful!

Other question: In the old code, the game held a lot of lists of objects by type in order to be able to easily access them. So for example, I'd have a CreaturesL, a LizardsL, a PlayersL, a SlugcatsL, a PupsL, etc. A player, for example, would appear both in PlayersL and in SlugcatsL, where the latter would also have references to all the pups. This was very useful (sometimes I wanted to check something against players only, and would then repeat through PlayersL, sometimes I wanted to check something against pups and players, and would then use SlugcatsL) but I have a hunch it might be considered impure programming-wise. Is that hunch correct, or can I go ahead with my many not-mutually-exclusive lists?

Other other question: For the Game, Hunt, ShortcutHandler instances, should I use singletons? Those seem to be very taboo?





   JLJac on March 15, 2014, 03:04:14 AM:

Thanks!

The reason I used those lists wasn't mainly optimization, but to make the code cleaner. Instead of looping through all the objects and clutter the loop with conditions, I could just ask for whatever category of object I wanted.

But maybe with inheritance I could make the same thing work with only one single if statement? Say that I have Player and Pup classes, and they both inherit from the Slugcat class. Players and Pups are in a huge ObjectL list with all object of all different classes, only sharing an interface. I want to get Players and Pups, but nothing else. Could I use the IS keyword and check for Slugcat?

Code:
for (int i = 0; i < ObjectsL.Count; i++){
  if (ObjectsL[i] is Slugcat){
    //do stuff
  }
}

If that would work it's a solution that's clean enough Smiley

Update 219

I've been researching the state pattern a bit, as I think I will use this a lot in rain world. In the old code I use switch cases on strings, and I use it for everything. AI states, animations, etc etc. This time around I want to do it properly, using the state pattern, which I feel I really like but haven't quite pinned down yet.

I've mocked up a little powerup system in Space Worms using the state pattern, and it seems to work well Smiley

There are a few things I feel weird about though. For example I've declared the state classes inside the Player class, as I think of it as a sub-system of the Player. Is this the way most people roll, or do they have an external text file for that stuff? The Player class is becoming rather big.

An other thing is that in an example I found, the guy created one instance of each state on start up, and had a currentState variable pointing to which one was active. I have chosen to instead create a new instance of the state when I change it, as it feels weird to have a couple of inactive states hanging around.

My idea is this, tell me if it's wrong: If I change state very often, like, every frame, it might be nice to have one instance of each state hanging around and just point to the active one. Because creating and deleting the state instances every frame would generate garbage. On the other hand, if you change state very seldom (say, once in 30 seconds for space worms powerups) you might as well kill and spawn the state instances, for cleanliness' sake.

For Rain World I don't quite know which approach I'll be going with yet. For AI I think it would be really cool to have an instance for each state hang around and be inactive, because then the creature could pick up its behavior where it left off once it goes back to it! Say that a Lizard is doing something, like searching through some tiles, and then it is interrupted by some other behavior, like snapping after annoying flies. With the state pattern and consistent instances, I could go back to the search behavior, and the list of tiles searched would be intact - the lizard could just pick up where it left off, like it had a memory! Totally cool!

Could maybe combine that with pushdown automata...





   JLJac on March 17, 2014, 09:57:48 AM:

I'll check out this LINQ thing :D

@eigenbom, that makes sense, I'll use static instances then!

Update 220
Copied the Space Worms unity project, re-named a few files, delete quite a few. Gave it a new name: RainWorld. Set up a game class and a main loop. Here we go Grin

Then I talked to my friend, who gave me a few general programming tips, and boy am I happy I made Space Worms to filter out the absolute worst of the worst. I'v been doing so many things wrong! Now I have quite a few things to study, and I will really try to keep calm and not get ahead of myself with RW development. Slow and steady takes the day. Most likely I'm still not through my beginner phase (this morning I thought I knew everything there was to know about C#, but then I had that talk with my friend...) so it's pretty likely that none of the lines I write will still be around in a month or two. But it's a start!

 Hand Shake Left Smiley





   JLJac on March 20, 2014, 08:13:54 AM:

Update 221

Hi there! I won't share all of my code hehe, but here's a sample I've written of my Room class so far. If any of you guys feel like looking at it and be my ground control so I'm not floating away into crazyness right from the start, it would be greatly appreciated. Anything I'm doing a weird or peculiar way, let me know! Smiley

I'm especially interested in if I got the overloading right (GetTile functions). The code executes, but I'd just want to know if I'm using it correctly and as intended.

Also, having Tile as a mini class inside Room, good or bad?

Code:
using UnityEngine;
using System.Collections;
using RWCustom;

public class Room
{
//Setting up properties for width and height of the room, and functions to get height and width as tiles or pixels
private int Width;
private int Height;

public int TileWidth{ get { return Width; } }

public int TileHeight{ get { return Height; } }

public float PixelWidth{ get { return (float)Width * 20f; } }

public float PixelHeight{ get { return (float)Height * 20f; } }

//2D array that holds the tiles
private Tile[,] Tiles;
//DefaultTile is the template tile that occupies any position outside of the room (used when indexes are outside the Tiles array)
private Tile DefaultTile;

public Room ()
{
Height = 40;
Width = 52;

//Creating Tiles array and filling it with Tile instances
Tiles = new Tile[Width, Height];
for (int x = 0; x < Width; x++) {
for (int y = 0; y < Height; y++) {
Tiles [x, y] = new Tile (x, y, Tile.TerrainType.Air);
}
}
//Defining DefaultTile
DefaultTile = new Tile (-1, -1, Tile.TerrainType.Air);
}

public void Update ()
{
}

// Returns the tile which is occupied by position given as a 2D vector
public Tile GetTile(Vector2 pos)
{
return GetTile ((int)(pos.x / 20f), (int)(pos.y / 20f));
}

//Returns a tile from Tiles
public Tile GetTile (int x, int y)
{
if (x > -1 && y > -1 && x < Tiles.GetLength (0) && y < Tiles.GetLength (1)) {
return Tiles [x, y];
} else {
return DefaultTile;
}
}

public class Tile
{
//Defining enum for terrain types and creating property to hold it
public enum TerrainType
{
Air,
Solid
}
public TerrainType Terrain{ get; private set; }

//The location of this current tile in in Tiles array
public int X{ get; private set; }

public int Y{ get; private set; }

public Tile (int x, int y, TerrainType tType)
{
X = x;
Y = y;
Terrain = tType;
}
}



}


//Example command: Debug.Log (Rooms [0].GetTile (new Vector2 (234f, 101.6f)).Terrain);
//Output: Air
//It seems to work!


So much fun to have gotten started!





   JLJac on March 20, 2014, 09:06:51 AM:

Cool! So, what's the deal with properties? I've been told to use them, but I'm still not 100% on why they're so useful - I can use them to make the get public but the set private, which is cool I guess, but I never really had any problems with accidentally changing numbers from outside, so I don't think it's that crucial. And then I can also, in the future, add weird little behaviors whenever a certain property is accessed, (playing a sound when score is increased or something I guess) but I'm not entirely sure I see the usefulness in that either... Like, I don't want to play the pling EVERY time I change the score, for example it should be quiet if I just restart a game session. So then I might as well play the sound manually when I also add the score, right? 

Oh, and when I have you here, what's the deal with naming conventions? The c# documentation seems to be saying different things. At one point they say "no underscores, Pascal capitalization" another time they write in one of their examples something like

Code:
private int _score;
public Score{get{return _score;} set{_score = value;}}

And leave me super confused. They say that I should name properties with Capital Letters, but then I can't use the same name for a class and an instance, right
Code:
Public Room Room = new Room();
that doesn't work, does it? Then I should call it MyRoom or something, and that seems strange. Can I rely on the case sensitivity and do things like
Quote
Room room = new Room();
or is that considered unsafe?

Tell me how you name stuff Smiley





   JLJac on March 20, 2014, 10:50:58 AM:

Thanks guys! Ok, so I think I'm most comfortable with PascalCase for classes and methods, and camelCase for variables. That way an object can have a method Stun() and a variable int stun, for example.

If the only downside to Properties is performance, and they're preferred over fields for everything else, I'll go by the "No premature optimization" commandment and use properties until something starts to annoy me by being too slow. It's not like the game is going to be slower than the lingo version either way haha!





   jamesprimate on March 20, 2014, 08:23:32 PM:

you guys are so rad   Hand Thumbs Up Left Hand Thumbs Up Left Hand Thumbs Up Left





   JLJac on March 22, 2014, 01:38:16 AM:

The real reason I don't like to use getters/setters is code bloat and the fact those are one easy step into overengineering of classes/engine architecture.

I never seriously coded anything in C#, but the performance-impact should be similar to what it is in most OO languages. I.e. barely noticeable at all (again, unless in performance critical code, where squeezing out every additional millisecond could actually matter).

So don't overthink these sort of things too much, just roll with whatever you feel most comfortable with and get a feel for whatever you're using while you've your hands right into it  Hand Thumbs Up Left

Thanks! I will Smiley
Actually I have found something that seems pretty annoying with getters/setters, almost to the point where I'm considering not using them. It seems that for a compound variable or whatever you want to call it, such as a vector, you can't set the sub-varaibles individually. For example I can't do this:
Code:
bodyChunk.position.x = 5.5f;
because it will give me an error message. Instead I have to do this:
Code:
bodyChunk.position = new Vector2(5.5f, bodyChunk.position.y);
which is longer, harder to read, generally clunkier and totally rubs me the wrong way with my "it feels like I'm declaring new Vector2's everywhere, that can't be good"-complex.

One great real world use for properties, is to use them to (for instance) only up a speed variable if it is less than a maximum, otherwise set it to the maximum
This seems totally valid though! In theory I could use a Mathf.Clamp every time I set the value to achieve the same result, but if I want to change the max or min of that clamp, I'll be happy if I used a property :S

Update 222
Quite a lot has happened! A basic "creature" (two dots) is in the game. I have the very basics of how a rain world creature works up and running, and this time around I have a much more general and slick framework for it. Basically a creature (or physical object, at the very top of the inheritance tree) consists of a number of BodyChunks, and a number of BodyChunkConnections. The former is the standard unit that builds bodies and moves about with classic newtonian physics, colliding with walls and each other. The latter is the internal bonds that hold the BodyChunks of a specific creature together, so they don't drift apart.

Basic terrain collision is in, but I'm not sure how well it works at this point because I haven't yet set up tools to test it properly. It's able to keep an object that moves around with random forces applied within the level boundries, so that's something. At this point it's a straight port from the old rain world code, but I think I'll go over it an re-think parts of it that are a bit whacky. It's certainly a huge help to have a template to look at when coding though. I don't have to invent the wheel, merely make it roll.

What I'm most proud of though, is my camera system. In previous games, I've always had a fairly standard approach to how I do rendering. When an object is created, it asks some kind of sprite engine for a couple of sprites. Then it stores them in a list, and each frame move them around. When deleted, it returns them to the sprite engine or deletes them.

Not this time around! My starting point was this - objects shouldn't be responsible for being visible, they should just exist, and instead there should be a camera viewing them. Instead of having objects take care of their individual sprites, they should just take care of their behaviours, and the sprites should be handled by a self contained camera object. They shouldn't even know they're being watched.

Why do I want this? Because in the old game, the level you were viewing was the only one that existed. I tried to fake a bit of off-screen movement, but it wasn't the real deal. This time I want to make everything completely independent on whether it's being watched. The world should just exist, and the camera should be a ghost moving around watching it. The other big thing is that if I get Futile to work with unity's split screen, I could have two cameras viewing the same game world.

So this is the way I do this: Objects sign up to an IDrawable interface which contains an initiate method and a draw method. The Room has a DrawableObjects list, which contains all objects signed up to that interface. The Camera is assigned to watching a specific Room.

Inside the Camera, there's a sub-class (is that the term? A class defined within another class) called SpriteLeaser. My english wasn't really sufficient to come up with a good name for this thing, but basically it lends sprites to an object. It consists of only an array of sprites, a reference to an object and a "remove me" flag.

Say that the Camera changes rooms. Now it goes through all the drawables of the new room, and for each of them it creates a SpriteLeaser. The SpriteLeaser calls the object's initiate method, passes itself as a parameter, and says "Hi, I'm a SpriteLeaser at your service!" The object is like "Cool, I'm a Slugcat so I'm gonna need 12 sprites, this sprite should have this graphic, this sprite should have that graphic..." etc.

The next frame, the Camera will get its Update method called. Then it will go through all of its SpriteLeasers, and tell each of them to contact their respective objects through the Draw method, once again with themselves passed as a parameter. The object will rearrange the sprites according to its new position, and if it's slated for removal or in another room than the camera, it will also tell the SpriteLeaser to slate itself for removal.

The thing here is that the objects are passive. They don't take care of sprites, the just passively respond to the initiate and draw commands. If the camera moves to another room, the object won't even notice. It doesn't have to do anything, it just stops recieving the Draw commands, which are completely separate from all other code.

This was the best solution I could come up with for a self-contained camera and a world that goes about its behaviours with or without being watched. I know I'm probably re-inveting the wheel, but it was really fun doing it! Smiley





   JLJac on March 23, 2014, 12:03:37 AM:

The finite state machine for player animation is becoming humongous... And the player should have two of these, one for "body modes" as well. They're going to be like, a thousand lines each o.0 Should I separate it into a PlayerAnimation class?

It feels weird to have a separate class that's 100% dependent on another class, and that only exists as one instance per owner. There is no motivation at all to have it as a separate class except from trying to make the text files a bit shorter.

What would you guys do?





   JLJac on March 23, 2014, 12:40:52 PM (Last Edit: March 23, 2014, 12:59:13 PM):

That's totally true! I've been contemplating quite a lot on this stuff, and I really would like to have some kind of general system, because as you say, players and pups share a lot of behaviours.

Update 223
But, hehe, listen to this... So I created this really cool (IMO) finite state machine. It consists of a base class for PlayerAnimations, which has an initiate and an update method, and a lot of derived classes such as PlayerAnimationStandUp etc. It also had an enum with all the animations.
And an array PlayerAnimation[] animations. The array holds an instance of each animation derived class (as eigenbom suggested, they're all alive simultaneously) and the enum is used to map to the array positions, so it's possible to change the state using a name rather than a weird number.

Code:

//Array which holds an instance of each state class
public PlayerAnimation[] animations;

//Enum for all the animation states
public enum AnimationIndex
{
None,
CrawlTurn,
StandUp,
DownOnFours,
LedgeCrawl,
HangFromBeam,
GetUpOnBeam,
StandOnBeam,
ClimbOnBeam,
BeamTip,
Dead
}
public AnimationIndex animation{ get; private set; }

        //Changes the Animation
public void ChangeAnimation (AnimationIndex anIndx)
{
animation = anIndx;
animations [(int)anIndx].Initiate ();
        }

public void Update ()
{
animations [(int)animation].Update ();
}
Like this, see? When setting the animations I could use the AnimationIndex enum, and get the names through auto complete, by just mapping the enum to an integer and making sure that a given enum leads to the right animation instance in the array.

Super cool!

But.

Thing #1. No inheritance. I did think long and hard about how I could create inheritance so I could have a general FSM class to inherit from everywhere I needed this behaviour, but what would that class contain? Not the enum, that has to be declared specifically for each implementation. Not the array of states, same goes for that. Basically the only thing I could inherit would be some sort of base class for the states. Almost everything in this solution has to be written again each time I applied this solution.

And Thing #2. This whole elaborate solution does nothing that a switch case doesn't do. Except occupy more memory, being clunkier, and involving more properties. And being unable to access the privates of the owner object because it's its own class. The only thing it has on the switch case would be being able to run initiate methods for each state, but I don't have any functionality like that, and if I needed to I could just run a generic init method with its own switch statement in it.

Conclusion: The coolest and most elaborate solution might not be the best. Here I really tried for an elegant solution, and ended up creating the opposite. Instead, I've found the partial keyword, which allows me to split a class over several text files. So I'm going to go ahead and scrap that fancy FSM, and just create a big, fat switch statement insrtead Smiley





   JLJac on March 24, 2014, 08:51:10 AM:

Haha! Ok, so FSM is mostly useful when you have exponential stuff like transition states between all the other states and the like?

Update 224
Converting code! Moved a fat chunk of the player behaviour from the old game to the new one today. Still not entirely there, but it's looking more like it. Tomorrow I'll be able to run around and jump on platforms, I think!

Some of this code is so horrible to look at you wouldn't even believe it. Almost all of it is old enough to have moss and fungi growing all over it, for most chunks I have to think long and hard about what they're actually supposed to do. All of it is just one giant, multi-headed beast of nested if statements. Some pieces sit around doing nothing at all, seemingly, I leave a note at those.

Some code looks weird and useless, and but when I run without it there is some bug, and if I introduce it, the bug goes away. In one spot I've even left a comment "I don't remember how this code works, but it prevents this and that problem. So let it be!" Thankfully that's an exception though, otherwise I've been able to figure out what the code is doing after a little bit of tinkering.

In either case, I'm always thankful when I stumble upon some strange looking solution and implement it, and it immediately works. It's so long ago I don't really remember it, but I can imagine I spent several days in frustration trying to find those solutions, and now I'm really happy to get them for free!





   JLJac on March 26, 2014, 11:09:26 PM:

Update 225
Trudging along... Don't get me wrong, I'm having a wonderful time, but my ambition to divide the work into manageable chunks is down the drain. My idea was to first convert the player - but in order to work on the player's movement behaviors I need to be able to save and load a level, and in order for that to happen I need to understand how to handle XML and text files, etc etc etc.



The biggest convertion push for the player is done though, ie basic terrain interaction. Still have all the behaviors involving poles, and a few other special cases left.


Throwing a few questions out there:

Currently I'm researching on saving and loading a level from a text file, any general tips on that?

Right now my tiles (all the little things that populate the 2d array of a room) are classes. Should I go with structs instead?

If I fetch one property of a struct, and it has other, big, properties, does it pass its heavy value-based self through all the methods used to fetch it?
Example:
Code:
public struct MyStruct()
{
public bool verySmallProp;
public int[,,,,,,] SUPERBIGPROP;
}

if (object.anotherObject.thirdObject.fetchMyStruct().verySmallProp){//...}
Is the data of SUPERBIGPROP unnecessarily passed as well, slowing everything down? In that case, would a class be quicker? (Which is, to my understanding, reference based and thus not passed at all)
I'm asking because every object is asking the surrounding tiles about their status many many times per frame, so I want that to run as smoothly as possible.

A tile can have several things on it, such as poles vertically and horizontally, fly hives, etc etc etc. How would you guys store that information? A lot of bools, or a list with tags?