MarcusAseth

Making Breakout - Code Structure help requested

Recommended Posts

I'm following the list of games a begginner should make suggested by Alpha_ProgDes and I'm about to start making Breakout, though this time I'll go the hardcore way with C++ & SDL instead of Unreal Engine.
I'll figure out  how to write the classes and make it work, though I wanted to ask you guys about what I will need to make and how it should be organized, so that I have a clear roadmap that I can breeze trough step by step, without hitting any dead ends :D
So this are my initial thoughts:
●I will need a "Timer" class which keeps track of ms since last frame
●I will need a "Game" class which has a Timer and takes care of initializing the SDL_Window and SDL_Renderer, also with a destructor that takes care to destroy them.
●I will need a "TextureManager" class which containst a map<string, Texture*> to which I can ask for a texture by its name from within other classes, so pretty much every Actor (taking unreal naming for semplicity here) need to include this "TextureManager". Also texture manager destructor takes care of destroying all the textures.
●I need a base Actor class which will contain member variables x,y centered pivot coordinates for the actor sprite, SDL_Rect for the sprite position/size and a Texture* for the sprite, also virtual draw() and virtual update() methods
Well that all I can think for now, I don't have a very clear idea for how the input handling should be done, is just like a super giant switch inside the game loop, or it is like a class "InputManager" that keep track of which actor is interested in which key input and forward the inputs to the approriete actors or... mh... no idea really how it should be done :S
So, whatever feedback or suggestion or "Structure Roadmap" you can present me to put me on the right tracks, is very welcome! :P 
I only need knowledge of a reasonably correct structure and I will fill in the blanks :)

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

My first suggestion is that you don't need to have a list of classes up-front. If we tried to do that for AAA games we'd never start coding.

My other comments:

  • I like to have a separate App class which contains a Game class. Game is for, well, gamey things. I'd create the window and other input/output in the App, as well as an instance of the Game.
  • Actors shouldn't need TextureManagers. There's no part of 'acting' that needs to look up textures. If you want Actors to be responsible for drawing themselves, that's fine (at least at this level), but you should pass in the texture to use in each case.
  • Input handling for a game like this can stay simple. I'd start with a function that is called from the main loop, with the paddle passed in as an argument. Call methods on the paddle to implement movement, based on input state. If you have the separate Game/App system like I do, then the App's input handling can call through to the Game's input handling.

Share this post


Link to post
Share on other sites

I usually start at the global picture, instead of the small details. What data do you have, what activities must be done (at high level, so "game map", "textures", "character", and "drawing the screen" is more than enough.

Make big building blocks (eg on a single sheet of paper) where those things roughly go. It should give you an overview of the program as a whole, even though your picture may be wrong, but the only way to find out is by trying to build it.

You will hit dead ends, but it's part of the process. Programs are so complicated, it is impossible to get all the details right on the first try. Don't be afraid of it, learn to recognize it happening, and how to recover from it.

Finally, nobody says you must do all coding in one project. If you want to figure out how to do some detail, eg movement with keys or so, and you don't know how, use paper and your grey matter to work it out. If it needs experimenting, make a small side-program for experiments. When done, apply the knowledge in your main project (which may include code of the experiment, but in general rewriting improves code).

Share this post


Link to post
Share on other sites

A classic issue for a lot of people (myself included) is the tendency to over engineer things. Frankly the best way to learn what you need is to just make something and set small goals, milestones if you will. I used to create these really complicated classes before even knowing what I needed, but often it either got thrown away or simply went unused or the architecture changed somewhat so I had to rewrite it anyway. For example, since you're making a breakout game you might just want to start simple, "well I need a game loop and a window, now I need to draw something onscreen, now I need to make a ball, okay now the ball needs to bounce against the edges of the screen and re-spawn."

The first two things you mentioned are fine, for the texture manager I would question if you even need one. Is the game complex enough that sprites require managing? Honestly in most arcade games that isn't the case, sprites may be used only once and the entire game contains a small enough number of them for you to simply load them all in some function and pass them around. Important questions are things like -when- to load them too, if you can you might as well load them all at the start. Frankly unless you KNOW for a fact that you need something to be complex, it is almost always better to start off simple and build up from there.

Share this post


Link to post
Share on other sites

Thank you for answering guys :)

Quote

The first two things you mentioned are fine, for the texture manager I would question if you even need one. Is the game complex enough that sprites require managing?

Frankly unless you KNOW for a fact that you need something to be complex, it is almost always better to start off simple and build up from there.

I see that point, though my point would be that all the games in the list of games a begginner should make seems like they don't require a TextureManager as well, so even if I don't need a TextureManager right now or to learn how to make a Singleton, when do I get to learn it then?! :P

I am kind of throwing extra stuff in exactly because the project is simple, so the scale is small and I can learn this concepts in realive comfort/safety.

So from my point of view, I actually value something that over-complicate the project if it is just for the sake of learning a new thing, basically making this game is not really the main goal. So if you guys think I could research and apply an interesting design pattern to this project feel free to suggest, because for me is an opportunity to fiinally learn a new/useful thing :P 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
3 minutes ago, MarcusAseth said:

I see that point, though my point would be that all the games in the list of games a begginner should make seems like they don't require a TextureManager as well, so even if I don't need a TextureManager right now or to learn how to make a Singleton, when do I get to learn it then?!

I am kind of throwing extra stuff in exactly because the project is simple, so the scale is small and I can learn this concepts in realive comfort/safety.

So from my point of view, I actually value something that over-complicate the project if it is just for the sake of learning a new thing, basically making this game is not really the main goal. So if you guys think I could research and apply an interesting design pattern to this project feel free to suggest, because for me is an opportunity to fiinally learn a new/useful thing  

Which is fine, I experiment with ideas myself on a regular basis, the problem is it becomes easy for you to start doing that for everything. Particularly when it is that, experimenting, you can quickly get in over your head and make the code a mess of things you aren't sure are good architecture, and dig yourself into a corner that it feels frustrating to get out of.

Sometimes it might be better to experiment on standalone tech demos and things, or to save writing something complex like that until you actually need it. That's a bit of an unspoken rule that people don't often actually explain, software only gets complicated because it needs to. If you could write the next Battlefield game just by making a function that loads all the game data at the start and not bother with subsystems dedicated to managing things, then they probably would.

You might want to consider that the faster you finish a game the faster you get to try another project as well, and possibly explore more concepts or have more challenging rules to write for.

Share this post


Link to post
Share on other sites
6 minutes ago, MarcusAseth said:

all the games in the list of games a begginner should make seems like they don't require a TextureManager as well, so even if I don't need a TextureManager right now or to learn how to make a Singleton, when do I get to learn it then?!

  1. Maybe you never need a TextureManager....
  2. You CERTAINLY don't need a Singleton.
  3. On that list, Ikari Warriors and Super Mario Bros have sufficient numbers of sprites and graphics to make some sort of image asset management worthwhile.
  4. The point of following a list like this in order is that each one introduces new challenges. As the article says, this time around you'll be learning "Lessons of pong, powerups, maps (brick arrangements)". Those are the things you probably want to focus on - how should they be implemented?

Share this post


Link to post
Share on other sites

Done some progress, I'm thinking to paste here the code I write during this project in case someone notices and point out some ugly stuff I may end up doing so that I avoid ending up with bad coding habits.

I'll put it into spoiler just to not flood the entire page with a single reply :S

The only problem I am currently having is inside Game.cpp, code below:

#define BACKGROUND "Graphics/Background.png";
#define PADDLE "Graphics/Paddle.png";
#define BALL "Graphics/Ball.png";

Game::Game(SDL_Window* Window, SDL_Renderer* Renderer)
	:Window{ Window }, Renderer{ Renderer }
{
	LoadImage(BACKGROUND);
	LoadImage(PADDLE);
	LoadImage(BALL);
}

LoadImage takes a const char* but those 3 macro are not expanding into that for some reason, since VS is giving me a red squigly line... what argument type should that function take in order to work with my Macros? :S


 

Spoiler

 

main.cpp


#include <iostream>
#include "SDL2\SDL.h"
#include "SDL2\SDL_image.h"
#include "App.h"

int main(int argc, char* argv[])
{
	App GameClient;

	while (GameClient.IsRunning())
	{

	}

	return 0;
}

App.h


#pragma once
#include "SDL2\SDL.h"
#include "Game.h"
class App
{
	bool Running = false;
	Uint32  Width = 1280;
	Uint32  Height = 960;
	Uint32  WinFlags = 0;
	Uint32  RenFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
	SDL_Window* Window;
	SDL_Renderer* Renderer;
	Game* GameInstance;

	bool Init();
	bool CreateWindow();
	bool CreateRenderer();
public:
	App();
	~App();
	
	App(const App&) = delete;
	App& operator=(const App&) = delete;
	
	App(App&&) = delete;
	App& operator=(App&&) = delete;
	
	////
	
	inline bool IsRunning()const { return Running; }
};

App.cpp


#include "App.h"
#include "Utility.h"


App::App()
	:Window{ nullptr }, Renderer{ nullptr }
{
	Running = Init();
	
	if (Running)
	{GameInstance = new Game(Window, Renderer);}
}


App::~App()
{
	if (Window) { SDL_DestroyWindow; }
	if (Renderer) { SDL_DestroyRenderer; }
	delete GameInstance;
	SDL_Quit();
}

bool App::Init()
{
	if ( 0 != SDL_Init(SDL_INIT_EVERYTHING)){ return Error(SDL_GetError()); }

	return CreateWindow() ? (CreateRenderer() ? true : false) : (false);
}

bool App::CreateWindow()
{
	Window = SDL_CreateWindow("Breakout",
							  SDL_WINDOWPOS_CENTERED,
							  SDL_WINDOWPOS_CENTERED,
							  Width, Height, WinFlags);
	return Window ? true : Error(SDL_GetError());
}

bool App::CreateRenderer()
{
	Renderer = SDL_CreateRenderer(Window, -1, RenFlags);
	return Renderer ? true : Error(SDL_GetError());
}

Game.h


#pragma once
#include <map>
#include <string>
#include "SDL2\SDL.h"

class Game
{
	SDL_Window* Window;
	SDL_Renderer* Renderer;
	std::map<std::string, SDL_Texture*> Textures;

	bool LoadImage(const char* path);
public:
	Game(SDL_Window* Window, SDL_Renderer* Renderer);
	~Game();

	Game(const Game&) = delete;
	Game& operator=(const Game&) = delete;

	Game(Game&&) = delete;
	Game& operator=(Game&&) = delete;

	////

	SDL_Texture* GetTexture(const char* path)const;
};

Game.cpp


#include "Game.h"
#include "Utility.h"
#include "SDL2\SDL_image.h"

#define BACKGROUND "Graphics/Background.png";
#define PADDLE "Graphics/Paddle.png";
#define BALL "Graphics/Ball.png";

Game::Game(SDL_Window* Window, SDL_Renderer* Renderer)
	:Window{ Window }, Renderer{ Renderer }
{
	LoadImage(BACKGROUND);
	LoadImage(PADDLE);
	LoadImage(BALL);
}


Game::~Game()
{
	for (auto& elem : Textures)
	{ SDL_DestroyTexture(elem.second); }
}

bool Game::LoadImage(const char * path)
{
	if (Textures.find(path) != Textures.end())
	{ return  Error("Ettempting to Load an already Loaded Texture."); }

	SDL_Surface* Surface = IMG_Load(path);
	if (Surface)
	{
		Textures[path] = SDL_CreateTextureFromSurface(Renderer, Surface);
		SDL_FreeSurface(Surface);
		return true;
	}
	else
	{ return Error(SDL_GetError()); }
}

SDL_Texture* Game::GetTexture(const char* path)const
{
	auto& Texture = Textures.find(path);
	return (Texture != Textures.end()) ? Texture->second : nullptr;
}

Actor.h


#pragma once
#include "SDL2\SDL.h"
#include "Game.h"

enum class PivotMode: Uint8 {CENTER,TOP_LEFT};

class Actor
{
SDL_Texture* RequestTexture(const char* path)const;
void SetSpriteRect(Uint32 x, Uint32 y, PivotMode InputMode);
protected:
	Uint32 XCenter;
	Uint32 YCenter;
	SDL_Rect SpriteRect;
	SDL_Texture* Sprite;
	Game* GameRef;
public:
	Actor(Game* GameRef, PivotMode InputMode, Uint32 x, Uint32 y, const char* path);
	virtual ~Actor();

	Actor(const Actor&) = delete;
	Actor& operator=(const Actor&) = delete;

	Actor(Actor&&) = delete;
	Actor& operator=(Actor&&) = delete;

	////
};

Actor.cpp


#include "Actor.h"

#define BACKGROUND "Graphics/Background.png";
#define PADDLE "Graphics/Paddle.png";
#define BALL "Graphics/Ball.png";


Actor::Actor(Game* GameRef,PivotMode InputMode, Uint32 x, Uint32 y, const char* path)
	:GameRef{ GameRef }
{
	if (GameRef)
	{Sprite = RequestTexture(path);}

	if (Sprite)
	{SetSpriteRect(x, y, InputMode);}
}


Actor::~Actor()
{
}

SDL_Texture* Actor::RequestTexture(const char* path)const
{
	return GameRef->GetTexture(path);
}

void Actor::SetSpriteRect(Uint32 x, Uint32 y, PivotMode InputMode)
{
	SDL_QueryTexture(Sprite, NULL, NULL, &SpriteRect.w, &SpriteRect.h);
	switch (InputMode)
	{
		case PivotMode::CENTER:
		{
			SpriteRect.x = x - SpriteRect.w / 2;
			SpriteRect.y = y - SpriteRect.h / 2;
			XCenter = x;
			YCenter = y;
		}break;
		case PivotMode::TOP_LEFT:
		{
			SpriteRect.x = x;
			SpriteRect.y = y;
			XCenter = x + SpriteRect.w / 2;
			YCenter = y + SpriteRect.h / 2;
		}break;
	}
}

 


 

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

 

53 minutes ago, MarcusAseth said:

Done some progress, I'm thinking to paste here the code I write during this project in case someone notices and point out some ugly stuff I may end up doing so that I avoid ending up with bad coding habits.

 

Don't use macros for constants. Use "const" or "constexpr" (if your version of C++ has it). 

What is the actual error you're getting when you compile? The "red underlines" produced by Visual Studio are produced by the Intellisense compiler, which is (a) different from the compiler that actually builds your code and (b) often wrong.

Share this post


Link to post
Share on other sites

I didn't had tried to compile so far (until you asked), otherwise I would have realized that I shouldn't put the ';' at the end of the macro, which was expanding the ';' into LoadImage("Graphics/Background";); :P

Anyway I'll go with constexpr then, thanks :D

 

Share this post


Link to post
Share on other sites
Just now, MarcusAseth said:

I didn't had tried to compile so far (until you asked), otherwise I would have realized that I shouldn't put the ';' at the end of the macro, which was expanding the ';' into LoadImage("Graphics/Background";); :P

Exactly :)

Other stuff, from your hidden code:

  • You don't initialize GameInstance in your App constructor to nullptr; this means that when you get to ~App(), if the game wasn't running, the GameInstance pointer is random garbage. Attempting to delete such a pointer is undefined behavior and will likely crash you. You should consider using std::unique_ptr<Game> to manage this object instead of having to manually manage it.
  • In ~App, you don't actually appear to call SDL_DestroyWindow and friends. You are missing your parentheses.
  • Methods defined in the class definition (IsRunning) are automatically inline; you don't need the keyword. It's largely useless these days anyhow. As a matter of sanity I tend to avoid defining anything in a header, except when needed (templates), because link-time optimization is usually good enough and I like the faster recompiles. Your mileage may vary.
  • This "return Foo() ? (Bar() ? : true : false) : false" construct is horrid. Not only is it redundant (because Bar() is already returning true or false), the nesting makes it onerous to read.
  • I am worried about what the Error() function is actually doing. It very much looks like it conflates recording of the error with presentation or handling of the error, which is not a great long-term pattern.
  • const char* for strings should be reserved, generally, for inter-operation with C APIs in C++. Use std::string and use its c_str() member when you need to pass data to C APIs like SDL.
  • Prefer nullptr to NULL.

 

 

 

Share this post


Link to post
Share on other sites

Thanks for all the tips and for reading trough my code jpetrie ;)

Resolution of the day: all pointers will be forever initialized to nullptr.

The SDL_DestroyWindow was really careless, but thankfully it gets catched by the compiler

point 4 made me laugh, disgusting people trough code xD

This is my Error() function:

bool Error(const char* err)
{
	std::cout << err << std::endl;
	return false;
}

I either pass the GetError() or a error message written by me, and it always return false.

Though aside from that case where I took the ternary operator TOO FAR, using it like in the code below is "elegant", right? :P

return Window ? true : Error(SDL_GetError());

Anyway I'll be sure to apply all fixes, thanks !

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
3 minutes ago, MarcusAseth said:

This is my Error() function

This looks like a questionable habit to develop.

You're munging together three concerns here: logging, error propagation, and error presentation. These should probably be three different things.

Logging can be useful for recording information about some event at the site of that event, for future diagnostics purposes. You should have a dedicated function for logging things, if you want to use that capability. Things you may want to log are not always errors.

Error propagation is about bubbling errors up to the place where they can be reasonably dealt with, and including all the relevant information about the error in that bubbling. Right now all your error handling boils down to is returning booleans, which the implicit assumption that there is only one way for a thing to fail. This doesn't scale, and in fact you've already scaled past it: several of your functions can return via Error() using two different messages. It's impossible for the caller of LoadImage to know why an image failed to load, and if that error is something that can be recovered from or handled by retrying or what.

Error presentation at this level is usually simple, usually the same as logging. But as you build things that are more and more advanced, this kind of "immediately present the error" approach falls apart. Consider if you were trying to tell the user "Error("Could not connect to login server, try again in five minutes.")." This is a typical message you'd like to surface to a user, and as such will usually be rendered in the UI style of your game. But you can't put up a blocking modal dialog deep inside your code like that; you need to have that error information propagated outwards (as above) and then handled by the appropriate UI presentation layer in your code.

Share this post


Link to post
Share on other sites

I can and will certainly add the Logging() function, but all after that, is just too much for me to consider right now x_x

First I'll focus on getting a playable game.

Also I don't actually think as what I am doing as "error handling", is just like a warning in the console for me to roughly know "around which part of the code I fucked up and should place a breakpoint and hunt for bugs"

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
4 minutes ago, MarcusAseth said:

Also I don't actually think as what I am doing as "error handling", is just like a warning in the console for me to roughly know "around which part of the code I fucked up and should place a breakpoint and hunt for bugs"

That's reasonable, but then I'd change the name of the Error() function to Log(). :D

You're right to focus on getting a thing that works and is a game first, before worrying about the minutiae of some of my above points. But they are still worth keeping in the back of your mind for consideration as you build new things, because good habits (particularly with respect to dealing with errors in some fashion beyond "oh shit, well, let's just terminate the whole process") are easily to build early.

Share this post


Link to post
Share on other sites

Small progress today,  trying to get the time stuff right, and probably still isn't, code below.

I've read this whole page again and I am not quite sure of the need/usage for the MAX_FRAMESKIP and that's why I didn't added it to my code x_x

I post the code in case anyone would be so kind to doublecheck :P

GameTimer.h

#pragma once
#include <chrono>
#include <string>
using namespace std::chrono;


class GameTimer
{
	milliseconds MsSinceLastFrame;
	time_point<steady_clock> TimeNow;
public:
	time_point<steady_clock> TimeBegin;
	time_point<steady_clock> PrevUpdateTime;
	time_point<steady_clock> NextUpdateTime;
	
	GameTimer();
	~GameTimer();

	time_point<steady_clock> CurrentTime();
	std::string FPS();
	std::string GameSpeed();

	void RecordTimeSinceLastFrame();
};

GameTimer.cpp

#include "GameTimer.h"



GameTimer::GameTimer()
	:MsSinceLastFrame{0}
{
	TimeBegin = TimeNow = PrevUpdateTime = NextUpdateTime = steady_clock::now();
}


GameTimer::~GameTimer()
{
}

time_point<steady_clock> GameTimer::CurrentTime()
{
	TimeNow = steady_clock::now();
	return TimeNow;
}

std::string GameTimer::FPS()
{
	
	return "| FPS: "+ std::to_string(static_cast<float>(MsSinceLastFrame.count())) + "ms |";
}

std::string GameTimer::GameSpeed()
{
	return "";
}

void GameTimer::RecordTimeSinceLastFrame()
{
	MsSinceLastFrame = duration_cast<milliseconds>(CurrentTime() - PrevUpdateTime);
	PrevUpdateTime = CurrentTime();
}

GameLoop:

void App::GameLoop()
{
	//GameUpdateTickPerSecond   suggested ratio 1/25 seconds = 40ms per udpate
	static duration<uint32_t, std::ratio<1, GameUpdatesPerSec>> GameUpdateTPS{ 1 };

	while (Game->IsRunning())
	{
		Timer->RecordTimeSinceLastFrame();

		while (Timer->CurrentTime() > Timer->NextUpdateTime)
		{
			Game->Update();
			Timer->NextUpdateTime += GameUpdateTPS;
		}

		auto TimeOffset = Timer->CurrentTime() + GameUpdateTPS - Timer->NextUpdateTime;
		auto GameUpdateTPSns = duration_cast<nanoseconds>(GameUpdateTPS);
		
		float Interpolation = float(TimeOffset.count()) / float(GameUpdateTPSns.count());
		Game->Draw(Interpolation);


		/*DEGUB*/LogConsole(std::to_string(Interpolation).c_str());
		std::string AppTitle = "Breakout" + Timer->FPS() + Timer->GameSpeed();
		SDL_SetWindowTitle(Window, AppTitle.c_str());
	}
}

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

I think maybe I should briefly mention something (from my limited understanding) about the chrono library, so maybe other begginners in this section can benefit from it too so that my post/code is less obscure to them and not useful only to me. Also is to review my understanding of it since anyone can correct what I say.

Chrono library is a time library part of the STL, you just need to #include <chrono> in order to use it. Most of the code live inside namespace std::chrono::  .The library doesn't allow inplicit conversions of arithmetic types to durations therefore you can say "seconds MySeconds = 3;//Error" because "3 what?! 3 hours?"

It is mainly composed by 3 things: duration,    time_point,    clocks.

clocks: it has 3 of these, the system_clock which is basically a calender (has functions to convert a time point to a real date), like your Window time, the steady_clock which is basically a stopwatch in nanoseconds (at least on my machine, no idea if this can change) and is great for timing, and lastly the high_resolution_clock which just gives you back one of the other 2 (the one with the shortest tick period).

name_of_one_of_those_3_clocks::now() returns you the current time.

duration: this is a template class on o the form of duration<rap, ratio<num,den>>. It is used to store an arbitrary duration of time, some of the default durations defined in the library are seconds and milliseconds .

Rap is the internal rapresentation used to store the time, it is usually a long long but you can also pass a float or double to it if you want to have your operations on that duration return "fractions of a tick". 

ratio<num,den> is a ratio made up of numerator and denominator used to allow for proper conversion between different duration, seconds default to ratio<1,1> and milliseconds is ratio<1,1000> , so that if you do:

//s is a literal representing seconds, declared with many others in std::literals::chrono_literals 
//but you can just do "using namespace std::chrono;" and it will give you access to those as well
seconds MySeconds = 4s;
milliseconds MyMilliseconds = MySeconds;

//Because of the ratio thing, now MyMilliseconds contains the value 4000

also some default ratios like the one used by milliseconds are provided so that you can do std::milli instead of writing ratio<1,100> 

So in my code in the reply above

static duration<uint32_t, std::ratio<1, GameUpdatesPerSec>> GameUpdateTPS{ 1 };

GameUpdatePerSec is set to 25 and my  GameUpdateTPS contains just 1 of this duration, so that if you convert it to milliseconds or assign one of this to milliseconds you get 40ms ,    1000ms/25 = 40ms.

time_point: this are different than duration because this is a duration from a point in time. You can't just assign a time_point to a duration.

If I have got it right, then:

time_point + time_point returns error

time_point - time_point returns  duration

time_point + duration returns  time_point

time_point - duration returns  time_point

You can always get a duration out of a time_point by calling it's member function time_since_epoch()

Lastly, back to duration, no implicit conversion will happen between a "finer precision" duration and a "coarser precision" duration, so between ms and s for example because you would lose precision, but the implicit conversion will happen the other way around because it is safe to go from coarser to finer.

You can still use duration_cast<Put_To_duration_type_here>(MyTime)  to force that "upward" conversion which will result in truncation of the value stored inside the duration.

And is pretty much the chrono library to my understanding ;)

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

MAX_FRAMESKIP exists so that if updates are too slow, you still get to render every once in a while. I would expect it's unlikely you'll hit this problem.

You don't need to set the window title every time through the game loop.

Chrono is part of the standard library. It's not called the STL, and hasn't been for many years.

Share this post


Link to post
Share on other sites
26 minutes ago, Kylotan said:

Chrono is part of the standard library. It's not called the STL, and hasn't been for many years.

I'm confused by this line, didn't I said the same thing? :D

quoting myself:

Quote

 part of the STL, you just need to #include <chrono>

isn't STL == standard template library == standard library?

Also the window title is holding the ms since last frame display, that's why I keep refreshing it

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

STL is the Standard Template Library. The "Standard Template Library" is an old name for part of the C++ standard library, specifically the containers, algorithms, iterators and functors. These days, we just talk about the standard library, which includes the former bits, plus tons of new stuff. Much of it is templates, but not all.

Sorry, must have missed the milliseconds in the window title. I suggest getting some other form of onscreen text debugging would be a useful thing to do. :)

Share this post


Link to post
Share on other sites

I found a tutorial for making Breakout a while back. It uses OpenGL version 3.3. In my opinion it has a pretty good code structure, but it can be improved upon. It has a static singleton/global resource manager, which just simplifies the loading of assets. "Game Coding Complete" written by Mike McShaffry and David 'Rez' Graham has a better but far more complex way of loading/managing resources. I mentioned it because it contains good examples of how to structure you game, but they're a lot more complex than what you need for Breakout. Here's the link to the tutorial https://learnopengl.com/#!In-Practice/2D-Game/Breakout

Share this post


Link to post
Share on other sites

I know that OpenGL tutorial :P At a certain point in time during the last year I was following it, I had to abandon it because it wasn't enough clear when he start making shaders and uses GLSL and stuff wasn't compiling on my end, and I had nowhere to ask, but with you guys help now things would probably be different! :)

Thanks for letting me know about Game Coding Complete, not scared about complexity don't worry, (I paused this project because I wanted to do some simple composition using templates for this project and follow what he does in this video which I yet can't understand , so I am studying more C++ and templates right now, beforegoing back to his video multiple times and then resume this project :P ) so eventually I'll be picking up that book

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Announcements

  • Forum Statistics

    • Total Topics
      628294
    • Total Posts
      2981882
  • Similar Content

    • By aejt
      I recently started getting into graphics programming (2nd try, first try was many years ago) and I'm working on a 3d rendering engine which I hope to be able to make a 3D game with sooner or later. I have plenty of C++ experience, but not a lot when it comes to graphics, and while it's definitely going much better this time, I'm having trouble figuring out how assets are usually handled by engines.
      I'm not having trouble with handling the GPU resources, but more so with how the resources should be defined and used in the system (materials, models, etc).
      This is my plan now, I've implemented most of it except for the XML parts and factories and those are the ones I'm not sure of at all:
      I have these classes:
      For GPU resources:
      Geometry: holds and manages everything needed to render a geometry: VAO, VBO, EBO. Texture: holds and manages a texture which is loaded into the GPU. Shader: holds and manages a shader which is loaded into the GPU. For assets relying on GPU resources:
      Material: holds a shader resource, multiple texture resources, as well as uniform settings. Mesh: holds a geometry and a material. Model: holds multiple meshes, possibly in a tree structure to more easily support skinning later on? For handling GPU resources:
      ResourceCache<T>: T can be any resource loaded into the GPU. It owns these resources and only hands out handles to them on request (currently string identifiers are used when requesting handles, but all resources are stored in a vector and each handle only contains resource's index in that vector) Resource<T>: The handles given out from ResourceCache. The handles are reference counted and to get the underlying resource you simply deference like with pointers (*handle).  
      And my plan is to define everything into these XML documents to abstract away files:
      Resources.xml for ref-counted GPU resources (geometry, shaders, textures) Resources are assigned names/ids and resource files, and possibly some attributes (what vertex attributes does this geometry have? what vertex attributes does this shader expect? what uniforms does this shader use? and so on) Are reference counted using ResourceCache<T> Assets.xml for assets using the GPU resources (materials, meshes, models) Assets are not reference counted, but they hold handles to ref-counted resources. References the resources defined in Resources.xml by names/ids. The XMLs are loaded into some structure in memory which is then used for loading the resources/assets using factory classes:
      Factory classes for resources:
      For example, a texture factory could contain the texture definitions from the XML containing data about textures in the game, as well as a cache containing all loaded textures. This means it has mappings from each name/id to a file and when asked to load a texture with a name/id, it can look up its path and use a "BinaryLoader" to either load the file and create the resource directly, or asynchronously load the file's data into a queue which then can be read from later to create the resources synchronously in the GL context. These factories only return handles.
      Factory classes for assets:
      Much like for resources, these classes contain the definitions for the assets they can load. For example, with the definition the MaterialFactory will know which shader, textures and possibly uniform a certain material has, and with the help of TextureFactory and ShaderFactory, it can retrieve handles to the resources it needs (Shader + Textures), setup itself from XML data (uniform values), and return a created instance of requested material. These factories return actual instances, not handles (but the instances contain handles).
       
       
      Is this a good or commonly used approach? Is this going to bite me in the ass later on? Are there other more preferable approaches? Is this outside of the scope of a 3d renderer and should be on the engine side? I'd love to receive and kind of advice or suggestions!
      Thanks!
    • By deltaKshatriya
      Hey all,
      As some of you may know, I do have a Computer Science background, but either by chance/design/fate/insert stupid excuse here, I didn't take any graphics courses in my undergraduate degree, but now I'd be very interested in at least learning the basics of graphics and potentially pursuing more in graphics. I'm interested in all sorts of graphics in general, so everything from real-time engines to rendering engines like Arnold, Octane, etc. Can anyone point me in the right directions for books/tutorials?
      Thanks in advance!
      EDIT: Apologies in advance if I missed the proper channels for this as well
    • By ConsolaLarry
      After my first thread and some painful deleting AND some lengthy drive resizing, I now have Unity and Visual Studio Enterprise
      As the hype of me finally being able to make a game that I've always dreamed of faded away because of school schedule being a douchebag, I came to a painful realization that I basically don't know anything about Unity (making progress at least, with the tutorial, the rest....well....I don't have a credit card yet, and my age is 2^4 + 1 (don't wanna be too....public)) nor C# (hopefully dotnetcademy.net's C# course for complete beginners can somehow help me with this).
      At least I know what I am doing (I guess) with my game: 2D, Top down, Isometric, Pixel Art (because I'm on my own and I can't draw like an artist and I'm too broke), RPG with EXP, Class Advancement system and probably some sort of a seeding mechanism for randomized gameplay
      So, as a complete greenhorn stepping into the field with a completely wrong set of equipments, I'd love some advices from the pros and the experienced (all advices are welcomed OwO)/ ), esp to these questions:
      - Should I take on regular C# and then learn Unity C# or skip regular C# and straight to Unity C#?
      - Is pixel art really a way out for me on the visual part? Sprites, maps, items, effects, etc......
      - Is my idea okay? Is there anything I can add in or cross out?
      - Should I do this alone? Or should I get some accomplices? I'm not planning to rush it anyway.
       
      Thank you in advance. Sorry, no potato this time
    • By Cyan_Cap
      I want to ask a question about how much time it normally takes to make large games.
      I am doing a proposal assignment and wanted some sources for how much time it would normally take for larger games to be developed and released. I just thought I could ask around here while doing google searches elsewhere.
       
      Sources I found so far:
      https://kotaku.com/how-much-does-it-cost-to-make-a-big-video-game-1501413649
      https://www.economist.com/blogs/economist-explains/2014/09/economist-explains-15
  • Popular Now