Sign in to follow this  

I think I'm a really bad programmer

This topic is 3627 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The title says it all, I think. Tell me if I'm wrong. Below is a bunch of code for a 2d shooter game that I made, it's called KnocKout. It's written in VS2005 using C++ and SDL version 1.2 (or 1.3) And if this helps I have about 2 years experience in C++ (but haven't been coding all of the time, took some quite long breaks every once in a while) and I have a few months experience in SDL. I want to know what you think about the code. Main.cpp
#include "lib.h" 

const int MAIN =  0; 
const int GAME =  1; 
const int SHOP =  2; 
const int HELP =  3; 
const int ABOUT = 4; 

SDL_Surface *screen = NULL; 
SDL_Surface *background = NULL;	 
SDL_Surface *tileSheet = NULL;  
SDL_Event event; 
SDL_Rect tileClips[TOTAL_TILE_TYPES]; 
Mix_Music *mainMusic = NULL; 
Mix_Music *battleMusic = NULL; 
CURSOR cursor; 
BUTTON button[TOTAL_OPT_BUTTON]; 
TILE *tile[TOTAL_TILES_LEVEL]; 
bool quit = false;			
bool playing = true;
bool battle = false; 
SDL_Rect camera; 
int bgFlag = MAIN; 
int atFlag = MAIN; 
PLAYER player; 


bool loadTileMap(string filename)
{
	int tileX = 0; 
	int tileY = 0; 
	int tileType = 0; 
	int tileCount = 0; 

	ifstream map(filename.c_str()); 
	if (!map)
	{
		ERR("Could not load tile map"); 
		return false; 
	}

	while (!map.eof())
	{
		map >> tileType; 

		if (tileType >= TILE_BUSH && tileType <= TILE_OCEANBLOCK)
		{
			tile[tileCount] = new TILE(tileX, tileY, tileType); 
			tileX += TILE_WIDTH; 
			tileCount++; 
		}
		else
		{
			ERR("Invalid tile type"); 
			map.close(); 
			return false; 
		}		  

		if (tileCount > TOTAL_TILES_LEVEL+1)
		{
			ERR("Limit of 240 tiles per map has been exceeded"); 
			map.close(); 
			return false; 
		}

		if (tileX >= LEVEL_WIDTH)
		{
			tileX = 0; 
			tileY += TILE_HEIGHT; 
		}
	}

	map.close(); 
	return true; 
}


int doGame()
{
	//move
	player.moveAvatar(camera, tile); 

	//blit
	for (int i = 0; i < TOTAL_TILES_LEVEL; i++)
	{
		if (tile[i] != NULL)
		{
			if (checkCollision(camera, tile[i]->getBox()))
			{
				tile[i]->showTile(camera, tileSheet, tileClips, screen); 
			}
		}
	}
 
	player.showAvatar(screen, camera); 
	return GAME_WON; 
}


bool doCreate()
{
	SDL_Init(SDL_INIT_EVERYTHING); 
	TTF_Init(); 
	Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 4096); 

	if ( (screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_SWSURFACE) ) == NULL)
	{
		ERR("Error at: SDL_SetVideoMode(...)"); 
		return false; 
	}

	if ( (background = loadSurface("main_background.png", false) ) == NULL)
	{
		ERR("Could not load 'main_background.png'"); 
		return false; 
	}

	if ( (tileSheet = loadSurface("tile.png", false) ) == NULL)
	{
		ERR("Could not load 'tile.png'");
		return false; 
	}

	if (cursor.setupCursor() == false)
	{
		ERR("Could not load 'cursor.png'"); 
		return false;
	}

	if ( (mainMusic = Mix_LoadMUS("music_main.mp3") ) == NULL)
	{
		ERR("Could not load 'music_main.mp3'"); 
		return false; 
	}

	if ( (battleMusic = Mix_LoadMUS("music_battle.mp3") ) == NULL)
	{
		ERR("Could not load 'music_battle.mp3'"); 
		return false; 
	}

	for (int y = 0; y < TOTAL_TILE_TYPES; y++)
	{
		tileClips[y].x = y * TILE_WIDTH; 
		tileClips[y].y = 0; 
		tileClips[y].w = TILE_WIDTH; 
		tileClips[y].h = TILE_HEIGHT; 
	}

	string title[TOTAL_OPT_BUTTON] =
	{
		"Play Game",
		"Character", 
		"Guide", 
		"About",
		"Quit", 
		"Ok", 
		"Next", 
		"Back",
		"1) Forest",
		"2) Grass", 
		"3) House", 
		"4) Space", 
		"5) Temple", 
		"6) Volcano", 
		"7) Lava", 
		"8) Void", 
		"9) Abyss", 
		"10) Sea", 
		"11) Dark", 
		"12) Hell", 
		"Buy", 
		"Sell"
	};

	for (int i = 0; i < TOTAL_OPT_BUTTON; i++)
	{
		if (button[i].createButton(265, 115 + (i * 100), title[i]) == false)
		{
			ERR("Error at: button[i].createButton(...)"); 
			return false; 
		}
	}

	if (player.createAvatar() == false)
	{
		ERR("Could not create player avatar"); 
		return false; 
	}

	camera.x = 0; 
	camera.y = 0; 
	camera.w = CAMERA_WIDTH; 
	camera.h = CAMERA_HEIGHT; 

	Mix_PlayMusic(mainMusic, -1); 
	SDL_WM_SetCaption("KnocKout", "icon1.ico"); 
	SDL_ShowCursor(SDL_DISABLE); 
	return true; 
}


void doQuit()
{
	for (int i = 0; i < TOTAL_TILES_LEVEL; i++)
	{
		if (tile[i] != NULL)
		{
			delete tile[i]; 
			tile[i] = NULL; 
		}
	}

	player.saveFile(); 

	SDL_FreeSurface(screen); 
	SDL_FreeSurface(background); 
	SDL_FreeSurface(tileSheet); 
	Mix_FreeMusic(mainMusic); 
	Mix_FreeMusic(battleMusic); 

	SDL_Quit();
	TTF_Quit(); 
	Mix_CloseAudio(); 
}


void doFrame()
{
	if (battle == false)
	{
		blitSurface(0, 0, background, screen, NULL); 
	}
	else
	{
		blitSurface(0, 0, background, screen, &camera); 
	}

	if (atFlag == MAIN)
	{
		if (bgFlag != MAIN)
		{
			SDL_FreeSurface(background); 
			background = loadSurface("main_background.png", false); 
			bgFlag = MAIN; 
		}

		for (int i = 0; i < 5; i++)
		{
			if (button[i].loopButton(event, screen) == BUTTON_ACTIVATED)
			{
				switch (i)
				{
				case 0:
					atFlag = GAME;	 
					Mix_HaltMusic(); 
					Mix_PlayMusic(battleMusic, -1); 
					break;

				case 1:
					atFlag = SHOP;
					break;

				case 2:
					atFlag = HELP; 
					break;

				case 3:
					atFlag = ABOUT; 
					break;

				case 4:
					{
						playing = false; 

						if (MessageBox(GetActiveWindow(), "Are you sure you want to quit? ", "Quit?", MB_YESNO) == IDYES)
						{
							quit = true; 
						}

						playing = true; 
					}
					break;
				}
			}
		}
	}

	else if (atFlag == GAME)
	{
		static int mapNumber = 0; 

		if (bgFlag == GAME && battle == true)
		{
			SDL_FreeSurface(background); 
			background = loadSurface("game_background.png", false); 
		
			switch (doGame())
			{
			case GAME_WON:
				break;

			case GAME_LOST:
				break;
			}
		}

		if (bgFlag != GAME && battle == false)
		{
			SDL_FreeSurface(background); 
			background = loadSurface("gamemenu_background.png", false); 
			bgFlag = GAME; 
		}

		if (battle == false)
		{ 
			button[8].setPosition(40, 215); 
			button[9].setPosition(40, 315); 
			button[10].setPosition(40, 415); 
			button[11].setPosition(40, 515); 
			button[12].setPosition(290, 215); 
			button[13].setPosition(290, 315); 
			button[14].setPosition(290, 415); 
			button[15].setPosition(290, 515); 
			button[16].setPosition(540, 215); 
			button[17].setPosition(540, 315); 
			button[18].setPosition(540, 415); 
			button[19].setPosition(540, 515); 

			for (int show = 8; show < 20; show++)
			{
				if (button[show].loopButton(event, screen) == BUTTON_ACTIVATED)
				{
					mapNumber = show - 8; 
					string mapNames[TOTAL_MAPS] = 
					{
						"map_forest.map", 
						"map_grassland.map", 
						"map_house.map", 
						"map_space.map", 
						"map_temple.map", 
						"map_volcano.map", 
						"map_lava.map", 
						"map_void.map", 
						"map_abyss.map", 
						"map_sea.map", 
						"map_darkness.map", 
						"map_hell.map"
					}; 

					if (loadTileMap(mapNames[mapNumber].c_str()) == true)
					{
						battle = true; 
					}
					else
					{
						ERR("Could not load tile map for selected map"); 
					}  
				}
			}
		}
	}

	else if (atFlag == SHOP)
	{
	}

	else if (atFlag == HELP)
	{
		static int page = 1; 

		if (bgFlag != HELP)
		{
			SDL_FreeSurface(background); 
			background = loadSurface("guide_background_1.png", false); 
			bgFlag = HELP; 
		}
		
		button[6].setPosition(450, 470); 
		button[7].setPosition(200, 470); 

		if (page < 4)
		{
			if (button[6].loopButton(event, screen) == BUTTON_ACTIVATED)
			{
				page++; 
				char location[32]; 
				sprintf(location, "guide_background_%d.png", page); 
				SDL_FreeSurface(background); 
				background = loadSurface(location, false); 
			}
		}

		if (page > 1)
		{
			if (button[7].loopButton(event, screen) == BUTTON_ACTIVATED)
			{
				page--; 
				char location[32]; 
				sprintf(location, "guide_background_%d.png", page); 
				SDL_FreeSurface(background); 
				background = loadSurface(location, false); 
			}
		}

		if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN)
		{
			page = 1; 
			atFlag = MAIN; 
		}
	}

	else if (atFlag == ABOUT)
	{
		if (bgFlag != ABOUT)
		{
			SDL_FreeSurface(background); 
			background =  loadSurface("about_background.png", false); 
			bgFlag = ABOUT; 
		}

		button[5].setPosition(265, 450); 
		if (button[5].loopButton(event, screen) == BUTTON_ACTIVATED)
		{
			atFlag = MAIN; 
		}
	}

	cursor.showCursor(screen); 
	SDL_Flip(screen); 
	Sleep(1000 / FRAMES_PER_SECOND); 
}


int main(int argc, char *argv[])
{
	if (doCreate() == false)
	{
		return 1; 
	}

	player.loadFile(); 

	while (quit == false)
	{
		while (SDL_PollEvent(&event))
		{
			cursor.handleInput(event); 
			player.handleInput(event); 
			if (event.type == SDL_QUIT)
			{
				playing = false; 

				if (MessageBox(GetActiveWindow(), "Are you sure you want to quit? ", "Quit?", MB_YESNO) == IDYES)
				{
					quit = true; 
				}		   

				playing = true; 
			}

			else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)
			{
				playing = false; 

				if (MessageBox(GetActiveWindow(), "Are you sure you want to quit? ", "Quit?", MB_YESNO) == IDYES)
				{
					quit = true; 
				}

				playing = true; 
			}
		}

		if (playing)
		{
			doFrame(); 
		}
	}

	doQuit();
	return 0; 
}




Function.cpp
#include "lib.h" 


SDL_Surface *loadSurface(char *filename, bool useColorKeying)
{
	SDL_Surface *loadedImage = NULL; 
	SDL_Surface *optimizedImage = NULL; 
	loadedImage = IMG_Load(filename); 

	if (loadedImage == NULL)
	{
		char debug[32];
		sprintf(debug, "debug/%s", filename); 
		loadedImage = IMG_Load(debug); 
	}
	
	if (loadedImage == NULL)
	{
		char release[32]; 
		sprintf(release, "release/%s", filename); 
		loadedImage = IMG_Load(release); 
	}

	if (loadedImage != NULL)
	{
		if (useColorKeying)
		{
			Uint32 colorKey = SDL_MapRGB(loadedImage->format, 0, 0, 0); 
			SDL_SetColorKey(loadedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorKey); 
		}
	}

	optimizedImage = SDL_DisplayFormat(loadedImage); 
	SDL_FreeSurface(loadedImage); 
	return optimizedImage; 
}


void blitSurface(int x, int y, SDL_Surface *src, SDL_Surface *dest, SDL_Rect *clips)
{
	SDL_Rect offsets; 
	offsets.x = x; 
	offsets.y = y; 

	SDL_BlitSurface(src, clips, dest, &offsets); 
}


bool checkCollision(SDL_Rect boxA, SDL_Rect boxB)
{
	int topA, topB; 
	int bottomA, bottomB; 
	int leftA, leftB; 
	int rightA, rightB; 

	topA = boxA.y; 
	topB = boxB.y; 
	bottomA = boxA.y + boxA.h; 
	bottomB = boxB.y + boxB.h; 
	leftA = boxA.x; 
	leftB = boxB.x; 
	rightA = boxA.x + boxA.w; 
	rightB = boxB.x + boxB.w; 

	if ( (bottomA <= topB) || (topA >= bottomB) || (rightA <= leftB) || (leftA >= rightB) )
	{
		return false; 
	}
	return true; 
}


bool touchesWall(SDL_Rect box, TILE *tiles[])
{
	for (int i = 0; i < TOTAL_TILES_LEVEL; i++)
	{
		if (tiles[i] != NULL)
		{
			if (tiles[i]->getType() == TILE_BUSH || tiles[i]->getType() == TILE_GRAYBLOCK || tiles[i]->getType() == TILE_OCEANBLOCK)    
			{
				if (checkCollision(box, tiles[i]->getBox()))
				{
					return true; 
				}
			}
		}
	}
	return false;
}



Define.h


#define FRAMES_PER_SECOND 80

#define GAME_WON          70
#define GAME_LOST         71

#define AVATAR_PLAYER     1
#define AVATAR_COMPUTER   2
#define AVATAR_UNDEFINED  3

#define AVATAR_WIDTH      50
#define AVATAR_HEIGHT     50

#define DIRECTION_NORTH   0
#define DIRECTION_EAST    1
#define DIRECTION_SOUTH   2
#define DIRECTION_WEST    3
#define DIRECTION_NONE    10

#define SCREEN_WIDTH      800
#define SCREEN_HEIGHT     600

#define LEVEL_WIDTH       1280
#define LEVEL_HEIGHT      768

#define BATTLEMENU_WIDTH  800
#define BATTLEMENU_HEIGHT 200

#define CAMERA_WIDTH      800
#define CAMERA_HEIGHT      600

#define TOTAL_MAPS        12  
#define TOTAL_OPT_BUTTON  22

#define MAP_FOREST        0
#define MAP_GRASSLAND     1
#define MAP_HOUSE         2	 
#define MAP_SPACE         3
#define MAP_TEMPLE        4
#define MAP_VOLCANO       5
#define MAP_LAVA          6
#define MAP_VOID          7
#define MAP_ABYSS         8
#define MAP_SEA           9
#define MAP_DARKNESS      10
#define MAP_HELL          11

#define CURSOR_WIDTH      30
#define CURSOR_HEIGHT     30
#define CURSOR_NORMAL     0
#define CURSOR_PRESSED    1
#define TOTAL_CURSORS     2

#define BUTTON_WIDTH	  240
#define BUTTON_HEIGHT	  80
#define BUTTON_NORMAL     0
#define BUTTON_ONTOP      1
#define BUTTON_PRESSED    2
#define TOTAL_BUTTONS     3
#define BUTTON_ACTIVATED  0xFF
#define BUTTON_NOACTION   0

#define FONT_SIZE         32

#define PLAYER_WEAPON_1   0
#define PLAYER_WEAPON_2   1
#define PLAYER_WEAPON_3   2
#define PLAYER_WEAPON_4   3

#define TILE_WIDTH	      64
#define TILE_HEIGHT		  64
#define TOTAL_TILE_TYPES  12
#define TOTAL_ROW_TILES   20
#define TOTAL_COL_TILES   12
#define TOTAL_TILES_LEVEL 240

#define TILE_BUSH         0
#define TILE_LIGHTGRASS   1
#define TILE_DARKGRASS    2
#define TILE_BLACK        3
#define TILE_DARKBLUE     4
#define TILE_LIGHTBLUE    5
#define TILE_PURPLE       6
#define TILE_RED          7
#define TILE_BROWN        8
#define TILE_PINK         9
#define TILE_GRAYBLOCK    10
#define TILE_OCEANBLOCK   11
#define TILE_NONE         12


Lib.h
#define ERR(x) (MessageBox(GetActiveWindow(), x, "An error has occured!", MB_OK))

#include <windows.h> 
#include <stdlib.h> 
#include <time.h> 
#include <math.h> 
#include <string> 
#include <fstream>
using std::string;
using std::ifstream; 
using std::ofstream; 

#include "sdl.h" 
#include "sdl_image.h" 
#include "sdl_ttf.h" 
#include "sdl_mixer.h" 
#include "resource1.h" 

#include "define.h" 
#include "globals.h" 

#include "cursor.h" 
#include "button.h" 
#include "tile.h" 

#include "item.h" 
#include "weapon.h" 
#include "armor.h"

#include "avatar.h"
#include "player.h" 
#include "computer.h"



Globals.h
#pragma once

SDL_Surface *loadSurface(char *, bool); 
void blitSurface(int, int, SDL_Surface *, SDL_Surface *, SDL_Rect *); 
bool checkCollision(SDL_Rect, SDL_Rect); 

resource1.h (resource file)
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by KnocKout1.rc
//
#define IDI_ICON1                       101

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

Armor.h
#pragma once

class ARMOR : public ITEM
{
private:
	int defense; 

public:
	ARMOR()
	{
		defense = 0; 
	}

	void setDefense(int newDefense)
	{
		defense = newDefense; 
	}

	int getDefense()
	{
		return defense; 
	}

	void createWeapon(string newName, int newCost, int newDefense)
	{
		name = newName; 
		cost = newCost; 
		defense = newDefense; 
	}

	void setWeapon(WEAPON newWeapon)
	{
		name = newWeapon.name; 
		cost = newWeapon.cost; 
		defense = newWeapon.defense; 
	}
}; 


Avatar.h
#pragma once

bool touchesWall(SDL_Rect, TILE*[]); 


class AVATAR
{
protected:
	string name; 
	SDL_Rect box; 
	SDL_Rect clips[12]; 
	SDL_Surface *avatar;
	int level; 
	int xp; 
	int gold; 
	int health; 
	int maxHealth; 
	int attack, defense; 
	int xVel, yVel;
	int speed; 
	int frame; 
	int direction; 
	int type; 

public:
	AVATAR()
	{
		name = "Avatar"; 
		avatar = NULL; 
		level = 0; 
		xp = 0; 
		gold = 0; 
		health = 0; 
		maxHealth = 0; 
		attack = defense = 0; 
		xVel = yVel = 0; 
		box.x = 0; 
		box.y = 0; 
		frame = 0; 
		speed = 0; 
		direction = DIRECTION_EAST; 
		type = AVATAR_UNDEFINED; 

		for (int i = 0; i < 12; i++)
		{
			clips[i].x = i * AVATAR_WIDTH; 
			clips[i].y = 0; 
			clips[i].w = AVATAR_WIDTH; 
			clips[i].h = AVATAR_HEIGHT;
		}
	}

	~AVATAR()
	{
		SDL_FreeSurface(avatar); 
	}

	void moveAvatar(SDL_Rect &camera, TILE *tiles[])
	{
		box.x += xVel; 

		if (touchesWall(box, tiles))
		{
			box.x -= xVel; 
		}

		box.y += yVel; 

		if (touchesWall(box, tiles))
		{
			box.y -= yVel; 
		}

		//find direction of traveling
		if (xVel < 0)
		{
			direction = DIRECTION_WEST; 
		}
		else if (xVel > 0)
		{
			direction = DIRECTION_EAST; 
		}
		else if (yVel < 0)
		{
			direction = DIRECTION_NORTH; 
		}
		else if (yVel > 0)
		{
			direction = DIRECTION_SOUTH; 
		}

		//update animations
		if (direction != DIRECTION_NONE && (xVel > 0 || xVel < 0 || yVel > 0 || yVel < 0 ) )
		{
			frame++; 
		}
		else
		{
			frame = 0; 
		}
		if (frame > 2)
		{
			frame = 0; 
		}

		//check character's coordinates
		if (box.x < 0)
		{
			box.x = 0;
		}
		if (box.x + AVATAR_WIDTH > LEVEL_WIDTH)
		{
			box.x = LEVEL_WIDTH - AVATAR_HEIGHT; 
		}
		if (box.y < 0)
		{
			box.y = 0; 
		}
		if (box.y + AVATAR_HEIGHT > LEVEL_HEIGHT)
		{
			box.y = LEVEL_HEIGHT - AVATAR_HEIGHT; 
		}

		//reposition camera if its on player character
		if (type == AVATAR_PLAYER)
		{
			camera.x = (box.x + AVATAR_WIDTH / 2) - CAMERA_WIDTH / 2;
			camera.y = (box.y + AVATAR_HEIGHT / 2) - CAMERA_HEIGHT / 2; 

			if (camera.x < 0)
			{
				camera.x = 0; 
			}
			if (camera.x + CAMERA_WIDTH > LEVEL_WIDTH)
			{
				camera.x = LEVEL_WIDTH - CAMERA_WIDTH; 
			}
			if (camera.y < 0)
			{
				camera.y = 0; 
			}
			if (camera.y + CAMERA_HEIGHT > LEVEL_HEIGHT)
			{
				camera.y = LEVEL_HEIGHT - CAMERA_HEIGHT; 
			}
		}
	}

	void showAvatar(SDL_Surface *screen, SDL_Rect camera)
	{					
		blitSurface(box.x - camera.x, box.y - camera.y, avatar, screen, &clips[(direction*3)+frame]); 
	}

	void setName(string newName)
	{
		name = newName; 
	}
    
	string getName()
	{
		return name; 
	}

	void setLevel(int newLevel)
	{
		level = newLevel; 
	}

	int getLevel()
	{
		return level; 
	}

	void setXP(int newXP)
	{
		xp = newXP;
	}

	void addXP(int amount)
	{
		xp += amount; 
	}

	int getXP()
	{
		return xp;
	}

	void getGold(int newGold)
	{
		gold = newGold; 
	}

	void addGold(int amount)
	{
		gold += amount; 
	}

	void loseGold(int amount)
	{
		gold -= amount; 
	}

	int getGold()
	{
		return gold; 
	}

	void setHealth(int newHealth)
	{
		health = newHealth; 
	}

	void loseHealth(int amount)
	{
		health -= amount; 
	}

	int getHealth()
	{
		return health; 
	}

	void setMaxHealth(int newMaxHealth)
	{
		maxHealth = newMaxHealth; 
	}

	int getMaxHealth()
	{
		return maxHealth; 
	}

	void setAttack(int newAttack)
	{
		attack = newAttack; 
	}

	int getAttack()
	{
		return attack; 
	}

	void setDefense(int newDefense)
	{
		defense = newDefense; 
	}

	int getDefense()
	{
		return defense; 
	}

	void setSpeed(int newSpeed)
	{
		speed = newSpeed; 
	}

	int getSpeed()
	{
		return speed; 
	}

	void setX(int x)
	{
		box.x = x; 
	}

	int getX()
	{
		return box.x; 
	}

	void setY(int y)
	{
		box.y = y; 
	}

	int getY()
	{
		return box.y; 
	}
}; 

Button.h
#pragma once

bool touchesWall(SDL_Rect, TILE*[]); 


class AVATAR
{
protected:
	string name; 
	SDL_Rect box; 
	SDL_Rect clips[12]; 
	SDL_Surface *avatar;
	int level; 
	int xp; 
	int gold; 
	int health; 
	int maxHealth; 
	int attack, defense; 
	int xVel, yVel;
	int speed; 
	int frame; 
	int direction; 
	int type; 

public:
	AVATAR()
	{
		name = "Avatar"; 
		avatar = NULL; 
		level = 0; 
		xp = 0; 
		gold = 0; 
		health = 0; 
		maxHealth = 0; 
		attack = defense = 0; 
		xVel = yVel = 0; 
		box.x = 0; 
		box.y = 0; 
		frame = 0; 
		speed = 0; 
		direction = DIRECTION_EAST; 
		type = AVATAR_UNDEFINED; 

		for (int i = 0; i < 12; i++)
		{
			clips[i].x = i * AVATAR_WIDTH; 
			clips[i].y = 0; 
			clips[i].w = AVATAR_WIDTH; 
			clips[i].h = AVATAR_HEIGHT;
		}
	}

	~AVATAR()
	{
		SDL_FreeSurface(avatar); 
	}

	void moveAvatar(SDL_Rect &camera, TILE *tiles[])
	{
		box.x += xVel; 

		if (touchesWall(box, tiles))
		{
			box.x -= xVel; 
		}

		box.y += yVel; 

		if (touchesWall(box, tiles))
		{
			box.y -= yVel; 
		}

		//find direction of traveling
		if (xVel < 0)
		{
			direction = DIRECTION_WEST; 
		}
		else if (xVel > 0)
		{
			direction = DIRECTION_EAST; 
		}
		else if (yVel < 0)
		{
			direction = DIRECTION_NORTH; 
		}
		else if (yVel > 0)
		{
			direction = DIRECTION_SOUTH; 
		}

		//update animations
		if (direction != DIRECTION_NONE && (xVel > 0 || xVel < 0 || yVel > 0 || yVel < 0 ) )
		{
			frame++; 
		}
		else
		{
			frame = 0; 
		}
		if (frame > 2)
		{
			frame = 0; 
		}

		//check character's coordinates
		if (box.x < 0)
		{
			box.x = 0;
		}
		if (box.x + AVATAR_WIDTH > LEVEL_WIDTH)
		{
			box.x = LEVEL_WIDTH - AVATAR_HEIGHT; 
		}
		if (box.y < 0)
		{
			box.y = 0; 
		}
		if (box.y + AVATAR_HEIGHT > LEVEL_HEIGHT)
		{
			box.y = LEVEL_HEIGHT - AVATAR_HEIGHT; 
		}

		//reposition camera if its on player character
		if (type == AVATAR_PLAYER)
		{
			camera.x = (box.x + AVATAR_WIDTH / 2) - CAMERA_WIDTH / 2;
			camera.y = (box.y + AVATAR_HEIGHT / 2) - CAMERA_HEIGHT / 2; 

			if (camera.x < 0)
			{
				camera.x = 0; 
			}
			if (camera.x + CAMERA_WIDTH > LEVEL_WIDTH)
			{
				camera.x = LEVEL_WIDTH - CAMERA_WIDTH; 
			}
			if (camera.y < 0)
			{
				camera.y = 0; 
			}
			if (camera.y + CAMERA_HEIGHT > LEVEL_HEIGHT)
			{
				camera.y = LEVEL_HEIGHT - CAMERA_HEIGHT; 
			}
		}
	}

	void showAvatar(SDL_Surface *screen, SDL_Rect camera)
	{					
		blitSurface(box.x - camera.x, box.y - camera.y, avatar, screen, &clips[(direction*3)+frame]); 
	}

	void setName(string newName)
	{
		name = newName; 
	}
    
	string getName()
	{
		return name; 
	}

	void setLevel(int newLevel)
	{
		level = newLevel; 
	}

	int getLevel()
	{
		return level; 
	}

	void setXP(int newXP)
	{
		xp = newXP;
	}

	void addXP(int amount)
	{
		xp += amount; 
	}

	int getXP()
	{
		return xp;
	}

	void getGold(int newGold)
	{
		gold = newGold; 
	}

	void addGold(int amount)
	{
		gold += amount; 
	}

	void loseGold(int amount)
	{
		gold -= amount; 
	}

	int getGold()
	{
		return gold; 
	}

	void setHealth(int newHealth)
	{
		health = newHealth; 
	}

	void loseHealth(int amount)
	{
		health -= amount; 
	}

	int getHealth()
	{
		return health; 
	}

	void setMaxHealth(int newMaxHealth)
	{
		maxHealth = newMaxHealth; 
	}

	int getMaxHealth()
	{
		return maxHealth; 
	}

	void setAttack(int newAttack)
	{
		attack = newAttack; 
	}

	int getAttack()
	{
		return attack; 
	}

	void setDefense(int newDefense)
	{
		defense = newDefense; 
	}

	int getDefense()
	{
		return defense; 
	}

	void setSpeed(int newSpeed)
	{
		speed = newSpeed; 
	}

	int getSpeed()
	{
		return speed; 
	}

	void setX(int x)
	{
		box.x = x; 
	}

	int getX()
	{
		return box.x; 
	}

	void setY(int y)
	{
		box.y = y; 
	}

	int getY()
	{
		return box.y; 
	}
}; 

Button.h
#pragma once

class BUTTON
{
private:
	SDL_Surface *surface; 
	SDL_Surface *message; 
	TTF_Font *font; 
	SDL_Rect box; 
	SDL_Rect clips[TOTAL_BUTTONS];
	string text; 
	int state; 
	bool holdDown; 
	int r, g, b; 

public:
	BUTTON()
	{
		surface = NULL; 
		message = NULL; 
		font = NULL; 
		box.x = 0; 
		box.y = 0; 
		box.w = BUTTON_WIDTH; 
		box.h = BUTTON_HEIGHT;
		
		for (int i = 0; i < TOTAL_BUTTONS; i++)
		{
			clips[i].x = i * BUTTON_WIDTH; 
			clips[i].y = 0; 
			clips[i].w = BUTTON_WIDTH; 
			clips[i].h = BUTTON_HEIGHT; 
		}

		text = "Unnamed";
		state = BUTTON_NORMAL; 
		holdDown = false; 
		r = g = b = 0; 
	}

	~BUTTON()
	{
		SDL_FreeSurface(surface); 
		SDL_FreeSurface(message); 
		TTF_CloseFont(font); 
	}

	bool createButton(int x, int y, string newMsg)
	{
		if ( (surface = loadSurface("button.png", true) ) == NULL)
		{
			return false; 
		}
		
		if ( (font = TTF_OpenFont("c:/windows/fonts/ariblk.ttf", FONT_SIZE) ) == NULL)
		{
			return false; 
		}

		SDL_Color fontColor = { 78, 167, 75 }; 
		message = TTF_RenderText_Solid(font, newMsg.c_str(), fontColor); 

		box.x = x; 
		box.y = y; 
		text = newMsg; 
		return true; 
	}

	
	void setPosition(int x, int y)
	{
		box.x = x; 
		box.y = y;
	}

	
	int loopButton(SDL_Event event, SDL_Surface *screen)
	{
		SDL_Rect mouse; 
		mouse.x = event.button.x; 
		mouse.y = event.button.y; 
		mouse.w = CURSOR_WIDTH; 
		mouse.h = CURSOR_HEIGHT; 

		blitSurface(box.x, box.y, surface, screen, &clips[state]); 
		blitSurface(box.x + 30, box.y + 20, message, screen, NULL); 
	
		if (checkCollision(box, mouse) )
		{
			if (holdDown)
			{
				if (event.type == SDL_MOUSEBUTTONUP)
				{
					if (event.button.button == SDL_BUTTON_LEFT)
					{
						holdDown = false; 
						state = BUTTON_PRESSED; 
						return BUTTON_ACTIVATED;
					}
				}
				else 
				{
					holdDown = true; 
					state = BUTTON_PRESSED; 
				}
			}
			else
			{
				if (event.type == SDL_MOUSEBUTTONDOWN)
				{		
					if (event.button.button == SDL_BUTTON_LEFT)
					{
						holdDown = true; 
					}
				}
				state = BUTTON_ONTOP; 
			}
		}
		else
		{
			holdDown = false; 
			state = BUTTON_NORMAL; 
		}
		return BUTTON_NOACTION; 
	}
}; 

Computer.h
//not done yet
#pragma once

class COMPUTER : public AVATAR
{
private:
public:
	COMPUTER()
	{
		type = AVATAR_COMPUTER; 
	}
};

Cursor.h
#pragma once

class CURSOR 
{
private:
	SDL_Surface *surface;
	SDL_Rect clips[TOTAL_CURSORS]; 
	SDL_Rect box; 
	int state; 

public:
	CURSOR()
	{
		surface = NULL; 
		state = CURSOR_NORMAL; 

		box.x = 0; 
		box.y = 0; 
		box.w = CURSOR_WIDTH; 
		box.h = CURSOR_HEIGHT; 

		for (int i = 0; i < TOTAL_CURSORS; i++)
		{
			clips[i].x = i * CURSOR_WIDTH; 
			clips[i].y = 0; 
			clips[i].w = CURSOR_WIDTH; 
			clips[i].h = CURSOR_HEIGHT; 
		}
	}


	~CURSOR()
	{
		SDL_FreeSurface(surface); 
	}


	bool setupCursor()
	{
		if ( (surface = loadSurface("cursor.png", true) ) == NULL)
		{
			return false; 
		}
		return true; 
	}

	void handleInput(SDL_Event event)
	{
		if (event.type == SDL_MOUSEMOTION)
		{
			box.x = event.button.x; 
			box.y = event.button.y; 
		}

		else if (event.type == SDL_MOUSEBUTTONDOWN)
		{
			if (event.button.button == SDL_BUTTON_LEFT)
			{
				state = CURSOR_PRESSED; 
			}
		}

		else if (event.type == SDL_MOUSEBUTTONUP)
		{
			state = CURSOR_NORMAL; 
		}
	}

	void showCursor(SDL_Surface *screen)
	{
		blitSurface(box.x, box.y, surface, screen, &clips[state]); 
	}
};


Item.h
#pragma once

class ITEM
{
protected:
	string name; 
	int cost; 

public:
	ITEM()
	{
		name = "Unnamed"; 
		cost = 0; 
	}

	void setName(string newName)
	{
		name = newName; 
	}

	string getName()
	{
		return name; 
	}

	void setCost(int newCost)
	{
		cost = newCost; 
	}

	int getCost()
	{
		return cost; 
	}
}; 

Player.h

#pragma once


class PLAYER : public AVATAR
{
private:
	WEAPON weapon[4]; 
	ARMOR armor; 

public:
	PLAYER()
	{
		type = AVATAR_PLAYER; 
	}

	bool createAvatar(string newName)
	{
		if ( (avatar = loadSurface("char_player.png", true) ) == NULL)
		{
			return false; 
		}

		name = newName; 
		level = 1; 
		xp = 0; 
		gold = 100; 
		health = 50; 
		maxHealth = 50; 
		attack = 5; 
		defense = 5; 
		speed = 15; 

		//save
		saveFile(); 
		return true; 
	}

	void saveFile()
	{
		string _name = name; 
		int _level = level; 
		int _xp = xp; 
		int _gold = gold;
		int _health = health; 
		int _maxHealth = maxHealth; 
		int _attack = attack; 
		int _defense = defense; 
		int _speed = speed; 
		int weaponCount = 0; 
		for (weaponCount = 0; weapon[weaponCount].getCost() > 0; weaponCount++);
		string weaponName[4]; 
		int weaponCost[4]; 
		int weaponAttack[4]; 
		string armorName; 
		int armorCost = 0; 
		int armorDefense = 0; 
		
		for (int i = 0; i < weaponCount; i++)
		{
			weaponName[i] = weapon[i].getName(); 
			weaponCost[i] = weapon[i].getCost(); 
			weaponAttack[i] = weapon[i].getAttack(); 
		}

		armorName = armor.getName(); 
		armorCost = armor.getCost(); 
		armorDefense = armor.getDefense(); 

		ofstream out("avatar.dat", ios::binary); 

		out.write(name, sizeof(name)); 
		out.write((char*)&_level, sizeof(int)); 
		out.write((char*)&_xp, sizeof(int)); 
		out.write((char*)&_gold, sizeof(int)); 
		out.write((char*)&_health, sizeof(int)); 
		out.write((char*)&_maxHealth, sizeof(int)); 
		out.write((char*)&_attack, sizeof(int)); 
		out.write((char*)&_defense, sizeof(int)); 
		out.write((char*)&_speed, sizeof(int)); 
		out.write((char*)&weaponCount, sizeof(int)); 

		for (int t = 0; t < weaponCount; t++)
		{
			out.write(weaponName[t], sizeof(weaponName[t])); 
			out.write((char*)&weaponCost[t], sizeof(int)); 
			out.write((char*)&weaponAttack[t], sizeof(int)); 
		}

		out.write(armorName, sizeof(armorName)); 
		out.write((char*)&armorCost, sizeof(int)); 
		out.write((char*)&armorDefense, sizeof(int)); 
		out.close(); 
	}


	void loadFile()
	{
		string _name = ""; 
		int _level = 0;
		int _xp = 0; 
		int _gold = 0;
		int _health = 0; 
		int _maxHealth = 0;
		int _attack = 0;
		int _defense = 0;
		int _speed = 0;
		int weaponCount = 0; 
		string weaponName[4]; 
		int weaponCost[4]; 
		int weaponAttack[4]; 
		string armorName; 
		int armorCost = 0; 
		int armorDefense = 0;

		ifstream in("avatar.dat", ios::binary); 

		if (!in)
		{
			return;
		}

		in.read(_name, sizeof(_name)); 
		in.read((char*)&_xp, sizeof(int)); 
		in.read((char*)&_gold, sizeof(int)); 
		in.read((char*)&_health, sizeof(int)); 
		in.read((char*)&_maxHealth, sizeof(int)); 
		in.read((char*)&

		in.close(); 
	}


	void handleInput(SDL_Event event)
	{
		if (event.type == SDL_KEYDOWN)
		{
			switch (event.key.keysym.sym)
			{
			case SDLK_w:
				yVel -= speed; 
				break;

			case SDLK_s:
				yVel += speed; 
				break;

			case SDLK_a:
				xVel -= speed; 
				break;

			case SDLK_d:
				xVel += speed; 
				break;
			}
		}

		else if (event.type == SDL_KEYUP)
		{
			switch (event.key.keysym.sym)
			{
			case SDLK_w:
				yVel += speed; 
				break;

			case SDLK_s:
				yVel -= speed; 
				break;

			case SDLK_a:
				xVel += speed; 
				break;

			case SDLK_d:
				xVel -= speed; 
				break;
			}
		}
	}

	bool checkForLevelUp()
	{
		if (xp >= level * level * 50)
		{
			level++; 
			xp = 0; 
			gold += level * 2 * 50; 

			if (level < 10)   //all stats +2
			{
				maxHealth += 20; 
				health = maxHealth; 
				attack += 2; 
				defense += 2; 
				speed += 1; 
			}
			else              //all stats +4
			{
				maxHealth += 30; 
				health = maxHealth; 
				attack += 4; 
				defense += 4; 
				speed += 2; 
			}
			return true; 
		}
		return false; 
	}

	WEAPON *GetWeapon(int x)
	{
		return &weapon[x]; 
	}

	ARMOR *GetArmor()
	{
		return &armor; 
	}
}; 

Tile.h
#pragma once

class TILE
{
private:
	SDL_Rect box; 
	int type; 

public:
	TILE()
	{
		box.x = 0; 
		box.y = 0;
		box.w = TILE_WIDTH; 
		box.h = TILE_HEIGHT;
		type = TILE_NONE; 
	}

	TILE(int x, int y, int tileType)
	{
		box.x = x; 
		box.y = y; 
		box.w = TILE_WIDTH; 
		box.h = TILE_HEIGHT; 
		type = tileType; 
	}

	void showTile(SDL_Rect camera, SDL_Surface *tileSheet, SDL_Rect *tileClips, SDL_Surface *screen)
	{
		if (checkCollision(box, camera) == true)
		{
			blitSurface(box.x - camera.x, box.y - camera.y, tileSheet, screen, &tileClips[type]); 
		}
	}

	int getType()
	{
		return type; 
	}

	SDL_Rect getBox()
	{
		return box; 
	}
}; 

Weapon.h
#pragma once

class WEAPON : public ITEM
{
private:
	int attack; 

public:
	WEAPON()
	{
		attack = 0; 
	}

	void setAttack(int newAttack)
	{
		attack = newAttack; 
	}

	int getAttack()
	{
		return atack; 
	}

	void createWeapon(string newName, int newCost, int newAttack)
	{
		name = newName; 
		cost = newCost; 
		attack = newAttack; 
	}

	void setWeapon(WEAPON newWeapon)
	{
		name = newWeapon.name; 
		cost = newWeapon.cost; 
		attack = newWeapon.attack; 
	}
}; 

Any comments would be nice (even if it's criticism) thanks! Oh and any ideas on how to improve my code would be nice too :D

Share this post


Link to post
Share on other sites
Quote:

Any comments would be nice (even if it's criticism) thanks!
Oh and any ideas on how to improve my code would be nice too :D


Lots of comments and ideas. But almost too many to post here. This isn't bad though. Could I get a copy of the project? If you are interested drop me a PM with a link to the files hosted somewhere. I'll try refactor it to show you some of the ideas.

Share this post


Link to post
Share on other sites
First few things I noticed.

A) Comments! Even if they are "// main loop for game", you should put at least a brief comment about the function, member function or class you are defining. Even if its only you coding, I find it much, much easier to locate the begining of sections of code if I have comments. Without comments its hard to distinguish separate sections of code.

B) Never define your shared classes and functions in the header. Including (but explicitly excluding them using #pragma once) definitions in multiple cpp files is a messy business.

Instead prototype them, and make a cpp file to define your classes and functions. This way when you change the implementation of a particular function or class function, the files that include the function/class's header do not have to recompile, only the definition cpp you modified. For example:

object.h
#ifndef OBJECT_H  // you can still use #pragma once
#define OBJECT_H

// declares the Object class
class Object
{
public:
// Sets the typename of the object
void SetType (std::string type);

private:
std::string m_type;
};

// a function to create a "monster" object
Object * createMonsterObject (void);

#endif


object.cpp
#include "object.h"

// Sets the typename of the object
void Object::SetType (std::string type)
{
m_type = type;
}

// a function to create a "monster" object
Object * createMonsterObject (void)
{
Object * obj = new Object;
obj->SetName ("monster");
return obj;
}


main.cpp
#include "object.h"

int main ()
{
Object * obj = createMonsterObject ();
delete obj;
return 0;
}


B) Use enumerations instead of defines and const integers. For example:

Instead of:
#define MENU_PLAY 0
#define MENU_OPTIONS 1
#define MENU_HELP 2
#define MENU_EXIT 3

const int ACTION_JUMP = 0;
const int ACTION_RUN = 1;
const int ACTION_DUCK = 2;


Do this: (enums.h)
// Menu button indices
enum MenuButton
{
Menu_Play = 0, // auto increments to 1, 2 etc - in fact you don't even need the =0 as 0 is the initial value
Menu_Options,
Menu_Help,
Menu_Exit
};

// Action type
enum ActionType
{
Action_Jump,
Action_Run,
Action_Duck
};


main.cpp
#include "object.h"
#include "enums.h"

// no dont do what im about to do (defining in main.cpp)
// and also the object itself would do the action not this function
void doActionOnObject (Object * obj, ActionType type)
{
switch (type) {
case Action_Jump:
// make object jump
break;

case Action_Run:
// move object forward
break;
}
}

int main ()
{
Object * obj = createMonsterObject ();
doActionOnObject (obj, Action_Jump);
delete obj;
return 0;
}





Just some tips on some coding practices to try. Of course, exactly how you name identifiers, and indent code blocks and name classes etc, is up to you. Following these above practices will help you on your way to making readable, high quality code. These are only a small amount of 'good practises' for decent code quality though and my advice should be taken as advice not a guideline on how to code as this is how I code and not how everyone codes. But anyway, hope you understand where I'm coming from with my coding tips.

Share this post


Link to post
Share on other sites
Quote:
Original post by thre3dee
A) Comments! Even if they are "// main loop for game", you should put at least a brief comment about the function, member function or class you are defining. Even if its only you coding, I find it much, much easier to locate the begining of sections of code if I have comments. Without comments its hard to distinguish separate sections of code.


I disagree a bit with this. Comments are certainly purposeful and should be used when necessary/helpful, but superfluous comments are, well, superfluous. IMO, comments like this:

// declares the Object class
class Object
{


Are completely useless; you can see on the line directly below the comment that you are, in fact, declaring the Object class. Ideally, you want descriptive enough names for variables and functions that the code becomes self-documenting. Save the comments for explaining your choice of algorithm, particularly "clever" bits of code that really need the further explanation, and in general to explain why you did something, not necessarily how.

Share this post


Link to post
Share on other sites
Well I find code annoying to change etc when i have no cues as to where things are. Comments are one way this can be achieved. Unless of course you aren't using a syntax highlighter which ends up being ugly text.

And really, you wouldn't just write "declares object class". That wasn't a very good example actually. Something more along the lines of the below. Its also good for people who have never seen your code, such as if someone wants to know what a class does.

// Base entity class which describes generic methods and properties
// for entity based objects such as items or characters.
class Entity
{
public:
// sets the model object used by the entity and optionally creates a root scene node for it
void SetModel (Model * model, bool create_node = false);

// loads the entity using an entity definition XML document node
void LoadFromScript (XMLNode * node);
};


Think about it, would you rather figure out what you want to do with a class through a header that looked like this^^ or a header that looked like this:

class Entity
{
Model*model;
XMLNode *xmlnode;
SceneNode*node;
EntityCallback onUse;
EntityCallback onDie;
EntityManager *parent;
public:
void SetModel (Model * model, bool create_node = false);
void LoadFromScript (XMLNode * node);
EntityManager*getParent(void);
};


Most engines are fairly well commented and are subsequently a breeze to figure out some little problem you need simply by looking at the header instead of bringing up the help manual.

You may not need it for your own unshared code but nobody writes headers and code in a game studio and not expect someone to look at and think "wtf is this guy writing? I can't see any structure in it!".

Share this post


Link to post
Share on other sites
I just wonder where did you get that idea, but I can tell that you aren't, I have seen a lot worse. :)

I didn't read all codes, but some of them. Respect from these :
- Use of magic number, there were a few places, mostly you did pretty well.
- Naming was pretty well done, I was able to understand it.
- Code was clear, didn't have troubles understanding it.

Share this post


Link to post
Share on other sites
Quote:
Original post by Arex
I just wonder where did you get that idea, but I can tell that you aren't, I have seen a lot worse. :)

I didn't read all codes, but some of them. Respect from these :
- Use of magic number, there were a few places, mostly you did pretty well.
- Naming was pretty well done, I was able to understand it.
- Code was clear, didn't have troubles understanding it.


I agree. The code itself was fairly good. Its the structure, such as defining implementations in header files which gets me. You'll find that pretty much all non inline code will defined as I have explained earlier when dealing with shared code. Libraries (APIs), engines (essentially biiig APIs) and most well designed applications, strive on this architecture.

Share this post


Link to post
Share on other sites
Hmm. The OP appears to have been banned. However I have sent a PM with a compiling (though I can't test it) version written with more idiomatic C++ in various places. AFAIK banned people can still log in and check these, but I could be wrong.

Share this post


Link to post
Share on other sites

This topic is 3627 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Guest
This topic is now closed to further replies.
Sign in to follow this