Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

slayemin

Member Since 23 Feb 2001
Offline Last Active Mar 06 2013 01:50 AM
-----

#4918667 Game Save Data

Posted by slayemin on 02 March 2012 - 12:51 PM

I like the idea of encryption :)

You could use the Ceasar Cypher: When you're encrypting a bit, add a fixed value to it before writing it to file. If your addition value is +2, then A => C. It's super simple to implement and its also pretty simple to thwart. You could make it slightly more complicated by using a pseudo random number generator to generate your fixed values. The key is that the sequence of random numbers needs to be the same every time. So, if you generate a random value between 1->26, and then add that value to your byte, you'd get something like:
Unencrpted string: {AAAA}
Random Numbers: {13, 21, 4, 16}
Encrypted String: {A+13 => N, A+21 => U, A+4=>D, A+16=>Q}

So, if someone knows that their health is 16 and they open up your file to look for that value, they won't find it :) But, if they are really determined and reverse engineer your code to figure out what encryption algorithm you're using and the random number seed you're using as a key, then they can easily decrypt and encrypt your saved data file. I'd probably not concern myself with the 0.01% of the population who might do that.
If you want to use a nuke to hammer a fly, you could look into using AES 256 bit encryption. Nobody will crack that without extreme effort and hardware. It's military grade :)


#4918378 How would a filling clock drawing algorythm work?

Posted by slayemin on 01 March 2012 - 04:03 PM

You can do this pretty easily with primitives. If you're still using .NET 3.5, you can use a Triangle Fan. If you're using .NET 4.0, the triangle fan is gone so you can only use triangle lists or triangle strips (more verts, yuck!). The coloring can be accomplished by using vertext colors. I created a very similar project to show days, hours, minutes, and seconds with four pies. If you include enough triangles, you can create a circle ;)

The basic idea is to find a center position for your pie fan. Every triangle will have one of its verticies at this center position. Then, you want to be able to create a function which accepts a percentage value (0->100%) and figures out from there how many triangles to draw and where they should be placed. You may want to use an angle or radian value as an alternative (or overloaded member function). You'll also want to feed in the radius to indicate how large your pie should be. After you have all of this information, it's just a matter of using simple trigonometery to figure out where to place the other two verticies for your triangles.
It should look something like this:

Vert0 = new Vector2(center);

Vert1.x = center.x + Math.Cos(theta) * Radius;
Vert1.y = center.y + Math.Sin(theta) * Radius;

Vert2.x = center.x + Math.Cos(theta + stepsize) * Radius;
Vert2.y = center.y + Math.Sin(theta + stepsize) * Radius;



#4918372 [C#] Is my game structure any good?

Posted by slayemin on 01 March 2012 - 03:39 PM

The only reason a customized serializer would be better is because you know the details of the object your serializing and you can control the order of how you serialize the object. This allows you to serialize the object into a very small byte array. Example:

class Knight
{
	static uint NextID;
	uint UniqueID;

	int Health;
	int Attack;
	int Speed;
	Vector2 Position;

	public Knight()
	{
		  UniqueID = ++NextID;
		  Health = 10;
		  Attack = 5;
		  Speed = 4;
		  Position = new Vector2(5,5);
	}

	 public byte[] Serialize()
	 {
		  byte[] ret = new byte[24];			   //you know this size because you know the number of variables and their byte sizes
		  ret += UniqueID.ToByteArray();	 //not syntactically correct, just for illustration purposes
		  ret += Health.ToByteArray();
		  ret += Attack.ToByteArray();
		  ret += Speed.ToByteArray();
		  ret += Position.X.ToByteArray();
		  ret += Position.Y.ToByteArray();
		  return ret;
	 }

	 public Knight Deserialize(byte[] data)
	 {
		  Knight k = new Knight();						 //probably should have made an empty constructor now that I think about it...

		  k.UniqueID = uint.parse(data[0], 4);		  //not syntactically correct, but reads the first four bytes as an unsigned int
		  k.Health = int.parse(data[4],4);					//next 4 bytes are the health
		  k.Attack = int.parse(data[8],4);
		  k.Speed = int.parse(data[12],4);
		  k.Position = new Vector2(int.parse(data[16],4), int.parse(data[20],4));

		  return k;
	 }
}

The size of my example Knight class is 24 bytes. If I use the [Serializeable] attribute for the class and use the built in method, the serialized data size is ~150bytes.

[Serializable()]
class Knight
{
	static uint NextID;
	uint UniqueID;

	int Health;
	int Attack;
	int Speed;
	Vector2 Position;

}

void main void()
{
	 Knight k = new Knight();		  //just use the default values assigned by constructor

	 BinaryFormatter serializer = new BinaryFormatter();
	 FileStream fs = File.Create("test.txt");
	 serializer.Serialize(fs, k);		  //writes the serialized data of the knight to the file stream
	 fs.Close();

	 //now, the knight is stored as binary data in a file, ready to be deserialized...
	 fs = File.Open("text.txt", FileMode.Open);
	 while(fs.Position < fs.Length)
	 {
		  object o = serializer.Deserialize(fs);
		  Type t = o.GetType();
		  switch(t.Name)
		  {
			   case "Knight":
			   {
					Knight asdf = (Knight)o;		  //just casting the object into a knight object
					break;
			   }
			   //add more case statements for each object you've got serialized
		  }
	 }
	 fs.close();
}

Now, the built in serializer works pretty damn well. If you have object inheritance, it will serialize the inherited data automagically. If you decide to add more member variables to your class, it will automatically include that in the new serial stream (but, watch out for attempting to deserialize an outdated binary). At the cost of a few extra bytes, you as a programmer don't have to worry about maintaining the serialization and deserialization of your objects.

However, if you do want that extra amount of granular control over your serialized data size, you can do the serialization/deserialization manually. 24 bytes vs 150 bytes can make a big difference when you're sending 1000 objects through a network, sixty times a second. If your object gets more member variables, you need to update your serialization and deserialization methods and then test it to make sure it works as planned. The first few times, it may not annoy you but after doing it a lot, it'll annoy and wear you down.

I won't say which method is better because each has their pros and cons. I leave it up to you to decide which method you'd like to use based on the situation your in Posted Image

Edit: The reason the built in serializer creates bigger binary data is because it has to include meta-data about your class. It uses this meta data to deserialize your class. When you manually serialize/deserialize your classes, the meta data is already baked into your deserializer so you can get away with smaller binary data sizes.


#4918076 [C#] Is my game structure any good?

Posted by slayemin on 29 February 2012 - 09:46 PM

...so, if you can't take the project from work due to the nature of security, are you ever planning on deploying your game or is it just a learning exercise? What's the point of building a reusable code library if you can't really reuse it on other non-work related projects?

As far as code structure for your project goes, its similar to what I'm doing in my projects so it sounds like you're on the right track.

Static keywords are important for classes which are accessed by multiple threads (ie, your network connection threads). Just be careful about how crazy you get with them. Treat them like global variables. Also, if multiple threads are accessing the same shared object at the same time, you'll have to worry about serializing their access via "locks" (lock keyword, spin locks, mutexes, semaphores, etc).

You can manually serialize your game objects into string and byte arrays, as you're currently doing. It works and its light weight, but it also puts a significant amount of overhead in your development time and effort for every object you want to send over the network. Since you're using .NET, you should look into the [Serializable] parameter. You can use a built-in serializer to convert your object into a serial stream and then either write it to disk or a network stream. Then, when you read in the serialized data, you deserialize it into an object, get its type, and then cast that object into your game object and everything is done for you. This helps you avoid having to write customized parser code. However, this comes at a bit of cost: The serialized data is often quite bloated compared to what you could get with customized data serialization. If you aren't too concerned with bandwidth/diskspace, this isn't an issue.


#4915953 Organizing and managing code?

Posted by slayemin on 23 February 2012 - 01:17 PM

:((( I write some code and then immediately step through it line by line with the debugger to make sure that it's working as I expected. Occasionally, I find errors or mistakes I wasn't expecting.

I'm pretty good with the debugger, but not good enough to read x86 assembly. Here are some tips for you:
-Keep your code clean, simple and readable. Whitespace is good for preventing eye strain and information overload.

-Every time you use a 'new' keyword to allocate memory, automatically create a 'delete' keyword to deallocate it and make sure that the delete is reached.

-Be consistent with your naming conventions.

-Comment your code. It's for you. When your eyes are bleary, your brain is mush, or six months from now when you have to relearn your code, you'll be happier to read comments than code to figure out what you were thinking.

-floating point precision errors are a bitch to find and debug. If you're comparing floats for equivalence without a tolerance threshold, you're doing it wrong.

-If you're creating a mathematically oriented function and you know the range of valid inputs, throw it into a for loop and iterate through each valid value. Did you get divide by zero errors? did you handle negative values properly? if you're using floats, was your step size small enough to test for floating point precision errors?

-Sometimes it helps to create classes in a seperate project so that you can test and develop them in isolation. Once you know that your class and its member functions are rock solid, you can copy them into your main project and have a higher degree of confidence that they'll work without problems. This also helps to keep your classes loosely coupled.

-Aside from the debugger, my second most useful tool for debugging is pen and paper. Draw out the conceptual idea you're trying to implement and then synchronize the steps with the debugger (example: inserting nodes into a linked list at the front, tail and middle).

-The best bugs are the ones you don't have. A little bit of planning before code writing will go a LONG ways. There are three types of errors: Syntax errors, program errors, and design errors. Syntax errors prevent you from compiling. Program errors are stuff like referencing a null pointer or dividing by zero. Design errors are when you code a program with a broken design and you don't realize it until hours/days/weeks/months later. Planning and diagraming helps avoid them and  helps keep your code organized.

-Lastly, stay disciplined. It's easy to get lazy and code something up really quick, but I've found that taking a little bit of extra effort to do things right the first time saves more time and effort since I don't have to refactor what I did out of laziness.

Good luck!


#4915938 Making Game Development team

Posted by slayemin on 23 February 2012 - 12:38 PM

You should probably post this in the Help Wanted section.


#4913706 Basic Game Development

Posted by slayemin on 16 February 2012 - 11:21 AM

After failing many projects, I can tell you what works and what doesn't work. (btw, I think this is more of a project management problem)
Here's how the typical project starts:

1. Someone has an idea. They start thinking about it and it generates a bunch of new ideas. They get super excited about it along the way. Then, they want to make the idea come to life. Either they can bring the idea to life by themselves or they have to find other people who can do it for them. The initial enthusiasm is the jolt of energy required to get people to start investing their time and money into the idea. A lot of game ideas fail to launch because they never get past this phase.

2. Either the idea dies on the vine or a more formalized process of development begins to take place. The idea is still nebulous, so lots of thought needs to be invested on nailing down the specifics for how the idea works. In terms of a game, this means defining the game mechanics, the units, the story, the player experience, interfaces, etc. This is typically done with a game design document or rapid prototyping.

3. The project eventually moves into the construction phase (if it's gotten this far). This is where the going gets tough and the initial spark of enthusiasm fades. Once the enthusiasm fades, people who aren't getting something from the project will quit (be it money, experience, satisfaction, promises, etc). If your project loses key people, it will most likely fail and/or the remaining team will suffer from lower morale. When the going gets tough, morale is everything because it alone is what keeps the team going forward with the project. The construction phase of the project is also where new ideas for features come up. Some of those features may really enhance the game. Other features may be cool "glitter" but will only waste time (but, consider the morale cost and chilling effect on creativity of excluding it). The most common case is the notorious 'feature creep' which is a feature which changes the size and scope of your project, which then translates into requiring more work and time, eventually leading to a project which grows beyond the capabilities of the existing team. If it seems that a project grows too big, it may never be completed and this leads to a sense of futility and despair with the team members, which also has a negative consequence to team morale and leads to project failure. You as a designer, are the gatekeeper for deciding which features get added and excluded. You must hold the reigns tight because the project success depends on it. Having a clearly written and well defined game design document will be like the light house of clarity in a sea of ideas.

4. If you've miraculously gotten past the construction phase, you'll move on into the testing phase of development. Here, you hunt for bugs, design flaws, and balance issues. Most likely, you'll have been doing lots of iterative game play testing during your construction phase, so the testing phase is a quality assurance and wrap up phase. I may only write a few sentences on it, but this phase may be one of the most important phases for guaranteeing project success. If you ship a non-working or buggy product, it will sell poorly and damage the reputation of your game and your company/team/organization and anyone affiliated with you. Lots of incomplete or buggy games have been shipped prematurely with the "oh, we'll just submit a patch a few weeks after release" mentality. Don't do this or overlook the importance of testing.

5. The next phase is deployment/release. This is where you get your game out in front of your users, turn on the registration servers, the login servers, the game servers, etc. and get ready for business. This phase of the project is a responsibility jointly shared by the business side and the technical side of the house. You can flub this up and all the hard work you and your team have put into the project leading up to this moment may have been for nothing, regardless of how great your product may be. Did you do marketing for the game prior to release? How are you distributing the game? (digital? retail? free download?) What technical work needs to be done? Can your hardware infrastructure handle the network load? etc etc. Doing well in this phase is an exponential multiplier. Based on some of the games I've seen, you could make wheelbarrows of money by selling polished turds if you execute this well (*cough* farmville *cough*).

6. The last phase is the training and maintenance phase of the project. It's often overlooked but also quite important because it extends the lifetime of your product (notice how the verbage has changed from 'project' to 'product'.) I've had the experience of developing a software tool and executed all the previous phases perfectly but seen the project fail because I couldn't maintain it or train end users on how to use the software. A lot of my life energy was wasted because the product couldn't be maintained (I wrote some software while I was in Iraq and I left the country). Your team may lose some members. With those members goes their technical expertise in your product. They may be fired or laid off by the company, may have some family emergency, get hit by a bus (or randomly blown up by a mortar/rocket), get hired by someone else, get bored and move on to bigger and better things, etc. How do you fill in the vacuume of knowledge left in their wake? Documentation. Cross training. Commented code. If your game has a critical bug fix that needs to be applied, who will do it and how will you get it out to your users? Take a lesson on the importance of this step in the project lifecycle from a company who did this well: Valve. Half-life came out in the late 1990's and had a good lifespan. Valve also encouraged and supported the modding community which extended the lifespan even further (via Counter-strike and other HL mods). The popularity of CS entrenched Valve in the minds of the customers. When HL2 came out, it was a sure bet that it would sell well. It then became the launching platform for Valves digital distribution hub "Steam", which was able to gain a majority of the market share for DD, further cementing their position as a major player in the game industry (and actually revolutionizing the distribution model).

All in all, when you're designing your game, take stock of your resources before deciding how complex it's going to be. It's better to create an overly simple game which gets finished and polished than to create an overly complicated game which may or may not get completed to a high standard of quality (hardest lesson to learn and remember). For a lesson on the bounties of simplicity, just look at the front page of Google. As one of my Operating Systems professors once said, "Make it simple for now, we can always add complexity later" (he's the windows kernel architect at Microsoft).


#4911919 Immutable World State for Parallelization

Posted by slayemin on 11 February 2012 - 03:38 AM

I recently did a small project with multithreading. I had a problem with race conditions, so I implemented a binary semaphoreto indicate if a shared resource was being used by another thread. It might be something you could find useful. Here is the general idea followed by pseudocode:

I have a static list of objects which need to be accessed by multiple threads. I also need to maintain the list of objects. Part of the list maintenance means that a thread may add or remove objects from the list. If two threads are modifying the size of the list, then a runtime error occurs. So, if a thread needs to access the list, I need to guarantee that the size of the list won't be changed by another thread. I create a static boolean variable to indicate whether or not the list is in use by another thread. When a thread wants to access the list, it checks to see if the list is unlocked before going forward.

static List<gameobject> m_objects = new list<gameobject>();
static bool m_listLocked = false;

Thread 1:
while(m_listLocked);
m_listLocked = true;
foreach(item in the list)
  do stuff;
m_listLocked = false;

Thread 2:
while(m_listLocked);
m_listLocked = true;
foreach(item in the list)
  do stuff;
m_listLocked = false;

I use an empty spin lock, but I could add a short sleep cycle inside of the while loop to save the CPU a bit.

Note that I don't do any thread synchronization with game frames.


#4911912 what is capable to do a compter scientist?

Posted by slayemin on 11 February 2012 - 03:17 AM

Yes, "Computer Science" means that you're doing science with computers (or, put another way, using computers to do science). Programming languages are just a useful tool to getting computers to do what you need them to do. With that in mind, a good computer scientist has a background in science and mathematics.

...but, since this is a game programming site, I imagine that you're trying to pick up the necessary skills to make games. If you're going to be a game programmer, programming is absolutely necessary. A solid understanding of datastructures and algorithms will be your bread and butter. My personal recommendation is to just start teaching yourself by using online tutorials and references to make simple games and use the university education to supplement your existing knowledge and experience. The classes you'll take will have much more meaning for you when you have something to put it into context with.


#4814062 How Gamestop Reduces Developers' Sales

Posted by slayemin on 21 May 2011 - 07:44 PM

I think if you're going to protest against gamestop for reselling games because it decreases the number of new purchasing customers, then in principle, you should also be completely opposed to public libraries, movie rental businesses, and swap meets.

Public libraries purchase only a few copies of a book and then let users borrow the book for a period of time so that they can consume the content. The author of the book only makes money at the time when the library purchases the book. The number of people who read the book is somewhat irrelevant. Should public libraries be banned?

A similar situation applies to movie rentals. Should Netflix be shutdown because they purchase a movie once and then ship it out to be consumed by multiple individuals? Is that cheating the movie industry from lost revenue?

To get slightly more abstract, consider a swap meet. Suppose I bought an expensive name brand purse which I no longer need because I bought a version which was more in style. I go to a swap meet and trade in my designer purse for some other property. Is the purse designer being cheated out of a lost sale? Should swap meets, pawn shops, and second hand stores be illegal?

Personally, I don't think this is a very big issue (At least for PC games industry). Most PC games are turning towards digital distribution so the seller/reseller business model of game stop is endangered -- You don't need physical media to play new PC games. As a result, you see primarily console games at Gamestop. If/when console developers get digital distribution going, gamestop is probably going to go bankrupt. I'd be selling my stocks if I currently owned any in gamestop.


#4810034 what kinds of control would you want in a particle system

Posted by slayemin on 12 May 2011 - 07:25 PM

Interesting I'm surprised I never thought of having emitters emit emitters. Do you consider all your particles as emitters, and emitters as particles... ie are they derived from the same object?

Alpha transparency is controlled through the color values. These can be anything and can shuffle through any amount of colors as long as there is enough memory to store all the values... which is pretty much infinite. The way my framework works, being able to emit primitives instead of sprites (quads), work mean a refactoring of the base framework, but does sound tempting.


Here is a rough sketch of my class inheritance hierarchy. The names are probably not the best, but it's good enough for me.

Posted Image

I use a lot bit of polymorphism and the classes I left out are just manager classes which maintain memory pools for particles and emitters.

The "Emitter Object" has a ParticleBase object which can be cast into either a particle or an emitter. Emitters are just manager classes which create "Emitter Objects"

class EmitterObject
	{
    	Vector2 m_emissionVelocity; 	//this is the velocity applied to all emitted objects
    	Range m_emissionSpeed;
    	Range m_emissionDirection;  	//the direction objects are being emitted     		(Radians)
    	Range m_emissionSpread; 		//how much variance you have in the emission direction  (Radians)
    	
    	int m_emissionCount;        	//how many objects will be emitted during the emission cycle
    	ParticleBase m_emissionObject;  //this is the generic object our emitter will emit

    	int m_emissionDelay;        	//how long to wait before emitting objects
    	int m_emissionPeriod;   		//how much time must elapse before next particle is sent out
    	int m_nextEmissionTime; 		//the next point in time in which we emit our objects
    	Color m_color;              	//the color applied to the objects being emitted
   ....
  }

My base particle class also has a function pointer which lets the user specify the mathematical function to use for alpha transparency (constant, linear decay, exponential decay, gaussian, etc).

My reasoning for including primitive particles with sprite particles is because I've seen some interesting effects being done with primitives as particles... Pixels are very versatile and very fast to draw. Lots of small triangles can make some convincing fire effects. Connected line segments can be used for simulating streaks of shrapnel in an explosion (and the alpha decay ties in nicely here).


#4774070 Reluctancy to continue on a project

Posted by slayemin on 14 February 2011 - 07:33 AM

I'm in the same boat. I've found INCREDIBLE solution(s) to this problem.

1. Do NOT end work on something that is halfway finished. When you're figuring out how to implement a system, the code and systems architecture is fresh in your mind. If you stop halfway, it's harder to dive back in and begin where you left off. This becomes a source of procrastination and can lead to project failure.

2. With #1 in mind, this means you NEED to take your project on in bite sized chunks! How long can you work for this day? Only take on what you can complete today!

3. Don't develop the next chunk in your main game project. Create a NEW project and develop the chunk in there. This does a few awesome things for you:
  • Your modules are very loosely coupled
  • Loosely coupled modules can easily be reused in any project
  • Coding and testing a module is fast and simple because there isn't irrelevant junk to interfere or distract you
  • You begin to see your architectural dependencies
  • Allows for rapid prototyping
  • Progress is fast and tangible which is more motivating.
4. If you absolutely have to break rule #2, then create a good stopping point and an easy entry point for yourself. Also, write yourself a note! Explain what you were trying to do, how you are thinking of solving the problem, and where you are at. If you comment your code well, it is much faster to begin where you left off.

5. Have long term plans. Why are you working on project XYZ? Are you trying to learn something new? Trying an experiment? Selling it to an audience? What are the criteria for project success? Reflect on how your day to day work brings you closer to accomplishing your long term goal. What progress have you made towards project success? If you have the perception of no progress, it's demotivating even if you actually made progress.
Example: I wrote an application to simulate gravitational effects in our solar system using newtonian physics. Everything was to scale and used real data. I abandoned the project after realizing just how freaking HUGE the universe really is. Even though I abandoned the project, it was a success because I learned a bit more about gravity and became completely puzzled as to how accretion disks actually form out of a particle cloud.

6. Sometimes when I'm coding up a solution, I realize that I need to solve something else first. (ie, a particle engine can't be implemented before you can render primitives or textures to the screen). Sometimes these tangential rabbit holes can go many layers down and you'll forget what you're trying to do and/or why you're trying to do it. Sometimes the problem you're trying to solve won't help you solve the bigger problem. Sometimes it doesn't even need to be solved. I like to keep Notepad++ open and write down a quick note on what I'm currently working on and why. When its done, I throw away my note. Anyways, the point is that its easy to get lost and the fastest problems to solve are the problems you don't have to solve.

7. Feature Creep can be a project killer. So can over-engineering a simple solution. Learn to recognize when you're doing this. Then stop it. Code for your current requirements, not possible future requirements (note that there's a fine line between rigidity and robustness here).

8. Pace yourself. Take breaks. Projects are a marathon, not a sprint. You don't want to burn yourself out by doing 16+ hours/day, 7 days/week and lasting for 2 weeks. It's a painfully excruciating pace. When you burn out, the marathon runner will pass you by because he's plodding along at a comfortably maintainable pace. He'll finish his project and yours will remain unfinished and useless. The initial passion you have for a project can be lengthened if you take it slower from the beginning instead of churning ahead at full steam, yielding longer levels of motivation and higher productivity.

9. Have fun. That's why we do this, right? Game development is the marriage of the right side of the brain with the left side. If the developer isn't having fun anymore, chances are that the game won't end up being much fun either (emotions are contagious & emotions are embedded into artforms).

If you manage yourself and your project right, it can be the most interesting thing you want to do from all the things there are to do (play games, watch videos, chat, browse web, etc). I hope this helps & good luck!




PARTNERS