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

Highest Reputation Content


#4756238 What Does Everyone Think About The New Site Layout?

Posted by Mike.Popoloski on 09 January 2011 - 03:24 PM

I have to say that I'm unhappy with the new site. I liked the old one, and while it definitely needed improvement, I wouldn't call what we have now anything more than a step in the right direction.

1. De-emphasis of the forums - For some reason the forums feel even more hidden away than they were before. It takes an extra click to go through the drop-down menu now, and the recent topics menu has been moved all the way down the main page. So much emphasis is being placed on the Careers and Articles sections, even though GDNet does not excel in those areas. Looking at the Careers page is pretty pathetic, and the articles section hardly ever has real technical content. I thought the new site would focus more on the forums, which are GDNet's strongest feature.

2. Web 2.0 - I think it's easy to see that they went way overboard in this area. Every page feels cluttered with tons of junk that isn't even that useful. Why are there sharing buttons all over the place? Why is so much space wasted? What is the point of friend lists? Why are there status updates next to the forum listing? It's like all this stuff was added just because they could. GDNet is not Facebook, and it is not Twitter. I don't see why it should be trying to emulate them either.

3. Death of GDNet+ - I think you guys are really shooting yourselves in the foot here with this one. You've cheapened GDNet+ significantly by giving everyone journals and avatars, when instead you should have been trying to add as many new things to GDNet+ as possible to make it more attractive and a more viable source of revenue. I mean, this is now listed as a primary feature of GDNet+:
"Up to 500 personal messages (10x more!)"

Seriously? You're touting an increased MAILBOX SIZE as a selling point? I've been subscribing to GDNet+ for years now, but I think when the renewal comes around again I'll be dropping it.

4. Widescreen Users - Why have we squished everything together, when everyone and their mom is moving towards widescreen monitors these days? It just makes no sense at all. So much horizontal space is lost, which in turn increases the vertical space required to read anything. Very frustrating.

5. Losing the Rating System - I know the rating system has always been controversial, but what you have now is completely pointless and should not even exist. No more down voting removes any incentive to keep your posts to community standards. As long as you don't do anything explicitly bannable, you can get away with whatever you like. Additionally, voting on posts and not users leads to run-away inflation for users who post a lot. Want more reputation? Just post more! It emphasizes quantity over quality, which is never a great idea. Finally, the rating is so hidden now that it might as well not even exist. The way I see it, you should either do it properly, or just remove the feature entirely if you feel GDNet users shouldn't be worrying about ratings at all. One or the other; not this middle ground.

6. Sane Defaults - I like that notifications are now very customizable, but someone wasn't thinking when the defaults were set. I started receiving emails for all sorts of useless events here, such as a user adding me as a friend. So much so, in fact, that GMail started putting everything coming from GDNet into the spam folder. Another questionable default is that of allowing people to be friends with you; apparently the default is to let them add you as a friend without you having any say in the matter. Now that they're friends, I have no way of getting rid of them, so they're not really friends as much as they are fans at this point :rolleyes:

Some of these problems are expected from a new software product, and I'm sure some will be fixed in the months to come. Unfortunately, I think a lot of them are explicit design decisions that have already been made. Hopefully not everything is set in stone at this point.


#5016969 Good habits for game development

Posted by Servant of the Lord on 02 January 2013 - 10:28 PM

My personal and non-professional opinion:
  • Write clean code the first time through. Don't write messy code and promise yourself that you'll "clean it up later".
  • Recognize that clean code is better than fast code. It's easy for clean code to be made fast, but hard for fast code to be made clean.
  • Counter tip: Don't be so obsessed with clean code that your project's progress stalls.
  • Avoid macroes, except when they make your code easier, safer, and cleaner.
  • Avoid globals, except when they make your code easier, safer, and cleaner.
  • Avoid gotos, except when they make your code easier, safer, and cleaner.
  • Avoid people that say macroes, globals, and gotos are perfectly fine.
  • Avoid people that say macroes, globals, and gotos are never allowed.
  • Listen to people that say macroes, globals, and gotos should be rarely* used, but who recognize exceptions. smile.png
  • Use RAII, Single Responsibility Principle, and other similar concepts.
  • Don't embed content into code - load content from file or something similar.
  • Create and use a consistent coding style for your code.
  • Use the C++11 smart pointers and std::make_shared(). (use Boost's versions if you can't use C++11)
  • Avoid calling 'new' and 'delete' yourself, except in the rare situations** where they are required.
  • Don't re-invent the wheel, unless it's a small wheel, isn't in the standard library, and won't take you long.
  • Make your code as self-documenting as possible, so it can be easily understood without comments.
  • Comment the code it anyway.
  • Finish the projects and features you start.
  • After you learn to finish the projects or you start, then learn to shoot the projects or features that need to die.
  • Worry about writing poor code. Aim for high quality code, or at least good code.
  • Don't worry about writing perfect code.
  • Really. Don't worry about writing perfect code.

*90% of the time, a global shouldn't be a global, 95% of the time, a macro should be a template or a regular function, 99.9% of the time, a goto is being misused. 100% of these percentages are made up, but illustrate a point anyway. =)

 

**I find that it's rare, but not extremely rare. For performance reasons, probably 19 out of 20 of my dynamic allocations should be smart pointers - but I suppose that would vary from project to project. The vast majority allocations should be on the stack, and neither smart pointers nor raw allocations.




#4970905 Realistic Encouragement vs Trolling Tear-down

Posted by Lance42 on 18 August 2012 - 01:49 PM

I've lurked here for a long time, and have been a Senior Programmer/Systems analyst for 15 years.  Occasionally I see a beginning game programmer, full of dreams and desires end up having those dreams crushed by those who would have them believe they are naive, too inexperienced, and stupid for not being able to see it. While I appreciate those who are trying to educate about the realities of the gaming industry, and encourage as they do it, I think it is taken too far by a select few. These few use their knowledge to appear superior to their peers, and really have little motive for "helping" beyond that. My message is not for them. (It wouldn't do any good if it was.)

My message is for the downtrodden who now feel their GameDev dream is out of reach, who are frustrated and considering giving up, and who might be feeling that perhaps the mean-hearted claims of those mentioned above are correct. Don't give up. Yes, there are realities and requirements that you must satisfy before you're ready to get a job at that big game company, or to start your own game studio, or whatever your dream is, but if you want it badly enough, then you wont let the nay-sayers tell you what you can and can't do. Did you know the Walt Disney was fired by a newspaper editor because he "lacked imagination and had no good ideas"? Most of us laugh at the idea right now. He didn't let that newspaper editor tell him what he was capable of, and neither should you. Go out, do your research, learn about the industry, learn your trade, grab your dream by the horns and make it yours. Be realistic, but don't let anybody tell you you can't make it. You're better than that, and you owe it to yourself to make the most of what you want. I did once, and now I'm doing it again. So can you.

Lance...


#4983074 What programmers want from a designer

Posted by jbadams on 23 September 2012 - 07:52 PM

Disclaimer: I'm probably going to write as if I'm speaking on behalf of many (or all) programmers, because I feel it is the style in which I am best able to express these ideas, but the following is all based upon my own personal opinions and experiences.  Other programmers may disagree with some or all of my points of view.

I know you wanted to look beyond them, but before putting them aside I'd like to expand a little bit on money and on the idea.


Money

Obviously, it can really help your recruiting efforts if you're able to pay your programmer.  We put hundreds (even thousands) of hours into learning our skill, and we have limited time available in which to use that skill.  If you're able to pay for that time it's more likely a programmer will be interested in spending time to work on your project.  However, not all projects can afford to spend much -- if anything -- and programmers are sometimes willing to work for discounted rates or even for free.

For a project to be considered without pay, it still needs to satisfy a couple of other money-related conditions:

  • It needs to be fair.  If you're not paying us then you shouldn't be getting paid either, or if there is pay involved you shouldn't be offering your programmer some small amount whilst others -- especially yourself -- get much more.
  • Even if you're not paying for it, it needs to be obvious that you understand and respect that our time is valuable.  You might be able to find a programmer who would be willing to work for free or at a discount, but they would be unlikely to do so for a project where people think programming isn't worth paying for.
  • Beyond compensating people for their time, money also goes towards showing commitment to and belief in the project.  If you're not paying your team -- programmers and otherwise -- then you damn well better show your commitment and belief in the project in other ways.
  • You need to show that you're sensible and -- even if you're not an expert -- have a bit of basic business sense.  If you're aiming for a commercial product then profit sharing is a nice thing to do, but you should be realistic about the fact that this doesn't count as paying your staff; they might not get anything out of such a deal for a variety of reasons including not completing the project, poor sales/conversions, or even running into legal problems either before or after release.
  • By not paying your team members you're asking them to volunteer their valuable time to the project.  You should be making a similar -- if not greater -- contribution of your own time.  Skilled programmers will not work for the dreaded "idea guy", and as essential as an idea is, you should not expect us to attach more than a small amount of value to your idea; you need to be contributing some value beyond that.

You might also show both your commitment, belief in the project, and good business sense by saving up your own money in order to pay other costs such as licencing fees for tools and engines, website or repository hosting, etc.


The idea

In addition to grabbing the programmer's interest, the idea needs to be specific, detailed, and well thought-out.  If you just have a general, high-level concept then you're probably going to have difficulty finding a programmer -- they have general, high-level concepts (and probably even more detailed ideas) of their own.

However, you shouldn't be expecting to simply hand over a design document and have it treated as The Word of God™ to be followed exactly to the letter so that the One True Game™ will result; that's code-monkey work, and you have no choice but to pay for it to be done.  Any experienced programmer will be expecting that a successful game will be the result of an iterative process.

You need to be willing to share the idea.  No skilled programmer is going to waste time privately contacting you on the chance that your idea might be good, you need to provide the idea -- or at least a substantial part thereof -- up-front to be assessed and hopefully gain interest.  Don't suffer from "stupid paranoia", and don't be one of those foolish people who thinks every facet of their latest idea is truly unique.



So... what else are we looking for...


Clear communication (and good presentation)

For both designers and project leaders, one of the most important skills is communication, and our first impression of this is your recruiting advert and any documentation you choose to attach.  You need to put your best foot forward:

  • Take the time to use proper spelling, grammar, and punctuation.  Don't use "1337" or "txt" speak, or unnecessary abbreviations.
  • Don't just ramble.  Take the time to properly structure both your advert and any responses.  Use formatting options, and white-space including paragraphs, indentation, etc.
  • Test any links you include to make sure they work correctly and take the time to fix them if they're broken.

Your contribution (you need to be useful!)

I covered this to an extent in the section on money, but your idea is not enough.  If you're just providing an idea that you want made you're going to have to pay someone.

Otherwise you need to provide useful skills, and you need to be contributing as much time and effort to the project yourself as you expect from others.  It does not count to say you've already finished your contribution by writing up the idea.

You might also be contributing to marketing, sales, etc., and that's a great skill to have that will really help a final product, but again it isn't enough:  you need to be contributing something during the project whilst the programmer is also working on it.

Ideally, you might produce some or all of the art and/or audio for the game, or might be doing an equal share of the programming yourself.  If you're claiming to have design skills that will be used throughout the project -- and again, having created the idea up-front does not count -- you'll need to be able to clearly explain what those skills are, and you'll need something (previous projects, demo games made with Game Maker, board games, card games, etc.) that demonstrates you're actually capable with those skills.


Understanding of the industry/market/processes

Programmers want to be confident that you understand the realities of the industry and market, and that you have some idea of the process that goes into creating a game.  

Gaps in your knowledge are fine if you're both up front and honest about them and are willing to learn -- even better if you're obviously pro-active about it -- from others, but no one wants to work with someone who is completely ignorant or misinformed about how things really work.  This is especially true if you stubbornly stick to your guns when provided with evidence to the contrary; it's fine to want to try an unusual approach, but you need to at least acknowledge it as such, and should never simply stick your head in the sand and refuse to change an incorrect belief.

You don't need to be an expert at everything -- you wouldn't need us if you were! -- but you should have at least a general idea of the entire process.


Reasonable expectations

If you're not paying your programmers, you can't expect us to treat your project like a proper job.  It's probably going to take longer than you might have liked, and you'll have to gracefully accept the occasional interruptions due to real-life issues or the opportunity for paying work.

You should also not be expecting to make a super smash hit game of AAA quality with hour upon hour of intricate storyline.

You should expect to face difficulties and to have to work really hard to see your project through to completion.


Honesty and integrity

We're more comfortable working with someone who is open and honest.  Don't misrepresent yourself or the project, and don't try to rip people off, or no programmer will want to work with you, and you almost certainly will be caught out eventually.


A sensibly sized (i.e. small) team

AAA games are made by huge teams with massive budgets, and they have a lot of management and official policy -- as well as the incentive of proper pay -- to make that happen properly.

Successful indie and hobbyist games are usually the product of much smaller teams, often ranging from only two people up to a handful.  Larger long-term open-sourced projects might have more contributors over time, but even then usually have a smaller active "core" team working at any one time; they also begin with either an individual or a much smaller team, and only end up with those larger numbers of contributors once substantial progress has been made.

If you're looking to recruit large numbers of people to an unpaid project, most skilled programmers will expect you to fail like many projects before and won't consider you.  Trying to do this probably indicates unreasonable goals and expectations, and is in most cases indicative of an overly ambitious project.



Art, documentation, pre-recorded audio, etc?

Good presentation of whatever you do have is very important, and it should be obvious that you are capable and committed to the project.

The working demo or video of a semi-functional game is great to see.

Concept art that was specifically created for your project is good.  Completed (or nearly complete work-in-progress) art is much better.  Concept art that you simply collected from existing sources might help to explain your project to artists, but often isn't ideal and can sometimes be indicative of a lack of commitment; why not simply delay and save up to get your own?

Audio usually seems premature unless your project is to the stage of having a working demo or game-play video.

Detailed documentation is good, bearing in mind the notes above about iterative design and the understanding that your idea (and any design documents containing it) are not the be-all and end-all, and will not be acceptable as your only contribution.


Oh, and don't bother with "I'll have next week", where x is concept art, a video, a website, or whatever.  Wait till next week and post with x included.

...wow, that ended up quite long, I hope it's helpful!  Perhaps I should clean this up into an article at some point...
Posted Image Posted Image

 




#5044042 The games that everybody writes.

Posted by Haps on 17 March 2013 - 03:26 PM

Crash to Desktop is wildly popular amongst beginners and experts alike.




#5020002 Lines of Coding Per Day

Posted by Servant of the Lord on 10 January 2013 - 02:45 PM

Lines of code is a very poor measurement tool for several reasons:

 

A) One line of code in one language at a higher level of abstraction might be worth twenty in another language.

B) A poor programmer might write 10 lines of code when 5 might suffice (not properly re-factoring into functions), or a poor programmer might write 5 lines of code when 10 would be better (example: skipping error checking).

C) A poor programmer might write 50 lines of code, and have to re-write it later because the first time it was done wrong. Does that mean he wrote 100 lines of code, despite only 50 ending up in the final project?




#5057627 Microsoft burned down my home, where now?

Posted by Hodgman on 28 April 2013 - 08:39 PM

...

You're talking as if Microsoft has deleted all copies of XNA from the earth, when all they've done is announced that it's reached maturity and won't be developed any further. D3D9 isn't being updated either, and it's still used to create games.

  • You can keep using the existing versions of XNA.
  • You can switch over to the open-source versions of XNA, like Monogame.
  • You can use C# and D3D via SlimDX, etc.
  • You can use C++ and D3D (for free; no you don't have to buy anything).

DON'T PANIC




#4993693 Create a Game Engine

Posted by Hodgman on 24 October 2012 - 11:34 PM

A game engine is just a tool. If you want to make a tool, you need to know specifically what you're going to be using it for.

If you're turning screws, you want a screwdriver. If you're hitting nails, you want a hammer.

If you're making a new tool, you should know what problems it will be used to solve.
If you do know what problems you will use this tool to solve, then tell us those specific problems and we can help you design this tool appropriately.
If you don't know what problems you'll be using this tool for, you have to find that out first before blindly creating tools with no explicit purpose, otherwise you'll end up with a mallet when you really needed scissors...


#5045308 Tetris clone in BASH script

Posted by SynaGl0w on 21 March 2013 - 11:14 AM

Way back while learning BASH scripting I made a tetris clone, as is common practice when learning a new language. Being a C++ guy, the result was horrible to look at. You can also tell that I got lazy with comments. Plenty of unfinished things as well. Behold:

 

#!/bin/bash

#-----------------------------------------------------------------------------
# A tetromino stacking game written entirely in BASH script! =D
#
# Because I can...
# 
#-----------------------------------------------------------------------------
# Version 0.1 Beta:
#	- The game is functional
#	- Todo:
#		- Overtime bonus to score after all 10 lines of level 10 are cleared
#		- Highscores
#=============================================================================

#=============================================================================
#-----------------------------------------------------------------------------
# [ Global Variables ]
#-----------------------------------------------------------------------------
#=============================================================================
declare -r TETRIBASHTITLE="TetriBASH"
declare -ri TETRIBASHVERSION=0
declare -ri TETRIBASHSUBVERS=1
declare -r TETRIBASHRELEASE="Beta"
declare -r TETRIBASHDATE="2010 - 2012"
declare -r TETRIBASHINFO="A tetromino stacking game written entirely in"
declare -r TETRIBASHINFO2="BASH script! =D"
declare -r TETRIBASHINFO3="Because I can..."

declare -i TETRIBASHSTATE=0	# Indicates the current game state
declare -i TETRIBASHDEBUG=0	# Value of 1 enables debug mode

declare TIMESTART="0.0" 	# Start time of a frame
declare TIMEEND="0.0"		# End time of a frame
declare DELTATIME="0.0"		# Time elapsed for the frame
declare ACCUMULATOR="0.0"	# Primary gameplay accumulator

declare -ri TERMULT=2	# and chaos		# Multiplier to determin tetromino block width in characters (Do not change!)
declare -ri TERMWIDTH=$(tput cols)		# Character width of the terminal
declare -ri TERMHEIGHT=$(tput lines)	# Character height of the terminal

declare -ri GAMEWIDTH=34											# Width of the game area
declare -ri GAMEOFFSETX=$((($TERMWIDTH / 2) - ($GAMEWIDTH / 2)))	# X offset of the game area
declare -ri GAMEOFFSETY=2											# Y offset of the game area

declare -ri GAMEBLOCKSIZE=4											# Width and height of the game block array
declare -ri GAMEBLOCKAREA=$(($GAMEBLOCKSIZE * $GAMEBLOCKSIZE))		# Size of the game block array

declare -i GAMESCORE=0			# Game score
declare -i GAMESCOREMULTDEF=33	# Score Multiplier Default
declare -i GAMESCOREMULT=33		# Score Multiplier
declare -i GAMESCOREMULTINC=100	# Score Multiplier increase per level
declare -i GAMELEVEL=0			# Game level
declare -i GAMELINES=0			# Number of lines cleared
declare -i GAMELINESPERLEVEL=10	# Number of lines that need to be cleared to advance in level
declare -i GAMELEVELLINES=0		# Number of lines cleared this level	
declare -i GAMEFAILUREMAX=10	# NUmber of blocks to place after failure before showing Game Over message
declare -i GAMEFAILURECOUNT=0	# Number of blocks placed on top of eachother
declare -i GAMEFAILURE=0		# Indicates a game is determined to be lost
declare -i GAMECURRENT=0		# Current active block ID
declare -i GAMECURRENTROT=0		# Current active block rotation
declare -i GAMENEXT=0			# The next block ID
declare -i GAMERUNNING=0		# Indicates the game is running

declare -a GAMECURRENTARRAY		# Current active block array
declare -a GAMENEXTARRAY		# Next block array
declare -a GAMEBLOCKBUFFER		# Current active block rotation buffer

declare -i GAMECLEARINPROGRESS=0	# Indicates a line clear is in progress
declare -i GAMEOVERINPROGRESS=0		# Indicates game over is in progress
declare -i GAMELINESTOCLEAR=0		# Number of lines that need clearing
declare -a GAMELINESBUFFER			# Lists of lines that need clearing
declare -i GAMECLEARANIMFRAMES=3	# Number of frames of clearing animation
declare -r GAMECLEARCHAR=":"

declare -i GAMEBLOCKX=0			# X position of active game block relative to terminal
declare -i GAMEBLOCKY=0			# Y position of active game block relative to terminal		
declare -i GAMEBLOCKAPX=0		# X position of active game block relative to the play area
declare -i GAMEBLOCKAPY=0		# Y position of active game block relative to the play area

declare GAMEINTERVAL="0.5"		# Fall rate in seconds
declare GAMECLEARINTERVAL="0.2"	# Clear rate in seconds
declare GAMEOVERINTERVAL="5.0"	# Game Over message interval in seconds

declare -i FRAMEUPDATED=0		# Indicates drawing has been done in the current frame

declare -ri TBASHW=10									# Width of the play area in blocks
declare -ri TBASHH=20									# Height of the play area in blocks
declare -ri TBASHSIZE=$(($TBASHW * $TBASHH))			# Size of the play area array
declare -ri TBASHAREAOFFSETX=$GAMEOFFSETX				# X offset of play area including border
declare -ri TBASHAREAOFFSETY=$GAMEOFFSETY				# Y offset of play area including border
declare -ri TBASHAREAW=$((($TBASHW * $TERMULT) + 2))	# Width of play area including border
declare -ri TBASHAREAH=$(($TBASHH + 2))					# Height of play area including border
declare -ri TBASHOFFSETX=$(($TBASHAREAOFFSETX + 1))		# X offset of play area
declare -ri TBASHOFFSETY=$(($TBASHAREAOFFSETY + 1))		# Y offset of play area

declare -ri TBASHGAMEOVEROFFSETX=$(($TBASHAREAOFFSETX + 2))
declare -ri TBASHGAMEOVEROFFSETY=$(($TBASHAREAOFFSETY + ($TBASHAREAH / 2) - 2))
declare -ri TBASHGAMEOVERWIDTH=$(($TBASHAREAW - 4))
declare -ri TBASHGAMEOVERHEIGHT=3

declare -ri TBASHSCOREW=10
declare -ri TBASHSCOREH=3
declare -ri TBASHSCOREOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX))
declare -ri TBASHSCOREOFFSETY=$GAMEOFFSETY
declare -ri TBASHSCOREVALUEX=$(($TBASHSCOREOFFSETX + 1))
declare -ri TBASHSCOREVALUEY=$(($TBASHSCOREOFFSETY + 1))

declare -ri TBASHLEVELW=10
declare -ri TBASHLEVELH=3
declare -ri TBASHLEVELOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX))
declare -ri TBASHLEVELOFFSETY=$(($GAMEOFFSETY + 1 + $TBASHSCOREH))
declare -ri TBASHLEVELVALUEX=$(($TBASHLEVELOFFSETX + 1))
declare -ri TBASHLEVELVALUEY=$(($TBASHLEVELOFFSETY + 1))

declare -ri TBASHLINESW=10
declare -ri TBASHLINESH=3
declare -ri TBASHLINESOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX))
declare -ri TBASHLINESOFFSETY=$(($GAMEOFFSETY + 1 + $TBASHSCOREH + 1 + $TBASHLEVELH))
declare -ri TBASHLINESVALUEX=$(($TBASHLINESOFFSETX + 1))
declare -ri TBASHLINESVALUEY=$(($TBASHLINESOFFSETY + 1))

declare -ri TBASHNEXTW=10
declare -ri TBASHNEXTH=6
declare -ri TBASHNEXTOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX))
declare -ri TBASHNEXTOFFSETY=$(($GAMEOFFSETY + $TBASHAREAH - $TBASHNEXTH))
declare -ri TBASHNEXTVALUEX=$(($TBASHNEXTOFFSETX + 1))
declare -ri TBASHNEXTVALUEY=$(($TBASHNEXTOFFSETY + 1))

declare -ri MAINTITLEW=49
declare -ri MAINTITLEH=5
declare -ri MAINTITLEX=$((($TERMWIDTH / 2) - ($MAINTITLEW / 2)))
declare -ri MAINTITLEY=1
declare -r MAINTITLELINE1="\e[0;31m  ______      __       _ ____  ___   _____ __  __\e[0m"
declare -r MAINTITLELINE2="\e[1;31m /_  __/___  / /______(_) __ )/   | / ___// / / /\e[0m"
declare -r MAINTITLELINE3="\e[0;33m  / /  / _ \\/ __/ ___/ / __  / /| | \\__ \\/ /_/ / \e[0m"
declare -r MAINTITLELINE4="\e[1;33m / /  /  __/ /_/ /  / / /_/ / ___ |___/ / __  /  \e[0m"
declare -r MAINTITLELINE5="\e[1;37m/_/   \\___/\\__/_/  /_/_____/_/  |_/____/_/ /_/   \e[0m"

declare -ri TBASHABOUTW=49
declare -ri TBASHABOUTH=7
declare -ri TBASHABOUTX=$((($TERMWIDTH / 2) - ($TBASHABOUTW / 2)))
declare -ri TBASHABOUTY=$(($MAINTITLEH + 5))

declare -ri MAINMENUW=15
declare -ri MAINMENUH=4
declare -ri MAINMENUX=$((($TERMWIDTH / 2) - ($MAINMENUW / 2)))
declare -ri MAINMENUY=$(($MAINTITLEH + $MAINTITLEY + 3))
declare -ri MAINMENUITEMCOUNT=4
declare -a MAINMENUITEMS
MAINMENUITEMS[0]="New Game\e[0m"
MAINMENUITEMS[1]="High Scores\e[0m"
MAINMENUITEMS[2]="About\e[0m"
MAINMENUITEMS[3]="Exit\e[0m"
declare -a MAINMENUITEMY
MAINMENUITEMY[0]=$MAINMENUY
MAINMENUITEMY[1]=$(($MAINMENUY + 2))
MAINMENUITEMY[2]=$(($MAINMENUY + 4))
MAINMENUITEMY[3]=$(($MAINMENUY + 6))
declare -i MAINMENUSELECTION=0
declare -r MAINMENUITEMNOTSEL="    \e[0;33m"
declare -r MAINMENUITEMSELECT="\e[1;37m──> \e[1;33m"

declare -ri MENUBOTTOMDECORX=$MAINTITLEX
declare -ri MENUBOTTOMDECORY=$(($TERMHEIGHT - 5))

declare -r SCREENINFOSTRING=$(printf "%s %d.%d %s" "$TETRIBASHTITLE" $TETRIBASHVERSION $TETRIBASHSUBVERS "$TETRIBASHRELEASE")
declare -ri SCREENINFOSTRINGX=$((($TERMWIDTH / 2) - (${#SCREENINFOSTRING} / 2)))
declare -ri SCREENINFOSTRINGY=$(($TERMHEIGHT - 1))

declare -r BH="─"
declare -r BV="│"
declare -r BTL="┌"
declare -r BTR="┐"
declare -r BBL="└"
declare -r BBR="┘"

declare -r BLK1="\e[43m\e[1;33m[]"
declare -r BLK2="\e[42m\e[1;32m()"
declare -r BLK3="\e[46m\e[1;36m::"
declare -r BLK4="\e[41m\e[1;31m[]"
declare -r BLK5="\e[44m\e[1;34m{}"
declare -r BLK6="\e[47m\e[1;37m++"
declare -r BLK7="\e[45m\e[1;35m<>"

declare -a TBASHARRAY

#================================== Block 1 ==================================
declare -a BLK1ARRAY=(0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0)
declare -a BLK1ARRAYR2=(0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0)
declare -a BLK1ARRAYR3=(0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0)
declare -a BLK1ARRAYR4=(0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0)

#================================== Block 2 ==================================
declare -a BLK2ARRAY=(0 0 0 0 0 2 2 0 0 2 2 0 0 0 0 0)

#================================== Block 3 ==================================
declare -a BLK3ARRAY=(0 0 0 0 3 3 3 3 0 0 0 0 0 0 0 0)
declare -a BLK3ARRAYR2=(0 0 3 0 0 0 3 0 0 0 3 0 0 0 3 0)
declare -a BLK3ARRAYR3=(0 3 0 0 0 3 0 0 0 3 0 0 0 3 0 0)

#================================== Block 4 ==================================
declare -a BLK4ARRAY=(0 0 0 0 4 4 0 0 0 4 4 0 0 0 0 0)
declare -a BLK4ARRAYR2=(0 4 0 0 4 4 0 0 4 0 0 0 0 0 0 0)

#================================== Block 5 ==================================
declare -a BLK5ARRAY=(0 0 0 0 0 5 5 0 5 5 0 0 0 0 0 0)
declare -a BLK5ARRAYR2=(5 0 0 0 5 5 0 0 0 5 0 0 0 0 0 0)

#================================== Block 6 ==================================
declare -a BLK6ARRAY=(0 0 0 0 6 6 6 0 0 0 6 0 0 0 0 0)
declare -a BLK6ARRAYR2=(0 6 0 0 0 6 0 0 6 6 0 0 0 0 0 0)
declare -a BLK6ARRAYR3=(6 0 0 0 6 6 6 0 0 0 0 0 0 0 0 0)
declare -a BLK6ARRAYR4=(0 6 6 0 0 6 0 0 0 6 0 0 0 0 0 0)

#================================== Block 7 ==================================
declare -a BLK7ARRAY=(0 0 0 0 7 7 7 0 7 0 0 0 0 0 0 0)
declare -a BLK7ARRAYR2=(7 7 0 0 0 7 0 0 0 7 0 0 0 0 0 0)
declare -a BLK7ARRAYR3=(0 0 7 0 7 7 7 0 0 0 0 0 0 0 0 0)
declare -a BLK7ARRAYR4=(0 7 0 0 0 7 0 0 0 7 7 0 0 0 0 0)

#=============================================================================
#-----------------------------------------------------------------------------
# [ Function Declarations ]
#-----------------------------------------------------------------------------
#=============================================================================
function ZeroTetriBashArray()
{
	for((i=0; i<TBASHSIZE; i++)); do
	{
		TBASHARRAY[$i]=0
	}
	done
}

function GameOverClearTetriBashArray()
{
	for((i=0; i<TBASHSIZE; i++)); do
	{
		TBASHARRAY[$i]=8
	}
	done
}

function ZeroBlockBuffer()
{
	for((i=0; i<GAMEBLOCKAREA; i++)); do
	{
		GAMEBLOCKBUFFER[$i]=0
	}
	done
}

function ZeroLinesBuffer()
{
	for((i=0; i<TBASHH; i++)); do
	{
		GAMELINESBUFFER[$i]=0
	}
	done
}

function DrawBorder()
{
	if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then
	{
		return 1
	}
	fi

	local BWIDTH=$(($3 - 2))
	local BHEIGHT=$(($4 - 2))
	local BVERTVPOS=$(($2 + 1))
	local BVERTHPOS=$1

	printf "\e[%d;%dH${BTL}" $2 $1

	for((i=0; i<BWIDTH; i++)); do
	{
		printf "${BH}"
	}
	done

	printf "${BTR}"

	for((i=0; i<BHEIGHT; i++)); do
	{
		printf "\e[%d;%dH${BV}" $BVERTVPOS $BVERTHPOS
		BVERTVPOS=$(($BVERTVPOS + 1))
	}
	done

	BVERTVPOS=$(($2 + 1))
	BVERTHPOS=$(($1 + $3 - 1))

	for((i=0; i<BHEIGHT; i++)); do
	{
		printf "\e[%d;%dH${BV}" $BVERTVPOS $BVERTHPOS
		BVERTVPOS=$(($BVERTVPOS + 1))
	}
	done

	printf "\e[%d;%dH${BBL}" $(($2 + $4 - 1)) $1
	
	for((i=0; i<BWIDTH; i++)); do
	{
		printf "${BH}"
	}
	done

	printf "${BBR}"

	return 0
}

function DrawTetriBashArray()
{
	local BLAPOS=0

	for((i=0; i<TBASHH; i++)); do
	{
		for((j=0; j<TBASHW; j++)); do
		{
			BLAPOS=$((($i * $TBASHW) + $j))
			
			case ${TBASHARRAY[$BLAPOS]} in
				1) printf "\e[%d;%dH${BLK1}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				2) printf "\e[%d;%dH${BLK2}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				3) printf "\e[%d;%dH${BLK3}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				4) printf "\e[%d;%dH${BLK4}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				5) printf "\e[%d;%dH${BLK5}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				6) printf "\e[%d;%dH${BLK6}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				7) printf "\e[%d;%dH${BLK7}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				8) printf "\e[%d;%dH::\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
			esac
		}
		done
	}
	done

	FRAMEUPDATED=1
}

function DrawTetriBashArrayEx()
{
	local BLAPOS=0

	for((i=0; i<TBASHH; i++)); do
	{
		for((j=0; j<TBASHW; j++)); do
		{
			BLAPOS=$((($i * $TBASHW) + $j))
			
			case ${TBASHARRAY[$BLAPOS]} in
				0) printf "\e[%d;%dH  \e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				1) printf "\e[%d;%dH${BLK1}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				2) printf "\e[%d;%dH${BLK2}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				3) printf "\e[%d;%dH${BLK3}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				4) printf "\e[%d;%dH${BLK4}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				5) printf "\e[%d;%dH${BLK5}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				6) printf "\e[%d;%dH${BLK6}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
				7) printf "\e[%d;%dH${BLK7}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
			esac
		}
		done
	}
	done

	FRAMEUPDATED=1
}

function HUDDrawArea()
{
	DrawBorder $TBASHAREAOFFSETX $TBASHAREAOFFSETY $TBASHAREAW $TBASHAREAH
	FRAMEUPDATED=1
}

function HUDDrawGameOver()
{
	DrawBorder $TBASHGAMEOVEROFFSETX $TBASHGAMEOVEROFFSETY $TBASHGAMEOVERWIDTH $TBASHGAMEOVERHEIGHT
	printf "\e[%d;%dH\e[1;31m   Game Over!   \e[0m" $(($TBASHGAMEOVEROFFSETY + 1)) $(($TBASHGAMEOVEROFFSETX + 1))
	FRAMEUPDATED=1
}

function HUDDrawScore()
{
	DrawBorder $TBASHSCOREOFFSETX $TBASHSCOREOFFSETY $TBASHSCOREW $TBASHSCOREH
	printf "\e[%d;%dH\e[1;33mScore\e[0m" $(($TBASHSCOREOFFSETY + 0)) $(($TBASHSCOREOFFSETX + 2))
	FRAMEUPDATED=1
}

function HUDDrawLevel()
{
	DrawBorder $TBASHLEVELOFFSETX $TBASHLEVELOFFSETY $TBASHLEVELW $TBASHLEVELH
	printf "\e[%d;%dH\e[1;33mLevel\e[0m" $(($TBASHLEVELOFFSETY + 0)) $(($TBASHLEVELOFFSETX + 2))
	FRAMEUPDATED=1
}

function HUDDrawLines()
{
	DrawBorder $TBASHLINESOFFSETX $TBASHLINESOFFSETY $TBASHLINESW $TBASHLINESH
	printf "\e[%d;%dH\e[1;33mLines\e[0m" $(($TBASHLINESOFFSETY + 0)) $(($TBASHLINESOFFSETX + 2))
	FRAMEUPDATED=1
}

function HUDDrawNext()
{
	DrawBorder $TBASHNEXTOFFSETX $TBASHNEXTOFFSETY $TBASHNEXTW $TBASHNEXTH
	printf "\e[%d;%dH\e[1;33mNext\e[0m" $(($TBASHNEXTOFFSETY + 0)) $(($TBASHNEXTOFFSETX + 2))
	FRAMEUPDATED=1
}

function HUDUpdateScore()
{
	printf "\e[%d;%dH\e[1;36m%d\e[0m" $TBASHSCOREVALUEY $TBASHSCOREVALUEX $GAMESCORE
	FRAMEUPDATED=1
}

function HUDUpdateLevel()
{
	printf "\e[%d;%dH\e[1;36m%d\e[0m" $TBASHLEVELVALUEY $TBASHLEVELVALUEX $GAMELEVEL
	FRAMEUPDATED=1
}

function HUDUpdateLines()
{
	printf "\e[%d;%dH\e[1;36m%d\e[0m" $TBASHLINESVALUEY $TBASHLINESVALUEX $GAMELINES
	FRAMEUPDATED=1
}

function HUDUpdateNext()
{
	local BLAPOS=0;
	local VY=$TBASHNEXTVALUEY;

	case $GAMENEXT in
		0) GAMENEXTARRAY=("${BLK1ARRAY[@]}");;
		1) GAMENEXTARRAY=("${BLK2ARRAY[@]}");;
		2) GAMENEXTARRAY=("${BLK3ARRAY[@]}");;
		3) GAMENEXTARRAY=("${BLK4ARRAY[@]}");;
		4) GAMENEXTARRAY=("${BLK5ARRAY[@]}");;
		5) GAMENEXTARRAY=("${BLK6ARRAY[@]}");;
		6) GAMENEXTARRAY=("${BLK7ARRAY[@]}");;
	esac

	printf "\e[%d;%dH" $TBASHNEXTVALUEY $TBASHNEXTVALUEX

	for((i=0; i<GAMEBLOCKSIZE; i++)); do
	{
		for((j=0; j<GAMEBLOCKSIZE; j++)); do
		{
			BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
			
			case ${GAMENEXTARRAY[$BLAPOS]} in
				0) printf "\e[0m  ";;
				1) printf "${BLK1}";;
				2) printf "${BLK2}";;
				3) printf "${BLK3}";;
				4) printf "${BLK4}";;
				5) printf "${BLK5}";;
				6) printf "${BLK6}";;
				7) printf "${BLK7}";;
				*) printf "\e[0m  ";;
			esac
		}
		done
		
		VY=$(($VY + 1))
		printf "\e[%d;%dH" $VY $TBASHNEXTVALUEX
	}
	done

	FRAMEUPDATED=1
}

function DrawTetriBashHUD()
{
	HUDDrawArea
	HUDDrawScore
	HUDDrawLevel
	HUDDrawLines
	HUDDrawNext

	HUDUpdateScore
	HUDUpdateLevel
	HUDUpdateLines
	HUDUpdateNext

	FRAMEUPDATED=1
}

function FillArrayDemoBlocks()
{
	TBASHARRAY[15]=1
	TBASHARRAY[16]=1
	TBASHARRAY[17]=1
	TBASHARRAY[26]=1
	TBASHARRAY[21]=2
	TBASHARRAY[22]=2
	TBASHARRAY[31]=2
	TBASHARRAY[32]=2
	TBASHARRAY[38]=3
	TBASHARRAY[48]=3
	TBASHARRAY[58]=3
	TBASHARRAY[68]=3
	TBASHARRAY[51]=4
	TBASHARRAY[52]=4
	TBASHARRAY[62]=4
	TBASHARRAY[63]=4
	TBASHARRAY[75]=5
	TBASHARRAY[76]=5
	TBASHARRAY[84]=5
	TBASHARRAY[85]=5
	TBASHARRAY[103]=6
	TBASHARRAY[113]=6
	TBASHARRAY[114]=6
	TBASHARRAY[115]=6
	TBASHARRAY[138]=7
	TBASHARRAY[146]=7
	TBASHARRAY[147]=7
	TBASHARRAY[148]=7
}

function DrawTetriBashTitle()
{
	printf "\e[%d;%dH${MAINTITLELINE1}" $MAINTITLEY $MAINTITLEX
	printf "\e[%d;%dH${MAINTITLELINE2}" $(($MAINTITLEY + 1)) $MAINTITLEX
	printf "\e[%d;%dH${MAINTITLELINE3}" $(($MAINTITLEY + 2)) $MAINTITLEX
	printf "\e[%d;%dH${MAINTITLELINE4}" $(($MAINTITLEY + 3)) $MAINTITLEX
	printf "\e[%d;%dH${MAINTITLELINE5}" $(($MAINTITLEY + 4)) $MAINTITLEX
	FRAMEUPDATED=1
}

function DrawTetriBashMenuDecor()
{
	printf "\e[%d;%dH \e[0m" $MENUBOTTOMDECORY $MENUBOTTOMDECORX
	printf "\e[%d;%dH \e[0m" $(($MENUBOTTOMDECORY + 1)) $MENUBOTTOMDECORX
	printf "\e[%d;%dH \e[0m" $(($MENUBOTTOMDECORY + 2)) $MENUBOTTOMDECORX
	printf "\e[%d;%dH \e[0m" $(($MENUBOTTOMDECORY + 3)) $MENUBOTTOMDECORX
	FRAMEUPDATED=1
}

function DrawTetriBashVersionString()
{
	printf "\e[%d;%dH%s\e[0m" $SCREENINFOSTRINGY $SCREENINFOSTRINGX "$SCREENINFOSTRING"
	FRAMEUPDATED=1
}

function DrawTetriBashMainMenu()
{
	for((i=0; i<MAINMENUITEMCOUNT; i++)); do
	{
		if [ $i -eq $MAINMENUSELECTION ]; then
		{
			printf "\e[%d;%dH${MAINMENUITEMSELECT}${MAINMENUITEMS[$i]}" ${MAINMENUITEMY[$i]} $MAINMENUX
		}
		else
		{
			printf "\e[%d;%dH${MAINMENUITEMNOTSEL}${MAINMENUITEMS[$i]}" ${MAINMENUITEMY[$i]} $MAINMENUX
		}
		fi
	}
	done
	
	FRAMEUPDATED=1
}

function SetMainMenuSelection()
{
	if [ -z "$1" ]; then
	{
		return 1
	}
	fi
	
	if [ $1 -lt 0 ] || [ $1 -ge $MAINMENUITEMCOUNT ]; then
	{
		return 1
	}
	fi

	if [ $1 -eq $MAINMENUSELECTION ]; then
	{
		return 0
	}
	fi
	
	printf "\e[%d;%dH${MAINMENUITEMNOTSEL}${MAINMENUITEMS[$MAINMENUSELECTION]}" ${MAINMENUITEMY[$MAINMENUSELECTION]} $MAINMENUX
	MAINMENUSELECTION=$1
	printf "\e[%d;%dH${MAINMENUITEMSELECT}${MAINMENUITEMS[$MAINMENUSELECTION]}" ${MAINMENUITEMY[$MAINMENUSELECTION]} $MAINMENUX
	FRAMEUPDATED=1

	return 0
}

function ChangeMainMenuSelectionUp()
{
	local NEXTITEM=$MAINMENUSELECTION
	
	if [ $NEXTITEM -eq 0 ]; then
	{
		NEXTITEM=$(($MAINMENUITEMCOUNT - 1))
	}
	else
	{
		NEXTITEM=$(($NEXTITEM - 1))
	}
	fi
	
	SetMainMenuSelection $NEXTITEM
}

function ChangeMainMenuSelectionDown()
{
	local NEXTITEM=$MAINMENUSELECTION
	
	if [ $NEXTITEM -eq $(($MAINMENUITEMCOUNT - 1)) ]; then
	{
		NEXTITEM=0
	}
	else
	{
		NEXTITEM=$(($NEXTITEM + 1))
	}
	fi
	
	SetMainMenuSelection $NEXTITEM
}

function GameSetCurrentBlock()
{
	case $GAMECURRENT in
		0) GAMECURRENTARRAY=("${BLK1ARRAY[@]}");;
		1) GAMECURRENTARRAY=("${BLK2ARRAY[@]}");;
		2) GAMECURRENTARRAY=("${BLK3ARRAY[@]}");;
		3) GAMECURRENTARRAY=("${BLK4ARRAY[@]}");;
		4) GAMECURRENTARRAY=("${BLK5ARRAY[@]}");;
		5) GAMECURRENTARRAY=("${BLK6ARRAY[@]}");;
		6) GAMECURRENTARRAY=("${BLK7ARRAY[@]}");;
	esac

	GAMEBLOCKX=$(($TBASHOFFSETX + ($GAMEBLOCKSIZE * 2) - 2))
	GAMEBLOCKY=$TBASHOFFSETY
	GAMEBLOCKAPX=3
	GAMEBLOCKAPY=0
}

function GameDrawCurrentBlock()
{
	local BLAPOS=0

	for((i=0; i<GAMEBLOCKSIZE; i++)); do
	{
		for((j=0; j<GAMEBLOCKSIZE; j++)); do
		{
			BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
			
			case ${GAMECURRENTARRAY[$BLAPOS]} in
				1) printf "\e[%d;%dH${BLK1}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				2) printf "\e[%d;%dH${BLK2}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				3) printf "\e[%d;%dH${BLK3}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				4) printf "\e[%d;%dH${BLK4}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				5) printf "\e[%d;%dH${BLK5}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				6) printf "\e[%d;%dH${BLK6}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				7) printf "\e[%d;%dH${BLK7}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
			esac
		}
		done
	}
	done

	FRAMEUPDATED=1
}

function GameClearCurrentBlock()
{
	local BLAPOS=0

	for((i=0; i<GAMEBLOCKSIZE; i++)); do
	{
		for((j=0; j<GAMEBLOCKSIZE; j++)); do
		{
			BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
			
			case ${GAMECURRENTARRAY[$BLAPOS]} in
				1) printf "\e[%d;%dH\e[0m  \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				2) printf "\e[%d;%dH\e[0m  \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				3) printf "\e[%d;%dH\e[0m  \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				4) printf "\e[%d;%dH\e[0m  \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				5) printf "\e[%d;%dH\e[0m  \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				6) printf "\e[%d;%dH\e[0m  \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
				7) printf "\e[%d;%dH\e[0m  \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
			esac
		}
		done
	}
	done

	FRAMEUPDATED=1
}

function GameGenerateBlock()
{
	GAMECURRENTROT=0
	GAMECURRENT=$GAMENEXT
	GAMENEXT=$(($RANDOM % 7))
	GameSetCurrentBlock
	GameDrawCurrentBlock
	HUDUpdateNext
}

function GameCommitBlock()
{
	local BLAPOS=0
	local BLKX=0
	local BLKY=0

	for((i=0; i<GAMEBLOCKSIZE; i++)); do
	{
		for((j=0; j<GAMEBLOCKSIZE; j++)); do
		{
			BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))			
			BLKX=$(($j + $GAMEBLOCKAPX))			
			BLKY=$(($i + $GAMEBLOCKAPY))			

			if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then
			{
				continue
			}
			fi
			
			if [ $BLKY -gt $(($TBASHH - 1)) ]; then
			{
				continue	
			}
			fi

			if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then
			{
				if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX))]} -gt 0 ]; then
				{
					GAMEFAILURE=1
				}
				fi

				TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX))]=${GAMECURRENTARRAY[$BLAPOS]}
			}
			fi
		}
		done
	}
	done
	
	if [ $GAMEFAILURE -eq 0 ]; then
	{
		GAMESCORE=$(($GAMESCORE + 1))
		HUDUpdateScore
	}
	fi
}

function GameEraseLine()
{
	local BLAPOS=0
	local YPOSSTART=0

	if [ -z "$1" ]; then
	{
		return 0
	}
	fi

	YPOSSTART=$1

	if [ $1 -gt $(($TBASHH - 1)) ]; then
	{
		return 0
	}
	fi

	for((k=YPOSSTART; k>0; k--)); do
	{
		for((j=0; j<TBASHW; j++)); do
		{
			BLAPOS=$((($k * $TBASHW) + $j))
			TBASHARRAY[$BLAPOS]=${TBASHARRAY[$(($BLAPOS - $TBASHW))]}
		}
		done
	}
	done

	return 1
}

function GameClearLines()
{
	local BLAPOS=0

	for((i=0; i<GAMELINESTOCLEAR; i++)); do
	{
		GameEraseLine ${GAMELINESBUFFER[$i]}
	}
	done

	DrawTetriBashArrayEx
	GAMESCORE=$(($GAMESCORE + (($GAMELINESTOCLEAR * ($GAMELEVEL + 1)) * ($GAMESCOREMULT * ($GAMELEVEL + 1)))))
	GAMELINES=$(($GAMELINES + $GAMELINESTOCLEAR))
	GAMELEVELLINES=$(($GAMELEVELLINES + $GAMELINESTOCLEAR))	
	if [ $GAMELEVELLINES -ge $GAMELINESPERLEVEL ] && [ $GAMELEVEL -lt 10 ]; then
	{
		GAMELEVELLINES=$(($GAMELEVELLINES - $GAMELINESPERLEVEL))
		GAMELEVEL=$(($GAMELEVEL + 1))
		GAMESCOREMULT=$(($GAMESCOREMULTDEF + ($GAMELEVEL * $GAMESCOREMULTINC)))
		GAMEINTERVAL=$(echo "$GAMEINTERVAL - 0.03" | bc)
		HUDUpdateLevel
	}
	fi
	HUDUpdateScore
	HUDUpdateLines
}

function GameDetectLines()
{
	local BLAPOS=0
	local BLKCOUNT=0
	local LINECLEARS=0

	ZeroLinesBuffer	
	
	for((i=0; i<TBASHH; i++)); do
	{
		BLKCOUNT=0
		for((j=0; j<TBASHW; j++)); do
		{
			BLAPOS=$((($i * $TBASHW) + $j))
			
			if [ ${TBASHARRAY[$BLAPOS]} -gt 0 ]; then
			{
				BLKCOUNT=$(($BLKCOUNT + 1))
			}
			fi
		}
		done
		
		if [ $BLKCOUNT -eq $TBASHW ]; then
		{
			GAMELINESBUFFER[$LINECLEARS]=$i
			LINECLEARS=$(($LINECLEARS + 1))
		}
		fi
	}
	done

	if [ $LINECLEARS -gt 0 ]; then
	{
		GAMELINESTOCLEAR=$LINECLEARS
		GAMECLEARINPROGRESS=1
		ACCUMULATOR="0.0"
		GameDrawLineClear
		return 1
	}
	fi

	return 0
}

function GameDrawLineClear()
{
	local BLAPOS=0

	for((i=0; i<GAMELINESTOCLEAR; i++)); do
	{
		for((j=0; j<TBASHW; j++)); do
		{
			BLAPOS=$(((${GAMELINESBUFFER[$i]} * $TBASHW) + $j))
			printf "\e[%d;%dH${GAMECLEARCHAR}${GAMECLEARCHAR}\e[0m" $(($TBASHOFFSETY + ${GAMELINESBUFFER[$i]})) $(($TBASHOFFSETX + ($j * 2)))
		}
		done
	}
	done
	
	FRAMEUPDATED=1
}

function GameCheckMoveLeft()
{
	local BLAPOS=0
	local BLKX=0
	local BLKY=0

	for((i=0; i<GAMEBLOCKSIZE; i++)); do
	{
		for((j=0; j<GAMEBLOCKSIZE; j++)); do
		{
			BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))			
			BLKX=$(($j + $GAMEBLOCKAPX))			
			BLKY=$(($i + $GAMEBLOCKAPY))			

			if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then
			{
				continue
			}
			fi

			if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then
			{
				
				if [ $(($BLKX - 1)) -lt 0 ]; then
				{
					return 0
				}
				fi

				if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX - 1))]} -gt 0 ]; then
				{
					return 0
				}
				fi
			}
			fi
		}
		done
	}
	done

	return 1
}

function GameCheckMoveRight()
{
	local BLAPOS=0
	local BLKX=0
	local BLKY=0

	for((i=0; i<GAMEBLOCKSIZE; i++)); do
	{
		for((j=0; j<GAMEBLOCKSIZE; j++)); do
		{
			BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))			
			BLKX=$(($j + $GAMEBLOCKAPX))			
			BLKY=$(($i + $GAMEBLOCKAPY))			

			if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then
			{
				continue
			}
			fi

			if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then
			{
				
				if [ $(($BLKX + 1)) -gt $(($TBASHW - 1)) ]; then
				{
					return 0
				}
				fi
				
				if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX + 1))]} -gt 0 ]; then
				{
					return 0
				}
				fi
			}
			fi
		}
		done
	}
	done

	return 1
}

function GameCheckMoveDown()
{
	local BLAPOS=0
	local BLKX=0
	local BLKY=0

	for((i=0; i<GAMEBLOCKSIZE; i++)); do
	{
		for((j=0; j<GAMEBLOCKSIZE; j++)); do
		{
			BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))			
			BLKX=$(($j + $GAMEBLOCKAPX))			
			BLKY=$(($i + $GAMEBLOCKAPY))			

			if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then
			{
				continue
			}
			fi

			if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then
			{	
				if [ $(($BLAPOS + $GAMEBLOCKSIZE)) -lt $GAMEBLOCKAREA ]; then
				{
					if [ ${GAMECURRENTARRAY[$(($BLAPOS + $GAMEBLOCKSIZE))]} -gt 0 ]; then
					{
						continue
					}
					fi
				}
				fi

				if [ $(($BLKY + 1)) -gt $(($TBASHH - 1)) ]; then
				{
					return 0
				}
				fi

				if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX + $TBASHW))]} -gt 0 ]; then
				{
					return 0
				}
				fi
			}
			fi
		}
		done
	}
	done

	return 1
}

function GameMoveBlockLeft()
{
	GameCheckMoveLeft
	if [ $? -eq 1 ]; then
	{
		GameClearCurrentBlock
		GAMEBLOCKAPX=$(($GAMEBLOCKAPX - 1))
		GAMEBLOCKX=$(($GAMEBLOCKX - 2))
		GameDrawCurrentBlock
	}
	fi
}

function GameMoveBlockRight()
{
	GameCheckMoveRight
	if [ $? -eq 1 ]; then
	{
		GameClearCurrentBlock
		GAMEBLOCKAPX=$(($GAMEBLOCKAPX + 1))
		GAMEBLOCKX=$(($GAMEBLOCKX + 2))
		GameDrawCurrentBlock
	}
	fi
}

function GameMoveBlockDown()
{
	if [ ! -z "$1" ]; then
	{
		if [ $1 -eq 1 ]; then
		{
			if [ $GAMEFAILURE -eq 0 ]; then
			{
				ACCUMULATOR="0.0"
			}
			else
			{
				return
			}
			fi
		}
		fi
	}
	fi

	GameCheckMoveDown
	if [ $? -eq 1 ]; then
	{
		GameClearCurrentBlock
		GAMEBLOCKAPY=$(($GAMEBLOCKAPY + 1))
		GAMEBLOCKY=$(($GAMEBLOCKY + 1))
		GameDrawCurrentBlock
	}
	else
	{
		GameCommitBlock
		GameDetectLines
		if [ $? -eq 0 ]; then
		{
			GameGenerateBlock
		}
		fi
	}
	fi
}

function GameCheckRotate()
{
	local NEWROT=0
	local BLAPOS=0
	local BLKX=0
	local BLKY=0
	
	if [ -z "$1" ]; then
	{
		return 0
	}
	fi
	
	if [ $1 -eq 0 ]; then
	{
		if [ $GAMECURRENTROT -eq 0 ]; then
		{
			NEWROT=3
		}
		else
		{
			NEWROT=$(($GAMECURRENTROT - 1))
		}
		fi
	}
	else
	{
		if [ $GAMECURRENTROT -eq 3 ]; then
		{
			NEWROT=0
		}
		else
		{
			NEWROT=$(($GAMECURRENTROT + 1))
		}
		fi
	}
	fi

	ZeroBlockBuffer

	if [ $GAMECURRENT -eq 0 ]; then
	{
		case $NEWROT in
			0) GAMEBLOCKBUFFER=("${BLK1ARRAY[@]}");;
			1) GAMEBLOCKBUFFER=("${BLK1ARRAYR2[@]}");;
			2) GAMEBLOCKBUFFER=("${BLK1ARRAYR3[@]}");;
			3) GAMEBLOCKBUFFER=("${BLK1ARRAYR4[@]}");;
		esac
	}
	elif [ $GAMECURRENT -eq 1 ]; then
	{
		GAMEBLOCKBUFFER=("${BLK2ARRAY[@]}")
		return 1
	}
	elif [ $GAMECURRENT -eq 2 ]; then
	{
		case $NEWROT in
			0) GAMEBLOCKBUFFER=("${BLK3ARRAY[@]}");;
			1) GAMEBLOCKBUFFER=("${BLK3ARRAYR2[@]}");;
			2) GAMEBLOCKBUFFER=("${BLK3ARRAY[@]}");;
			3) GAMEBLOCKBUFFER=("${BLK3ARRAYR3[@]}");;
		esac
	}
	elif [ $GAMECURRENT -eq 3 ]; then
	{
		case $NEWROT in
			0) GAMEBLOCKBUFFER=("${BLK4ARRAY[@]}");;
			1) GAMEBLOCKBUFFER=("${BLK4ARRAYR2[@]}");;
			2) GAMEBLOCKBUFFER=("${BLK4ARRAY[@]}");;
			3) GAMEBLOCKBUFFER=("${BLK4ARRAYR2[@]}");;
		esac
	}
	elif [ $GAMECURRENT -eq 4 ]; then
	{
		case $NEWROT in
			0) GAMEBLOCKBUFFER=("${BLK5ARRAY[@]}");;
			1) GAMEBLOCKBUFFER=("${BLK5ARRAYR2[@]}");;
			2) GAMEBLOCKBUFFER=("${BLK5ARRAY[@]}");;
			3) GAMEBLOCKBUFFER=("${BLK5ARRAYR2[@]}");;
		esac
	}
	elif [ $GAMECURRENT -eq 5 ]; then
	{
		case $NEWROT in
			0) GAMEBLOCKBUFFER=("${BLK6ARRAY[@]}");;
			1) GAMEBLOCKBUFFER=("${BLK6ARRAYR2[@]}");;
			2) GAMEBLOCKBUFFER=("${BLK6ARRAYR3[@]}");;
			3) GAMEBLOCKBUFFER=("${BLK6ARRAYR4[@]}");;
		esac
	}
	elif [ $GAMECURRENT -eq 6 ]; then
	{
		case $NEWROT in
			0) GAMEBLOCKBUFFER=("${BLK7ARRAY[@]}");;
			1) GAMEBLOCKBUFFER=("${BLK7ARRAYR2[@]}");;
			2) GAMEBLOCKBUFFER=("${BLK7ARRAYR3[@]}");;
			3) GAMEBLOCKBUFFER=("${BLK7ARRAYR4[@]}");;
		esac
	}
	fi

	for((i=0; i<GAMEBLOCKSIZE; i++)); do
	{
		for((j=0; j<GAMEBLOCKSIZE; j++)); do
		{
			BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))			
			BLKX=$(($j + $GAMEBLOCKAPX))			
			BLKY=$(($i + $GAMEBLOCKAPY))

			if [ ${GAMEBLOCKBUFFER[$BLAPOS]} -gt 0 ]; then
			{	
				if [ $BLKY -gt $(($TBASHH - 1)) ] || [ $BLKX -gt $(($TBASHW - 1)) ] || [ $BLKX -lt 0 ]; then
				{
					return 0
				}
				fi

				if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX))]} -gt 0 ]; then
				{
					return 0
				}
				fi
			}
			fi
		}
		done
	}
	done
	
	GAMECURRENTROT=$NEWROT
	return 1
}

function GameRotateBlockLeft()
{
	GameCheckRotate 0
	if [ $? -eq 1 ]; then
	{
		GameClearCurrentBlock
		GAMECURRENTARRAY=("${GAMEBLOCKBUFFER[@]}")
		GameDrawCurrentBlock
	}
	fi
}

function GameRotateBlockRight()
{
	GameCheckRotate 1
	if [ $? -eq 1 ]; then
	{
		GameClearCurrentBlock
		GAMECURRENTARRAY=("${GAMEBLOCKBUFFER[@]}")
		GameDrawCurrentBlock
	}
	fi
}

function InitGame()
{
	GAMESCORE=0
	GAMELEVEL=0
	GAMELINES=0
	GAMEFAILURE=0
	GAMEFAILURECOUNT=0
	GAMEOVERINPROGRESS=0
	GAMECLEARINPROGRESS=0
	GAMELINESTOCLEAR=0
	GAMESCOREMULT=$(($GAMESCOREMULTDEF + ($GAMELEVEL * $GAMESCOREMULTINC)))
	GAMECURRENT=$(($RANDOM % 7))
	GAMENEXT=$(($RANDOM % 7))
	GAMEINTERVAL="0.5"
	ACCUMULATOR="0.0"
	
	ZeroTetriBashArray
	DrawTetriBashArray
	GameSetCurrentBlock
	GameDrawCurrentBlock
}

function SetGameStateMenu()
{
	TETRIBASHSTATE=1
	GAMERUNNING=0
	clear
	DrawTetriBashTitle
	DrawTetriBashMainMenu
	DrawTetriBashMenuDecor
	DrawTetriBashVersionString
}

function SetGameStatePlay()
{
	clear
	TETRIBASHSTATE=2
	GAMERUNNING=1
	InitGame
	DrawTetriBashHUD
}

function SetGameStateAbout()
{
	clear
	TETRIBASHSTATE=3
	GAMERUNNING=0
	DrawTetriBashTitle
	DrawTetriBashVersionString
	DrawBorder $TBASHABOUTX $TBASHABOUTY $TBASHABOUTW $TBASHABOUTH
	printf "\e[%d;%dH\e[1;32m${TETRIBASHINFO}\e[0m" $(($TBASHABOUTY + 1)) $(($TBASHABOUTX + 1))
	printf "\e[%d;%dH\e[1;32m${TETRIBASHINFO2}\e[0m" $(($TBASHABOUTY + 2)) $(($TBASHABOUTX + 1))
	printf "\e[%d;%dH\e[1;32m${TETRIBASHINFO3}\e[0m" $(($TBASHABOUTY + 4)) $(($TBASHABOUTX + 1))
}

function SetGameStatePause()
{
	clear
	TETRIBASHSTATE=4
	GAMERUNNING=0
}

function SetGameStateExit()
{
	clear
	TETRIBASHSTATE=0
	GAMERUNNING=0
}

function ExecuteMainMenuSelection()
{
	case $MAINMENUSELECTION in
		0) SetGameStatePlay;;
		2) SetGameStateAbout;;
		3) SetGameStateExit;;
	esac
}


#=============================================================================
#-----------------------------------------------------------------------------
# [ TetriBASH Script ]
#-----------------------------------------------------------------------------
#=============================================================================
# Clear Screen
clear
stty -echo -icanon time 0 min 0

SetGameStateMenu

# Game Loop
while true; do
{
	TIMESTART=$(date +%s.%N)	

	KEY=$(dd bs=1 count=1 2> /dev/null; echo ".")
	KEY=${KEY%.}
	if [ $TETRIBASHSTATE -eq 1 ]; then
	{
		case $KEY in
			q) SetGameStateExit;;
			w) ChangeMainMenuSelectionUp;;
			a) ChangeMainMenuSelectionUp;;
			s) ChangeMainMenuSelectionDown;;
			d) ChangeMainMenuSelectionDown;;
			k) ExecuteMainMenuSelection;;
			# ?) printf "$KEY" ;;
		esac
	}
	elif [ $TETRIBASHSTATE -eq 2 ]; then
	{
		if [ $GAMERUNNING -eq 1 ]; then
		{
			if [ $GAMECLEARINPROGRESS -eq 1 ]; then
			{
				case $KEY in
					q) SetGameStateMenu;;
				esac

				if [[ $(echo "if (${ACCUMULATOR} > ${GAMECLEARINTERVAL}) 1" | bc) -eq 1 ]]; then
				{
					GameClearLines
					GAMECLEARINPROGRESS=0
					GAMELINESTOCLEAR=0
					GameGenerateBlock
				}
				fi
			}
			elif [ $GAMEOVERINPROGRESS -eq 1 ]; then
			{
				case $KEY in
					q) SetGameStateMenu;;
				esac

				if [[ $(echo "if (${ACCUMULATOR} > ${GAMEOVERINTERVAL}) 1" | bc) -eq 1 ]]; then
				{
					SetGameStateMenu
				}
				fi
			}
			else
			{
				case $KEY in
					q) SetGameStateMenu;;
					w) DrawTetriBashArray;;
					a) GameMoveBlockLeft;;
					s) GameMoveBlockDown 1;;
					d) GameMoveBlockRight;;
					j) GameRotateBlockLeft;;
					l) GameRotateBlockRight;;
					# ?) printf "%d\n" "'$KEY" ;;
				esac

				if [[ $(echo "if (${ACCUMULATOR} > ${GAMEINTERVAL}) 1" | bc) -eq 1 ]]; then
				{
					GameMoveBlockDown
					if [ $GAMEFAILURE -eq 1 ]; then
					{
						GAMEFAILURECOUNT=$(($GAMEFAILURECOUNT + 1))
						if [ $GAMEFAILURECOUNT -eq $GAMEFAILUREMAX ]; then
						{
							GAMEOVERINPROGRESS=1
							ACCUMULATOR="0.0"
							GameOverClearTetriBashArray
							DrawTetriBashArray
							HUDDrawGameOver
						}
						fi
						GAMEINTERVAL=$(echo "$GAMEINTERVAL - 0.05" | bc)
					}
					fi
					ACCUMULATOR=$(echo "$ACCUMULATOR - $GAMEINTERVAL" | bc)
				}
				fi
			}
			fi
		}
		fi
	}
	elif [ $TETRIBASHSTATE -eq 3 ]; then
	{
		case $KEY in
			q) SetGameStateMenu;;
		esac
	}
	elif [ $TETRIBASHSTATE -eq 4 ]; then
	{
		case $KEY in
			q) SetGameStateExit ;;
			w) DrawTetriBashArray ;;
			a) DrawBorder 4 2 10 10 ;;
			s) DrawTetriBashHUD ;;
			d) DrawTetriBashTitle;;
			?) printf "%d\n" "'$KEY" ;;
		esac
	}
	else
	{
		break
	}
	fi

	if [ $FRAMEUPDATED -eq 1 ]; then
	{
		if [ $TETRIBASHDEBUG -eq 1 ]; then
		{	
			if [ $TETRIBASHSTATE -eq 2 ]; then
			{	
				printf "\e[1;2H\e[1;32mDebug:BlkPos(%d,%d) BlkTerm(%d,%d) Delta(%2.3g) Accu(%2.3g) LC(%d)      \e[0m" $GAMEBLOCKAPX $GAMEBLOCKAPY $GAMEBLOCKX $GAMEBLOCKY $DELTATIME $ACCUMULATOR $GAMECLEARINPROGRESS
			}
			fi
 		}
		fi
		printf "\e[1;1H"
		FRAMEUPDATED=0
	}
	fi

	TIMEEND=$(date +%s.%N)
	DELTATIME=$(echo "$TIMEEND - $TIMESTART" | bc)
	if [ $TETRIBASHSTATE -eq 2 ] && [ $GAMERUNNING -eq 1 ]; then
	{
		ACCUMULATOR=$(echo "$ACCUMULATOR + $DELTATIME" | bc)
	}
	fi
}
done

# Clean Up
printf "\e[0m"
clear
stty sane
exit 0

 

I attached the script file as well, just drop the .txt.

 

The controls are as follows:

K - Select menu item

Q - quit or back

WASD - menu nav and block movement

J and L - rotate piece

 

Don't hold down keys too long or the key buffer will sometimes fill up quicker than it gets emptied (does not seem to happen as quickly while running slower in a VM) .

Attached Thumbnails

  • tbash01.png
  • tbash02.png
  • tbash03.png
  • tbash04.png
  • tbash05.png
  • tbash06.png

Attached Files




#5001505 Impotant! Books to start learning video game programming ! I need it...

Posted by kd7tck on 16 November 2012 - 05:15 AM

If you are not a good programmer then you might want to get books that teach the languages themselves, not game architecture.

edit:
To other readers, please don't downvote beginner questions. It frightens them into not wanting to ask questions.


#4980172 C++, should I switch?

Posted by Telastyn on 14 September 2012 - 02:38 PM

Don't switch.

Experiment.


#4986477 Communicating with Programmers

Posted by BCullis on 03 October 2012 - 12:23 PM

Not really.  I mean, we usually just beep and whirr at each other because the data transfer and encoding is more efficient, but our human analog languages work just fine.

...

OK, but seriously, just be flexible and clear in requirements and questions.  The worst case answer to "I want to be able to do _____" is "that will take more resources than current computing can handle".  You don't need to know programming languages unless you'll be writing/reading code.  Having clear and relaxed conversations with your programming person/crew will tell you why certain things are or are not possible.  Otherwise you'll just need to trust them when they say "you can keep two of these ideas, but all three won't work well together".  I don't think I've ever been in a situation where I wished the other person knew a little more about programming, it's kind of part of the package as a code-writing team member to translate spoken and high-level requirements into specific pieces of code and design.


#4980301 C++, should I switch?

Posted by Hodgman on 15 September 2012 - 12:02 AM

C++ is the only sane language.

Once you know c++ there is no reason to use anything else. Unless of course you want the best speed possible in that case you would use assembly (sometimes I use it inline with c++ just for speed). As for making your own code for complicated things you can either have fun and do it yourself or use a third party library.

I tried learning JAVA, I decided it was just like c++ but slower and with too many rules.

C++ is by far my favorite language, but there's a lot of reasons to use other languages. It's incredibly self-harming to restrict yourself to a single language.

e.g. Some personal experiences:
* I want a really simple program to copy certain files from Windows directory A to directory B -- C++ is overkill, I can write this program in 30 seconds with Batch.
* I want to do some basic analysis of some data and display it in a simple table for my own use only -- C++ requires me to build a GUI and write a lot of boilerplate code. Instead I could write 10 lines of JavaScript and spit out HTML to a web-browser.
* I want to write some non-performance-critical gameplay code without worrying about memory management, and would like to use modern features such as closures (on platforms that don't yet have C++11 compilers), and dynamic code reloading (for fast iteration) -- I'll just use Lua.
* I'm doing a bunch of data-processing work, which requires me to be able to quickly iterate on GUIs, load XML files and write out binary streams, while making use of a lot of "standard" data structures. I don't care about memory usage or performance that much, I just want quick development time -- I'll use C#.
* I'm targeting a GPU -- I'll use HLSL, for obvious enough reasons.

Every programmer should learn as many languages as they can and put them in their toolbox. A bigger toolbox gives you more options so you're not hitting nails with a screwdriver...

As for performance, algorithmic optimisation and memory-layout optimisation are much more important than reducing cycles by outsmarting the compiler with manually written assmebly. It should be very rare that there's a need to use inline assembly (and in many of those cases, intrinsics can be a better option).


#5039024 Article Inspiration

Posted by Michael Tanczos on 04 March 2013 - 07:14 AM

We are going to be launching one of the biggest community efforts to build a comprehensive game development library of topics since our initial creation back in 1999.   Our goal is to ensure that we as a community can build a resource library that all game developers can use for years to come and is entirely free to use.   It will be fully tagged, easily searchable and should provide source code examples wherever possible.   The look of articles should be consistent and clean, almost like a book of sorts.

 

I'm looking for people who can help begin the process by suggesting article topics that you would expect a complete library of game development articles to have.   The skill range is from beginner to expert.   Literally I am asking for article topics that cover every facet of the development process.   Don't worry about checking to see if our archive already has these topics and don't worry about duplicating other ideas in this thread.   Initially for this forum we can list ideas in this thread and I'll combine them into a running list and cull out duplicates.  

 

Note:  The list below is being updated as people post new ideas so it will be constantly evolving over the life of this thread

 

Some topic ideas so far:

 

Physics

http://www.gamedev.net/topic/639778-article-topics-math-and-physics/

 

Math

http://www.gamedev.net/topic/639778-article-topics-math-and-physics/

 
 

Suggested Projects

http://www.gamedev.net/topic/639775-article-topics-suggested-projects/

 

Game Architecture

How to make a save system/replay system/undo-redo system

How to make effects that apply for some time (spells, power ups)

Introduction into scene traversal ( scene graphs, portals, ...)
Resource management ( real-time reloading of assets, load resources from archives during release builds,...)
Timestepping

Reinforcements of just how important state machines are in game development.

State machines in managing game state
State machines in managing object lifetime
State machines in game-style AI  (and the difference between machine learning and game AI)
State machines in animations
Frame independent movement and fixed time-steps
Logging systems
Message bus/ global event systems
Local event systems
Hooks into scripting systems
Hooks into animation systems
Hooks into asynchronous systems
Hooks into OS systems
Hooks into existing libraries
Serialization and IO: How to serialize and deserialize data
Serialization and IO: Applications of serialization in save games and persistance
Serialization and IO: Applications of serialization in interprocess communication
Serialization and IO: Applications of serialization in local multiplayer games.
Serialization and IO: Applications of serialization in networked games.
 
APIs and Tools

The major 2D frameworks and hardware abstraction layers: SDL, Allegro, SFML

All the 3D engines: Unity, Ogre, Irrlicht, etc.

All the cross-platform mobile game frameworks: Corona, cocos2d-x, Marmalade, etc.

All of the physics engines: Bullet, Box2d, Chipmunk, etc.

 

Game Programming

Beginner's Guide to Game Programming

How do I Make Games?  

How Sprite Animation Works

Working with Sprite Sheets

Multithreading - Not the low level stuff but effective uses in game development (for example demo showing how to correctly separate the render thread from main thread)
Introduction into sound programming
Introduction into cross platform development ( how to use make files etc)
Introduction into localization

2D / 3D Resolution Independence

Using asynchronous calls from the OS and other libraries
Using scripting libraries
Why scripting languages are useful
Incorporating scripting engines into your game
Grab-bag of useful techniques, such as auto-reloading of resources, in-game tuning, live patching of a running process, and much more.
 
 
 

Game Design

Creating a Game Design Document

Character Design

Genres of gameplay
Evolution of games
Implementation systems for introducing stories into games
Achievement systems (technical side of "how to implement them" and design side "why and how to include them")
Punishment systems (how to teach meta-game/rules etc)
Goals and motivation (short-term: collect coins/defeat enemies, mid-term: reach level exit as fast as possible, long-term goals: rescue princess)
Feedback! (make users aware of every important state, acknowledge input, make aware of options etc.)
Onion layer model (core game, meta game, tokens, ...)
 
Lighting
Realistic / non-realistic shaders
Global illumination techniques (at least an overview and a few pointers to techniques used in specific games)
Shadow maps
basic algorithm explained in exhaustive detail (explain everything, make no assumptions)
exponential shadow mapping (current state of the art - explain everything)
variance shadow mapping (current state of the art - explain everything)
 
 

Writing

Lexicon of common game terms (with translations for localization) with easy downloading

Creative writing for games
Technical writing for games 
Writing spoken dialogue for games
Story writing and narration

How to develop background stories for games.

 

Program Design 
Design patterns and antipatterns
DIY vs Libraries.  Why libraries are usually better, and why you still need to know what is inside.
Basic game code architectures (for projects of different types and sizes, to give an idea of how to organize all that code and data)
How to keep code error free (simple stuff like logging or asserts or watever)
Security measures for protecting games from piracy
Importance of commenting code
 
CPU, Memory and Performance Optimizations
Introduction into SIMD programming
Introduction into memory management (for example allocation tracking, how to use dlmalloc, virtual memory,... )
Introduction into optimization (performance)
Introduction into programming tools ( profilers, graphics debuggers, ... )
Memory optimizations ( reduce total used memory, access patterns,...)
Basics of all hardware: the system bus; relative time between the CPU, cache, ram, and storage; cpu instructions; cycles; etc.
What we HAD twenty years ago (aka: what many books teach) and what we HAVE today.
Basics of modern hardware architecture, including long pipelines, multi-instruction decoding, out-of-order cores, speculative execution, etc.
Optimizations that used to make sense decades ago, but no longer do, and why.
 
Project Management (?)
Introduction to Revision Control Systems
Source version control: Git
Source version control: Subversion
Quality Assurance and Bug Testing
Managing Beta Testers
Refactoring
Debugging
Profiling
Optimizing
Automated Build systems
Tools development
Tools pipeline
How to work with teams remotely for game projects.

How to improve your communication skills for developers and designers.

Project management for games, Agile, PMP, etc...

 
User Interfaces
Building menus and controls of various kinds
How to make remappable keys
 
AI

http://www.gamedev.net/topic/640115-suggested-topics-artificial-intelligence/

 
Data Structures & Algorithms
Algorithms: Classification
Algorithms: Basics of complexity.  Understanding Big-O. Learning what is fast, what is slow, and what is impossible.
Algorithms: Divide and conquer, recursion, tree traversal
Algorithms: Assorted sorting routines, from bubble sort to quicksort, radix sort, mergesort, and shell sort, and why sometimes it is best to use an atypical sorting routine
Algorithms: Searching routines: sequential, binary search, binary search trees, indirect binary searches, trees, balanced trees, 
Algorithms: String processing
Algorithms: Pattern matching and regular expressions
Algorithms: Graph searching, depth-first and breadth first, both recursive and nonrecursive.
Algorithms: Range searching
Algorithms: Geometric algorithms
Algorithms: Closest point
Algorithms: Geometric intersections (point/triangle, point/sphere, ray/sphere, ray/tri, tri/tri, tri/sphere, etc)
Algorithms: Finding a convex hull.
Algorithms: kD searching and spatial grids
Data Structures: Arrays and linked lists.
Data Structures: Stacks and queues.
Data Structures: Trees and heaps and sets and maps.
Data Structures: Trees of all sorts (for searching, efficient storage of sparse data) - a language agnostic version along with some specific implementations
Data Structures: Graphs: cyclic and acyclic, directed and nondirectional
Data Structures: Trees and their relationship to graphs
Data Structures: Using 1D structures to represent kD spatial areas
Data Structures: Connectivity, weighted graphs, network flows, 
How to represent objects in code (creatures, buildings, inventory items...)
How to format your resources (images, settings, whatever, file or embedded in code etc.)
Fundamental data types and composite objects.  Why we need both.
Producer/Consumer models
Applications of producer/consumer models
Compiler theory
Operating systems
Formal languages
Parallel processing
Theory of parallel processing
Basic parallel systems like master/workers and trivially parallel problems, parallel search
More advanced parallel algorithms; parallel sort, parallel communication, load balancing
Dynamic programming
 
Multiplayer Programming
 
Game Art

Lighting/Shading

Perspective

Principles of animation

Figure Drawing/proportions

Color Theory

How is Game Art different?

Vector vs Raster (+ vs Pixel)

Assets vs concept art

Software

 

I'm keeping the initial list short because I'd like to get this topic out there and open to suggestions.




#5011815 A Few Words of Encouragement

Posted by mistervirtue on 17 December 2012 - 02:03 PM

I talked to my CIS professor a few days ago and she gave me a real nugget of wisdom I want to share with all of my fellow beginners here on gamedev. This is a quote from her e-mail she sent me.

"Programming is just like any other skill, if you want to be good at it you have to do it a lot. That being said you have to willing to be really bad it for awhile before you can see the fruits of you labor. Don't feel bad because you haven't made Baulder's Gate in one semester. Build upon small realistic goals. Just do the basics and gain a real understanding of the foundational skills. Work hard and work consistently and you will be great at whatever you want."

So I just want to say to everyone out there to keep trying and stay in good cheer, even when things get hard. Push through your obstacles and you will become the programmer you want to be. Keep working hard, you will be rewarded for it!


#4779551 reason i love my wife

Posted by Mike.Popoloski on 27 February 2011 - 12:27 AM

So what you're trying to tell us is that you love your wife because she's like 90% of the rest of the population, in that she's incapable of switching to any other interface than the one she's used to using. Maybe that's because you fall into the same category, and realize on an instinctual level that if she were much smarter than you maybe she wouldn't bother sticking around.


#4982194 Torque 3D Now Available on GitHub

Posted by DaveMB on 20 September 2012 - 05:42 PM

We have released Torque 3D under the MIT license on GitHub. We announced our intentions a little while ago, but now the repository is available to everyone. We had to do some final checking on some of the proprietary code before release. And now it is out the door!

Information about the repo and our community charter:
http://www.garagegames.com/community/blogs/view/21886

The GitHub repo location:
https://github.com/GarageGames/Torque3D

We would love to hear any feedback that you have!


#5043341 Am I a bad programmer?

Posted by L. Spiro on 15 March 2013 - 05:37 AM

I own memoryhacking.com and am a moderator at gamehacking.com.

 

The common theme is that when someone posts a tutorial, someone out there feels threatened and can’t accept growing young minds.

Those people need to hold their place of respect amongst the forum-goers (which is likely the only respect they have gotten yet) and need to bash in any way they can any new tutorials etc. that suddenly appear.

 

(I have been accused of needing to brush up on my psychology here.  Seriously?  How else do you think I got where I am?)

 

You need to ignore that crap and move on.  Frankly their reputations can be daunting, but with time you can surpass them, especially as your own knowledge grows.

 

That also does not mean your content is perfect.

A real-world example is when someone posted an auto-aim tutorial on gamehacking.com using Euler angles to calculate which direction to aim, to which I strongly wanted to reply with some advice on making that calculation easier to handle (use vectors).

But it’s okay for a tutorial to have a few flaws.  I have made flawed tutorials myself.  I let it go because beginners can probably relate to it better anyway.

Only people with inferiority issues complain about the little details, and it is nothing but a chance for them to show to everyone else on the forum how much more than you they know.

 

Don’t let it get to you.  You need to mainly realize when criticism is real and when it is just a power-play.  Some criticism can teach you.  Those people tend to seem more calm and try to shed their critiques in more positive light by trying to overshadow their negatives with positives, trying to give more compliments than criticism.

 

 

Ultimately you don’t need to worry about your own level regardless of what others say.

 

Firstly, I have made crap-tastic and utterly wrong tutorials or explanations myself, but I kept learning and later realized that for myself.

 

Everyone, including the highest-ranking members here, learns from ground zero.

You do too.

Don’t get too shaken up when someone says you are horrible.

The people who actually matter show more tact.

 

 

L. Spiro




PARTNERS