Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411424 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 19, 2024, 08:09:22 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsProject Rain World
Pages: 1 ... 70 71 [72] 73 74 ... 367
Print
Author Topic: Project Rain World  (Read 1443758 times)
mason
Level 1
*



View Profile
« Reply #1420 on: March 15, 2014, 11:14:54 AM »

why use LINQ for searching collections anyway when you can just use predicate delegates?
Logged

eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #1421 on: March 15, 2014, 03:01:52 PM »

I think of states as persistent, like a network that the current state pointer travels around. Therefore there will be one instance of each for the lifetime of the thing using the state machine. I think combing the concepts of "inactive state" with "unallocated object" will lead to some confusion. Moreover when creating your states you'll need to define your transitions somehow, and a pointer to the next state object seems simple enough -- which you can't use if you're destroying inactive states.
Logged

TheIndieForge
Level 0
**



View Profile WWW
« Reply #1422 on: March 16, 2014, 06:04:05 PM »

I don't have anything to add to this discussion, but I'm just going to quietly post to follow, this project is great!  SmileyHand Thumbs Up Right
Logged

JLJac
Level 10
*****



View Profile
« Reply #1423 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
Logged
JLJac
Level 10
*****



View Profile
« Reply #1424 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!
Logged
dancing_dead
Level 2
**


View Profile
« Reply #1425 on: March 20, 2014, 08:48:42 AM »

yup, that's how overloading works.
rest looks good, too. a bit too many properties for my taste, but there's nothing objectively bad about them (they're a tiiiiny bit slower than straight up fields, but that is all).

I'm looking forward to seeing all that code actually draw something Rain World-ish someday! Well, hello there!
Logged
JLJac
Level 10
*****



View Profile
« Reply #1426 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
Logged
Bandreus
Level 3
***


View Profile WWW
« Reply #1427 on: March 20, 2014, 09:58:41 AM »

Basically properties are good for encapsulation, they abstract away the actual internal structure of your classes and make your objects more black-box-ish.

There are several advantages to using them, they are very convenient when you want to force strict validation checks, for instance, and much much more.

Obviously all of this comes at the expense of some performance, but it's not that huge of a deal unless those are involved in critical pieces of code and you need to optimize badly for whatever reason. They also make code maintenance and refactoring somewhat easier of a task.

When it comes to me, I usually don't bother with getters/setters, unless I have a very good reason to. Especially if the code I'm writing is not for other people to use.

TL;DR: go with getters/setters if you need to encapsulate, otherwise fields are usually okay.

About naming conventions, everyone has her own. Just pick the style which makes code more readable to you, and religiously stick with it.

I like to use upper case first letter for Classes and Interfaces only, while variableNames and functionCalls always start with a lower letter not using underscore but camlCapitalNameStyle

The exception being, I sometime start _private and _protected field names with an underscore, but I'm not incredibly consistent with that
Logged

dancing_dead
Level 2
**


View Profile
« Reply #1428 on: March 20, 2014, 10:29:32 AM »

what Bandreus said, consistency is king when formatting code. in C# people usually employ Capitals for class names and stuff and camelCase for variables.
Player player = new Player(); is perfectly fine, imo, at least that's exactly how it looks in my projects, there's nothing unsafe about it, since if you write something weird, compiler will tell you about it (and so will Visual Studio even before compiler, not sure about MonoDevelop).
Logged
JLJac
Level 10
*****



View Profile
« Reply #1429 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!
Logged
Nico May
Level 0
***



View Profile WWW
« Reply #1430 on: March 20, 2014, 11:47:52 AM »

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
« Last Edit: March 20, 2014, 03:26:03 PM by NicoM » Logged

Bandreus
Level 3
***


View Profile WWW
« Reply #1431 on: March 20, 2014, 11:52:52 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
Logged

jamesprimate
Level 10
*****


wave emoji


View Profile WWW
« Reply #1432 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
Logged

Sebioff
Level 1
*



View Profile
« Reply #1433 on: March 21, 2014, 02:26:23 AM »

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

That actually does work in C# (but not in some other languages). I personally think it's somewhat confusing though and use lowercase names for my instances.

Code looks fine. I'm super excited for seeing some early screenshots Smiley
Logged

Current devlog: Parkitect, a theme park simulation, currently on Kickstarter | Twitter
JLJac
Level 10
*****



View Profile
« Reply #1434 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
Logged
JLJac
Level 10
*****



View Profile
« Reply #1435 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?
Logged
dancing_dead
Level 2
**


View Profile
« Reply #1436 on: March 23, 2014, 01:19:20 AM »

well, if you're going the FSM way for animation, certainly at least some of the more generic parts of it should be usable in contexts, other than the player itself? meaning, cubs, other lizards etc. could use a similar animation control mechanism.

and I don't feel weird about that at all. I mean, isn't AI, likewise, a separate part of each NPC that is always 100% dependent on it?

but if you do mean that this particular FSM is completely only for player's character, well, it can still be a separate class, if that helps you organize the code better, but it might as well be just a bunch of methods in the player class itself, but, like you said, it will make the player class super-lengthy.
Logged
JLJac
Level 10
*****



View Profile
« Reply #1437 on: March 23, 2014, 12:40:52 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
« Last Edit: March 23, 2014, 12:59:13 PM by JLJac » Logged
dancing_dead
Level 2
**


View Profile
« Reply #1438 on: March 23, 2014, 03:04:48 PM »

#1: you can replace the enum by a string property, store animations in a dictionary. while not as fast as an array, it'll be plenty fast, and it'll allow you to load that dictionary with specific stuff for each unit, so the code becomes re-usable.

#2: that thing is so simple, like you yourself remark, that I wouldn't venture to call it a proper FSM.
it only makes sense to make a more elaborate FSM, if you also handle, say, physics, input and animation all together in these states, then you can get cool stuff like specific movement input handling by just delegating the inputs to the currently active state in the FSM, where the state then goes on to handle the rest, including the transitions from one state to the next, i.e., character is in walking state, and you press jumping button, and walking state  on receiving jumping input transitions the whole machine to the jumping state, which then in turn draws the correct animation, handles all future inputs, performs jumping physics calculations, stuff like that. that would be more of an FSM than the simple animation switcher you got going on there.

but, haha, I have tried handling input via FSM like that, but I found that my previous approach of what I like to call "organized spaghetti" has so far been superior to both create and maintain for animations and movement.

but I can see the benefits of the FSM way, it's just that the in-game states and moves don't always map to neat states, and transitions can become very artificial feeling, depending on how granular the state is (you can get "fun" transitions like jumping standing -> jumping gliding -> jumping descent -> pls, stop -> norlySTAHP -> etc), but I bet it's possible to do it in a correct feeling way, too.
Logged
JLJac
Level 10
*****



View Profile
« Reply #1439 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!
Logged
Pages: 1 ... 70 71 [72] 73 74 ... 367
Print
Jump to:  

Theme orange-lt created by panic