So I want to be a game developer....

Started by
48 comments, last by obizues 11 years, 9 months ago

In truth, I think a Zelda style game is a pretty large jump from Pong. To implement a Zelda clone you need several systems that don't exist in pong or similar games. These include...


I do think I could handle most of it.. obviously over time. I've thought about an 8 section map slowly leading to an area. It would be more of a "tech demo" than a fully functional game utilizing UI for example with 4 characters on the screen at once. Then again, maybe I'm a little naive.



Here on GDNet you can post in the Help Wanted section. In a search engine you can search for "Sprite Sheets," however, keep in mind that all the art assets you get are copyrighted, and cannot be used in a game (that you distribute) without permission from the creator. So it's fine to use those for your own projects to learn from, but you can't use them beyond that.


I wouldn't use the art for a "real" game, it would basically just be for my own growth.


I do have my pong game "done" as of right now. I am going to e-mail Simon, and hopefully you can see it as well then if he posts a link.
Advertisement
i couldn't get it running though, (no executable and the .application installers(???) complain about missing .deploy files for all assets. (it looks like everything that is needed to re-build the application is there though so i'll give that a shot when i got some time to spare.

sourcecode and stuff for it:
http://www.reunited-guild.net/pong-chris.zip
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
Simon,

Sorry for not explaining. Gmail won't let me send any zips with .exe files so I actually need you to, like you said, rebuild it. It will auto-generate those files again and it should work.

Please let me know if it does not.

Simon,

Sorry for not explaining. Gmail won't let me send any zips with .exe files so I actually need you to, like you said, rebuild it. It will auto-generate those files again and it should work.

Please let me know if it does not.


I see, i'll try to get the XNA stuff installed after work today then (if i can get home at sane hours)
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
Simon,

Sorry for causing such a headache. Thanks again for all your help and support.
Ok Chris,

I got a chance to look at your Pong game. Here's some feedback if you're interested.

Assets

  • Don't duplicate art assets just to put an arrow in a different place in the menu. Instead, make the arrow it's own sprite, create one asset for the menu, then draw the arrow next to the menu item that is currently active.
  • Unless you're looking for very stylized text, it's often better to use SpriteFont to draw text against menu background, rather than putting the text in the image directly. Then, if you decide to change the text, localize it, etc... it just requires changing a line of code, not re-visiting an image editing program.
  • SpriteBatch works by drawing textures to the screen via 2D pre-transformed quads. Each time you switch textures for a different sprite, it has to do a sort of context switch. So instead of creating sprites as different image files, put them all in the same image file and use source rectangles to identify where in the sprite sheet to pull the texture from. This works for sprite sheets up to about 1024x1024. Anything bigger and you risk video cards not being able to load it effectively.


Objects & Classes
In your program you group data together such as this:
[source lang="csharp"]int ballSpeedX = 5;
int ballSpeedY = 1;
int ballDirectionY = -1;
int finalBallLocationX = -1;
int finalBallLocationY = -1;[/source]
This is the perfect place to create a Ball class. You can add to it [font=courier new,courier,monospace]ballTexture[/font] as well.

In your update method you have several if-else statements to determine what the current state is and then process the logic for that state. Additionally, in your Draw method you have several if statements for what to draw. Instead, look at the State Machine design pattern. Each of those states can be their own class, and then inside of [font=courier new,courier,monospace]Game.Update()[/font] you'd just call [font=courier new,courier,monospace]curretState.Update()[/font]. In [font=courier new,courier,monospace]Game.Draw()[/font] you'd call [font=courier new,courier,monospace]curretState.Draw()[/font]. The logic for switching between states is then embedded within each state, and your Game's Update and Draw methods become nice and clean.

Code Cleanliness
You call [font=courier new,courier,monospace]KeyboardState gameState = Keyboard.GetState();[/font] in each of your game state blocks. Instead, just call it once at the beginning of your update method, and then use the keyboard state as necessary in the rest of the method.

Even if you don't use an object to represent your game state code, you should switch from String to Enum for your game states. Enum is more type-safe, as string will allow the state to be literally any string value.

Your use of [font=courier new,courier,monospace]lastState [/font]and [font=courier new,courier,monospace]state [/font]can be restructured so you don't really need lastState except when entering or leaving a menu screen.

I'm not quite sure why you have [font=courier new,courier,monospace]finalBallLocation[/font]. I see you calculate it's value in several places, but don't immediately see it being used for much.

There are several complicated if-statements, especially in the collision detection section. It's a good idea to make the code self-documenting to break those clauses up into smaller chunks and wrap them in methods.

Perform static calculations once, and save the values. There are several places where you perform the following:


ball.Y = Window.ClientBounds.Height / 2 - ballTexture.Height / 2;
ball.X = Window.ClientBounds.Width / 2 - ballTexture.Width / 2;
pos1.Y = Window.ClientBounds.Height / 2 - texture.Height / 2;
pos2.Y = Window.ClientBounds.Height / 2 - texture.Height / 2;


Not only is the code present in your source file more than once, but it's called each time you enter the restart state, or exit state, even though it's a known value from the moment your application loads the texture. So instead, perform the above calculations in Initialize or LoadContent so you only perform the calculations once.

The same goes for things like this:

spriteBatch.Draw(player2Restart, new Vector2(Window.ClientBounds.Width / 2 - player1Main.Width / 2, Window.ClientBounds.Height / 2 - player2Main.Height / 2), Color.White);


That's a lot of calculations being performed each Draw, considering those are all known values. Compute them once, then keep re-using the calculated value. This is easiest if you create a Sprite class. Then you can create an instance of a Sprite for each object, set it's texture, position, etc... once, and just keep calling Draw on the sprite.

Commenting
Your code is over 800 lines, and there's about 5% commenting. Most of which are method headers that were auto-generated for you. If you're doing a complex if-checks, or if something isn't immediately readable, add a comment. Also, it's good to use comments to tell why you're doing something, not just what.
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints

I got a chance to look at your Pong game. Here's some feedback if you're interested.


Whelp! Back to the real world! Thank you very much for all this feedback I appreciate it!



  • Don't duplicate art assets just to put an arrow in a different place in the menu. Instead, make the arrow it's own sprite, create one asset for the menu, then draw the arrow next to the menu item that is currently active.
  • Unless you're looking for very stylized text, it's often better to use SpriteFont to draw text against menu background, rather than putting the text in the image directly. Then, if you decide to change the text, localize it, etc... it just requires changing a line of code, not re-visiting an image editing program.
  • SpriteBatch works by drawing textures to the screen via 2D pre-transformed quads. Each time you switch textures for a different sprite, it has to do a sort of context switch. So instead of creating sprites as different image files, put them all in the same image file and use source rectangles to identify where in the sprite sheet to pull the texture from. This works for sprite sheets up to about 1024x1024. Anything bigger and you risk video cards not being able to load it effectively.



I completely see what you're saying here. I agree and understand what you mean here. The reason I did it this way, was because I felt like I would have to guess and check over and over with whether or not the arrow was ligned up correctly. Is there an easier way to do this?

I also had no idea how the SpriteBatch worked, so your way makes complete sense. I was planning on doing it for animation sprites, but I can see how it's now important no matter what the situation.



Objects & Classes...


I realized about half way in the project I wasn't fully using objects and classes like I should. Part of the reason is the fact that I am not entirely sure how C# handles it compared to Java, so I thought I'd stay away from it until I read more about it. I completely agree with everything you said.


In your update method you have several if-else statements to determine what the current state is and then process the logic for that state. Additionally, in your Draw method you have several if statements for what to draw. Instead, look at the State Machine design pattern.


I'm not familiar with this design pattern. I definietely need to look this up and see what you mean. I just basically tried to use my own logic to do what I was trying to accomplish.



Code Cleanliness


I agree completely on this end. I need to perform those calculations once. I am not familiar with "Enum" and how it helps the situation. Perhaps this is something I will learn in reading more about the "game state model?" The "finalBallLocation" is meant to calculate where the ball is going to end up after the collision with the computer controlled left paddle. Then the right paddle moves to that spot on the Y-axis accordingly.


Commenting
Your code is over 800 lines, and there's about 5% commenting. Most of which are method headers that were auto-generated for you. If you're doing a complex if-checks, or if something isn't immediately readable, add a comment. Also, it's good to use comments to tell why you're doing something, not just what.


I understand what you mean. I built this game like I was the only one reading the code or using it... which is admittedly very bad practice. I also understand what you mean about something telling WHY I'm doing something.

Just out of curiosity how did you calculate how many lines of code were written, and what would you recommend as a good % for commenting?


I apprecaite ALL of these feedback, and it's a good slap back into reality, and to remind me where I am in the process. Would you recommend I go back and make changes to this game to reflect this feedback, or to just put it into practice on my next project?

Thank you very much again!

Whelp! Back to the real world! Thank you very much for all this feedback I appreciate it!


I tend to be on the more nitpicky side with my code reviews, but I feel it helps to develop good habits early on. Don't feel like it was a smack-down. Learning is a process and the fact you started and finished a game - even Pong, is a huge step, as many people never even get that far. Again, kudos to you, and please don't get discouraged, that wasn't my intention.


The reason I did it this way, was because I felt like I would have to guess and check over and over with whether or not the arrow was ligned up correctly. Is there an easier way to do this?


SpriteBatch allows you to specify the origin of an image as well as it's position. By default, the origin is in the top-left corner. However, if you move it to the left-center or center-center of an image, then you can vertically align to sprites by drawing them at the same vertical position.


I realized about half way in the project I wasn't fully using objects and classes like I should. Part of the reason is the fact that I am not entirely sure how C# handles it compared to Java, so I thought I'd stay away from it until I read more about it. I completely agree with everything you said.


C# and Java treat classes about the same. The only real difference is that Java doesn't have structs, so everything is pass-by-reference. If something feels like it should be a class, go ahead and make it one.


I'm not familiar with this design pattern. I definietely need to look this up and see what you mean. I just basically tried to use my own logic to do what I was trying to accomplish.


You can bing/google the design pattern for information on how to implement it. There's plenty of C# implementations out there as well for reference. Also, here's the Game State Management sample on the XBLIG website. Look it over.


I agree completely on this end. I need to perform those calculations once. I am not familiar with "Enum" and how it helps the situation.


Enums are the same in C# and Java I believe. They are a way of defining a set of things in code, which can be identified by their symbolic values. Such as having an enum of dates, and giving them the values Days.Monday, Days.Tuesday, etc... See the C# Documentation for a full description with plenty of examples. Scroll down pass the member information.


The "finalBallLocation" is meant to calculate where the ball is going to end up after the collision with the computer controlled left paddle. Then the right paddle moves to that spot on the Y-axis accordingly.


As an alternative, you can have the AI attempt to move up or down based on the "current" vertical position of the ball. So if the ball is at 200y, it'll change direction so the center is at 200y. Then, if you only update the AI every 10, 5, 2, 1, etc... updates, you can make the computer appear "smarter", as it'll respond more quickly to the current state. Nice way to provide a progressively more challenging AI.


Just out of curiosity how did you calculate how many lines of code were written, and what would you recommend as a good % for commenting?


I did a find for //, and then scrolled to the bottom of the file to see how many lines of code there was. Nothing magical, or even relatively accurate. There's no ideal % or ratio that I know of for comments to code. In general, the goal is to make the code self-documenting, such that reading variable, class, and method names makes it 100% clear what is happening at a single glance. But, if that's not the case, either because of a complex algorithm, or a particularly interesting implementation detail, it's a good idea to add a comment. If I had to guess, I'd say my ratio is at about 10-20% or 1:7 comments per lines of code. Again, there's no magic number.


I apprecaite ALL of these feedback, and it's a good slap back into reality, and to remind me where I am in the process. Would you recommend I go back and make changes to this game to reflect this feedback, or to just put it into practice on my next project?


Glad it helps, but please don't view it as a slap. They were just some friendly suggestions or direction, not reprimands. Go back and make the changes if you want practice in working with enums, using Finite State Machines, or object-oriented programming. If not, just incorporate those things into your toolbox as you move forward.

Cheers!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints

Glad it helps, but please don't view it as a slap. They were just some friendly suggestions or direction, not reprimands. Go back and make the changes if you want practice in working with enums, using Finite State Machines, or object-oriented programming. If not, just incorporate those things into your toolbox as you move forward.

Cheers!


I no I don't, I meant that a little tongue in cheek, but at the same token I realize I have a lot more to learn that what I already know. Thanks again for your time.
http://www.filedropper.com/ponginstaller

This is a link to my compressed installer. I understand that this is a setup.exe file, so please feel free to scan for viruses and such before hand.

At least this way I can have someone actually play the game as well as review my coding.

This topic is closed to new replies.

Advertisement