diff --git a/.gitignore b/.gitignore index 567609b..b92c8d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,8 @@ build/ + +lib/libbpg*/**/*.d +lib/libbpg*/**/*.o +lib/libbpg*/**/*.a +lib/libbpg*/bpgdec +lib/libbpg*/bpgenc +lib/libbpg*/bpgview diff --git a/CMakeLists.txt b/CMakeLists.txt index 808b74e..994f75b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable(${PROJECT_NAME} gameobj.d bpg.d texture.d + gameobjjumping.d lib/DerelictSDL2/source/derelict/sdl2/functions.d lib/DerelictSDL2/source/derelict/sdl2/image.d diff --git a/bpg.d b/bpg.d index f54bb03..f42354f 100644 --- a/bpg.d +++ b/bpg.d @@ -19,6 +19,7 @@ module bpg; import std.stdint; import std.array; +//Define structs as in the c header file (libbpg.h) struct BPGDecoderContext; struct BPGExtensionData { @@ -42,12 +43,14 @@ struct BPGImageInfo { uint16_t loop_count; /* animations: number of loop, 0 = infinity */ } +//Just a convenience struct to return the uncompressed image and its size struct DecodedBPGImage { ubyte[] data; int width; int height; } +//Enums, as defined in the c header (libbpg.h) enum BPGDecoderOutputFormat : int { BPG_OUTPUT_FORMAT_RGB24, BPG_OUTPUT_FORMAT_RGBA32, /* not premultiplied alpha */ @@ -65,17 +68,20 @@ enum BPGExtensionTagEnum : int { BPG_EXTENSION_TAG_ANIM_CONTROL = 5, }; -extern (C) BPGDecoderContext* bpg_decoder_open(); -extern (C) int bpg_decoder_keep_extension_data (BPGDecoderContext* s, int enable); -extern (C) int bpg_decoder_decode (BPGDecoderContext* s, const uint8_t* buf, int buf_len); -extern (C) BPGExtensionData bpg_decoder_get_extension_data (BPGDecoderContext* s); -extern (C) int bpg_decoder_get_info (BPGDecoderContext* s, BPGImageInfo* p); -extern (C) void bpg_decoder_close (BPGDecoderContext* s); -extern (C) void bpg_decoder_free_extension_data (BPGExtensionData* first_md); -extern (C) int bpg_decoder_start (BPGDecoderContext* s, BPGDecoderOutputFormat out_fmt); -extern (C) int bpg_decoder_get_line (BPGDecoderContext* s, void* buf); +//Declaration of the c functions +private extern (C) BPGDecoderContext* bpg_decoder_open(); +private extern (C) int bpg_decoder_keep_extension_data (BPGDecoderContext* s, int enable); +private extern (C) int bpg_decoder_decode (BPGDecoderContext* s, const uint8_t* buf, int buf_len); +private extern (C) BPGExtensionData bpg_decoder_get_extension_data (BPGDecoderContext* s); +private extern (C) int bpg_decoder_get_info (BPGDecoderContext* s, BPGImageInfo* p); +private extern (C) void bpg_decoder_close (BPGDecoderContext* s); +private extern (C) void bpg_decoder_free_extension_data (BPGExtensionData* first_md); +private extern (C) int bpg_decoder_start (BPGDecoderContext* s, BPGDecoderOutputFormat out_fmt); +private extern (C) int bpg_decoder_get_line (BPGDecoderContext* s, void* buf); -DecodedBPGImage decode_bpg_image (const(char)[] parData) { +//Use the c functions to decode the compressed data in parData. +//This function does just that, and only returns 24 bit images. +public DecodedBPGImage decode_bpg_image (const(char)[] parData) { auto context = bpg_decoder_open(); scope(exit) bpg_decoder_close(context); diff --git a/gameobj.d b/gameobj.d index 678504c..8356c51 100644 --- a/gameobj.d +++ b/gameobj.d @@ -16,66 +16,10 @@ */ module gameobj; -import derelict.sdl2.sdl; -import texture; -import std.stdio; -struct GameObj { -public: - @disable this(); - @disable this(this); - - this (SDL_Renderer* parRenderer) { - m_renderer = parRenderer; - m_wants_to_quit = false; - } - - ~this() { - writeln("Destroying GameObj"); - } - - void prepare() { - string texture_name = "bcruiser_normal.bpg"; - writeln("Loading texture %s", texture_name); - m_texture = Texture(texture_name, m_renderer); - } - - void destroy() { - } - - void exec() { - SDL_RenderClear(m_renderer); - m_texture.draw(); - SDL_RenderPresent(m_renderer); - m_wants_to_quit = do_events(); - } - - bool wants_to_quit() { - return m_wants_to_quit; - } - -private: - Texture m_texture; - SDL_Renderer* m_renderer; - bool m_wants_to_quit; -} - -bool do_events() { - SDL_Event eve; - while (SDL_PollEvent(&eve)) { - switch (eve.type) { - case SDL_KEYDOWN: - break; - - case SDL_KEYUP: - break; - - case SDL_QUIT: - return true; - - default: - break; - } - } - return false; +interface GameObj { + void prepare(); + void destroy(); + void exec(); + bool wants_to_quit() const; } diff --git a/gameobjjumping.d b/gameobjjumping.d new file mode 100644 index 0000000..504dadf --- /dev/null +++ b/gameobjjumping.d @@ -0,0 +1,84 @@ +/* Copyright 2015, Michele Santullo + * This file is part of "Jumping in D". + * + * "Jumping in D" is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * "Jumping in D" is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Jumping in D". If not, see . + */ + +module gameobjjumping; +public import gameobj; +import derelict.sdl2.sdl; +import texture; +import std.stdio; + +class GameObjJumping : GameObj { + //Don't disable this(), it's disable automatically when you define a + //custorm constructor. + //@disable this(); + + //Take the pointer to the renderer and set initial values + this (SDL_Renderer* parRenderer) { + m_renderer = parRenderer; + m_wants_to_quit = false; + } + + ~this() { + writeln("Destroying GameObj"); + } + + void prepare() { + string texture_name = "bcruiser_normal.bpg"; + writeln("Loading texture %s", texture_name); + m_texture = Texture(texture_name, m_renderer); + } + + void destroy() { + } + + //This is the function that is called at every frame + void exec() { + SDL_RenderClear(m_renderer); + m_texture.draw(); + SDL_RenderPresent(m_renderer); + m_wants_to_quit = do_events(); + } + + bool wants_to_quit() const { + return m_wants_to_quit; + } + +private: + Texture m_texture; + SDL_Renderer* m_renderer; + bool m_wants_to_quit; +} + +private bool do_events() { + SDL_Event eve; + while (SDL_PollEvent(&eve)) { + switch (eve.type) { + case SDL_KEYDOWN: + break; + + case SDL_KEYUP: + break; + + case SDL_QUIT: + return true; + + default: + break; + } + } + return false; +} diff --git a/main.d b/main.d index e848269..7073087 100644 --- a/main.d +++ b/main.d @@ -20,7 +20,7 @@ import std.stdio; import std.string; import std.conv; import derelict.sdl2.sdl; -import gameobj; +import gameobjjumping; void run_main_loop (ref GameObj parGame) { parGame.prepare(); @@ -33,19 +33,29 @@ void run_main_loop (ref GameObj parGame) { int main() { writeln("Hello world!"); + //Initialize DerelictSDL2 and SDL2 itself DerelictSDL2.load(); if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { - throw new Exception(format("Error initializing SDL: %s", text(SDL_GetError()))); + throw new Exception( + format("Error initializing SDL: %s", text(SDL_GetError())) + ); } + //Automatically uninitialize SDL2 on quitting - note that scope(exit) + //statements are called in reverse order, so SDL_Quit() will be the last. scope(exit) { writeln("Destroying SDL..."); SDL_Quit(); } + //Create a window... SDL_Window* win = SDL_CreateWindow("hello_d", 100, 100, 120, 120, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); scope(exit) { writeln("Destroying window..."); SDL_DestroyWindow(win); } + //...and a renderer SDL_Renderer* renderer = SDL_CreateRenderer(win, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); scope(exit) { writeln("Destroying renderer..."); SDL_DestroyRenderer(renderer); } - GameObj game = GameObj(renderer); + //This is our game object + GameObj game = new GameObjJumping(renderer); + scope(exit) clear(game); + run_main_loop(game); return 0; }