mirror of
https://bitbucket.org/King_DuckZ/jumping-in-d.git
synced 2024-10-30 02:49:01 +00:00
Clean up code and add more comments.
This commit is contained in:
parent
6d11e98499
commit
4b0ca89d7f
4 changed files with 79 additions and 22 deletions
|
@ -18,25 +18,44 @@
|
||||||
module gameobj;
|
module gameobj;
|
||||||
import derelict.sdl2.sdl;
|
import derelict.sdl2.sdl;
|
||||||
|
|
||||||
interface GameObj {
|
//We want to provide an interface for all game scenes. A game scene should
|
||||||
void prepare();
|
//implement some basic methods, such as prepare() and exec(), so the main loop
|
||||||
void destroy();
|
//can call them.
|
||||||
void exec();
|
//We also want our interface to store a renderer. This forces us to declare
|
||||||
bool wants_to_quit() const;
|
//an abstract class instead of an interface, becaues interfaces can't have
|
||||||
}
|
//constructors nor properties.
|
||||||
|
abstract class GameObj {
|
||||||
class GameObjBase : GameObj {
|
|
||||||
public:
|
public:
|
||||||
this (SDL_Renderer* parRenderer) {
|
this (SDL_Renderer* parRenderer) {
|
||||||
m_renderer = parRenderer;
|
m_renderer = parRenderer;
|
||||||
assert(m_renderer);
|
assert(m_renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Derived classes must implement those;
|
||||||
|
//failure to do so results in a compilation error.
|
||||||
|
//You need to mark them as "abstract" to let the compiler know there is
|
||||||
|
//no implementation for them. If you don't mark them as abstract and you
|
||||||
|
//forget to implement them in the derived game object, you will get a
|
||||||
|
//linker error instead, and potentially the wrong behaviour as you call them
|
||||||
|
//from a pointer to the base class.
|
||||||
|
abstract void prepare();
|
||||||
|
abstract void dispose();
|
||||||
|
abstract void exec();
|
||||||
|
abstract bool wants_to_quit() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SDL_Renderer* renderer() {
|
//Allow game objects inheriting from GameObj to retrieve the renderer they
|
||||||
|
//stored through GameObj's constructor. final means it can't be overridden
|
||||||
|
//(so no v-table entry required for this method); @property means you must
|
||||||
|
//not use () when you call renderer on an object, eg: r=my_game_obj.renderer
|
||||||
|
@property final SDL_Renderer* renderer() {
|
||||||
return m_renderer;
|
return m_renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Remember: private members can still be accessed from within this module.
|
||||||
|
//Or, from a different point of view if you come from a c++ background, within
|
||||||
|
//the gameobj module, everything is friend to everything else.
|
||||||
|
//One more good reason for putting each class into a different module.
|
||||||
private:
|
private:
|
||||||
SDL_Renderer* m_renderer;
|
SDL_Renderer* m_renderer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,11 @@ import derelict.sdl2.sdl;
|
||||||
import texture;
|
import texture;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
|
||||||
class GameObjJumping : GameObjBase {
|
//This is one possible game scene. It will draw a texture on the screen
|
||||||
//Don't disable this(), it's disable automatically when you define a
|
//and it will report user wants to quit if you press the close button in the
|
||||||
|
//window decoration.
|
||||||
|
class GameObjJumping : GameObj {
|
||||||
|
//Don't disable this(), it's disabled automatically when you define a
|
||||||
//custorm constructor.
|
//custorm constructor.
|
||||||
//@disable this();
|
//@disable this();
|
||||||
|
|
||||||
|
@ -32,28 +35,40 @@ class GameObjJumping : GameObjBase {
|
||||||
m_wants_to_quit = false;
|
m_wants_to_quit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Remember: class destructors are not guaranteed to be called
|
||||||
|
//deterministically, so all resource-freeing code should rather go in the
|
||||||
|
//dispose() method.
|
||||||
~this() {
|
~this() {
|
||||||
writeln("Destroying GameObj");
|
writeln("Destroying GameObj");
|
||||||
|
//m_texture's type is a struct, so destruction is implicit at this point
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare() {
|
override void prepare() {
|
||||||
string texture_name = "bcruiser_normal.bpg";
|
string texture_name = "bcruiser_normal.bpg";
|
||||||
writeln("Loading texture %s", texture_name);
|
writeln("Loading texture %s", texture_name);
|
||||||
m_texture = Texture(texture_name, renderer());
|
m_texture = Texture(texture_name, renderer());
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy() {
|
override void dispose() {
|
||||||
|
writeln("GameObjJumping dispose()");
|
||||||
|
//m_texture.dispose() is what you would normally expect to find here,
|
||||||
|
//but to demonstrate the use of clear() from the caller code, this
|
||||||
|
//method is intentionally empty.
|
||||||
|
//You can verify the program's output as you quit by uncommenting the
|
||||||
|
//following line:
|
||||||
|
//m_texture.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
//This is the function that is called at every frame
|
//This is the function that is called at every frame. It represents the
|
||||||
void exec() {
|
//main loop's body.
|
||||||
|
override void exec() {
|
||||||
SDL_RenderClear(renderer());
|
SDL_RenderClear(renderer());
|
||||||
m_texture.draw();
|
m_texture.draw();
|
||||||
SDL_RenderPresent(renderer());
|
SDL_RenderPresent(renderer());
|
||||||
m_wants_to_quit = do_events();
|
m_wants_to_quit = do_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wants_to_quit() const {
|
override bool wants_to_quit() const {
|
||||||
return m_wants_to_quit;
|
return m_wants_to_quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
src/main.d
31
src/main.d
|
@ -21,13 +21,14 @@ import std.string;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import derelict.sdl2.sdl;
|
import derelict.sdl2.sdl;
|
||||||
import gameobjjumping;
|
import gameobjjumping;
|
||||||
|
import std.typecons : scoped; //Only import scoped from std.typecons module
|
||||||
|
|
||||||
void run_main_loop (ref GameObj parGame) {
|
void run_main_loop (GameObj parGame) {
|
||||||
parGame.prepare();
|
parGame.prepare();
|
||||||
do {
|
do {
|
||||||
parGame.exec();
|
parGame.exec();
|
||||||
} while (!parGame.wants_to_quit());
|
} while (!parGame.wants_to_quit());
|
||||||
parGame.destroy();
|
parGame.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
@ -53,9 +54,31 @@ int main() {
|
||||||
scope(exit) { writeln("Destroying renderer..."); SDL_DestroyRenderer(renderer); }
|
scope(exit) { writeln("Destroying renderer..."); SDL_DestroyRenderer(renderer); }
|
||||||
|
|
||||||
//This is our game object
|
//This is our game object
|
||||||
GameObj game = new GameObjJumping(renderer);
|
//Because GameObjJumping implementation purposedly doesn't destroy resources
|
||||||
scope(exit) clear(game);
|
//in its dispose method (for this example's sake), you must make sure its
|
||||||
|
//destructor gets called. You have several choices:
|
||||||
|
//
|
||||||
|
//1 - call clear() (deprecated and removed in recent D compilers)
|
||||||
|
// GameObj game = new GameObjJumping(renderer);
|
||||||
|
// scope(exit) clear(game);
|
||||||
|
//
|
||||||
|
//2 - call destroy()
|
||||||
|
//note that while game.destroy() is semantically equivalent to the
|
||||||
|
//destroy(game) syntax, you should never write it that way in case game
|
||||||
|
//provides its own destroy() method. In that case the method will be
|
||||||
|
//preferred, and you will end up doing something potentially different than
|
||||||
|
//what you intended to. For the same reason, don't provide a destroy()
|
||||||
|
//method in your classes.
|
||||||
|
// GameObj game = new GameObjJumping(renderer);
|
||||||
|
// scope(exit) destroy(game);
|
||||||
|
//
|
||||||
|
//3 - use scope (deprecated)
|
||||||
|
// scope GameObj game = new GameObjJumping(renderer);
|
||||||
|
//
|
||||||
|
//4 - use scoped (no need for new)
|
||||||
|
// auto game = scoped!GameObjJumping(renderer);
|
||||||
|
|
||||||
|
auto game = scoped!GameObjJumping(renderer);
|
||||||
run_main_loop(game);
|
run_main_loop(game);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,10 @@ public:
|
||||||
|
|
||||||
~this() {
|
~this() {
|
||||||
writefln("Destroying texture %s (%s)", m_filename, m_texture);
|
writefln("Destroying texture %s (%s)", m_filename, m_texture);
|
||||||
destroy();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy() {
|
void dispose() {
|
||||||
if (m_texture) {
|
if (m_texture) {
|
||||||
SDL_DestroyTexture(m_texture);
|
SDL_DestroyTexture(m_texture);
|
||||||
m_texture = null;
|
m_texture = null;
|
||||||
|
|
Loading…
Reference in a new issue